This patch introduces show show bgp evpn commands to dump NLRI entries configured or received on BGP, related to EVPN route type 5. New command introduced is the following:
show bgp evpn [all | rd <rd name> ] [overlay] This command displays gw ip field of the RT-5 message in the nexthop field of the show command. Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com> --- bgpd/bgp_evpn.c | 495 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ bgpd/bgp_evpn.h | 1 + bgpd/bgp_route.c | 91 ++++++++++ bgpd/bgp_route.h | 1 + bgpd/bgpd.c | 1 + 5 files changed, 589 insertions(+) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 1d537fa7eab8..61335eaaa1ca 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -175,3 +175,498 @@ bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr, return 0; } + +static int +show_adj_route_evpn (struct vty *vty, struct peer *peer, struct prefix_rd *prd) +{ + struct bgp *bgp; + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_node *rm; + struct attr *attr; + int rd_header; + int header = 1; + char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s"; + + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (rn = bgp_table_top (bgp->rib[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]); rn; + rn = bgp_route_next (rn)) + { + if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) + { + rd_header = 1; + + for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) + if ((attr = rm->info) != NULL) + { + if (header) + { + vty_out (vty, "BGP table version is 0, local router ID is %s%s", + inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", + VTY_NEWLINE); + vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", + VTY_NEWLINE, VTY_NEWLINE); + vty_out (vty, v4_header, VTY_NEWLINE); + header = 0; + } + + if (rd_header) + { + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip; + u_char *pnt; + + pnt = rn->p.u.val; + + /* Decode RD type. */ + type = decode_rd_type (pnt); + /* Decode RD value. */ + if (type == RD_TYPE_AS) + decode_rd_as (pnt + 2, &rd_as); + else if (type == RD_TYPE_AS4) + decode_rd_as4 (pnt + 2, &rd_as); + else if (type == RD_TYPE_IP) + decode_rd_ip (pnt + 2, &rd_ip); + + vty_out (vty, "Route Distinguisher: "); + + if (type == RD_TYPE_AS) + vty_out (vty, "%u:%d", rd_as.as, rd_as.val); + else if (type == RD_TYPE_AS4) + vty_out (vty, "%u:%d", rd_as.as, rd_as.val); + else if (type == RD_TYPE_IP) + vty_out (vty, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); + + vty_out (vty, "%s", VTY_NEWLINE); + rd_header = 0; + } + route_vty_out_tmp (vty, &rm->p, attr, SAFI_MPLS_VPN); + } + } + } + return CMD_SUCCESS; +} + +enum bgp_show_type +{ + bgp_show_type_normal, + bgp_show_type_regexp, + bgp_show_type_prefix_list, + bgp_show_type_filter_list, + bgp_show_type_neighbor, + bgp_show_type_cidr_only, + bgp_show_type_prefix_longer, + bgp_show_type_community_all, + bgp_show_type_community, + bgp_show_type_community_exact, + bgp_show_type_community_list, + bgp_show_type_community_list_exact +}; + +#define SHOW_DISPLAY_STANDARD 0 +#define SHOW_DISPLAY_TAGS 1 +#define SHOW_DISPLAY_OVERLAY 2 + +static int +bgp_show_ethernet_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type, + void *output_arg, int option) +{ + afi_t afi = AFI_INTERNAL_L2VPN; + struct bgp *bgp; + struct bgp_table *table; + struct bgp_node *rn; + struct bgp_node *rm; + struct bgp_info *ri; + int rd_header; + int header = 1; + char v4_header[] = " Network Next Hop Metric LocPrf Weight Path%s"; + char v4_header_tag[] = " Network Next Hop In tag/Out tag%s"; + char v4_header_overlay[] = " Network Next Hop EthTag Overlay Index RouterMac%s"; + + unsigned long output_count = 0; + unsigned long total_count = 0; + + bgp = bgp_get_default (); + if (bgp == NULL) + { + vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE); + return CMD_WARNING; + } + + for (rn = bgp_table_top (bgp->rib[afi][SAFI_INTERNAL_EVPN]); rn; rn = bgp_route_next (rn)) + { + if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) + continue; + + if ((table = rn->info) != NULL) + { + rd_header = 1; + + for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm)) + for (ri = rm->info; ri; ri = ri->next) + { + total_count++; + if (type == bgp_show_type_neighbor) + { + union sockunion *su = output_arg; + + if (ri->peer->su_remote == NULL || ! sockunion_same(ri->peer->su_remote, su)) + continue; + } + if (header) + { + if (option == SHOW_DISPLAY_TAGS) + vty_out (vty, v4_header_tag, VTY_NEWLINE); + else if (option == SHOW_DISPLAY_OVERLAY) + vty_out (vty, v4_header_overlay, VTY_NEWLINE); + else + { + vty_out (vty, "BGP table version is 0, local router ID is %s%s", + inet_ntoa (bgp->router_id), VTY_NEWLINE); + vty_out (vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal%s", + VTY_NEWLINE); + vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s", + VTY_NEWLINE, VTY_NEWLINE); + vty_out (vty, v4_header, VTY_NEWLINE); + } + header = 0; + } + + if (rd_header) + { + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip; + u_char *pnt; + + pnt = rn->p.u.val; + + /* Decode RD type. */ + type = decode_rd_type (pnt); + /* Decode RD value. */ + if (type == RD_TYPE_AS) + decode_rd_as (pnt + 2, &rd_as); + else if (type == RD_TYPE_AS4) + decode_rd_as4 (pnt + 2, &rd_as); + else if (type == RD_TYPE_IP) + decode_rd_ip (pnt + 2, &rd_ip); + + vty_out (vty, "Route Distinguisher: "); + + if (type == RD_TYPE_AS) + vty_out (vty, "as2 %u:%d", rd_as.as, rd_as.val); + else if (type == RD_TYPE_AS4) + vty_out (vty, "as4 %u:%d", rd_as.as, rd_as.val); + else if (type == RD_TYPE_IP) + vty_out (vty, "ip %s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); + vty_out (vty, "%s", VTY_NEWLINE); + rd_header = 0; + } + if (option == SHOW_DISPLAY_TAGS) + route_vty_out_tag (vty, &rm->p, ri, 0, SAFI_INTERNAL_EVPN); + else if (option == SHOW_DISPLAY_OVERLAY) + route_vty_out_overlay (vty, &rm->p, ri, 0); + else + route_vty_out (vty, &rm->p, ri, 0, SAFI_INTERNAL_EVPN); + output_count++; + } + } + } + + if (output_count == 0) + { + vty_out (vty, "No prefixes displayed, %ld exist%s", total_count, VTY_NEWLINE); + } + else + vty_out (vty, "%sDisplayed %ld out of %ld total prefixes%s", + VTY_NEWLINE, output_count, total_count, VTY_NEWLINE); + return CMD_SUCCESS; +} + +DEFUN (show_bgp_evpn_all, + show_bgp_evpn_all_cmd, + "show bgp evpn all", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information about all EVPN NLRIs\n") +{ + return bgp_show_ethernet_vpn (vty, NULL, bgp_show_type_normal, NULL, + SHOW_DISPLAY_STANDARD); +} + +DEFUN (show_bgp_evpn_rd, + show_bgp_evpn_rd_cmd, + "show bgp evpn rd ASN:nn_or_IP-address:nn", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information for a route distinguisher\n" + "VPN Route Distinguisher\n") +{ + int ret; + struct prefix_rd prd; + + ret = str2prefix_rd (argv[0], &prd); + if (! ret) + { + vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); + return CMD_WARNING; + } + return bgp_show_ethernet_vpn (vty, &prd, bgp_show_type_normal, NULL, + SHOW_DISPLAY_STANDARD); +} + +DEFUN (show_bgp_evpn_all_tags, + show_bgp_evpn_all_tags_cmd, + "show bgp evpn all tags", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information about all EVPN NLRIs\n" + "Display BGP tags for prefixes\n") +{ + return bgp_show_ethernet_vpn (vty, NULL, bgp_show_type_normal, NULL, + SHOW_DISPLAY_TAGS); +} + +DEFUN (show_bgp_evpn_rd_tags, + show_bgp_evpn_rd_tags_cmd, + "show bgp evpn rd ASN:nn_or_IP-address:nn tags", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information for a route distinguisher\n" + "VPN Route Distinguisher\n" + "Display BGP tags for prefixes\n") +{ + int ret; + struct prefix_rd prd; + + ret = str2prefix_rd (argv[0], &prd); + if (! ret) + { + vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); + return CMD_WARNING; + } + return bgp_show_ethernet_vpn (vty, &prd, bgp_show_type_normal, NULL, + SHOW_DISPLAY_TAGS); +} + +DEFUN (show_bgp_evpn_all_overlay, + show_bgp_evpn_all_overlay_cmd, + "show bgp evpn all overlay", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information about all EVPN NLRIs\n" + "Display BGP tags for prefixes\n") +{ + return bgp_show_ethernet_vpn (vty, NULL, bgp_show_type_normal, NULL, + SHOW_DISPLAY_OVERLAY); +} + +DEFUN (show_bgp_evpn_rd_overlay, + show_bgp_evpn_rd_overlay_cmd, + "show bgp evpn rd ASN:nn_or_IP-address:nn overlay", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information for a route distinguisher\n" + "VPN Route Distinguisher\n" + "Display BGP tags for prefixes\n") +{ + int ret; + struct prefix_rd prd; + + ret = str2prefix_rd (argv[0], &prd); + if (! ret) + { + vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); + return CMD_WARNING; + } + return bgp_show_ethernet_vpn (vty, &prd, bgp_show_type_normal, NULL, + SHOW_DISPLAY_OVERLAY); +} + +DEFUN (show_bgp_evpn_all_neighbor_routes, + show_bgp_evpn_all_neighbor_routes_cmd, + "show bgp evpn all neighbors A.B.C.D routes", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information about all EVPN NLRIs\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Display routes learned from neighbor\n") +{ + union sockunion su; + struct peer *peer; + int ret; + + ret = str2sockunion (argv[0], &su); + if (ret < 0) + { + vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + peer = peer_lookup (NULL, &su); + if (! peer || ! peer->afc[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) + { + vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_show_ethernet_vpn (vty, NULL, bgp_show_type_neighbor, &su, + SHOW_DISPLAY_STANDARD); +} + +DEFUN (show_bgp_evpn_rd_neighbor_routes, + show_bgp_evpn_rd_neighbor_routes_cmd, + "show bgp evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information for a route distinguisher\n" + "VPN Route Distinguisher\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Display routes learned from neighbor\n") +{ + int ret; + union sockunion su; + struct peer *peer; + struct prefix_rd prd; + + ret = str2prefix_rd (argv[0], &prd); + if (! ret) + { + vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ret = str2sockunion (argv[1], &su); + if (ret < 0) + { + vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + peer = peer_lookup (NULL, &su); + if (! peer || ! peer->afc[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) + { + vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return bgp_show_ethernet_vpn (vty, &prd, bgp_show_type_neighbor, &su, + SHOW_DISPLAY_STANDARD); +} + +DEFUN (show_bgp_evpn_all_neighbor_advertised_routes, + show_bgp_evpn_all_neighbor_advertised_routes_cmd, + "show bgp evpn all neighbors A.B.C.D advertised-routes", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information about all EVPN NLRIs\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Display the routes advertised to a BGP neighbor\n") +{ + int ret; + struct peer *peer; + union sockunion su; + + ret = str2sockunion (argv[0], &su); + if (ret < 0) + { + vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + peer = peer_lookup (NULL, &su); + if (! peer || ! peer->afc[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) + { + vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return show_adj_route_evpn (vty, peer, NULL); +} + +DEFUN (show_bgp_evpn_rd_neighbor_advertised_routes, + show_bgp_evpn_rd_neighbor_advertised_routes_cmd, + "show bgp evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes", + SHOW_STR + IP_STR + BGP_STR + "Display EVPN NLRI specific information\n" + "Display information for a route distinguisher\n" + "VPN Route Distinguisher\n" + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Display the routes advertised to a BGP neighbor\n") +{ + int ret; + struct peer *peer; + struct prefix_rd prd; + union sockunion su; + + ret = str2sockunion (argv[1], &su); + if (ret < 0) + { + vty_out (vty, "%% Malformed address: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + peer = peer_lookup (NULL, &su); + if (! peer || ! peer->afc[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) + { + vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); + return CMD_WARNING; + } + + ret = str2prefix_rd (argv[0], &prd); + if (! ret) + { + vty_out (vty, "%% Malformed Route Distinguisher%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return show_adj_route_evpn (vty, peer, &prd); +} + +void +bgp_ethernetvpn_init (void) +{ + install_element (VIEW_NODE, &show_bgp_evpn_all_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_rd_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_all_tags_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_rd_tags_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_all_neighbor_routes_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_rd_neighbor_routes_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_all_neighbor_advertised_routes_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_rd_neighbor_advertised_routes_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_all_overlay_cmd); + install_element (VIEW_NODE, &show_bgp_evpn_rd_overlay_cmd); +} diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index a3c4f3498004..39e2db962a02 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -21,6 +21,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #ifndef _QUAGGA_BGP_EVPN_H #define _QUAGGA_BGP_EVPN_H +extern void bgp_ethernetvpn_init (void); extern int bgp_nlri_parse_evpn (struct peer *peer, struct attr *attr, struct bgp_nlri *packet); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 3c8ebcab8676..e90760aad9ec 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -58,6 +58,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_mpath.h" #include "bgpd/bgp_nht.h" #include "bgpd/bgp_evpn.h" +#include "bgpd/bgp_attr_evpn.h" /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; @@ -6890,6 +6891,18 @@ route_vty_out( } else { vty_out(vty, "?"); } + } else if (safi == SAFI_INTERNAL_EVPN) { + if (attr->extra) { + char buf[BUFSIZ]; + if (p->family == AF_INET) + vty_out (vty, "%s", inet_ntop(AF_INET, + &(attr->extra->evpn_overlay.gw_ip.ipv4), buf, BUFSIZ)); + else if (p->family == AF_INET6) + vty_out (vty, "%s", inet_ntop(AF_INET6, + &(attr->extra->evpn_overlay.gw_ip.ipv6), buf, BUFSIZ)); + } else { + vty_out(vty, "?"); + } } else { if (p->family == AF_INET) @@ -7063,6 +7076,84 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, vty_out (vty, "%s", VTY_NEWLINE); } +void +route_vty_out_overlay (struct vty *vty, struct prefix *p, + struct bgp_info *binfo, int display) +{ + struct attr *attr; + + if (!binfo->extra) + return; + + /* short status lead text */ + route_vty_short_status_out (vty, binfo); + + /* print prefix and mask */ + if (! display) + route_vty_out_route (p, vty); + else + vty_out (vty, "%*s", 17, " "); + + /* Print attribute */ + attr = binfo->attr; + if (attr) + { + if (p->family == AF_INET) + { + vty_out (vty, "%-16s", + inet_ntoa (attr->extra->mp_nexthop_global_in)); + } + else if (p->family == AF_INET6) + { + assert (attr->extra); + char buf[BUFSIZ]; + char buf1[BUFSIZ]; + if (attr->extra->mp_nexthop_len == 16) + vty_out (vty, "%s", + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, + buf, BUFSIZ)); + else if (attr->extra->mp_nexthop_len == 32) + vty_out (vty, "%s(%s)", + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, + buf, BUFSIZ), + inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, + buf1, BUFSIZ)); + } + } + + char buf[BUFSIZ]; + vty_out (vty, "%u/", attr->extra->eth_t_id); + if(attr->extra) + { + struct eth_segment_id *id = &(attr->extra->evpn_overlay.eth_s_id); + char *str = esi2str(id); + vty_out (vty, "%s", str); + free(str); + if (p->family == AF_INET) + { + vty_out (vty, "/%s", inet_ntoa (attr->extra->evpn_overlay.gw_ip.ipv4)); + } + else if (p->family == AF_INET6) + { + vty_out (vty, "/%s", + inet_ntop (AF_INET6, &(attr->extra->evpn_overlay.gw_ip.ipv6), + buf, BUFSIZ)); + } + if(attr->extra->ecommunity) + { + struct ecommunity_val *routermac = ecommunity_lookup (attr->extra->ecommunity, ECOMMUNITY_ENCODE_EVPN); + + if(routermac) + { + char *mac = ecom_mac2str(routermac->val); + vty_out (vty, "/%s",(char *)mac); + free(mac); + } + } + } + vty_out (vty, "%s", VTY_NEWLINE); +} + /* dampening route */ static void damp_route_vty_out (struct vty *vty, struct prefix *p, diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 4301088fed3d..908a91f99182 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -288,6 +288,7 @@ extern safi_t bgp_node_safi (struct vty *); extern void route_vty_out (struct vty *, struct prefix *, struct bgp_info *, int, safi_t); extern void route_vty_out_tag (struct vty *, struct prefix *, struct bgp_info *, int, safi_t); +extern void route_vty_out_overlay (struct vty *, struct prefix *, struct bgp_info *, int); extern void route_vty_out_tmp (struct vty *, struct prefix *, struct attr *, safi_t); extern void bgp_peer_clear_node_queue_drain_immediate (struct peer *peer); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 35266394b0cd..020182af6e55 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -5921,6 +5921,7 @@ bgp_init (void) bgp_scan_vty_init(); bgp_mplsvpn_init (); bgp_encap_init (); + bgp_ethernetvpn_init (); /* Access list initialize. */ access_list_init (); -- 2.1.4 _______________________________________________ Quagga-dev mailing list Quagga-dev@lists.quagga.net https://lists.quagga.net/mailman/listinfo/quagga-dev