From dc387b0fea1809aa082d40e497eb46a466c213b3 Mon Sep 17 00:00:00 2001 From: Lakshman Krishnamoorthy Date: Fri, 27 Sep 2019 11:45:38 -0700 Subject: [PATCH] bgpd: Fixing "show bgp l2vpn evpn neighbors x.x.x.x advertised-routes json Display output from adj_out instead of the rib table. Also fixes crash for the json output. RCA: prefix is written to json object using inet_ntop. But, this api returns null buffer for AF_EVPN address family (it works only for AF_INET and AF_INET6). This null buffer is then deref'd by json-object-to string api. Full output shown in PR: https://github.com/FRRouting/frr/pull/5078 Crash issue: https://github.com/FRRouting/frr/issues/5010 Signed-off-by: Lakshman Krishnamoorthy --- bgpd/bgp_route.c | 35 +++++++++++++--------- bgpd/bgp_vpn.c | 75 +++++++++++++++++++++++++++++++----------------- 2 files changed, 70 insertions(+), 40 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index d083586c93..c5bd02e24f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7517,7 +7517,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, json_object *json_status = NULL; json_object *json_net = NULL; char buff[BUFSIZ]; - char buf2[BUFSIZ]; + /* Route status display. */ if (use_json) { json_status = json_object_new_object(); @@ -7530,12 +7530,18 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, /* print prefix and mask */ if (use_json) { - json_object_string_add( - json_net, "addrPrefix", - inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ)); - json_object_int_add(json_net, "prefixLen", p->prefixlen); - prefix2str(p, buf2, PREFIX_STRLEN); - json_object_string_add(json_net, "network", buf2); + if (safi == SAFI_EVPN) + bgp_evpn_route2json((struct prefix_evpn *)p, json_net); + else if (p->family == AF_INET || p->family == AF_INET6) { + json_object_string_add( + json_net, "addrPrefix", + inet_ntop(p->family, &p->u.prefix, buff, + BUFSIZ)); + json_object_int_add(json_net, "prefixLen", + p->prefixlen); + prefix2str(p, buff, PREFIX_STRLEN); + json_object_string_add(json_net, "network", buff); + } } else route_vty_out_route(p, vty, NULL); @@ -7544,10 +7550,8 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, if (use_json) { if (p->family == AF_INET && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP - || safi == SAFI_EVPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP - || safi == SAFI_EVPN) + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) json_object_string_add( json_net, "nextHop", inet_ntoa( @@ -7565,7 +7569,11 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, inet_ntop(AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); - } + } else if (p->family == AF_EVPN && + !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) + json_object_string_add(json_net, + "nextHop", inet_ntoa( + attr->mp_nexthop_global_in)); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) @@ -7659,10 +7667,9 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, json_object_boolean_true_add(json_status, ">"); json_object_object_add(json_net, "appliedStatusSymbols", json_status); - char buf_cut[BUFSIZ]; - prefix2str(p, buf_cut, PREFIX_STRLEN); - json_object_object_add(json_ar, buf_cut, json_net); + prefix2str(p, buff, PREFIX_STRLEN); + json_object_object_add(json_ar, buff, json_net); } else vty_out(vty, "\n"); } diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c index 09b1cb429b..e48eda7231 100644 --- a/bgpd/bgp_vpn.c +++ b/bgpd/bgp_vpn.c @@ -29,6 +29,7 @@ #include "bgpd/bgp_attr.h" #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_vpn.h" +#include "bgpd/bgp_updgrp.h" int show_adj_route_vpn(struct vty *vty, struct peer *peer, struct prefix_rd *prd, afi_t afi, safi_t safi, @@ -38,14 +39,15 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, struct bgp_table *table; struct bgp_node *rn; struct bgp_node *rm; - struct bgp_path_info *path; int rd_header; int header = 1; json_object *json = NULL; json_object *json_scode = NULL; json_object *json_ocode = NULL; + json_object *json_adv = NULL; json_object *json_routes = NULL; - json_object *json_array = NULL; + char rd_str[BUFSIZ]; + unsigned long output_count = 0; bgp = bgp_get_default(); if (bgp == NULL) { @@ -59,8 +61,8 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, if (use_json) { json_scode = json_object_new_object(); json_ocode = json_object_new_object(); - json_routes = json_object_new_object(); json = json_object_new_object(); + json_adv = json_object_new_object(); json_object_string_add(json_scode, "suppressed", "s"); json_object_string_add(json_scode, "damped", "d"); @@ -83,16 +85,25 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, if (table == NULL) continue; - if (use_json) - json_array = json_object_new_array(); - else - json_array = NULL; rd_header = 1; + memset(rd_str, 0, sizeof(rd_str)); for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) { - path = bgp_node_get_bgp_path_info(rm); - if (path == NULL) + struct bgp_adj_out *adj = NULL; + struct attr *attr = NULL; + struct peer_af *paf = NULL; + + RB_FOREACH (adj, bgp_adj_out_rb, &rm->adj_out) + SUBGRP_FOREACH_PEER (adj->subgroup, paf) { + if (paf->peer != peer || !adj->attr) + continue; + + attr = adj->attr; + break; + } + + if (bgp_node_get_bgp_path_info(rm) == NULL) continue; if (header) { @@ -102,6 +113,13 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, json_object_string_add( json, "bgpLocalRouterId", inet_ntoa(bgp->router_id)); + json_object_int_add( + json, + "defaultLocPrf", + bgp->default_local_pref); + json_object_int_add( + json, "localAS", + bgp->as); json_object_object_add(json, "bgpStatusCodes", json_scode); @@ -112,6 +130,9 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, vty_out(vty, "BGP table version is 0, local router ID is %s\n", inet_ntoa(bgp->router_id)); + vty_out(vty, "Default local pref %u, ", + bgp->default_local_pref); + vty_out(vty, "local AS %u\n", bgp->as); vty_out(vty, "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); vty_out(vty, @@ -146,18 +167,19 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, decode_rd_vnc_eth(pnt, &rd_vnc_eth); #endif if (use_json) { - char buffer[BUFSIZ]; + json_routes = json_object_new_object(); + if (type == RD_TYPE_AS || type == RD_TYPE_AS4) - sprintf(buffer, "%u:%d", + sprintf(rd_str, "%u:%d", rd_as.as, rd_as.val); else if (type == RD_TYPE_IP) - sprintf(buffer, "%s:%d", + sprintf(rd_str, "%s:%d", inet_ntoa(rd_ip.ip), rd_ip.val); json_object_string_add( json_routes, - "routeDistinguisher", buffer); + "rd", rd_str); } else { vty_out(vty, "Route Distinguisher: "); @@ -192,24 +214,25 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, } rd_header = 0; } - if (use_json) { - char buf[BUFSIZ]; - - prefix2str(&rm->p, buf, sizeof(buf)); - json_object_object_add(json_routes, buf, - json_array); - } else { - route_vty_out_tmp(vty, &rm->p, path->attr, - safi, use_json, - json_array); - } + route_vty_out_tmp(vty, &rm->p, attr, + safi, use_json, + json_routes); + output_count++; } + + if (use_json) + json_object_object_add(json_adv, rd_str, json_routes); } + if (use_json) { - json_object_object_add(json, "routes", json_routes); + json_object_object_add(json, "advertisedRoutes", json_adv); + json_object_int_add(json, + "totalPrefixCounter", output_count); vty_out(vty, "%s\n", json_object_to_json_string_ext( json, JSON_C_TO_STRING_PRETTY)); json_object_free(json); - } + } else + vty_out(vty, "\nTotal number of prefixes %ld\n", output_count); + return CMD_SUCCESS; }