blob: 8863bc94868c37d715839b194d7987460ff6bc98 [file] [log] [blame]
Neale Ranns812ed392017-10-16 04:20:13 -07001/*
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
38namespace VOM {
39/**
40 * A representation of an interface in VPP
41 */
42class interface : public object_base
43{
44public:
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
828protected:
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
885private:
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