1 /* Ethernet-VPN Packet and vty Processing File
2 Copyright (C) 2017 6WIND
4 This file is part of Free Range Routing
6 Free Range Routing is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 Free Range Routing is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Free Range Routing; see the file COPYING. If not, write to the Free
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 #include "bgpd/bgpd.h"
27 #include "bgpd/bgp_table.h"
28 #include "bgpd/bgp_attr.h"
29 #include "bgpd/bgp_route.h"
30 #include "bgpd/bgp_mplsvpn.h"
31 #include "bgpd/bgp_vpn.h"
32 #include "bgpd/bgp_evpn_vty.h"
33 #include "bgpd/bgp_evpn.h"
35 #define SHOW_DISPLAY_STANDARD 0
36 #define SHOW_DISPLAY_TAGS 1
37 #define SHOW_DISPLAY_OVERLAY 2
40 bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
41 enum bgp_show_type type
, void *output_arg
, int option
,
44 afi_t afi
= AFI_L2VPN
;
46 struct bgp_table
*table
;
53 " Network Next Hop Metric LocPrf Weight Path%s";
54 char v4_header_tag
[] =
55 " Network Next Hop In tag/Out tag%s";
56 char v4_header_overlay
[] =
57 " Network Next Hop EthTag Overlay Index RouterMac%s";
59 unsigned long output_count
= 0;
60 unsigned long total_count
= 0;
61 json_object
*json
= NULL
;
62 json_object
*json_nroute
= NULL
;
63 json_object
*json_array
= NULL
;
64 json_object
*json_scode
= NULL
;
65 json_object
*json_ocode
= NULL
;
67 bgp
= bgp_get_default();
70 vty_out(vty
, "No BGP process is configured%s",
76 json_scode
= json_object_new_object();
77 json_ocode
= json_object_new_object();
78 json
= json_object_new_object();
79 json_nroute
= json_object_new_object();
81 json_object_string_add(json_scode
, "suppressed", "s");
82 json_object_string_add(json_scode
, "damped", "d");
83 json_object_string_add(json_scode
, "history", "h");
84 json_object_string_add(json_scode
, "valid", "*");
85 json_object_string_add(json_scode
, "best", ">");
86 json_object_string_add(json_scode
, "internal", "i");
88 json_object_string_add(json_ocode
, "igp", "i");
89 json_object_string_add(json_ocode
, "egp", "e");
90 json_object_string_add(json_ocode
, "incomplete", "?");
93 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
94 rn
= bgp_route_next(rn
)) {
96 continue; /* XXX json TODO */
98 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
101 if ((table
= rn
->info
) != NULL
) {
104 for (rm
= bgp_table_top(table
); rm
;
105 rm
= bgp_route_next(rm
))
106 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
108 if (type
== bgp_show_type_neighbor
) {
109 union sockunion
*su
=
112 if (ri
->peer
->su_remote
== NULL
113 || !sockunion_same(ri
->
127 json_object_string_add
133 json_object_object_add
137 json_object_object_add
149 SHOW_DISPLAY_OVERLAY
)
155 "BGP table version is 0, local router ID is %s%s",
161 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s",
164 "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s",
182 /* Decode RD type. */
183 type
= decode_rd_type(pnt
);
184 /* Decode RD value. */
185 if (type
== RD_TYPE_AS
)
186 decode_rd_as(pnt
+ 2,
188 else if (type
== RD_TYPE_AS4
)
189 decode_rd_as4(pnt
+ 2,
191 else if (type
== RD_TYPE_IP
)
192 decode_rd_ip(pnt
+ 2,
196 if (type
== RD_TYPE_AS
214 json_object_string_add
216 "routeDistinguisher",
220 "Route Distinguisher: ");
221 if (type
== RD_TYPE_AS
)
252 json_object_new_array();
255 if (option
== SHOW_DISPLAY_TAGS
)
256 route_vty_out_tag(vty
, &rm
->p
,
260 else if (option
== SHOW_DISPLAY_OVERLAY
)
261 route_vty_out_overlay(vty
,
266 route_vty_out(vty
, &rm
->p
, ri
,
274 if (output_count
== 0)
275 vty_out(vty
, "No prefixes displayed, %ld exist%s", total_count
,
278 vty_out(vty
, "%sDisplayed %ld out of %ld total prefixes%s",
279 VTY_NEWLINE
, output_count
, total_count
, VTY_NEWLINE
);
283 DEFUN(show_ip_bgp_l2vpn_evpn
,
284 show_ip_bgp_l2vpn_evpn_cmd
,
285 "show [ip] bgp l2vpn evpn [json]",
286 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
288 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
289 use_json(argc
, argv
));
292 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
293 show_ip_bgp_l2vpn_evpn_rd_cmd
,
294 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
300 "Display information for a route distinguisher\n"
301 "VPN Route Distinguisher\n" JSON_STR
)
303 int idx_ext_community
= 6;
305 struct prefix_rd prd
;
307 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
309 vty_out(vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
312 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
313 use_json(argc
, argv
));
316 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
317 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
318 "show [ip] bgp l2vpn evpn all tags",
324 "Display information about all EVPN NLRIs\n"
325 "Display BGP tags for prefixes\n")
327 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
331 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
332 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
333 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
339 "Display information for a route distinguisher\n"
340 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
342 int idx_ext_community
= 6;
344 struct prefix_rd prd
;
346 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
348 vty_out(vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
351 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
355 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
356 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
357 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
363 "Display information about all EVPN NLRIs\n"
364 "Detailed information on TCP and BGP neighbor connections\n"
365 "Neighbor to display information about\n"
366 "Display routes learned from neighbor\n" JSON_STR
)
372 u_char uj
= use_json(argc
, argv
);
374 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
377 json_object
*json_no
= NULL
;
378 json_no
= json_object_new_object();
379 json_object_string_add(json_no
, "warning",
380 "Malformed address");
382 json_object_to_json_string(json_no
),
384 json_object_free(json_no
);
386 vty_out(vty
, "Malformed address: %s%s",
387 argv
[idx_ipv4
]->arg
, VTY_NEWLINE
);
391 peer
= peer_lookup(NULL
, &su
);
392 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
394 json_object
*json_no
= NULL
;
395 json_no
= json_object_new_object();
396 json_object_string_add(json_no
, "warning",
397 "No such neighbor or address family");
399 json_object_to_json_string(json_no
),
401 json_object_free(json_no
);
403 vty_out(vty
, "%% No such neighbor or address family%s",
408 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
412 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
413 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
414 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
420 "Display information for a route distinguisher\n"
421 "VPN Route Distinguisher\n"
422 "Detailed information on TCP and BGP neighbor connections\n"
423 "Neighbor to display information about\n"
424 "Display routes learned from neighbor\n" JSON_STR
)
426 int idx_ext_community
= 6;
431 struct prefix_rd prd
;
432 u_char uj
= use_json(argc
, argv
);
434 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
437 json_object
*json_no
= NULL
;
438 json_no
= json_object_new_object();
439 json_object_string_add(json_no
, "warning",
440 "Malformed Route Distinguisher");
442 json_object_to_json_string(json_no
),
444 json_object_free(json_no
);
446 vty_out(vty
, "%% Malformed Route Distinguisher%s",
451 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
454 json_object
*json_no
= NULL
;
455 json_no
= json_object_new_object();
456 json_object_string_add(json_no
, "warning",
457 "Malformed address");
459 json_object_to_json_string(json_no
),
461 json_object_free(json_no
);
463 vty_out(vty
, "Malformed address: %s%s",
464 argv
[idx_ext_community
]->arg
, VTY_NEWLINE
);
468 peer
= peer_lookup(NULL
, &su
);
469 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
471 json_object
*json_no
= NULL
;
472 json_no
= json_object_new_object();
473 json_object_string_add(json_no
, "warning",
474 "No such neighbor or address family");
476 json_object_to_json_string(json_no
),
478 json_object_free(json_no
);
480 vty_out(vty
, "%% No such neighbor or address family%s",
485 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
489 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
490 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
491 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
497 "Display information about all EVPN NLRIs\n"
498 "Detailed information on TCP and BGP neighbor connections\n"
499 "Neighbor to display information about\n"
500 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
506 u_char uj
= use_json(argc
, argv
);
508 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
511 json_object
*json_no
= NULL
;
512 json_no
= json_object_new_object();
513 json_object_string_add(json_no
, "warning",
514 "Malformed address");
516 json_object_to_json_string(json_no
),
518 json_object_free(json_no
);
520 vty_out(vty
, "Malformed address: %s%s",
521 argv
[idx_ipv4
]->arg
, VTY_NEWLINE
);
524 peer
= peer_lookup(NULL
, &su
);
525 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
527 json_object
*json_no
= NULL
;
528 json_no
= json_object_new_object();
529 json_object_string_add(json_no
, "warning",
530 "No such neighbor or address family");
532 json_object_to_json_string(json_no
),
534 json_object_free(json_no
);
536 vty_out(vty
, "%% No such neighbor or address family%s",
541 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
544 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
545 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
546 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
552 "Display information for a route distinguisher\n"
553 "VPN Route Distinguisher\n"
554 "Detailed information on TCP and BGP neighbor connections\n"
555 "Neighbor to display information about\n"
556 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
558 int idx_ext_community
= 6;
562 struct prefix_rd prd
;
564 u_char uj
= use_json(argc
, argv
);
566 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
569 json_object
*json_no
= NULL
;
570 json_no
= json_object_new_object();
571 json_object_string_add(json_no
, "warning",
572 "Malformed address");
574 json_object_to_json_string(json_no
),
576 json_object_free(json_no
);
578 vty_out(vty
, "Malformed address: %s%s",
579 argv
[idx_ext_community
]->arg
, VTY_NEWLINE
);
582 peer
= peer_lookup(NULL
, &su
);
583 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
585 json_object
*json_no
= NULL
;
586 json_no
= json_object_new_object();
587 json_object_string_add(json_no
, "warning",
588 "No such neighbor or address family");
590 json_object_to_json_string(json_no
),
592 json_object_free(json_no
);
594 vty_out(vty
, "%% No such neighbor or address family%s",
599 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
602 json_object
*json_no
= NULL
;
603 json_no
= json_object_new_object();
604 json_object_string_add(json_no
, "warning",
605 "Malformed Route Distinguisher");
607 json_object_to_json_string(json_no
),
609 json_object_free(json_no
);
611 vty_out(vty
, "%% Malformed Route Distinguisher%s",
616 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
619 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
620 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
621 "show [ip] bgp l2vpn evpn all overlay",
627 "Display information about all EVPN NLRIs\n"
628 "Display BGP Overlay Information for prefixes\n")
630 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
631 SHOW_DISPLAY_OVERLAY
, use_json(argc
,
635 DEFUN(show_ip_bgp_evpn_rd_overlay
,
636 show_ip_bgp_evpn_rd_overlay_cmd
,
637 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
643 "Display information for a route distinguisher\n"
644 "VPN Route Distinguisher\n"
645 "Display BGP Overlay Information for prefixes\n")
647 int idx_ext_community
= 6;
649 struct prefix_rd prd
;
651 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
653 vty_out(vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
656 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
657 SHOW_DISPLAY_OVERLAY
, use_json(argc
,
661 /* For testing purpose, static route of MPLS-VPN. */
662 DEFUN(evpnrt5_network
,
664 "network <A.B.C.D/M|X:X::X:X/M> rd ASN:nn_or_IP-address:nn ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map WORD]",
665 "Specify a network to announce via BGP\n"
668 "Specify Route Distinguisher\n"
669 "VPN Route Distinguisher\n"
671 "Ethernet Tag Value\n"
674 "Ethernet Segment Identifier\n"
675 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
677 "Gateway IP ( A.B.C.D )\n"
678 "Gateway IPv6 ( X:X::X:X )\n"
679 "Router Mac Ext Comm\n"
680 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n")
682 int idx_ipv4_prefixlen
= 1;
683 int idx_ext_community
= 3;
688 int idx_routermac
= 13;
690 return bgp_static_set_safi(SAFI_EVPN
, vty
,
691 argv
[idx_ipv4_prefixlen
]->arg
,
692 argv
[idx_ext_community
]->arg
,
694 argv
[idx_rmap
] ? argv
[idx_gwip
]->arg
: NULL
,
695 EVPN_IP_PREFIX
, argv
[idx_esi
]->arg
,
696 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
697 argv
[idx_routermac
]->arg
);
700 /* For testing purpose, static route of MPLS-VPN. */
701 DEFUN(no_evpnrt5_network
,
702 no_evpnrt5_network_cmd
,
703 "no network <A.B.C.D/M|X:X::X:X/M> rd ASN:nn_or_IP-address:nn ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X>",
705 "Specify a network to announce via BGP\n"
708 "Specify Route Distinguisher\n"
709 "VPN Route Distinguisher\n"
711 "Ethernet Tag Value\n"
714 "Ethernet Segment Identifier\n"
715 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
716 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
718 int idx_ipv4_prefixlen
= 2;
719 int idx_ext_community
= 4;
724 return bgp_static_unset_safi(SAFI_EVPN
, vty
,
725 argv
[idx_ipv4_prefixlen
]->arg
,
726 argv
[idx_ext_community
]->arg
,
727 argv
[idx_label
]->arg
, EVPN_IP_PREFIX
,
728 argv
[idx_esi
]->arg
, argv
[idx_gwip
]->arg
,
729 argv
[idx_ethtag
]->arg
);
732 void bgp_ethernetvpn_init(void)
734 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
735 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
736 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
737 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
738 install_element(VIEW_NODE
,
739 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
740 install_element(VIEW_NODE
,
741 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
742 install_element(VIEW_NODE
,
743 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
744 install_element(VIEW_NODE
,
745 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
746 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
747 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
748 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
749 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);