VCL: add IPv6 to socket_test.sh and make test
[vpp.git] / src / vpp-api / vom / interface.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_H__
17 #define __VOM_INTERFACE_H__
18
19 #include "vom/enum_base.hpp"
20 #include "vom/hw.hpp"
21 #include "vom/inspect.hpp"
22 #include "vom/object_base.hpp"
23 #include "vom/om.hpp"
24 #include "vom/prefix.hpp"
25 #include "vom/route_domain.hpp"
26 #include "vom/rpc_cmd.hpp"
27 #include "vom/singular_db.hpp"
28
29 namespace VOM {
30 /**
31  * Forward declaration of the stats and events command
32  */
33 namespace interface_cmds {
34 class stats_enable_cmd;
35 class events_cmd;
36 };
37
38 /**
39  * A representation of an interface in VPP
40  */
41 class interface : public object_base
42 {
43 public:
44   /**
45    * The key for interface's key
46    */
47   typedef std::string key_t;
48
49   /**
50    * The iterator type
51    */
52   typedef singular_db<const std::string, interface>::const_iterator
53     const_iterator_t;
54
55   /**
56    * An interface type
57    */
58   struct type_t : enum_base<type_t>
59   {
60     /**
61      * Unkown type
62      */
63     const static type_t UNKNOWN;
64     /**
65      * A brideged Virtual interface (aka SVI or IRB)
66      */
67     const static type_t BVI;
68     /**
69      * VXLAN interface
70      */
71     const static type_t VXLAN;
72     /**
73      * Ethernet interface type
74      */
75     const static type_t ETHERNET;
76     /**
77      * AF-Packet interface type
78      */
79     const static type_t AFPACKET;
80     /**
81      * loopback interface type
82      */
83     const static type_t LOOPBACK;
84     /**
85      * Local interface type (specific to VPP)
86      */
87     const static type_t LOCAL;
88     /**
89      * TAP interface type
90      */
91     const static type_t TAP;
92
93     /**
94      * vhost-user interface type
95      */
96     const static type_t VHOST;
97
98     /**
99      * Convert VPP's name of the interface to a type
100      */
101     static type_t from_string(const std::string& str);
102
103   private:
104     /**
105      * Private constructor taking the value and the string name
106      */
107     type_t(int v, const std::string& s);
108   };
109
110   /**
111    * The admin state of the interface
112    */
113   struct admin_state_t : enum_base<admin_state_t>
114   {
115     /**
116      * Admin DOWN state
117      */
118     const static admin_state_t DOWN;
119     /**
120      * Admin UP state
121      */
122     const static admin_state_t UP;
123
124     /**
125      * Convert VPP's numerical value to enum type
126      */
127     static admin_state_t from_int(uint8_t val);
128
129   private:
130     /**
131      * Private constructor taking the value and the string name
132      */
133     admin_state_t(int v, const std::string& s);
134   };
135
136   /**
137    * The oper state of the interface
138    */
139   struct oper_state_t : enum_base<oper_state_t>
140   {
141     /**
142      * Operational DOWN state
143      */
144     const static oper_state_t DOWN;
145     /**
146      * Operational UP state
147      */
148     const static oper_state_t UP;
149
150     /**
151      * Convert VPP's numerical value to enum type
152      */
153     static oper_state_t from_int(uint8_t val);
154
155   private:
156     /**
157      * Private constructor taking the value and the string name
158      */
159     oper_state_t(int v, const std::string& s);
160   };
161
162   /**
163    * Construct a new object matching the desried state
164    */
165   interface(const std::string& name,
166             type_t type,
167             admin_state_t state,
168             const std::string& tag = "");
169   /**
170    * Construct a new object matching the desried state mapped
171    * to a specific route_domain
172    */
173   interface(const std::string& name,
174             type_t type,
175             admin_state_t state,
176             const route_domain& rd,
177             const std::string& tag = "");
178   /**
179    * Destructor
180    */
181   virtual ~interface();
182
183   /**
184    * Copy Constructor
185    */
186   interface(const interface& o);
187
188   static const_iterator_t cbegin();
189   static const_iterator_t cend();
190
191   /**
192    * Return the matching'singular' of the interface
193    */
194   std::shared_ptr<interface> singular() const;
195
196   /**
197    * convert to string format for debug purposes
198    */
199   virtual std::string to_string(void) const;
200
201   /**
202    * Return VPP's handle to this object
203    */
204   const handle_t& handle() const;
205
206   /**
207    * Return the interface type
208    */
209   const type_t& type() const;
210
211   /**
212    * Return the interface type
213    */
214   const std::string& name() const;
215
216   /**
217    * Return the interface type
218    */
219   const key_t& key() const;
220
221   /**
222    * Return the L2 Address
223    */
224   const l2_address_t& l2_address() const;
225
226   /**
227    * Set the admin state of the interface
228    */
229   void set(const admin_state_t& state);
230
231   /**
232    * Set the L2 Address
233    */
234   void set(const l2_address_t& addr);
235
236   /**
237    * Set the operational state of the interface, as reported by VPP
238    */
239   void set(const oper_state_t& state);
240
241   /**
242    * Set the tag to the interface
243    */
244   void set(const std::string& tag);
245
246   /**
247    * Comparison operator - only used for UT
248    */
249   virtual bool operator==(const interface& i) const;
250
251   /**
252    * A base class for interface Create commands
253    */
254   template <typename MSG>
255   class create_cmd : public rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>
256   {
257   public:
258     create_cmd(HW::item<handle_t>& item, const std::string& name)
259       : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
260       , m_name(name)
261     {
262     }
263
264     /**
265      * Destructor
266      */
267     virtual ~create_cmd() = default;
268
269     /**
270      * Comparison operator - only used for UT
271      */
272     virtual bool operator==(const create_cmd& o) const
273     {
274       return (m_name == o.m_name);
275     }
276
277     /**
278      * Indicate the succeeded, when the HW Q is disabled.
279      */
280     void succeeded()
281     {
282       rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>::succeeded();
283       interface::add(m_name, this->item());
284     }
285
286     /**
287      * add the created interface to the DB
288      */
289     void insert_interface() { interface::add(m_name, this->item()); }
290
291     virtual vapi_error_e operator()(MSG& reply)
292     {
293       int sw_if_index = reply.get_response().get_payload().sw_if_index;
294       int retval = reply.get_response().get_payload().retval;
295
296       VOM_LOG(log_level_t::DEBUG) << this->to_string() << " " << retval;
297
298       rc_t rc = rc_t::from_vpp_retval(retval);
299       handle_t handle = handle_t::INVALID;
300
301       if (rc_t::OK == rc) {
302         handle = sw_if_index;
303       }
304
305       HW::item<handle_t> res(handle, rc);
306
307       this->fulfill(res);
308
309       return (VAPI_OK);
310     }
311
312   protected:
313     /**
314      * The name of the interface to be created
315      */
316     const std::string& m_name;
317   };
318
319   /**
320    * Base class for intterface Delete commands
321    */
322   template <typename MSG>
323   class delete_cmd : public rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>
324   {
325   public:
326     delete_cmd(HW::item<handle_t>& item, const std::string& name)
327       : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
328       , m_name(name)
329     {
330     }
331
332     delete_cmd(HW::item<handle_t>& item)
333       : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
334       , m_name()
335     {
336     }
337
338     /**
339      * Destructor
340      */
341     virtual ~delete_cmd() = default;
342
343     /**
344      * Comparison operator - only used for UT
345      */
346     virtual bool operator==(const delete_cmd& o) const
347     {
348       return (this->m_hw_item == o.m_hw_item);
349     }
350
351     /**
352      * Indicate the succeeded, when the HW Q is disabled.
353      */
354     void succeeded() {}
355
356     /**
357      * remove the deleted interface from the DB
358      */
359     void remove_interface() { interface::remove(this->item()); }
360
361   protected:
362     /**
363      * The name of the interface to be created
364      */
365     const std::string m_name;
366   };
367
368   /**
369    * A class that listens to interface Events
370    */
371   class event_listener
372   {
373   public:
374     /**
375      * Default Constructor
376      */
377     event_listener();
378
379     /**
380      * Virtual function called on the listener when the command has data
381      * ready to process
382      */
383     virtual void handle_interface_event(interface_cmds::events_cmd* cmd) = 0;
384
385     /**
386      * Return the HW::item representing the status
387      */
388     HW::item<bool>& status();
389
390   protected:
391     /**
392      * The status of the subscription
393      */
394     HW::item<bool> m_status;
395   };
396
397   /**
398    * A class that listens to interface Stats
399    */
400   class stat_listener
401   {
402   public:
403     /**
404      * Default Constructor
405      */
406     stat_listener();
407
408     /**
409      * Virtual function called on the listener when the command has data
410      * ready to process
411      */
412     virtual void handle_interface_stat(
413       interface_cmds::stats_enable_cmd* cmd) = 0;
414
415     /**
416      * Return the HW::item representing the status
417      */
418     HW::item<bool>& status();
419
420   protected:
421     /**
422      * The status of the subscription
423      */
424     HW::item<bool> m_status;
425   };
426
427   /**
428    * The the singular instance of the interface in the DB by handle
429    */
430   static std::shared_ptr<interface> find(const handle_t& h);
431
432   /**
433    * The the singular instance of the interface in the DB by key
434    */
435   static std::shared_ptr<interface> find(const key_t& k);
436
437   /**
438    * Dump all interfaces into the stream provided
439    */
440   static void dump(std::ostream& os);
441
442   /**
443    * Enable stats for this interface
444    */
445   void enable_stats(stat_listener& el);
446
447 protected:
448   /**
449    * Set the handle of an interface object. Only called by the interface
450    * factory during the populate
451    */
452   void set(const handle_t& handle);
453   friend class interface_factory;
454
455   /**
456    * The SW interface handle VPP has asigned to the interface
457    */
458   HW::item<handle_t> m_hdl;
459
460   /**
461    * Return the matching 'singular' of the interface
462    */
463   virtual std::shared_ptr<interface> singular_i() const;
464
465   /**
466    * release/remove an interface form the singular store
467    */
468   void release();
469
470   /**
471    * Virtual functions to construct an interface create commands.
472    * Overridden in derived classes like the sub_interface
473    */
474   virtual std::queue<cmd*>& mk_create_cmd(std::queue<cmd*>& cmds);
475
476   /**
477    * Virtual functions to construct an interface delete commands.
478    * Overridden in derived classes like the sub_interface
479    */
480   virtual std::queue<cmd*>& mk_delete_cmd(std::queue<cmd*>& cmds);
481
482   /**
483    * Sweep/reap the object if still stale
484    */
485   virtual void sweep(void);
486
487   /**
488    * A map of all interfaces key against the interface's name
489    */
490   static singular_db<key_t, interface> m_db;
491
492   /**
493    * Add an interface to the DB keyed on handle
494    */
495   static void add(const key_t& name, const HW::item<handle_t>& item);
496
497   /**
498    * remove an interface from the DB keyed on handle
499    */
500   static void remove(const HW::item<handle_t>& item);
501
502 private:
503   /**
504    * Class definition for listeners to OM events
505    */
506   class event_handler : public OM::listener, public inspect::command_handler
507   {
508   public:
509     event_handler();
510     virtual ~event_handler() = default;
511
512     /**
513      * Handle a populate event
514      */
515     void handle_populate(const client_db::key_t& key);
516
517     /**
518      * Handle a replay event
519      */
520     void handle_replay();
521
522     /**
523      * Show the object in the Singular DB
524      */
525     void show(std::ostream& os);
526
527     /**
528      * Get the sortable Id of the listener
529      */
530     dependency_t order() const;
531   };
532
533   static event_handler m_evh;
534
535   /**
536    * enable the interface stats in the singular instance
537    */
538   void enable_stats_i(stat_listener& el);
539
540   /**
541    * Commit the acculmulated changes into VPP. i.e. to a 'HW" write.
542    */
543   void update(const interface& obj);
544
545   /*
546    * return the interface's handle in the singular instance
547    */
548   const handle_t& handle_i() const;
549
550   /*
551    * It's the OM class that calls singular()
552    */
553   friend class OM;
554
555   /**
556    * It's the singular_db class that calls replay()
557    */
558   friend class singular_db<key_t, interface>;
559
560   /**
561    * The interfaces name
562    */
563   const std::string m_name;
564
565   /**
566    * The interface type. clearly this cannot be changed
567    * once the interface has been created.
568    */
569   const type_t m_type;
570
571   /**
572    * shared pointer to the routeDoamin the interface is in.
573    * NULL is not mapped  - i.e. in the default table
574    */
575   std::shared_ptr<route_domain> m_rd;
576
577   /**
578    * shared pointer to the stats object for this interface.
579    */
580   std::shared_ptr<interface_cmds::stats_enable_cmd> m_stats;
581
582   /**
583    * The state of the interface
584    */
585   HW::item<admin_state_t> m_state;
586
587   /**
588    * HW state of the VPP table mapping
589    */
590   HW::item<route::table_id_t> m_table_id;
591
592   /**
593    * HW state of the L2 address
594    */
595   HW::item<l2_address_t> m_l2_address;
596
597   /**
598    * Operational state of the interface
599    */
600   oper_state_t m_oper;
601
602   /**
603    * tag of the interface
604    */
605   std::string m_tag;
606
607   /**
608    * A map of all interfaces keyed against VPP's handle
609    */
610   static std::map<handle_t, std::weak_ptr<interface>> m_hdl_db;
611
612   /**
613    * replay the object to create it in hardware
614    */
615   virtual void replay(void);
616
617   /**
618    * Create commands are firends so they can add interfaces to the
619    * handle store.
620    */
621   template <typename MSG>
622   friend class create_cmd;
623
624   /**
625    * Create commands are firends so they can remove interfaces from the
626    * handle store.
627    */
628   template <typename MSG>
629   friend class delete_cmd;
630 };
631 };
632 /*
633  * fd.io coding-style-patch-verification: ON
634  *
635  * Local Variables:
636  * eval: (c-set-style "mozilla")
637  * End:
638  */
639 #endif