1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 6WIND
4 * This file is part of FRRouting
6 * FRRouting 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 * FRRouting 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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
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
= 0;
305 struct prefix_rd prd
;
307 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
309 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
311 vty_out(vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
314 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
315 use_json(argc
, argv
));
318 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
319 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
320 "show [ip] bgp l2vpn evpn all tags",
326 "Display information about all EVPN NLRIs\n"
327 "Display BGP tags for prefixes\n")
329 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
333 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
334 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
335 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
341 "Display information for a route distinguisher\n"
342 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
344 int idx_ext_community
= 0;
346 struct prefix_rd prd
;
348 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
350 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
352 vty_out(vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
355 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
359 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
360 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
361 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
367 "Display information about all EVPN NLRIs\n"
368 "Detailed information on TCP and BGP neighbor connections\n"
369 "Neighbor to display information about\n"
370 "Display routes learned from neighbor\n" JSON_STR
)
376 u_char uj
= use_json(argc
, argv
);
378 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
380 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
383 json_object
*json_no
= NULL
;
384 json_no
= json_object_new_object();
385 json_object_string_add(json_no
, "warning",
386 "Malformed address");
388 json_object_to_json_string(json_no
),
390 json_object_free(json_no
);
392 vty_out(vty
, "Malformed address: %s%s",
393 argv
[idx_ipv4
]->arg
, VTY_NEWLINE
);
397 peer
= peer_lookup(NULL
, &su
);
398 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
400 json_object
*json_no
= NULL
;
401 json_no
= json_object_new_object();
402 json_object_string_add(json_no
, "warning",
403 "No such neighbor or address family");
405 json_object_to_json_string(json_no
),
407 json_object_free(json_no
);
409 vty_out(vty
, "%% No such neighbor or address family%s",
414 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
418 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
419 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
420 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
426 "Display information for a route distinguisher\n"
427 "VPN Route Distinguisher\n"
428 "Detailed information on TCP and BGP neighbor connections\n"
429 "Neighbor to display information about\n"
430 "Display routes learned from neighbor\n" JSON_STR
)
432 int idx_ext_community
= 0;
437 struct prefix_rd prd
;
438 u_char uj
= use_json(argc
, argv
);
440 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
441 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
443 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
446 json_object
*json_no
= NULL
;
447 json_no
= json_object_new_object();
448 json_object_string_add(json_no
, "warning",
449 "Malformed Route Distinguisher");
451 json_object_to_json_string(json_no
),
453 json_object_free(json_no
);
455 vty_out(vty
, "%% Malformed Route Distinguisher%s",
460 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
463 json_object
*json_no
= NULL
;
464 json_no
= json_object_new_object();
465 json_object_string_add(json_no
, "warning",
466 "Malformed address");
468 json_object_to_json_string(json_no
),
470 json_object_free(json_no
);
472 vty_out(vty
, "Malformed address: %s%s",
473 argv
[idx_ext_community
]->arg
, VTY_NEWLINE
);
477 peer
= peer_lookup(NULL
, &su
);
478 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
480 json_object
*json_no
= NULL
;
481 json_no
= json_object_new_object();
482 json_object_string_add(json_no
, "warning",
483 "No such neighbor or address family");
485 json_object_to_json_string(json_no
),
487 json_object_free(json_no
);
489 vty_out(vty
, "%% No such neighbor or address family%s",
494 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
498 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
499 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
500 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
506 "Display information about all EVPN NLRIs\n"
507 "Detailed information on TCP and BGP neighbor connections\n"
508 "Neighbor to display information about\n"
509 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
515 u_char uj
= use_json(argc
, argv
);
517 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
519 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
522 json_object
*json_no
= NULL
;
523 json_no
= json_object_new_object();
524 json_object_string_add(json_no
, "warning",
525 "Malformed address");
527 json_object_to_json_string(json_no
),
529 json_object_free(json_no
);
531 vty_out(vty
, "Malformed address: %s%s",
532 argv
[idx_ipv4
]->arg
, VTY_NEWLINE
);
535 peer
= peer_lookup(NULL
, &su
);
536 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
538 json_object
*json_no
= NULL
;
539 json_no
= json_object_new_object();
540 json_object_string_add(json_no
, "warning",
541 "No such neighbor or address family");
543 json_object_to_json_string(json_no
),
545 json_object_free(json_no
);
547 vty_out(vty
, "%% No such neighbor or address family%s",
552 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
555 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
556 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
557 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
563 "Display information for a route distinguisher\n"
564 "VPN Route Distinguisher\n"
565 "Detailed information on TCP and BGP neighbor connections\n"
566 "Neighbor to display information about\n"
567 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
569 int idx_ext_community
= 0;
573 struct prefix_rd prd
;
575 u_char uj
= use_json(argc
, argv
);
577 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
578 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
580 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
583 json_object
*json_no
= NULL
;
584 json_no
= json_object_new_object();
585 json_object_string_add(json_no
, "warning",
586 "Malformed address");
588 json_object_to_json_string(json_no
),
590 json_object_free(json_no
);
592 vty_out(vty
, "Malformed address: %s%s",
593 argv
[idx_ext_community
]->arg
, VTY_NEWLINE
);
596 peer
= peer_lookup(NULL
, &su
);
597 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
599 json_object
*json_no
= NULL
;
600 json_no
= json_object_new_object();
601 json_object_string_add(json_no
, "warning",
602 "No such neighbor or address family");
604 json_object_to_json_string(json_no
),
606 json_object_free(json_no
);
608 vty_out(vty
, "%% No such neighbor or address family%s",
613 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
616 json_object
*json_no
= NULL
;
617 json_no
= json_object_new_object();
618 json_object_string_add(json_no
, "warning",
619 "Malformed Route Distinguisher");
621 json_object_to_json_string(json_no
),
623 json_object_free(json_no
);
625 vty_out(vty
, "%% Malformed Route Distinguisher%s",
630 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
633 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
634 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
635 "show [ip] bgp l2vpn evpn all overlay",
641 "Display information about all EVPN NLRIs\n"
642 "Display BGP Overlay Information for prefixes\n")
644 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
645 SHOW_DISPLAY_OVERLAY
, use_json(argc
,
649 DEFUN(show_ip_bgp_evpn_rd_overlay
,
650 show_ip_bgp_evpn_rd_overlay_cmd
,
651 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
657 "Display information for a route distinguisher\n"
658 "VPN Route Distinguisher\n"
659 "Display BGP Overlay Information for prefixes\n")
661 int idx_ext_community
= 0;
663 struct prefix_rd prd
;
665 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
667 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
669 vty_out(vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
672 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
673 SHOW_DISPLAY_OVERLAY
, use_json(argc
,
677 /* For testing purpose, static route of MPLS-VPN. */
678 DEFUN(evpnrt5_network
,
680 "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]",
681 "Specify a network to announce via BGP\n"
684 "Specify Route Distinguisher\n"
685 "VPN Route Distinguisher\n"
687 "Ethernet Tag Value\n"
690 "Ethernet Segment Identifier\n"
691 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
693 "Gateway IP ( A.B.C.D )\n"
694 "Gateway IPv6 ( X:X::X:X )\n"
695 "Router Mac Ext Comm\n"
696 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
697 "Route-map to modify the attributes\n"
698 "Name of the route map\n")
700 int idx_ipv4_prefixlen
= 1;
701 int idx_ext_community
= 3;
706 int idx_routermac
= 13;
708 return bgp_static_set_safi(AFI_L2VPN
, SAFI_EVPN
, vty
,
709 argv
[idx_ipv4_prefixlen
]->arg
,
710 argv
[idx_ext_community
]->arg
,
712 argv
[idx_rmap
] ? argv
[idx_gwip
]->arg
: NULL
,
713 EVPN_IP_PREFIX
, argv
[idx_esi
]->arg
,
714 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
715 argv
[idx_routermac
]->arg
);
718 /* For testing purpose, static route of MPLS-VPN. */
719 DEFUN(no_evpnrt5_network
,
720 no_evpnrt5_network_cmd
,
721 "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>",
723 "Specify a network to announce via BGP\n"
726 "Specify Route Distinguisher\n"
727 "VPN Route Distinguisher\n"
729 "Ethernet Tag Value\n"
732 "Ethernet Segment Identifier\n"
733 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
734 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
736 int idx_ipv4_prefixlen
= 2;
737 int idx_ext_community
= 4;
742 return bgp_static_unset_safi(AFI_L2VPN
, SAFI_EVPN
, vty
,
743 argv
[idx_ipv4_prefixlen
]->arg
,
744 argv
[idx_ext_community
]->arg
,
745 argv
[idx_label
]->arg
, EVPN_IP_PREFIX
,
746 argv
[idx_esi
]->arg
, argv
[idx_gwip
]->arg
,
747 argv
[idx_ethtag
]->arg
);
750 void bgp_ethernetvpn_init(void)
752 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
753 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
754 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
755 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
756 install_element(VIEW_NODE
,
757 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
758 install_element(VIEW_NODE
,
759 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
760 install_element(VIEW_NODE
,
761 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
762 install_element(VIEW_NODE
,
763 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
764 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
765 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
766 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
767 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);