8863bc94868c37d715839b194d7987460ff6bc98
[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/dump_cmd.hpp"
20 #include "vom/enum_base.hpp"
21 #include "vom/event_cmd.hpp"
22 #include "vom/hw.hpp"
23 #include "vom/inspect.hpp"
24 #include "vom/object_base.hpp"
25 #include "vom/om.hpp"
26 #include "vom/prefix.hpp"
27 #include "vom/route_domain.hpp"
28 #include "vom/rpc_cmd.hpp"
29 #include "vom/singular_db.hpp"
30
31 #include <vapi/af_packet.api.vapi.hpp>
32 #include <vapi/interface.api.vapi.hpp>
33 #include <vapi/stats.api.vapi.hpp>
34 #include <vapi/tap.api.vapi.hpp>
35 #include <vapi/vapi.hpp>
36 #include <vapi/vpe.api.vapi.hpp>
37
38 namespace VOM {
39 /**
40  * A representation of an interface in VPP
41  */
42 class interface : public object_base
43 {
44 public:
45   /**
46    * The key for interface's key
47    */
48   typedef std::string key_type;
49
50   /**
51    * The iterator type
52    */
53   typedef singular_db<const std::string, interface>::const_iterator
54     const_iterator_t;
55
56   /**
57    * An interface type
58    */
59   struct type_t : enum_base<type_t>
60   {
61     /**
62      * Unkown type
63      */
64     const static type_t UNKNOWN;
65     /**
66      * A brideged Virtual interface (aka SVI or IRB)
67      */
68     const static type_t BVI;
69     /**
70      * VXLAN interface
71      */
72     const static type_t VXLAN;
73     /**
74      * Ethernet interface type
75      */
76     const static type_t ETHERNET;
77     /**
78      * AF-Packet interface type
79      */
80     const static type_t AFPACKET;
81     /**
82      * loopback interface type
83      */
84     const static type_t LOOPBACK;
85     /**
86      * Local interface type (specific to VPP)
87      */
88     const static type_t LOCAL;
89     /**
90      * TAP interface type
91      */
92     const static type_t TAP;
93
94     /**
95      * Convert VPP's name of the interface to a type
96      */
97     static type_t from_string(const std::string& str);
98
99   private:
100     /**
101      * Private constructor taking the value and the string name
102      */
103     type_t(int v, const std::string& s);
104   };
105
106   /**
107    * The admin state of the interface
108    */
109   struct admin_state_t : enum_base<admin_state_t>
110   {
111     /**
112      * Admin DOWN state
113      */
114     const static admin_state_t DOWN;
115     /**
116      * Admin UP state
117      */
118     const static admin_state_t UP;
119
120     /**
121      * Convert VPP's numerical value to enum type
122      */
123     static admin_state_t from_int(uint8_t val);
124
125   private:
126     /**
127      * Private constructor taking the value and the string name
128      */
129     admin_state_t(int v, const std::string& s);
130   };
131
132   /**
133    * The oper state of the interface
134    */
135   struct oper_state_t : enum_base<oper_state_t>
136   {
137     /**
138      * Operational DOWN state
139      */
140     const static oper_state_t DOWN;
141     /**
142      * Operational UP state
143      */
144     const static oper_state_t UP;
145
146     /**
147      * Convert VPP's numerical value to enum type
148      */
149     static oper_state_t from_int(uint8_t val);
150
151   private:
152     /**
153      * Private constructor taking the value and the string name
154      */
155     oper_state_t(int v, const std::string& s);
156   };
157
158   /**
159    * Construct a new object matching the desried state
160    */
161   interface(const std::string& name, type_t type, admin_state_t state);
162   /**
163    * Construct a new object matching the desried state mapped
164    * to a specific route_domain
165    */
166   interface(const std::string& name,
167             type_t type,
168             admin_state_t state,
169             const route_domain& rd);
170   /**
171    * Destructor
172    */
173   virtual ~interface();
174
175   /**
176    * Copy Constructor
177    */
178   interface(const interface& o);
179
180   static const_iterator_t cbegin();
181   static const_iterator_t cend();
182
183   /**
184    * Return the matching'singular' of the interface
185    */
186   std::shared_ptr<interface> singular() const;
187
188   /**
189    * convert to string format for debug purposes
190    */
191   virtual std::string to_string(void) const;
192
193   /**
194    * Return VPP's handle to this object
195    */
196   const handle_t& handle() const;
197
198   /**
199    * Return the interface type
200    */
201   const type_t& type() const;
202
203   /**
204    * Return the interface type
205    */
206   const std::string& name() const;
207
208   /**
209    * Return the interface type
210    */
211   const key_type& key() const;
212
213   /**
214    * Return the L2 Address
215    */
216   const l2_address_t& l2_address() const;
217
218   /**
219    * Set the L2 Address
220    */
221   void set(const l2_address_t& addr);
222
223   /**
224    * Set the operational state of the interface, as reported by VPP
225    */
226   void set(const oper_state_t& state);
227
228   /**
229    * A base class for interface Create commands
230    */
231   template <typename MSG>
232   class create_cmd : public rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>
233   {
234   public:
235     create_cmd(HW::item<handle_t>& item, const std::string& name)
236       : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
237       , m_name(name)
238     {
239     }
240
241     /**
242      * Destructor
243      */
244     virtual ~create_cmd() = default;
245
246     /**
247      * Comparison operator - only used for UT
248      */
249     virtual bool operator==(const create_cmd& o) const
250     {
251       return (m_name == o.m_name);
252     }
253
254     /**
255      * Indicate the succeeded, when the HW Q is disabled.
256      */
257     void succeeded()
258     {
259       rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>::succeeded();
260       interface::add(m_name, this->item());
261     }
262
263     virtual vapi_error_e operator()(MSG& reply)
264     {
265       int sw_if_index = reply.get_response().get_payload().sw_if_index;
266       int retval = reply.get_response().get_payload().retval;
267
268       VOM_LOG(log_level_t::DEBUG) << this->to_string() << " " << retval;
269
270       rc_t rc = rc_t::from_vpp_retval(retval);
271       handle_t handle = handle_t::INVALID;
272
273       if (rc_t::OK == rc) {
274         handle = sw_if_index;
275       }
276
277       HW::item<handle_t> res(handle, rc);
278
279       this->fulfill(res);
280
281       return (VAPI_OK);
282     }
283
284   protected:
285     /**
286      * The name of the interface to be created
287      */
288     const std::string& m_name;
289   };
290
291   /**
292    * A command class to create Loopback interfaces in VPP
293    */
294   class loopback_create_cmd : public create_cmd<vapi::Create_loopback>
295   {
296   public:
297     /**
298      * Constructor taking the HW::item to update
299      * and the name of the interface to create
300      */
301     loopback_create_cmd(HW::item<handle_t>& item, const std::string& name);
302     ~loopback_create_cmd() = default;
303
304     /**
305      * Issue the command to VPP/HW
306      */
307     rc_t issue(connection& con);
308     /**
309      * convert to string format for debug purposes
310      */
311     std::string to_string() const;
312   };
313
314   /**
315    * A command class to create af_packet interfaces in VPP
316    */
317   class af_packet_create_cmd : public create_cmd<vapi::Af_packet_create>
318   {
319   public:
320     /**
321      * Constructor taking the HW::item to update
322      * and the name of the interface to create
323      */
324     af_packet_create_cmd(HW::item<handle_t>& item, const std::string& name);
325     ~af_packet_create_cmd() = default;
326     /**
327      * Issue the command to VPP/HW
328      */
329     rc_t issue(connection& con);
330     /**
331      * convert to string format for debug purposes
332      */
333     std::string to_string() const;
334   };
335
336   /**
337    * A command class to create TAP interfaces in VPP
338    */
339   class tap_create_cmd : public create_cmd<vapi::Tap_connect>
340   {
341   public:
342     /**
343      * Constructor taking the HW::item to update
344      * and the name of the interface to create
345      */
346     tap_create_cmd(HW::item<handle_t>& item, const std::string& name);
347     ~tap_create_cmd() = default;
348
349     /**
350      * Issue the command to VPP/HW
351      */
352     rc_t issue(connection& con);
353
354     /**
355      * convert to string format for debug purposes
356      */
357     std::string to_string() const;
358   };
359
360   /**
361    * Base class for intterface Delete commands
362    */
363   template <typename MSG>
364   class delete_cmd : public rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>
365   {
366   public:
367     delete_cmd(HW::item<handle_t>& item, const std::string& name)
368       : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
369       , m_name(name)
370     {
371     }
372
373     delete_cmd(HW::item<handle_t>& item)
374       : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
375       , m_name()
376     {
377     }
378
379     /**
380      * Destructor
381      */
382     virtual ~delete_cmd() = default;
383
384     /**
385      * Comparison operator - only used for UT
386      */
387     virtual bool operator==(const delete_cmd& o) const
388     {
389       return (this->m_hw_item == o.m_hw_item);
390     }
391
392     /**
393      * Indicate the succeeded, when the HW Q is disabled.
394      */
395     void succeeded() {}
396
397   protected:
398     /**
399      * The name of the interface to be created
400      */
401     const std::string m_name;
402   };
403
404   /**
405    * A command class to delete loopback interfaces in VPP
406    */
407   class loopback_delete_cmd : public delete_cmd<vapi::Delete_loopback>
408   {
409   public:
410     /**
411      * Constructor taking the HW::item to update
412      */
413     loopback_delete_cmd(HW::item<handle_t>& item);
414
415     /**
416      * Issue the command to VPP/HW
417      */
418     rc_t issue(connection& con);
419     /**
420      * convert to string format for debug purposes
421      */
422     std::string to_string() const;
423   };
424
425   /**
426    * A command class to delete af-packet interfaces in VPP
427    */
428   class af_packet_delete_cmd : public delete_cmd<vapi::Af_packet_delete>
429   {
430   public:
431     /**
432      * Constructor taking the HW::item to update
433      * and the name of the interface to delete
434      */
435     af_packet_delete_cmd(HW::item<handle_t>& item, const std::string& name);
436
437     /**
438      * Issue the command to VPP/HW
439      */
440     rc_t issue(connection& con);
441     /**
442      * convert to string format for debug purposes
443      */
444     std::string to_string() const;
445   };
446
447   /**
448    * A command class to delete TAP interfaces in VPP
449    */
450   class tap_delete_cmd : public delete_cmd<vapi::Tap_delete>
451   {
452   public:
453     /**
454      * Constructor taking the HW::item to update
455      */
456     tap_delete_cmd(HW::item<handle_t>& item);
457
458     /**
459      * Issue the command to VPP/HW
460      */
461     rc_t issue(connection& con);
462     /**
463      * convert to string format for debug purposes
464      */
465     std::string to_string() const;
466   };
467
468   /**
469    * A command class to delete TAP interfaces in VPP
470    */
471   class set_tag
472     : public rpc_cmd<HW::item<handle_t>, rc_t, vapi::Sw_interface_tag_add_del>
473   {
474   public:
475     /**
476      * Constructor taking the HW::item to update
477      */
478     set_tag(HW::item<handle_t>& item, const std::string& name);
479
480     /**
481      * Issue the command to VPP/HW
482      */
483     rc_t issue(connection& con);
484
485     /**
486      * convert to string format for debug purposes
487      */
488     std::string to_string() const;
489
490     /**
491      * Comparison operator - only used for UT
492      */
493     bool operator==(const set_tag& i) const;
494
495   private:
496     /**
497      * The tag to add
498      */
499     const std::string m_name;
500   };
501
502   /**
503    * A cmd class that changes the admin state
504    */
505   class state_change_cmd : public rpc_cmd<HW::item<admin_state_t>,
506                                           rc_t,
507                                           vapi::Sw_interface_set_flags>
508   {
509   public:
510     /**
511      * Constructor taking the HW::item to update
512      * and the name handle of the interface whose state is to change
513      */
514     state_change_cmd(HW::item<admin_state_t>& s, const HW::item<handle_t>& h);
515
516     /**
517      * Issue the command to VPP/HW
518      */
519     rc_t issue(connection& con);
520     /**
521      * convert to string format for debug purposes
522      */
523     std::string to_string() const;
524
525     /**
526      * Comparison operator - only used for UT
527      */
528     bool operator==(const state_change_cmd& i) const;
529
530   private:
531     /**
532      * the handle of the interface to update
533      */
534     const HW::item<handle_t>& m_hdl;
535   };
536
537   /**
538    * A command class that binds an interface to an L3 table
539    */
540   class set_table_cmd : public rpc_cmd<HW::item<route::table_id_t>,
541                                        rc_t,
542                                        vapi::Sw_interface_set_table>
543   {
544   public:
545     /**
546      * Constructor taking the HW::item to update
547      * and the name handle of the interface whose table is to change
548      */
549     set_table_cmd(HW::item<route::table_id_t>& item,
550                   const l3_proto_t& proto,
551                   const HW::item<handle_t>& h);
552
553     /**
554      * Issue the command to VPP/HW
555      */
556     rc_t issue(connection& con);
557
558     /**
559      * convert to string format for debug purposes
560      */
561     std::string to_string() const;
562
563     /**
564      * Comparison operator - only used for UT
565      */
566     bool operator==(const set_table_cmd& i) const;
567
568   private:
569     /**
570      * the handle of the interface to update
571      */
572     const HW::item<handle_t>& m_hdl;
573
574     /**
575      * The L3 protocol of the table
576      */
577     l3_proto_t m_proto;
578   };
579
580   /**
581    * A command class that binds an interface to an L3 table
582    */
583   class set_mac_cmd : public rpc_cmd<HW::item<l2_address_t>,
584                                      rc_t,
585                                      vapi::Sw_interface_set_mac_address>
586   {
587   public:
588     /**
589      * Constructor taking the HW::item to update
590      * and the handle of the interface
591      */
592     set_mac_cmd(HW::item<l2_address_t>& item, const HW::item<handle_t>& h);
593
594     /**
595      * Issue the command to VPP/HW
596      */
597     rc_t issue(connection& con);
598
599     /**
600      * convert to string format for debug purposes
601      */
602     std::string to_string() const;
603
604     /**
605      * Comparison operator - only used for UT
606      */
607     bool operator==(const set_mac_cmd& i) const;
608
609   private:
610     /**
611      * the handle of the interface to update
612      */
613     const HW::item<handle_t>& m_hdl;
614   };
615
616   /**
617    * Forward declaration of the Event command
618    */
619   class events_cmd;
620
621   /**
622    * A class that listens to interface Events
623    */
624   class event_listener
625   {
626   public:
627     /**
628      * Default Constructor
629      */
630     event_listener();
631
632     /**
633      * Virtual function called on the listener when the command has data
634      * ready to process
635      */
636     virtual void handle_interface_event(events_cmd* cmd) = 0;
637
638     /**
639      * Return the HW::item representing the status
640      */
641     HW::item<bool>& status();
642
643   protected:
644     /**
645      * The status of the subscription
646      */
647     HW::item<bool> m_status;
648   };
649
650   /**
651    * A command class represents our desire to recieve interface events
652    */
653   class events_cmd
654     : public event_cmd<vapi::Want_interface_events, vapi::Sw_interface_event>
655   {
656   public:
657     /**
658      * Constructor taking the listner to notify
659      */
660     events_cmd(event_listener& el);
661
662     /**
663      * Issue the command to VPP/HW
664      */
665     rc_t issue(connection& con);
666
667     /**
668      * Retires the command - unsubscribe from the events.
669      */
670     void retire(connection& con);
671
672     /**
673      * convert to string format for debug purposes
674      */
675     std::string to_string() const;
676
677     /**
678      * Comparison operator - only used for UT
679      */
680     bool operator==(const events_cmd& i) const;
681
682     /**
683      * Called when it's time to poke the listeners
684      */
685     void notify();
686
687   private:
688     /**
689      * The listeners to notify when data/events arrive
690      */
691     event_listener& m_listener;
692   };
693
694   /**
695    * Forward declaration of the stat command
696    */
697   class stats_cmd;
698
699   /**
700    * A class that listens to interface Stats
701    */
702   class stat_listener
703   {
704   public:
705     /**
706      * Default Constructor
707      */
708     stat_listener();
709
710     /**
711      * Virtual function called on the listener when the command has data
712      * ready to process
713      */
714     virtual void handle_interface_stat(stats_cmd* cmd) = 0;
715
716     /**
717      * Return the HW::item representing the status
718      */
719     HW::item<bool>& status();
720
721   protected:
722     /**
723      * The status of the subscription
724      */
725     HW::item<bool> m_status;
726   };
727
728   /**
729    * A command class represents our desire to recieve interface stats
730    */
731   class stats_cmd : public event_cmd<vapi::Want_per_interface_combined_stats,
732                                      vapi::Vnet_per_interface_combined_counters>
733   {
734   public:
735     /**
736      * Constructor taking the listner to notify
737      */
738     stats_cmd(stat_listener& el, const std::vector<handle_t>& interfaces);
739
740     /**
741      * Issue the command to VPP/HW
742      */
743     rc_t issue(connection& con);
744
745     /**
746      * Retires the command - unsubscribe from the stats.
747      */
748     void retire(connection& con);
749
750     /**
751      * convert to string format for debug purposes
752      */
753     std::string to_string() const;
754
755     /**
756      * Comparison operator - only used for UT
757      */
758     bool operator==(const stats_cmd& i) const;
759
760     /**
761      * Called when it's time to poke the listeners
762      */
763     void notify();
764
765   private:
766     /**
767      * The listeners to notify when data/stats arrive
768      */
769     stat_listener& m_listener;
770
771     std::vector<handle_t> m_swifindex;
772   };
773
774   /**
775    * A cmd class that Dumps all the Vpp interfaces
776    */
777   class dump_cmd : public VOM::dump_cmd<vapi::Sw_interface_dump>
778   {
779   public:
780     /**
781      * Default Constructor
782      */
783     dump_cmd();
784
785     /**
786      * Issue the command to VPP/HW
787      */
788     rc_t issue(connection& con);
789     /**
790      * convert to string format for debug purposes
791      */
792     std::string to_string() const;
793
794     /**
795      * Comparison operator - only used for UT
796      */
797     bool operator==(const dump_cmd& i) const;
798   };
799
800   /**
801    * The the singular instance of the interface in the object_base-Model
802    */
803   static std::shared_ptr<interface> find(const interface& temp);
804
805   /**
806    * The the singular instance of the interface in the object_base-Model
807    * by handle
808    */
809   static std::shared_ptr<interface> find(const handle_t& h);
810
811   /**
812    * The the singular instance of the interface in the object_base-Model
813    * by name
814    */
815   static std::shared_ptr<interface> find(const std::string& s);
816
817   /**
818    * Dump all interfaces into the stream provided
819    */
820   static void dump(std::ostream& os);
821
822   /**
823    * Factory method to construct a new interface from the VPP record
824    */
825   static std::unique_ptr<interface> new_interface(
826     const vapi_payload_sw_interface_details& vd);
827
828 protected:
829   /**
830    * Construct an interface object with a handle and a HW address
831    */
832   interface(const handle_t& handle,
833             const l2_address_t& l2_address,
834             const std::string& name,
835             type_t type,
836             admin_state_t state);
837
838   /**
839    * The SW interface handle VPP has asigned to the interface
840    */
841   HW::item<handle_t> m_hdl;
842
843   /**
844    * Return the matching 'singular' of the interface
845    */
846   virtual std::shared_ptr<interface> singular_i() const;
847
848   /**
849    * release/remove an interface form the singular store
850    */
851   void release();
852
853   /**
854    * Virtual functions to construct an interface create commands.
855    * Overridden in derived classes like the sub_interface
856    */
857   virtual std::queue<cmd*>& mk_create_cmd(std::queue<cmd*>& cmds);
858
859   /**
860    * Virtual functions to construct an interface delete commands.
861    * Overridden in derived classes like the sub_interface
862    */
863   virtual std::queue<cmd*>& mk_delete_cmd(std::queue<cmd*>& cmds);
864
865   /**
866    * Sweep/reap the object if still stale
867    */
868   virtual void sweep(void);
869
870   /**
871    * A map of all interfaces key against the interface's name
872    */
873   static singular_db<const std::string, interface> m_db;
874
875   /**
876    * Add an interface to the DB keyed on handle
877    */
878   static void add(const std::string& name, const HW::item<handle_t>& item);
879
880   /**
881    * remove an interface from the DB keyed on handle
882    */
883   static void remove(const HW::item<handle_t>& item);
884
885 private:
886   /**
887    * Class definition for listeners to OM events
888    */
889   class event_handler : public OM::listener, public inspect::command_handler
890   {
891   public:
892     event_handler();
893     virtual ~event_handler() = default;
894
895     /**
896      * Handle a populate event
897      */
898     void handle_populate(const client_db::key_t& key);
899
900     /**
901      * Handle a replay event
902      */
903     void handle_replay();
904
905     /**
906      * Show the object in the Singular DB
907      */
908     void show(std::ostream& os);
909
910     /**
911      * Get the sortable Id of the listener
912      */
913     dependency_t order() const;
914   };
915
916   static event_handler m_evh;
917
918   /**
919    * Commit the acculmulated changes into VPP. i.e. to a 'HW" write.
920    */
921   void update(const interface& obj);
922
923   /*
924    * It's the OM class that calls singular()
925    */
926   friend class OM;
927
928   /**
929    * It's the singular_db class that calls replay()
930    */
931   friend class singular_db<const std::string, interface>;
932
933   /**
934    * The interfaces name
935    */
936   const std::string m_name;
937
938   /**
939    * The interface type. clearly this cannot be changed
940    * once the interface has been created.
941    */
942   const type_t m_type;
943
944   /**
945    * shared pointer to the routeDoamin the interface is in.
946    * NULL is not mapped  - i.e. in eht default table
947    */
948   const std::shared_ptr<route_domain> m_rd;
949
950   /**
951    * The state of the interface
952    */
953   HW::item<admin_state_t> m_state;
954
955   /**
956    * HW state of the VPP table mapping
957    */
958   HW::item<route::table_id_t> m_table_id;
959
960   /**
961    * HW state of the L2 address
962    */
963   HW::item<l2_address_t> m_l2_address;
964
965   /**
966    * Operational state of the interface
967    */
968   oper_state_t m_oper;
969
970   /**
971    * A map of all interfaces keyed against VPP's handle
972    */
973   static std::map<handle_t, std::weak_ptr<interface>> m_hdl_db;
974
975   /**
976    * replay the object to create it in hardware
977    */
978   virtual void replay(void);
979
980   /**
981    * Create commands are firends so they can add interfaces to the
982    * handle store.
983    */
984   template <typename MSG>
985   friend class create_cmd;
986
987   /**
988    * Create commands are firends so they can remove interfaces from the
989    * handle store.
990    */
991   template <typename MSG>
992   friend class delete_cmd;
993 };
994 };
995 /*
996  * fd.io coding-style-patch-verification: ON
997  *
998  * Local Variables:
999  * eval: (c-set-style "mozilla")
1000  * End:
1001  */
1002 #endif