diff options
author | Lou Berger <lberger@labn.net> | 2017-10-06 15:31:30 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-06 15:31:30 +0200 |
commit | 3782fb37b1c480f2a1c3811fb703bdd5981ca60a (patch) | |
tree | cb7a38fec2b8cdeb61c3f12f37da984da956af2c /bgpd | |
parent | Merge pull request #1299 from opensourcerouting/small_fixes (diff) | |
parent | bgpd: Fixup json with RouteDistinguishers (diff) | |
download | frr-3782fb37b1c480f2a1c3811fb703bdd5981ca60a.tar.xz frr-3782fb37b1c480f2a1c3811fb703bdd5981ca60a.zip |
Merge pull request #1295 from donaldsharp/more_1270
More 1270
Diffstat (limited to 'bgpd')
-rw-r--r-- | bgpd/bgp_mplsvpn.c | 291 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 907 | ||||
-rw-r--r-- | bgpd/bgp_route.h | 4 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 6 |
4 files changed, 505 insertions, 703 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 694cb1479..472b9d200 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -356,19 +356,6 @@ int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, { 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; - unsigned long output_count = 0; - unsigned long total_count = 0; - json_object *json = NULL; - json_object *json_mroute = NULL; - json_object *json_nroute = NULL; - json_object *json_array = NULL; - json_object *json_scode = NULL; - json_object *json_ocode = NULL; bgp = bgp_get_default(); if (bgp == NULL) { @@ -378,279 +365,31 @@ int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, vty_out(vty, "{}\n"); return CMD_WARNING; } - - if (use_json) { - json_scode = json_object_new_object(); - json_ocode = json_object_new_object(); - json = json_object_new_object(); - json_mroute = json_object_new_object(); - json_nroute = json_object_new_object(); - - json_object_string_add(json_scode, "suppressed", "s"); - json_object_string_add(json_scode, "damped", "d"); - json_object_string_add(json_scode, "history", "h"); - json_object_string_add(json_scode, "valid", "*"); - json_object_string_add(json_scode, "best", ">"); - json_object_string_add(json_scode, "internal", "i"); - - json_object_string_add(json_ocode, "igp", "i"); - json_object_string_add(json_ocode, "egp", "e"); - json_object_string_add(json_ocode, "incomplete", "?"); - } - - if ((afi != AFI_IP) && (afi != AFI_IP6)) { - vty_out(vty, "Afi %d not supported\n", afi); - return CMD_WARNING; - } - - for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); 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)) { - total_count++; - if (use_json) - json_array = json_object_new_array(); - else - json_array = NULL; - - for (ri = rm->info; ri; ri = ri->next) { - 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 (use_json) { - if (!tags) { - json_object_int_add( - json, - "bgpTableVersion", - 0); - json_object_string_add( - json, - "bgpLocalRouterId", - inet_ntoa( - bgp->router_id)); - json_object_object_add( - json, - "bgpStatusCodes", - json_scode); - json_object_object_add( - json, - "bgpOriginCodes", - json_ocode); - } - } else { - if (tags) - vty_out(vty, - V4_HEADER_TAG); - else { - vty_out(vty, - "BGP table version is 0, local router ID is %s\n", - inet_ntoa( - bgp->router_id)); - vty_out(vty, - "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); - vty_out(vty, - "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); - vty_out(vty, - V4_HEADER); - } - } - header = 0; - } - - if (rd_header) { - u_int16_t type; - struct rd_as rd_as; - struct rd_ip rd_ip = {0}; -#if ENABLE_BGP_VNC - struct rd_vnc_eth rd_vnc_eth = { - 0}; -#endif - 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); -#if ENABLE_BGP_VNC - else if (type - == RD_TYPE_VNC_ETH) - decode_rd_vnc_eth( - pnt, - &rd_vnc_eth); -#endif - - if (use_json) { - char buffer[BUFSIZ]; - if (type == RD_TYPE_AS - || type == RD_TYPE_AS4) - sprintf(buffer, - "%u:%d", - rd_as.as, - rd_as.val); - else if (type - == RD_TYPE_IP) - sprintf(buffer, - "%s:%d", - inet_ntoa( - rd_ip.ip), - rd_ip.val); - json_object_string_add( - json_nroute, - "routeDistinguisher", - buffer); - } else { - vty_out(vty, - "Route Distinguisher: "); - - if (type == RD_TYPE_AS - || 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); -#if ENABLE_BGP_VNC - else if ( - type - == RD_TYPE_VNC_ETH) - vty_out(vty, - "%u:%02x:%02x:%02x:%02x:%02x:%02x", - rd_vnc_eth - .local_nve_id, - rd_vnc_eth - .macaddr - .octet[0], - rd_vnc_eth - .macaddr - .octet[1], - rd_vnc_eth - .macaddr - .octet[2], - rd_vnc_eth - .macaddr - .octet[3], - rd_vnc_eth - .macaddr - .octet[4], - rd_vnc_eth - .macaddr - .octet[5]); -#endif - vty_out(vty, "\n"); - } - rd_header = 0; - } - if (tags) - route_vty_out_tag(vty, &rm->p, - ri, 0, - SAFI_MPLS_VPN, - json_array); - else - route_vty_out(vty, &rm->p, ri, - 0, SAFI_MPLS_VPN, - json_array); - output_count++; - } - - if (use_json) { - struct prefix *p; - char buf_a[BUFSIZ]; - char buf_b[BUFSIZ]; - p = &rm->p; - sprintf(buf_a, "%s/%d", - inet_ntop(p->family, - &p->u.prefix, buf_b, - BUFSIZ), - p->prefixlen); - json_object_object_add( - json_mroute, buf_a, json_array); - } - } - - if (use_json) { - struct prefix *p; - char buf_a[BUFSIZ]; - char buf_b[BUFSIZ]; - p = &rn->p; - sprintf(buf_a, "%s/%d", - inet_ntop(p->family, &p->u.prefix, - buf_b, BUFSIZ), - p->prefixlen); - json_object_object_add(json_nroute, buf_a, - json_mroute); - } - } - } - - if (use_json) { - json_object_object_add(json, "routes", json_nroute); - vty_out(vty, "%s\n", json_object_to_json_string_ext( - json, JSON_C_TO_STRING_PRETTY)); - json_object_free(json); - } else { - if (output_count == 0) - vty_out(vty, "No prefixes displayed, %ld exist\n", - total_count); - else - vty_out(vty, - "\nDisplayed %ld routes and %ld total paths\n", - output_count, total_count); - } - - return CMD_SUCCESS; + table = bgp->rib[afi][SAFI_MPLS_VPN]; + return bgp_show_table_rd(vty, bgp, SAFI_MPLS_VPN, + table, prd, type, output_arg, use_json); } DEFUN (show_bgp_ip_vpn_all_rd, show_bgp_ip_vpn_all_rd_cmd, "show bgp "BGP_AFI_CMD_STR" vpn all [rd ASN:NN_OR_IP-ADDRESS:NN] [json]", SHOW_STR - IP_STR BGP_STR BGP_VPNVX_HELP_STR "Display VPN NLRI specific information\n" + "Display VPN NLRI specific information\n" "Display information for a route distinguisher\n" "VPN Route Distinguisher\n" JSON_STR) { - int idx_rd = 5; int ret; struct prefix_rd prd; afi_t afi; int idx = 0; if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) { - if (argc >= 7 && argv[idx_rd]->arg) { - ret = str2prefix_rd(argv[idx_rd]->arg, &prd); + if (argv_find(argv, argc, "rd", &idx)) { + ret = str2prefix_rd(argv[idx+1]->arg, &prd); if (!ret) { vty_out(vty, "%% Malformed Route Distinguisher\n"); @@ -668,9 +407,21 @@ DEFUN (show_bgp_ip_vpn_all_rd, return CMD_SUCCESS; } +ALIAS(show_bgp_ip_vpn_all_rd, + show_bgp_ip_vpn_rd_cmd, + "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN [json]", + SHOW_STR + BGP_STR + BGP_VPNVX_HELP_STR + "Display VPN NLRI specific information\n" + "Display information for a route distinguisher\n" + "VPN Route Distinguisher\n" + JSON_STR) + +#ifdef KEEP_OLD_VPN_COMMANDS DEFUN (show_ip_bgp_vpn_rd, show_ip_bgp_vpn_rd_cmd, - "show [ip] bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN", + "show ip bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN", SHOW_STR IP_STR BGP_STR @@ -697,7 +448,6 @@ DEFUN (show_ip_bgp_vpn_rd, return CMD_SUCCESS; } -#ifdef KEEP_OLD_VPN_COMMANDS DEFUN (show_ip_bgp_vpn_all, show_ip_bgp_vpn_all_cmd, "show [ip] bgp <vpnv4|vpnv6>", @@ -1055,8 +805,9 @@ void bgp_mplsvpn_init(void) install_element(BGP_VPNV6_NODE, &no_vpnv6_network_cmd); install_element(VIEW_NODE, &show_bgp_ip_vpn_all_rd_cmd); - install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd); + install_element(VIEW_NODE, &show_bgp_ip_vpn_rd_cmd); #ifdef KEEP_OLD_VPN_COMMANDS + install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_cmd); install_element(VIEW_NODE, &show_ip_bgp_vpn_all_cmd); install_element(VIEW_NODE, &show_ip_bgp_vpn_all_tags_cmd); install_element(VIEW_NODE, &show_ip_bgp_vpn_rd_tags_cmd); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 3307f8608..762519715 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -6500,246 +6500,258 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, /* Print attribute */ attr = binfo->attr; - if (attr) { - /* - * For ENCAP and EVPN routes, nexthop address family is not - * neccessarily the same as the prefix address family. - * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field - * EVPN routes are also exchanged with a MP nexthop. Currently, - * this - * is only IPv4, the value will be present in either - * attr->nexthop or - * attr->mp_nexthop_global_in - */ - if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) { - char buf[BUFSIZ]; - int af = NEXTHOP_FAMILY(attr->mp_nexthop_len); - - switch (af) { - case AF_INET: - vty_out(vty, "%s", - inet_ntop(af, - &attr->mp_nexthop_global_in, - buf, BUFSIZ)); - break; - case AF_INET6: - vty_out(vty, "%s", - inet_ntop(af, &attr->mp_nexthop_global, - buf, BUFSIZ)); - break; - default: - vty_out(vty, "?"); - break; - } - } else if (safi == SAFI_EVPN) { - if (json_paths) { - json_nexthop_global = json_object_new_object(); + if (!attr) { + if (json_paths) + json_object_array_add(json_paths, json_path); + else + vty_out(vty, "\n"); - json_object_string_add( - json_nexthop_global, "ip", - inet_ntoa(attr->nexthop)); - json_object_string_add(json_nexthop_global, - "afi", "ipv4"); - json_object_boolean_true_add( - json_nexthop_global, "used"); - } else - vty_out(vty, "%-16s", inet_ntoa(attr->nexthop)); + return; + } + + /* + * For ENCAP and EVPN routes, nexthop address family is not + * neccessarily the same as the prefix address family. + * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field + * EVPN routes are also exchanged with a MP nexthop. Currently, + * this + * is only IPv4, the value will be present in either + * attr->nexthop or + * attr->mp_nexthop_global_in + */ + if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) { + char buf[BUFSIZ]; + char nexthop[128]; + int af = NEXTHOP_FAMILY(attr->mp_nexthop_len); + + switch (af) { + case AF_INET: + sprintf(nexthop, "%s", + inet_ntop(af, &attr->mp_nexthop_global_in, + buf, BUFSIZ)); + break; + case AF_INET6: + sprintf(nexthop, "%s", + inet_ntop(af, &attr->mp_nexthop_global, + buf, BUFSIZ)); + break; + default: + sprintf(nexthop, "?"); + break; } - /* IPv4 Next Hop */ - else if (p->family == AF_INET - && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { - if (json_paths) { - json_nexthop_global = json_object_new_object(); - if ((safi == SAFI_MPLS_VPN) - || (safi == SAFI_EVPN)) - json_object_string_add( - json_nexthop_global, "ip", - inet_ntoa( - attr->mp_nexthop_global_in)); - else - json_object_string_add( - json_nexthop_global, "ip", - inet_ntoa(attr->nexthop)); + if (json_paths) { + json_nexthop_global = json_object_new_object(); + + json_object_string_add(json_nexthop_global, + "afi", + (af == AF_INET) ? + "ip" : "ipv6"); + json_object_string_add(json_nexthop_global, + (af == AF_INET) ? + "ip" : "ipv6", + nexthop); + json_object_boolean_true_add(json_nexthop_global, + "used"); + } else + vty_out(vty, "%s", nexthop); + } else if (safi == SAFI_EVPN) { + if (json_paths) { + json_nexthop_global = json_object_new_object(); + + json_object_string_add(json_nexthop_global, "ip", + inet_ntoa(attr->nexthop)); + json_object_string_add(json_nexthop_global, + "afi", "ipv4"); + json_object_boolean_true_add(json_nexthop_global, + "used"); + } else + vty_out(vty, "%-16s", inet_ntoa(attr->nexthop)); + } + /* IPv4 Next Hop */ + else if (p->family == AF_INET + && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { + if (json_paths) { + json_nexthop_global = json_object_new_object(); + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_EVPN)) json_object_string_add(json_nexthop_global, - "afi", "ipv4"); - json_object_boolean_true_add( - json_nexthop_global, "used"); - } else { - if ((safi == SAFI_MPLS_VPN) - || (safi == SAFI_EVPN)) - vty_out(vty, "%-16s", - inet_ntoa( - attr->mp_nexthop_global_in)); - else - vty_out(vty, "%-16s", - inet_ntoa(attr->nexthop)); - } + "ip", + inet_ntoa(attr->mp_nexthop_global_in)); + else + json_object_string_add(json_nexthop_global, + "ip", + inet_ntoa(attr->nexthop)); + + json_object_string_add(json_nexthop_global, + "afi", "ipv4"); + json_object_boolean_true_add(json_nexthop_global, + "used"); + } else { + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_EVPN)) + vty_out(vty, "%-16s", + inet_ntoa( + attr->mp_nexthop_global_in)); + else + vty_out(vty, "%-16s", + inet_ntoa(attr->nexthop)); } + } - /* IPv6 Next Hop */ - else if (p->family == AF_INET6 - || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { - int len; - char buf[BUFSIZ]; + /* IPv6 Next Hop */ + else if (p->family == AF_INET6 + || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) { + int len; + char buf[BUFSIZ]; - if (json_paths) { - json_nexthop_global = json_object_new_object(); + if (json_paths) { + json_nexthop_global = json_object_new_object(); + json_object_string_add(json_nexthop_global, "ip", + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, buf, + BUFSIZ)); + json_object_string_add(json_nexthop_global, + "afi", "ipv6"); + json_object_string_add(json_nexthop_global, + "scope", "global"); + + /* We display both LL & GL if both have been + * received */ + if ((attr->mp_nexthop_len == 32) + || (binfo->peer->conf_if)) { + json_nexthop_ll = + json_object_new_object(); json_object_string_add( - json_nexthop_global, "ip", - inet_ntop(AF_INET6, - &attr->mp_nexthop_global, buf, - BUFSIZ)); - json_object_string_add(json_nexthop_global, + json_nexthop_ll, "ip", + inet_ntop( + AF_INET6, + &attr->mp_nexthop_local, + buf, BUFSIZ)); + json_object_string_add(json_nexthop_ll, "afi", "ipv6"); - json_object_string_add(json_nexthop_global, - "scope", "global"); + json_object_string_add(json_nexthop_ll, + "scope", + "link-local"); - /* We display both LL & GL if both have been - * received */ - if ((attr->mp_nexthop_len == 32) - || (binfo->peer->conf_if)) { - json_nexthop_ll = - json_object_new_object(); - json_object_string_add( - json_nexthop_ll, "ip", - inet_ntop( - AF_INET6, - &attr->mp_nexthop_local, - buf, BUFSIZ)); - json_object_string_add(json_nexthop_ll, - "afi", "ipv6"); - json_object_string_add(json_nexthop_ll, - "scope", - "link-local"); - - if ((IPV6_ADDR_CMP( - &attr->mp_nexthop_global, - &attr->mp_nexthop_local) - != 0) - && !attr->mp_nexthop_prefer_global) - json_object_boolean_true_add( - json_nexthop_ll, - "used"); - else - json_object_boolean_true_add( - json_nexthop_global, - "used"); - } else + if ((IPV6_ADDR_CMP( + &attr->mp_nexthop_global, + &attr->mp_nexthop_local) + != 0) + && !attr->mp_nexthop_prefer_global) json_object_boolean_true_add( - json_nexthop_global, "used"); - } else { - /* Display LL if LL/Global both in table unless - * prefer-global is set */ - if (((attr->mp_nexthop_len == 32) - && !attr->mp_nexthop_prefer_global) - || (binfo->peer->conf_if)) { - if (binfo->peer->conf_if) { - len = vty_out( - vty, "%s", - binfo->peer->conf_if); - len = 16 - len; /* len of IPv6 - addr + max - len of def - ifname */ - - if (len < 1) - vty_out(vty, "\n%*s", - 36, " "); - else - vty_out(vty, "%*s", len, - " "); - } else { - len = vty_out( - vty, "%s", - inet_ntop( - AF_INET6, - &attr->mp_nexthop_local, - buf, BUFSIZ)); - len = 16 - len; - - if (len < 1) - vty_out(vty, "\n%*s", - 36, " "); - else - vty_out(vty, "%*s", len, - " "); - } + json_nexthop_ll, + "used"); + else + json_object_boolean_true_add( + json_nexthop_global, + "used"); + } else + json_object_boolean_true_add( + json_nexthop_global, "used"); + } else { + /* Display LL if LL/Global both in table unless + * prefer-global is set */ + if (((attr->mp_nexthop_len == 32) + && !attr->mp_nexthop_prefer_global) + || (binfo->peer->conf_if)) { + if (binfo->peer->conf_if) { + len = vty_out( + vty, "%s", + binfo->peer->conf_if); + len = 16 - len; /* len of IPv6 + addr + max + len of def + ifname */ + + if (len < 1) + vty_out(vty, "\n%*s", + 36, " "); + else + vty_out(vty, "%*s", len, + " "); } else { len = vty_out( vty, "%s", inet_ntop( AF_INET6, - &attr->mp_nexthop_global, + &attr->mp_nexthop_local, buf, BUFSIZ)); len = 16 - len; if (len < 1) - vty_out(vty, "\n%*s", 36, " "); + vty_out(vty, "\n%*s", + 36, " "); else - vty_out(vty, "%*s", len, " "); + vty_out(vty, "%*s", len, + " "); } + } else { + len = vty_out(vty, "%s", + inet_ntop(AF_INET6, + &attr->mp_nexthop_global, + buf, BUFSIZ)); + len = 16 - len; + + if (len < 1) + vty_out(vty, "\n%*s", 36, " "); + else + vty_out(vty, "%*s", len, " "); } } + } - /* MED/Metric */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) - if (json_paths) - json_object_int_add(json_path, "med", - attr->med); - else - vty_out(vty, "%10u", attr->med); - else if (!json_paths) - vty_out(vty, " "); - - /* Local Pref */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) - if (json_paths) - json_object_int_add(json_path, "localpref", - attr->local_pref); - else - vty_out(vty, "%7u", attr->local_pref); - else if (!json_paths) - vty_out(vty, " "); + /* MED/Metric */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + if (json_paths) + json_object_int_add(json_path, "med", + attr->med); + else + vty_out(vty, "%10u", attr->med); + else if (!json_paths) + vty_out(vty, " "); + /* Local Pref */ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) if (json_paths) - json_object_int_add(json_path, "weight", attr->weight); + json_object_int_add(json_path, "localpref", + attr->local_pref); else - vty_out(vty, "%7u ", attr->weight); + vty_out(vty, "%7u", attr->local_pref); + else if (!json_paths) + vty_out(vty, " "); - if (json_paths) { - char buf[BUFSIZ]; - json_object_string_add(json_path, "peerId", - sockunion2str(&binfo->peer->su, - buf, - SU_ADDRSTRLEN)); - } + if (json_paths) + json_object_int_add(json_path, "weight", attr->weight); + else + vty_out(vty, "%7u ", attr->weight); - /* Print aspath */ - if (attr->aspath) { - if (json_paths) - json_object_string_add(json_path, "aspath", - attr->aspath->str); - else - aspath_print_vty(vty, "%s", attr->aspath, " "); - } + if (json_paths) { + char buf[BUFSIZ]; + json_object_string_add(json_path, "peerId", + sockunion2str(&binfo->peer->su, + buf, + SU_ADDRSTRLEN)); + } - /* Print origin */ - if (json_paths) - json_object_string_add( - json_path, "origin", - bgp_origin_long_str[attr->origin]); - else - vty_out(vty, "%s", bgp_origin_str[attr->origin]); - } else { + /* Print aspath */ + if (attr->aspath) { if (json_paths) - json_object_string_add(json_path, "alert", - "No attributes"); + json_object_string_add(json_path, "aspath", + attr->aspath->str); else - vty_out(vty, "No attributes to print\n"); + aspath_print_vty(vty, "%s", attr->aspath, " "); } + /* Print origin */ + if (json_paths) + json_object_string_add( + json_path, "origin", + bgp_origin_long_str[attr->origin]); + else + vty_out(vty, "%s", bgp_origin_str[attr->origin]); + if (json_paths) { if (json_nexthop_global || json_nexthop_ll) { json_nexthops = json_object_new_array(); @@ -8122,23 +8134,29 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, safi_t safi); -static int bgp_show_table(struct vty *vty, struct bgp *bgp, + +static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, struct bgp_table *table, enum bgp_show_type type, - void *output_arg, u_char use_json) + void *output_arg, u_char use_json, + char *rd, int is_last, + unsigned long *output_cum, unsigned long *total_cum) { struct bgp_info *ri; struct bgp_node *rn; int header = 1; int display; - unsigned long output_count; - unsigned long total_count; + unsigned long output_count = 0; + unsigned long total_count = 0; struct prefix *p; char buf[BUFSIZ]; char buf2[BUFSIZ]; json_object *json_paths = NULL; int first = 1; - if (use_json) { + if (output_cum && *output_cum != 0) + header = 0; + + if (use_json && header) { vty_out(vty, "{ \"vrfId\": %d, \"vrfName\": \"%s\", \"tableVersion\": %" PRId64 ", \"routerId\": \"%s\", \"routes\": { ", @@ -8146,252 +8164,290 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ? "Default" : bgp->name, table->version, inet_ntoa(bgp->router_id)); + if (rd) + vty_out(vty, " \"routeDistinguishers\" : {"); json_paths = json_object_new_object(); } - /* This is first entry point, so reset total line. */ - output_count = 0; - total_count = 0; + if (use_json && rd) { + vty_out(vty, " \"%s\" : { ", rd); + } /* Start processing of routes. */ - for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - if (rn->info != NULL) { - display = 0; - if (!first && use_json) { - vty_out(vty, ","); - } - if (use_json) - json_paths = json_object_new_array(); - else - json_paths = NULL; + for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { + if (rn->info == NULL) + continue; - for (ri = rn->info; ri; ri = ri->next) { - total_count++; - if (type == bgp_show_type_flap_statistics - || type == bgp_show_type_flap_neighbor - || type == bgp_show_type_dampend_paths - || type == bgp_show_type_damp_neighbor) { - if (!(ri->extra - && ri->extra->damp_info)) - continue; - } - if (type == bgp_show_type_regexp) { - regex_t *regex = output_arg; + display = 0; + if (!first && use_json) + vty_out(vty, ","); + if (use_json) + json_paths = json_object_new_array(); + else + json_paths = NULL; - if (bgp_regexec(regex, ri->attr->aspath) - == REG_NOMATCH) - continue; - } - if (type == bgp_show_type_prefix_list) { - struct prefix_list *plist = output_arg; + for (ri = rn->info; ri; ri = ri->next) { + total_count++; + if (type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_neighbor + || type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) { + if (!(ri->extra + && ri->extra->damp_info)) + continue; + } + if (type == bgp_show_type_regexp) { + regex_t *regex = output_arg; - if (prefix_list_apply(plist, &rn->p) - != PREFIX_PERMIT) - continue; - } - if (type == bgp_show_type_filter_list) { - struct as_list *as_list = output_arg; + if (bgp_regexec(regex, ri->attr->aspath) + == REG_NOMATCH) + continue; + } + if (type == bgp_show_type_prefix_list) { + struct prefix_list *plist = output_arg; - if (as_list_apply(as_list, - ri->attr->aspath) - != AS_FILTER_PERMIT) - continue; - } - if (type == bgp_show_type_route_map) { - struct route_map *rmap = output_arg; - struct bgp_info binfo; - struct attr dummy_attr; - int ret; + if (prefix_list_apply(plist, &rn->p) + != PREFIX_PERMIT) + continue; + } + if (type == bgp_show_type_filter_list) { + struct as_list *as_list = output_arg; - bgp_attr_dup(&dummy_attr, ri->attr); + if (as_list_apply(as_list, ri->attr->aspath) + != AS_FILTER_PERMIT) + continue; + } + if (type == bgp_show_type_route_map) { + struct route_map *rmap = output_arg; + struct bgp_info binfo; + struct attr dummy_attr; + int ret; - binfo.peer = ri->peer; - binfo.attr = &dummy_attr; + bgp_attr_dup(&dummy_attr, ri->attr); - ret = route_map_apply(rmap, &rn->p, - RMAP_BGP, &binfo); - if (ret == RMAP_DENYMATCH) - continue; - } - if (type == bgp_show_type_neighbor - || type == bgp_show_type_flap_neighbor - || type == bgp_show_type_damp_neighbor) { - union sockunion *su = output_arg; - - if (ri->peer == NULL - || ri->peer->su_remote == NULL - || !sockunion_same( - ri->peer->su_remote, su)) - continue; - } - if (type == bgp_show_type_cidr_only) { - u_int32_t destination; + binfo.peer = ri->peer; + binfo.attr = &dummy_attr; - destination = - ntohl(rn->p.u.prefix4.s_addr); - if (IN_CLASSC(destination) - && rn->p.prefixlen == 24) - continue; - if (IN_CLASSB(destination) - && rn->p.prefixlen == 16) - continue; - if (IN_CLASSA(destination) - && rn->p.prefixlen == 8) - continue; - } - if (type == bgp_show_type_prefix_longer) { - struct prefix *p = output_arg; + ret = route_map_apply(rmap, &rn->p, + RMAP_BGP, &binfo); + if (ret == RMAP_DENYMATCH) + continue; + } + if (type == bgp_show_type_neighbor + || type == bgp_show_type_flap_neighbor + || type == bgp_show_type_damp_neighbor) { + union sockunion *su = output_arg; + + if (ri->peer == NULL + || ri->peer->su_remote == NULL + || !sockunion_same(ri->peer->su_remote, + su)) + continue; + } + if (type == bgp_show_type_cidr_only) { + u_int32_t destination; - if (!prefix_match(p, &rn->p)) - continue; - } - if (type == bgp_show_type_community_all) { - if (!ri->attr->community) - continue; - } - if (type == bgp_show_type_community) { - struct community *com = output_arg; + destination = ntohl(rn->p.u.prefix4.s_addr); + if (IN_CLASSC(destination) + && rn->p.prefixlen == 24) + continue; + if (IN_CLASSB(destination) + && rn->p.prefixlen == 16) + continue; + if (IN_CLASSA(destination) + && rn->p.prefixlen == 8) + continue; + } + if (type == bgp_show_type_prefix_longer) { + struct prefix *p = output_arg; - if (!ri->attr->community - || !community_match( - ri->attr->community, - com)) - continue; - } - if (type == bgp_show_type_community_exact) { - struct community *com = output_arg; + if (!prefix_match(p, &rn->p)) + continue; + } + if (type == bgp_show_type_community_all) { + if (!ri->attr->community) + continue; + } + if (type == bgp_show_type_community) { + struct community *com = output_arg; - if (!ri->attr->community - || !community_cmp( - ri->attr->community, - com)) - continue; - } - if (type == bgp_show_type_community_list) { - struct community_list *list = - output_arg; + if (!ri->attr->community + || !community_match(ri->attr->community, + com)) + continue; + } + if (type == bgp_show_type_community_exact) { + struct community *com = output_arg; - if (!community_list_match( - ri->attr->community, list)) - continue; - } - if (type - == bgp_show_type_community_list_exact) { - struct community_list *list = - output_arg; + if (!ri->attr->community + || !community_cmp(ri->attr->community, + com)) + continue; + } + if (type == bgp_show_type_community_list) { + struct community_list *list = output_arg; - if (!community_list_exact_match( - ri->attr->community, list)) - continue; - } - if (type == bgp_show_type_lcommunity) { - struct lcommunity *lcom = output_arg; + if (!community_list_match( + ri->attr->community, list)) + continue; + } + if (type + == bgp_show_type_community_list_exact) { + struct community_list *list = output_arg; - if (!ri->attr->lcommunity - || !lcommunity_match( - ri->attr->lcommunity, - lcom)) - continue; - } - if (type == bgp_show_type_lcommunity_list) { - struct community_list *list = - output_arg; + if (!community_list_exact_match( + ri->attr->community, list)) + continue; + } + if (type == bgp_show_type_lcommunity) { + struct lcommunity *lcom = output_arg; - if (!lcommunity_list_match( - ri->attr->lcommunity, list)) - continue; - } - if (type == bgp_show_type_lcommunity_all) { - if (!ri->attr->lcommunity) - continue; - } - if (type == bgp_show_type_dampend_paths - || type == bgp_show_type_damp_neighbor) { - if (!CHECK_FLAG(ri->flags, - BGP_INFO_DAMPED) - || CHECK_FLAG(ri->flags, - BGP_INFO_HISTORY)) - continue; - } + if (!ri->attr->lcommunity + || !lcommunity_match(ri->attr->lcommunity, + lcom)) + continue; + } + if (type == bgp_show_type_lcommunity_list) { + struct community_list *list = output_arg; - if (!use_json && header) { - vty_out(vty, - "BGP table version is %" PRIu64 - ", local router ID is %s\n", - table->version, - inet_ntoa(bgp->router_id)); - vty_out(vty, BGP_SHOW_SCODE_HEADER); - vty_out(vty, BGP_SHOW_OCODE_HEADER); - if (type == bgp_show_type_dampend_paths - || type == bgp_show_type_damp_neighbor) - vty_out(vty, - BGP_SHOW_DAMP_HEADER); - else if ( - type == bgp_show_type_flap_statistics - || type == bgp_show_type_flap_neighbor) - vty_out(vty, - BGP_SHOW_FLAP_HEADER); - else - vty_out(vty, BGP_SHOW_HEADER); - header = 0; - } + if (!lcommunity_list_match( + ri->attr->lcommunity, list)) + continue; + } + if (type == bgp_show_type_lcommunity_all) { + if (!ri->attr->lcommunity) + continue; + } + if (type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) { + if (!CHECK_FLAG(ri->flags, BGP_INFO_DAMPED) + || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) + continue; + } + if (!use_json && header) { + vty_out(vty, + "BGP table version is %" PRIu64 + ", local router ID is %s\n", + table->version, + inet_ntoa(bgp->router_id)); + vty_out(vty, BGP_SHOW_SCODE_HEADER); + vty_out(vty, BGP_SHOW_OCODE_HEADER); if (type == bgp_show_type_dampend_paths || type == bgp_show_type_damp_neighbor) - damp_route_vty_out( - vty, &rn->p, ri, display, - SAFI_UNICAST, use_json, - json_paths); - else if (type == bgp_show_type_flap_statistics - || type == bgp_show_type_flap_neighbor) - flap_route_vty_out( - vty, &rn->p, ri, display, - SAFI_UNICAST, use_json, - json_paths); + vty_out(vty, BGP_SHOW_DAMP_HEADER); + else if ( + type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_neighbor) + vty_out(vty, BGP_SHOW_FLAP_HEADER); else - route_vty_out(vty, &rn->p, ri, display, - SAFI_UNICAST, json_paths); - display++; + vty_out(vty, BGP_SHOW_HEADER); + header = 0; } - - if (display) { - output_count++; - if (use_json) { - p = &rn->p; - sprintf(buf2, "%s/%d", - inet_ntop(p->family, - &p->u.prefix, buf, - BUFSIZ), - p->prefixlen); - vty_out(vty, "\"%s\": ", buf2); - vty_out(vty, "%s", - json_object_to_json_string( - json_paths)); - json_object_free(json_paths); - first = 0; - } + if (rd != NULL && !display && !output_count) { + if (!use_json) + vty_out(vty, + "Route Distinguisher: %s\n", + rd); } + if (type == bgp_show_type_dampend_paths + || type == bgp_show_type_damp_neighbor) + damp_route_vty_out(vty, &rn->p, ri, display, + safi, use_json, + json_paths); + else if (type == bgp_show_type_flap_statistics + || type == bgp_show_type_flap_neighbor) + flap_route_vty_out(vty, &rn->p, ri, display, + safi, use_json, + json_paths); + else + route_vty_out(vty, &rn->p, ri, display, + safi, json_paths); + display++; } + if (display) { + output_count++; + if (!use_json) + continue; + + p = &rn->p; + sprintf(buf2, "%s/%d", + inet_ntop(p->family, &p->u.prefix, + buf, BUFSIZ), + p->prefixlen); + vty_out(vty, "\"%s\": ", buf2); + vty_out(vty, "%s", + json_object_to_json_string(json_paths)); + json_object_free(json_paths); + first = 0; + } + } + + if (output_cum) { + output_count += *output_cum; + *output_cum = output_count; + } + if (total_cum) { + total_count += *total_cum; + *total_cum = total_count; + } if (use_json) { json_object_free(json_paths); - vty_out(vty, " } }\n"); + if (is_last) + vty_out(vty, " } }\n"); + else + vty_out(vty, " }, "); } else { - /* No route is displayed */ - if (output_count == 0) { - if (type == bgp_show_type_normal) + if (is_last) { + /* No route is displayed */ + if (output_count == 0) { + if (type == bgp_show_type_normal) + vty_out(vty, + "No BGP prefixes displayed, %ld exist\n", + total_count); + } else vty_out(vty, - "No BGP prefixes displayed, %ld exist\n", - total_count); - } else - vty_out(vty, - "\nDisplayed %ld routes and %ld total paths\n", - output_count, total_count); + "\nDisplayed %ld routes and %ld total paths\n", + output_count, total_count); + } } return CMD_SUCCESS; } +int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, + struct bgp_table *table, struct prefix_rd *prd_match, + enum bgp_show_type type, void *output_arg, + u_char use_json) +{ + struct bgp_node *rn, *next; + unsigned long output_cum = 0; + unsigned long total_cum = 0; + + for (rn = bgp_table_top(table); rn; rn = next) { + next = bgp_route_next(rn); + if (prd_match && memcmp(rn->p.u.val, prd_match->val, 8) != 0) + continue; + if (rn->info != NULL) { + struct prefix_rd prd; + char rd[BUFSIZ]; + + memcpy(&prd, &(rn->p), sizeof(struct prefix_rd)); + if (prefix_rd2str(&prd, rd, BUFSIZ) == NULL) + sprintf(rd, + "Unknown Type: %u", + decode_rd_type(prd.val)); + bgp_show_table(vty, bgp, safi, rn->info, type, + output_arg, use_json, + rd, next == NULL, + &output_cum, &total_cum); + } + } + if (use_json) + vty_out(vty, " } }"); + return CMD_SUCCESS; +} static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, enum bgp_show_type type, void *output_arg, u_char use_json) { @@ -8409,18 +8465,18 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, return CMD_WARNING; } + table = bgp->rib[afi][safi]; /* use MPLS and ENCAP specific shows until they are merged */ if (safi == SAFI_MPLS_VPN) { - return bgp_show_mpls_vpn(vty, afi, NULL, type, output_arg, 0, - use_json); + return bgp_show_table_rd(vty, bgp, safi, table, NULL, type, + output_arg, use_json); } /* labeled-unicast routes live in the unicast table */ else if (safi == SAFI_LABELED_UNICAST) safi = SAFI_UNICAST; - table = bgp->rib[afi][safi]; - - return bgp_show_table(vty, bgp, table, type, output_arg, use_json); + return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json, + NULL, 1, NULL, NULL); } static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, @@ -9090,12 +9146,7 @@ DEFUN (show_ip_bgp_json, return bgp_show(vty, bgp, afi, safi, bgp_show_type_community_all, NULL, uj); } - - if (safi == SAFI_MPLS_VPN) - return bgp_show_mpls_vpn(vty, afi, NULL, bgp_show_type_normal, - NULL, 0, uj); - else - return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj); + return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj); } DEFUN (show_ip_bgp_route, diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 6caa1c893..6fbeed896 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -442,4 +442,8 @@ extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, struct bgp_info *binfo, afi_t afi, safi_t safi, json_object *json_paths); +extern int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, + struct bgp_table *table, struct prefix_rd *prd, + enum bgp_show_type type, void *output_arg, + u_char use_json); #endif /* _QUAGGA_BGP_ROUTE_H */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 4ddb49982..355d1037b 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -9868,17 +9868,13 @@ static int bgp_show_neighbor_vty(struct vty *vty, const char *name, /* "show [ip] bgp neighbors" commands. */ DEFUN (show_ip_bgp_neighbors, show_ip_bgp_neighbors_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|vpnv4 <all|rd ASN:NN_OR_IP-ADDRESS:NN>>] neighbors [<A.B.C.D|X:X::X:X|WORD>] [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6>] neighbors [<A.B.C.D|X:X::X:X|WORD>] [json]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR "Address Family\n" "Address Family\n" - "Address Family\n" - "Display information about all VPNv4 NLRIs\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" "Neighbor to display information about\n" |