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