bgpd: when showing routes, add nexthop vrf and announce-self flag

As part of recent vpn-vrf leaking changes, it is now possible for a
route to refer to a nexthop in a different vrf. There is also a new
route flag that means "when announcing this route, indicate myself
as the next-hop."

route_vty_out(): nexthops are appended with:

    "@VRFID" (where VRFID is the numerical vrf id) when different from
    the route's vrf;

    "<" when the route's BGP_INFO_ANNC_NH_SELF is set

This change also shows the route table's vrf id in the table header.

route_vty_out_detail(): show nexthop's vrf and announce-nh-self flag if
appropriate.

Both functions are also augmented to add json elements nhVrfId, nhVrfName,
and announceNexthopSelf as appropriate.

The intent of these changes is to make it easier to understand/debug
the relationship between a route and its nexthops.

Signed-off-by: G. Paul Ziemba <paulz@labn.net>
This commit is contained in:
G. Paul Ziemba 2018-04-09 13:28:11 -07:00
parent d90b2b73cb
commit 9df8b37c72
2 changed files with 163 additions and 17 deletions

View File

@ -99,6 +99,8 @@ static const struct message bgp_pmsi_tnltype_str[] = {
{0}
};
#define VRFID_NONE_STR "-"
struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
safi_t safi, struct prefix *p,
struct prefix_rd *prd)
@ -6471,6 +6473,13 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
json_object *json_nexthops = NULL;
json_object *json_nexthop_global = NULL;
json_object *json_nexthop_ll = NULL;
char vrf_id_str[VRF_NAMSIZ] = {0};
bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
? true
: false;
bool nexthop_othervrf = false;
vrf_id_t nexthop_vrfid;
const char *nexthop_vrfname = "Default";
if (json_paths)
json_path = json_object_new_object();
@ -6499,6 +6508,39 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
return;
}
/*
* If vrf id of nexthop is different from that of prefix,
* set up printable string to append
*/
if (binfo->extra && binfo->extra->bgp_orig) {
const char *self = "";
if (nexthop_self)
self = "<";
nexthop_othervrf = true;
nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
if (binfo->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
snprintf(vrf_id_str, sizeof(vrf_id_str),
"@%s%s", VRFID_NONE_STR, self);
else
snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
binfo->extra->bgp_orig->vrf_id, self);
if (binfo->extra->bgp_orig->inst_type !=
BGP_INSTANCE_TYPE_DEFAULT)
nexthop_vrfname = binfo->extra->bgp_orig->name;
} else {
const char *self = "";
if (nexthop_self)
self = "<";
snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
}
/*
* For ENCAP and EVPN routes, nexthop address family is not
* neccessarily the same as the prefix address family.
@ -6541,7 +6583,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
json_object_boolean_true_add(json_nexthop_global,
"used");
} else
vty_out(vty, "%s", nexthop);
vty_out(vty, "%s%s", nexthop, vrf_id_str);
} else if (safi == SAFI_EVPN) {
if (json_paths) {
json_nexthop_global = json_object_new_object();
@ -6553,7 +6595,8 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
json_object_boolean_true_add(json_nexthop_global,
"used");
} else
vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
vty_out(vty, "%-16s%s", inet_ntoa(attr->nexthop),
vrf_id_str);
} else if (safi == SAFI_FLOWSPEC) {
if (attr->nexthop.s_addr != 0) {
if (json_paths) {
@ -6587,11 +6630,17 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
json_object_boolean_true_add(json_nexthop_global,
"used");
} else {
char buf[BUFSIZ];
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
vty_out(vty, "%-16s",
inet_ntoa(attr->mp_nexthop_global_in));
snprintf(buf, sizeof(buf), "%s%s",
inet_ntoa(attr->mp_nexthop_global_in),
vrf_id_str);
else
vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
snprintf(buf, sizeof(buf), "%s%s",
inet_ntoa(attr->nexthop),
vrf_id_str);
vty_out(vty, "%-16s", buf);
}
}
@ -6658,11 +6707,12 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
vty_out(vty, "%*s", len, " ");
} else {
len = vty_out(
vty, "%s",
vty, "%s%s",
inet_ntop(
AF_INET6,
&attr->mp_nexthop_local,
buf, BUFSIZ));
buf, BUFSIZ),
vrf_id_str);
len = 16 - len;
if (len < 1)
@ -6672,10 +6722,11 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
}
} else {
len = vty_out(
vty, "%s",
vty, "%s%s",
inet_ntop(AF_INET6,
&attr->mp_nexthop_global, buf,
BUFSIZ));
BUFSIZ),
vrf_id_str);
len = 16 - len;
if (len < 1)
@ -6733,6 +6784,21 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo,
else
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
if (json_paths) {
if (nexthop_self)
json_object_boolean_true_add(json_path,
"announceNexthopSelf");
if (nexthop_othervrf) {
json_object_string_add(json_path, "nhVrfName",
nexthop_vrfname);
json_object_int_add(json_path, "nhVrfId",
((nexthop_vrfid == VRF_UNKNOWN)
? -1
: (int)nexthop_vrfid));
}
}
if (json_paths) {
if (json_nexthop_global || json_nexthop_ll) {
json_nexthops = json_object_new_array();
@ -7333,6 +7399,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
int addpath_capable;
int has_adj;
unsigned int first_as;
bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF)
? true
: false;
if (json_paths) {
json_path = json_object_new_object();
@ -7636,6 +7705,49 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
}
}
/*
* Note when vrfid of nexthop is different from that of prefix
*/
if (binfo->extra && binfo->extra->bgp_orig) {
vrf_id_t nexthop_vrfid = binfo->extra->bgp_orig->vrf_id;
if (json_paths) {
const char *vn;
if (binfo->extra->bgp_orig->inst_type ==
BGP_INSTANCE_TYPE_DEFAULT)
vn = "Default";
else
vn = binfo->extra->bgp_orig->name;
json_object_string_add(json_path, "nhVrfName",
vn);
if (nexthop_vrfid == VRF_UNKNOWN) {
json_object_int_add(json_path,
"nhVrfId", -1);
} else {
json_object_int_add(json_path,
"nhVrfId", (int)nexthop_vrfid);
}
} else {
if (nexthop_vrfid == VRF_UNKNOWN)
vty_out(vty, " vrf ?");
else
vty_out(vty, " vrf %u", nexthop_vrfid);
}
}
if (nexthop_self) {
if (json_paths) {
json_object_boolean_true_add(json_path,
"announceNexthopSelf");
} else {
vty_out(vty, " announce-nh-self");
}
}
if (!json_paths)
vty_out(vty, "\n");
@ -8333,10 +8445,16 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
if (!use_json && header) {
vty_out(vty, "BGP table version is %" PRIu64
", local router ID is %s\n",
", local router ID is %s, vrf id ",
table->version,
inet_ntoa(bgp->router_id));
if (bgp->vrf_id == VRF_UNKNOWN)
vty_out(vty, "%s", VRFID_NONE_STR);
else
vty_out(vty, "%u", bgp->vrf_id);
vty_out(vty, "\n");
vty_out(vty, BGP_SHOW_SCODE_HEADER);
vty_out(vty, BGP_SHOW_NCODE_HEADER);
vty_out(vty, BGP_SHOW_OCODE_HEADER);
if (type == bgp_show_type_dampend_paths
|| type == bgp_show_type_damp_neighbor)
@ -10146,9 +10264,15 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
"0.0.0.0");
} else {
vty_out(vty, "BGP table version is %" PRIu64
", local router ID is %s\n",
", local router ID is %s, vrf id ",
table->version, inet_ntoa(bgp->router_id));
if (bgp->vrf_id == VRF_UNKNOWN)
vty_out(vty, "%s", VRFID_NONE_STR);
else
vty_out(vty, "%u", bgp->vrf_id);
vty_out(vty, "\n");
vty_out(vty, BGP_SHOW_SCODE_HEADER);
vty_out(vty, BGP_SHOW_NCODE_HEADER);
vty_out(vty, BGP_SHOW_OCODE_HEADER);
vty_out(vty, "Originating default network 0.0.0.0\n\n");
@ -10179,11 +10303,20 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
json_ocode);
} else {
vty_out(vty,
"BGP table version is 0, local router ID is %s\n",
"BGP table version is 0, local router ID is %s, vrf id ",
inet_ntoa(
bgp->router_id));
bgp->router_id));
if (bgp->vrf_id == VRF_UNKNOWN)
vty_out(vty, "%s",
VRFID_NONE_STR);
else
vty_out(vty, "%u",
bgp->vrf_id);
vty_out(vty, "\n");
vty_out(vty,
BGP_SHOW_SCODE_HEADER);
vty_out(vty,
BGP_SHOW_NCODE_HEADER);
vty_out(vty,
BGP_SHOW_OCODE_HEADER);
}
@ -10237,12 +10370,24 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
} else {
vty_out(vty,
"BGP table version is %" PRIu64
", local router ID is %s\n",
", local router ID is %s, vrf id ",
table->version,
inet_ntoa(
bgp->router_id));
if (bgp->vrf_id ==
VRF_UNKNOWN)
vty_out(vty,
"%s",
VRFID_NONE_STR);
else
vty_out(vty,
"%u",
bgp->vrf_id);
vty_out(vty, "\n");
vty_out(vty,
BGP_SHOW_SCODE_HEADER);
vty_out(vty,
BGP_SHOW_NCODE_HEADER);
vty_out(vty,
BGP_SHOW_OCODE_HEADER);
}

View File

@ -54,10 +54,11 @@ enum bgp_show_type {
#define BGP_SHOW_SCODE_HEADER \
"Status codes: s suppressed, d damped, " \
"Status codes: s suppressed, d damped, " \
"h history, * valid, > best, = multipath,\n" \
" i internal, r RIB-failure, S Stale, R Removed\n"
#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"
" i internal, r RIB-failure, S Stale, R Removed\n"
#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"
#define BGP_SHOW_NCODE_HEADER "Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self\n"
#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
/* Maximum number of labels we can process or send with a prefix. We