4c7f3915cf298e57dc0719fbcb4b3040a944c867
[vpp.git] / src / vpp-api / vom / interface_ip6_nd.hpp
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #ifndef __VOM_INTERFACE_IP6_ND_H__
17 #define __VOM_INTERFACE_IP6_ND_H__
18
19 #include "vom/dump_cmd.hpp"
20 #include "vom/hw.hpp"
21 #include "vom/inspect.hpp"
22 #include "vom/interface.hpp"
23 #include "vom/object_base.hpp"
24 #include "vom/om.hpp"
25 #include "vom/ra_config.hpp"
26 #include "vom/ra_prefix.hpp"
27 #include "vom/rpc_cmd.hpp"
28 #include "vom/singular_db.hpp"
29 #include "vom/sub_interface.hpp"
30
31 namespace VOM {
32 /**
33  * A representation of L3 configuration on an interface
34  */
35 template <typename CLASS, typename CMD>
36 class interface_ip6_nd : public object_base
37 {
38 public:
39   typedef CLASS class_t;
40   /**
41    * Construct a new object matching the desried state
42    */
43   interface_ip6_nd(const interface& itf, const class_t cls)
44     : m_itf(itf.singular())
45     , m_cls(cls)
46     , m_config(true)
47   {
48   }
49
50   /**
51    * Copy Constructor
52    */
53   interface_ip6_nd(const interface_ip6_nd& o)
54     : m_itf(o.m_itf)
55     , m_cls(o.m_cls)
56     , m_config(o.m_config)
57   {
58   }
59
60   /**
61    * Destructor
62    */
63   ~interface_ip6_nd()
64   {
65     sweep();
66     m_db.release(m_itf->key(), this);
67   }
68
69   /**
70    * Return the 'singular instance' of the interface ip6nd that matches
71    * this object
72  */
73   std::shared_ptr<interface_ip6_nd> singular() const
74   {
75     return find_or_add(*this);
76   }
77
78   /**
79    * convert to string format for debug purposes
80    */
81   std::string to_string() const
82   {
83     std::ostringstream s;
84     s << "interface-ip6-nd:["
85       << " itf:" << m_itf->to_string() << " " << m_cls.to_string() << " "
86       << m_config.to_string() << "]";
87
88     return (s.str());
89   }
90
91   /**
92    * Dump all config into the stream provided
93    */
94   static void dump(std::ostream& os) { m_db.dump(os); }
95
96   /**
97    * The key type for interface ip6 nd
98    */
99   typedef interface::key_type key_t;
100
101   /**
102    * Find an singular instance in the DB for the interface passed
103    */
104   static std::shared_ptr<interface_ip6_nd> find(const interface& i)
105   {
106     /*
107      * Loop throught the entire map looking for matching interface.
108      * not the most efficient algorithm, but it will do for now. The
109      * number of ra configs is low.
110      */
111     std::deque<std::shared_ptr<interface_ip6_nd>> rac;
112
113     auto it = m_db.cbegin();
114
115     while (it != m_db.cend()) {
116       /*
117        * The key in the DB is a pair of the interface's name.
118        * If the keys match, save the ra-config
119        */
120       auto key = it->first;
121
122       if (i.key() == key.first) {
123         rac.push_back(it->second.lock());
124       }
125
126       ++it;
127     }
128
129     return (rac);
130   }
131
132   /**
133    * A functor class that binds the ra config to the interface
134    */
135   class config_cmd : public rpc_cmd<HW::item<bool>, rc_t, CMD>
136   {
137   public:
138     /**
139      * Constructor
140      */
141     config_cmd(HW::item<bool>& item, const handle_t& itf, const class_t& cls)
142       : rpc_cmd<HW::item<bool>, rc_t, CMD>(item)
143       , m_itf(itf)
144       , m_cls(cls)
145     {
146     }
147
148     /**
149      * Issue the command to VPP/HW
150      */
151     rc_t issue(connection& con);
152
153     /**
154      * convert to string format for debug purposes
155      */
156     std::string to_string() const
157     {
158       std::ostringstream s;
159       s << "interface-ip6-nd: " << this->item().to_string()
160         << " itf:" << m_itf.to_string() << " " << m_cls.to_string();
161
162       return (s.str());
163     }
164
165     /**
166      * Comparison operator - only used for UT
167      */
168     bool operator==(const config_cmd& other) const
169     {
170       return ((m_itf == other.m_itf) && (m_cls == other.m_cls));
171     }
172
173   private:
174     /**
175      * Reference to the interface to bind to
176      */
177     const handle_t& m_itf;
178
179     /**
180      * Reference to the config class
181      */
182     const class_t& m_cls;
183   };
184
185   /**
186    * A cmd class that Unbinds L3 Config from an interface
187    */
188   class unconfig_cmd : public rpc_cmd<HW::item<bool>, rc_t, CMD>
189   {
190   public:
191     /**
192      * Constructor
193      */
194     unconfig_cmd(HW::item<bool>& item, const handle_t& itf, const class_t& cls)
195       : rpc_cmd<HW::item<bool>, rc_t, CMD>(item)
196       , m_itf(itf)
197       , m_cls(cls)
198     {
199     }
200
201     /**
202      * Issue the command to VPP/HW
203      */
204     rc_t issue(connection& con);
205
206     /**
207      * convert to string format for debug purposes
208      */
209     std::string to_string() const
210     {
211       std::ostringstream s;
212       s << "interface-ip6-nd: " << this->item().to_string()
213         << " itf:" << m_itf.to_string() << " " << m_cls.to_string();
214
215       return (s.str());
216     }
217
218     /**
219      * Comparison operator - only used for UT
220      */
221     bool operator==(const unconfig_cmd& other) const
222     {
223       return ((m_itf == other.m_itf) && (m_cls == other.m_cls));
224     }
225
226   private:
227     /**
228      * Reference to the interface to unbind fomr
229      */
230     const handle_t& m_itf;
231
232     /**
233      * Reference to the config class to undo configurations
234      */
235     const class_t& m_cls;
236   };
237
238 private:
239   /**
240    * Class definition for listeners to OM events
241    */
242   class event_handler : public OM::listener, public inspect::command_handler
243   {
244   public:
245     event_handler()
246     {
247       OM::register_listener(this);
248       inspect::register_handler({ "ip6_nd " }, "interface ip6 nd", this);
249     }
250
251     virtual ~event_handler() = default;
252
253     /**
254      * Handle a populate event
255      */
256     void handle_populate(const client_db::key_t& key)
257     {
258       /**
259        * VPP provides no dump for ra config
260        */
261     }
262
263     /**
264      * Handle a replay event
265      */
266     void handle_replay() { m_db.replay(); }
267
268     /**
269      * Show the object in the Singular DB
270      */
271     void show(std::ostream& os) { m_db.dump(os); }
272
273     /**
274      * Get the sortable Id of the listener
275      */
276     dependency_t order() const { return (dependency_t::BINDING); }
277   };
278
279   /**
280    * event_handler to register with OM
281    */
282   static event_handler m_evh;
283
284   /**
285    * Enqueue commands to the VPP for the update
286    */
287   void update(const interface_ip6_nd& obj)
288   {
289     if (!m_config) {
290       HW::enqueue(new config_cmd(m_config, m_itf->handle(), m_cls));
291     }
292   }
293
294   void sweep()
295   {
296     if (m_config) {
297       HW::enqueue(new unconfig_cmd(m_config, m_itf->handle(), m_cls));
298     }
299     HW::write();
300   }
301
302   /**
303    * Replay the objects state to HW
304    */
305   void replay(void)
306   {
307     if (m_config) {
308       HW::enqueue(new config_cmd(m_config, m_itf->handle(), m_cls));
309     }
310   }
311
312   /**
313    * Find or add the singular instance in the DB
314    */
315   static std::shared_ptr<interface_ip6_nd> find_or_add(
316     const interface_ip6_nd& temp)
317   {
318     return (m_db.find_or_add(temp.m_itf->key(), temp));
319   }
320
321   /*
322    * It's the VPPHW class that updates the objects in HW
323    */
324   friend class OM;
325
326   /**
327    * It's the singular_db class that calls replay()
328    */
329   friend class singular_db<key_t, interface_ip6_nd>;
330
331   const std::shared_ptr<interface> m_itf;
332
333   const class_t m_cls;
334
335   const key_t m_key;
336
337   /**
338    * HW configuration for the binding. The bool representing the
339    * do/don't bind.
340  */
341   HW::item<bool> m_config;
342
343   /**
344    * A map of all interface ip6 nd keyed against a combination of the
345    * interface and subnet's keys.
346    */
347   static singular_db<key_t, interface_ip6_nd> m_db;
348 };
349
350 /**
351  * Typedef the ip6nd_ra_config
352  */
353 typedef interface_ip6_nd<ra_config, vapi::Sw_interface_ip6nd_ra_config>
354   ip6nd_ra_config;
355
356 /**
357  * Typedef the ip6nd_ra_prefix
358  */
359 typedef interface_ip6_nd<ra_prefix, vapi::Sw_interface_ip6nd_ra_prefix>
360   ip6nd_ra_prefix;
361
362 /**
363  * Definition of the static singular_db for ACL Lists
364  */
365 template <typename CLASS, typename CMD>
366 singular_db<typename interface_ip6_nd<CLASS, CMD>::key_t,
367             interface_ip6_nd<CLASS, CMD>>
368   interface_ip6_nd<CLASS, CMD>::m_db;
369
370 template <typename CLASS, typename CMD>
371 typename interface_ip6_nd<CLASS, CMD>::event_handler
372   interface_ip6_nd<CLASS, CMD>::m_evh;
373 };
374
375 /*
376  * fd.io coding-style-patch-verification: ON
377  *
378  * Local Variables:
379  * eval: (c-set-style "mozilla")
380  * End:
381  */
382
383 #endif