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 unsigned long output_count
= 0;
54 unsigned long total_count
= 0;
55 json_object
*json
= NULL
;
56 json_object
*json_nroute
= NULL
;
57 json_object
*json_array
= NULL
;
58 json_object
*json_scode
= NULL
;
59 json_object
*json_ocode
= NULL
;
61 bgp
= bgp_get_default();
64 vty_out (vty
,"No BGP process is configured\n");
69 json_scode
= json_object_new_object();
70 json_ocode
= json_object_new_object();
71 json
= json_object_new_object();
72 json_nroute
= json_object_new_object();
74 json_object_string_add(json_scode
, "suppressed", "s");
75 json_object_string_add(json_scode
, "damped", "d");
76 json_object_string_add(json_scode
, "history", "h");
77 json_object_string_add(json_scode
, "valid", "*");
78 json_object_string_add(json_scode
, "best", ">");
79 json_object_string_add(json_scode
, "internal", "i");
81 json_object_string_add(json_ocode
, "igp", "i");
82 json_object_string_add(json_ocode
, "egp", "e");
83 json_object_string_add(json_ocode
, "incomplete", "?");
86 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
87 rn
= bgp_route_next(rn
)) {
89 continue; /* XXX json TODO */
91 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
94 if ((table
= rn
->info
) != NULL
) {
97 for (rm
= bgp_table_top(table
); rm
;
98 rm
= bgp_route_next(rm
))
99 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
101 if (type
== bgp_show_type_neighbor
) {
102 union sockunion
*su
=
105 if (ri
->peer
->su_remote
== NULL
106 || !sockunion_same(ri
->
120 json_object_string_add
126 json_object_object_add
130 json_object_object_add
138 vty_out(vty
, V4_HEADER_TAG
);
140 SHOW_DISPLAY_OVERLAY
)
141 vty_out(vty
, V4_HEADER_OVERLAY
);
144 "BGP table version is 0, local router ID is %s\n",
145 inet_ntoa(bgp
->router_id
));
147 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
149 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
150 vty_out(vty
, V4_HEADER
);
163 /* Decode RD type. */
164 type
= decode_rd_type(pnt
);
165 /* Decode RD value. */
166 if (type
== RD_TYPE_AS
)
167 decode_rd_as(pnt
+ 2,
169 else if (type
== RD_TYPE_AS4
)
170 decode_rd_as4(pnt
+ 2,
172 else if (type
== RD_TYPE_IP
)
173 decode_rd_ip(pnt
+ 2,
177 if (type
== RD_TYPE_AS
195 json_object_string_add
197 "routeDistinguisher",
201 "Route Distinguisher: ");
202 if (type
== RD_TYPE_AS
)
226 vty_out (vty
, "\n\n");
232 json_object_new_array();
235 if (option
== SHOW_DISPLAY_TAGS
)
236 route_vty_out_tag(vty
, &rm
->p
,
240 else if (option
== SHOW_DISPLAY_OVERLAY
)
241 route_vty_out_overlay(vty
,
246 route_vty_out(vty
, &rm
->p
, ri
,
254 if (output_count
== 0)
255 vty_out (vty
, "No prefixes displayed, %ld exist\n",
258 vty_out (vty
, "\nDisplayed %ld out of %ld total prefixes\n", output_count
, total_count
);
262 DEFUN(show_ip_bgp_l2vpn_evpn
,
263 show_ip_bgp_l2vpn_evpn_cmd
,
264 "show [ip] bgp l2vpn evpn [json]",
265 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
267 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
268 use_json(argc
, argv
));
271 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
272 show_ip_bgp_l2vpn_evpn_rd_cmd
,
273 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
279 "Display information for a route distinguisher\n"
280 "VPN Route Distinguisher\n" JSON_STR
)
282 int idx_ext_community
= 0;
284 struct prefix_rd prd
;
286 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
288 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
290 vty_out (vty
, "%% Malformed Route Distinguisher\n");
293 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
294 use_json(argc
, argv
));
297 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
298 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
299 "show [ip] bgp l2vpn evpn all tags",
305 "Display information about all EVPN NLRIs\n"
306 "Display BGP tags for prefixes\n")
308 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
312 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
313 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
314 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
320 "Display information for a route distinguisher\n"
321 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
323 int idx_ext_community
= 0;
325 struct prefix_rd prd
;
327 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
329 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
331 vty_out (vty
, "%% Malformed Route Distinguisher\n");
334 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
338 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
339 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
340 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
346 "Display information about all EVPN NLRIs\n"
347 "Detailed information on TCP and BGP neighbor connections\n"
348 "Neighbor to display information about\n"
349 "Display routes learned from neighbor\n" JSON_STR
)
355 u_char uj
= use_json(argc
, argv
);
357 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
359 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
362 json_object
*json_no
= NULL
;
363 json_no
= json_object_new_object();
364 json_object_string_add(json_no
, "warning",
365 "Malformed address");
366 vty_out (vty
, "%s\n",
367 json_object_to_json_string(json_no
));
368 json_object_free(json_no
);
370 vty_out (vty
, "Malformed address: %s\n",
371 argv
[idx_ipv4
]->arg
);
375 peer
= peer_lookup(NULL
, &su
);
376 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
378 json_object
*json_no
= NULL
;
379 json_no
= json_object_new_object();
380 json_object_string_add(json_no
, "warning",
381 "No such neighbor or address family");
382 vty_out (vty
, "%s\n",
383 json_object_to_json_string(json_no
));
384 json_object_free(json_no
);
387 "%% No such neighbor or address family\n");
391 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
395 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
396 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
397 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
403 "Display information for a route distinguisher\n"
404 "VPN Route Distinguisher\n"
405 "Detailed information on TCP and BGP neighbor connections\n"
406 "Neighbor to display information about\n"
407 "Display routes learned from neighbor\n" JSON_STR
)
409 int idx_ext_community
= 0;
414 struct prefix_rd prd
;
415 u_char uj
= use_json(argc
, argv
);
417 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
418 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
420 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
423 json_object
*json_no
= NULL
;
424 json_no
= json_object_new_object();
425 json_object_string_add(json_no
, "warning",
426 "Malformed Route Distinguisher");
427 vty_out (vty
, "%s\n",
428 json_object_to_json_string(json_no
));
429 json_object_free(json_no
);
431 vty_out (vty
,"%% Malformed Route Distinguisher\n");
435 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
438 json_object
*json_no
= NULL
;
439 json_no
= json_object_new_object();
440 json_object_string_add(json_no
, "warning",
441 "Malformed address");
442 vty_out (vty
, "%s\n",
443 json_object_to_json_string(json_no
));
444 json_object_free(json_no
);
446 vty_out (vty
, "Malformed address: %s\n",
447 argv
[idx_ext_community
]->arg
);
451 peer
= peer_lookup(NULL
, &su
);
452 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
454 json_object
*json_no
= NULL
;
455 json_no
= json_object_new_object();
456 json_object_string_add(json_no
, "warning",
457 "No such neighbor or address family");
458 vty_out (vty
, "%s\n",
459 json_object_to_json_string(json_no
));
460 json_object_free(json_no
);
463 "%% No such neighbor or address family\n");
467 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
471 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
472 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
473 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
479 "Display information about all EVPN NLRIs\n"
480 "Detailed information on TCP and BGP neighbor connections\n"
481 "Neighbor to display information about\n"
482 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
488 u_char uj
= use_json(argc
, argv
);
490 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
492 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
495 json_object
*json_no
= NULL
;
496 json_no
= json_object_new_object();
497 json_object_string_add(json_no
, "warning",
498 "Malformed address");
499 vty_out (vty
, "%s\n",
500 json_object_to_json_string(json_no
));
501 json_object_free(json_no
);
503 vty_out (vty
, "Malformed address: %s\n",
504 argv
[idx_ipv4
]->arg
);
507 peer
= peer_lookup(NULL
, &su
);
508 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
510 json_object
*json_no
= NULL
;
511 json_no
= json_object_new_object();
512 json_object_string_add(json_no
, "warning",
513 "No such neighbor or address family");
514 vty_out (vty
, "%s\n",
515 json_object_to_json_string(json_no
));
516 json_object_free(json_no
);
519 "%% No such neighbor or address family\n");
523 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
526 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
527 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
528 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
534 "Display information for a route distinguisher\n"
535 "VPN Route Distinguisher\n"
536 "Detailed information on TCP and BGP neighbor connections\n"
537 "Neighbor to display information about\n"
538 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
540 int idx_ext_community
= 0;
544 struct prefix_rd prd
;
546 u_char uj
= use_json(argc
, argv
);
548 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
549 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
551 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
554 json_object
*json_no
= NULL
;
555 json_no
= json_object_new_object();
556 json_object_string_add(json_no
, "warning",
557 "Malformed address");
558 vty_out (vty
, "%s\n",
559 json_object_to_json_string(json_no
));
560 json_object_free(json_no
);
562 vty_out (vty
, "Malformed address: %s\n",
563 argv
[idx_ext_community
]->arg
);
566 peer
= peer_lookup(NULL
, &su
);
567 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
569 json_object
*json_no
= NULL
;
570 json_no
= json_object_new_object();
571 json_object_string_add(json_no
, "warning",
572 "No such neighbor or address family");
573 vty_out (vty
, "%s\n",
574 json_object_to_json_string(json_no
));
575 json_object_free(json_no
);
578 "%% No such neighbor or address family\n");
582 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
585 json_object
*json_no
= NULL
;
586 json_no
= json_object_new_object();
587 json_object_string_add(json_no
, "warning",
588 "Malformed Route Distinguisher");
589 vty_out (vty
, "%s\n",
590 json_object_to_json_string(json_no
));
591 json_object_free(json_no
);
593 vty_out (vty
,"%% Malformed Route Distinguisher\n");
597 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
600 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
601 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
602 "show [ip] bgp l2vpn evpn all overlay",
608 "Display information about all EVPN NLRIs\n"
609 "Display BGP Overlay Information for prefixes\n")
611 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
612 SHOW_DISPLAY_OVERLAY
, use_json(argc
,
616 DEFUN(show_ip_bgp_evpn_rd_overlay
,
617 show_ip_bgp_evpn_rd_overlay_cmd
,
618 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
624 "Display information for a route distinguisher\n"
625 "VPN Route Distinguisher\n"
626 "Display BGP Overlay Information for prefixes\n")
628 int idx_ext_community
= 0;
630 struct prefix_rd prd
;
632 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
634 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
636 vty_out (vty
, "%% Malformed Route Distinguisher\n");
639 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
640 SHOW_DISPLAY_OVERLAY
, use_json(argc
,
644 /* For testing purpose, static route of MPLS-VPN. */
645 DEFUN(evpnrt5_network
,
647 "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]",
648 "Specify a network to announce via BGP\n"
651 "Specify Route Distinguisher\n"
652 "VPN Route Distinguisher\n"
654 "Ethernet Tag Value\n"
657 "Ethernet Segment Identifier\n"
658 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
660 "Gateway IP ( A.B.C.D )\n"
661 "Gateway IPv6 ( X:X::X:X )\n"
662 "Router Mac Ext Comm\n"
663 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
664 "Route-map to modify the attributes\n"
665 "Name of the route map\n")
667 int idx_ipv4_prefixlen
= 1;
668 int idx_ext_community
= 3;
673 int idx_routermac
= 13;
675 return bgp_static_set_safi(AFI_L2VPN
, SAFI_EVPN
, vty
,
676 argv
[idx_ipv4_prefixlen
]->arg
,
677 argv
[idx_ext_community
]->arg
,
679 argv
[idx_rmap
] ? argv
[idx_gwip
]->arg
: NULL
,
680 EVPN_IP_PREFIX
, argv
[idx_esi
]->arg
,
681 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
682 argv
[idx_routermac
]->arg
);
685 /* For testing purpose, static route of MPLS-VPN. */
686 DEFUN(no_evpnrt5_network
,
687 no_evpnrt5_network_cmd
,
688 "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>",
690 "Specify a network to announce via BGP\n"
693 "Specify Route Distinguisher\n"
694 "VPN Route Distinguisher\n"
696 "Ethernet Tag Value\n"
699 "Ethernet Segment Identifier\n"
700 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
701 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
703 int idx_ipv4_prefixlen
= 2;
704 int idx_ext_community
= 4;
709 return bgp_static_unset_safi(AFI_L2VPN
, SAFI_EVPN
, vty
,
710 argv
[idx_ipv4_prefixlen
]->arg
,
711 argv
[idx_ext_community
]->arg
,
712 argv
[idx_label
]->arg
, EVPN_IP_PREFIX
,
713 argv
[idx_esi
]->arg
, argv
[idx_gwip
]->arg
,
714 argv
[idx_ethtag
]->arg
);
717 void bgp_ethernetvpn_init(void)
719 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
720 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
721 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
722 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
723 install_element(VIEW_NODE
,
724 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
725 install_element(VIEW_NODE
,
726 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
727 install_element(VIEW_NODE
,
728 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
729 install_element(VIEW_NODE
,
730 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
731 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
732 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
733 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
734 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);