From f08b5ca0d919462cf92ff71da51d88af509e3fdd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 May 2019 20:54:34 -0400 Subject: [PATCH 1/3] bgpd: Switch data structure passing to route_vty_out_detail Instead of just passing in the prefix, pass in the particular bgp_node we are using. This is setup for a future commit to use this data. The long term goal is to collect data about why a particular bgp_path_info was selected as best and to display that reason. Signed-off-by: Donald Sharp --- bgpd/bgp_evpn_vty.c | 12 ++++++------ bgpd/bgp_route.c | 19 ++++++++++--------- bgpd/bgp_route.h | 3 ++- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 4296604c4a4a..9e09d1789347 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -681,7 +681,7 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, json_path = json_object_new_array(); if (detail) - route_vty_out_detail(vty, bgp, &rn->p, pi, + route_vty_out_detail(vty, bgp, rn, pi, AFI_L2VPN, SAFI_EVPN, json_path); else @@ -2089,7 +2089,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp, if (json) json_path = json_object_new_array(); - route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi, + route_vty_out_detail(vty, bgp, rn, pi, afi, safi, json_path); if (json) @@ -2159,7 +2159,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp, if (json) json_path = json_object_new_array(); - route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi, + route_vty_out_detail(vty, bgp, rn, pi, afi, safi, json_path); if (json) @@ -2266,7 +2266,7 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp, if (json) json_path = json_object_new_array(); - route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi, + route_vty_out_detail(vty, bgp, rn, pi, afi, safi, json_path); if (json) @@ -2371,7 +2371,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, if (json) json_path = json_object_new_array(); - route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi, + route_vty_out_detail(vty, bgp, rn, pi, afi, safi, json_path); if (json) @@ -2521,7 +2521,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, if (detail) { route_vty_out_detail( - vty, bgp, &rn->p, pi, AFI_L2VPN, + vty, bgp, rn, pi, AFI_L2VPN, SAFI_EVPN, json_path); } else route_vty_out(vty, &rn->p, pi, 0, diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 82a395d8e6d2..819178204735 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7822,9 +7822,9 @@ static void route_vty_out_tx_ids(struct vty *vty, } } -void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, - struct bgp_path_info *path, afi_t afi, safi_t safi, - json_object *json_paths) +void route_vty_out_detail(struct vty *vty, struct bgp *bgp, + struct bgp_node *bn, struct bgp_path_info *path, + afi_t afi, safi_t safi, json_object *json_paths) { char buf[INET6_ADDRSTRLEN]; char buf1[BUFSIZ]; @@ -7864,7 +7864,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, if (!json_paths && safi == SAFI_EVPN) { char tag_buf[30]; - bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2)); + bgp_evpn_route2str((struct prefix_evpn *)&bn->p, + buf2, sizeof(buf2)); vty_out(vty, " Route %s", buf2); tag_buf[0] = '\0'; if (path->extra && path->extra->num_labels) { @@ -7979,8 +7980,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, /* Line2 display Next-hop, Neighbor, Router-id */ /* Display the nexthop */ - if ((p->family == AF_INET || p->family == AF_ETHERNET - || p->family == AF_EVPN) + if ((bn->p.family == AF_INET || bn->p.family == AF_ETHERNET + || bn->p.family == AF_EVPN) && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { @@ -8062,7 +8063,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, if (path->peer == bgp->peer_self) { if (safi == SAFI_EVPN - || (p->family == AF_INET + || (bn->p.family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { if (json_paths) json_object_string_add( @@ -9429,7 +9430,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, BGP_PATH_MULTIPATH) || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)))) - route_vty_out_detail(vty, bgp, &rm->p, + route_vty_out_detail(vty, bgp, rm, pi, AFI_IP, safi, json_paths); } @@ -9473,7 +9474,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, pi->flags, BGP_PATH_SELECTED)))) route_vty_out_detail( - vty, bgp, &rn->p, pi, + vty, bgp, rn, pi, afi, safi, json_paths); } } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 7bbc14b46f2b..0d16ffc90c35 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -604,7 +604,8 @@ extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, struct prefix_rd *prd, afi_t afi, safi_t safi, json_object *json); extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp, - struct prefix *p, struct bgp_path_info *path, + struct bgp_node *bn, + struct bgp_path_info *path, 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, From fdf81fa0280031419aa15afaeedcb410683c12a1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 May 2019 21:05:37 -0400 Subject: [PATCH 2/3] bgpd: Store reason why bestpath was choosen Store in bgp_node the reason why we choose a particular best path over another. At this point we do not do anything other than just store this data when we make the decision. Future commits will display it. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 62 ++++++++++++++++++++++++++++++++++----- bgpd/bgp_route.h | 3 +- bgpd/bgp_table.h | 27 +++++++++++++++++ bgpd/rfapi/rfapi_import.c | 5 +++- 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 819178204735..d24a152f1385 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -434,7 +434,8 @@ void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf) static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, struct bgp_path_info *exist, int *paths_eq, struct bgp_maxpaths_cfg *mpath_cfg, int debug, - char *pfx_buf, afi_t afi, safi_t safi) + char *pfx_buf, afi_t afi, safi_t safi, + enum bgp_path_selection_reason *reason) { struct attr *newattr, *existattr; bgp_peer_sort_t new_sort; @@ -463,6 +464,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, /* 0. Null check. */ if (new == NULL) { + *reason = bgp_path_selection_none; if (debug) zlog_debug("%s: new is NULL", pfx_buf); return 0; @@ -472,6 +474,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, bgp_path_info_path_with_addpath_rx_str(new, new_buf); if (exist == NULL) { + *reason = bgp_path_selection_first; if (debug) zlog_debug("%s: %s is the initial bestpath", pfx_buf, new_buf); @@ -514,6 +517,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (newattr->sticky && !existattr->sticky) { + *reason = bgp_path_selection_evpn_sticky_mac; if (debug) zlog_debug( "%s: %s wins over %s due to sticky MAC flag", @@ -522,6 +526,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (!newattr->sticky && existattr->sticky) { + *reason = bgp_path_selection_evpn_sticky_mac; if (debug) zlog_debug( "%s: %s loses to %s due to sticky MAC flag", @@ -534,6 +539,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, exist_mm_seq = mac_mobility_seqnum(existattr); if (new_mm_seq > exist_mm_seq) { + *reason = bgp_path_selection_evpn_seq; if (debug) zlog_debug( "%s: %s wins over %s due to MM seq %u > %u", @@ -543,6 +549,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (new_mm_seq < exist_mm_seq) { + *reason = bgp_path_selection_evpn_seq; if (debug) zlog_debug( "%s: %s loses to %s due to MM seq %u < %u", @@ -557,6 +564,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, */ nh_cmp = bgp_path_info_nexthop_cmp(new, exist); if (nh_cmp < 0) { + *reason = bgp_path_selection_evpn_lower_ip; if (debug) zlog_debug( "%s: %s wins over %s due to same MM seq %u and lower IP %s", @@ -565,6 +573,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, return 1; } if (nh_cmp > 0) { + *reason = bgp_path_selection_evpn_lower_ip; if (debug) zlog_debug( "%s: %s loses to %s due to same MM seq %u and higher IP %s", @@ -579,6 +588,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, exist_weight = existattr->weight; if (new_weight > exist_weight) { + *reason = bgp_path_selection_weight; if (debug) zlog_debug("%s: %s wins over %s due to weight %d > %d", pfx_buf, new_buf, exist_buf, new_weight, @@ -587,6 +597,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (new_weight < exist_weight) { + *reason = bgp_path_selection_weight; if (debug) zlog_debug("%s: %s loses to %s due to weight %d < %d", pfx_buf, new_buf, exist_buf, new_weight, @@ -603,6 +614,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, exist_pref = existattr->local_pref; if (new_pref > exist_pref) { + *reason = bgp_path_selection_local_pref; if (debug) zlog_debug( "%s: %s wins over %s due to localpref %d > %d", @@ -612,6 +624,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (new_pref < exist_pref) { + *reason = bgp_path_selection_local_pref; if (debug) zlog_debug( "%s: %s loses to %s due to localpref %d < %d", @@ -627,6 +640,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, */ if (!(new->sub_type == BGP_ROUTE_NORMAL || new->sub_type == BGP_ROUTE_IMPORTED)) { + *reason = bgp_path_selection_local_route; if (debug) zlog_debug( "%s: %s wins over %s due to preferred BGP_ROUTE type", @@ -636,6 +650,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, if (!(exist->sub_type == BGP_ROUTE_NORMAL || exist->sub_type == BGP_ROUTE_IMPORTED)) { + *reason = bgp_path_selection_local_route; if (debug) zlog_debug( "%s: %s loses to %s due to preferred BGP_ROUTE type", @@ -655,6 +670,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, aspath_hops += aspath_count_confeds(newattr->aspath); if (aspath_hops < (exist_hops + exist_confeds)) { + *reason = bgp_path_selection_confed_as_path; if (debug) zlog_debug( "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d", @@ -665,6 +681,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (aspath_hops > (exist_hops + exist_confeds)) { + *reason = bgp_path_selection_confed_as_path; if (debug) zlog_debug( "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d", @@ -677,6 +694,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, int newhops = aspath_count_hops(newattr->aspath); if (newhops < exist_hops) { + *reason = bgp_path_selection_as_path; if (debug) zlog_debug( "%s: %s wins over %s due to aspath hopcount %d < %d", @@ -686,6 +704,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (newhops > exist_hops) { + *reason = bgp_path_selection_as_path; if (debug) zlog_debug( "%s: %s loses to %s due to aspath hopcount %d > %d", @@ -698,6 +717,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, /* 5. Origin check. */ if (newattr->origin < existattr->origin) { + *reason = bgp_path_selection_origin; if (debug) zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s", pfx_buf, new_buf, exist_buf, @@ -707,6 +727,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (newattr->origin > existattr->origin) { + *reason = bgp_path_selection_origin; if (debug) zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s", pfx_buf, new_buf, exist_buf, @@ -732,6 +753,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, exist_med = bgp_med_value(exist->attr, bgp); if (new_med < exist_med) { + *reason = bgp_path_selection_med; if (debug) zlog_debug( "%s: %s wins over %s due to MED %d < %d", @@ -741,6 +763,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (new_med > exist_med) { + *reason = bgp_path_selection_med; if (debug) zlog_debug( "%s: %s loses to %s due to MED %d > %d", @@ -756,6 +779,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, if (new_sort == BGP_PEER_EBGP && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) { + *reason = bgp_path_selection_peer; if (debug) zlog_debug( "%s: %s wins over %s due to eBGP peer > iBGP peer", @@ -765,6 +789,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, if (exist_sort == BGP_PEER_EBGP && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) { + *reason = bgp_path_selection_peer; if (debug) zlog_debug( "%s: %s loses to %s due to iBGP peer < eBGP peer", @@ -834,6 +859,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { if (new_sort == BGP_PEER_CONFED && exist_sort == BGP_PEER_IBGP) { + *reason = bgp_path_selection_confed; if (debug) zlog_debug( "%s: %s wins over %s due to confed-external peer > confed-internal peer", @@ -843,6 +869,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, if (exist_sort == BGP_PEER_CONFED && new_sort == BGP_PEER_IBGP) { + *reason = bgp_path_selection_confed; if (debug) zlog_debug( "%s: %s loses to %s due to confed-internal peer < confed-external peer", @@ -918,6 +945,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, "%s: %s loses to %s after IGP metric comparison", pfx_buf, new_buf, exist_buf); } + *reason = bgp_path_selection_igp_metric; return ret; } @@ -928,6 +956,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID) && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) { if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) { + *reason = bgp_path_selection_older; if (debug) zlog_debug( "%s: %s wins over %s due to oldest external", @@ -936,6 +965,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) { + *reason = bgp_path_selection_older; if (debug) zlog_debug( "%s: %s loses to %s due to oldest external", @@ -959,6 +989,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, exist_id.s_addr = exist->peer->remote_id.s_addr; if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) { + *reason = bgp_path_selection_router_id; if (debug) zlog_debug( "%s: %s wins over %s due to Router-ID comparison", @@ -967,6 +998,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) { + *reason = bgp_path_selection_router_id; if (debug) zlog_debug( "%s: %s loses to %s due to Router-ID comparison", @@ -979,6 +1011,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr); if (new_cluster < exist_cluster) { + *reason = bgp_path_selection_cluster_length; if (debug) zlog_debug( "%s: %s wins over %s due to CLUSTER_LIST length %d < %d", @@ -988,6 +1021,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (new_cluster > exist_cluster) { + *reason = bgp_path_selection_cluster_length; if (debug) zlog_debug( "%s: %s loses to %s due to CLUSTER_LIST length %d > %d", @@ -1001,6 +1035,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, * valid peer information (as the connection may or may not be up). */ if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) { + *reason = bgp_path_selection_stale; if (debug) zlog_debug( "%s: %s wins over %s due to latter path being STALE", @@ -1009,6 +1044,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) { + *reason = bgp_path_selection_stale; if (debug) zlog_debug( "%s: %s loses to %s due to former path being STALE", @@ -1017,14 +1053,19 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } /* locally configured routes to advertise do not have su_remote */ - if (new->peer->su_remote == NULL) + if (new->peer->su_remote == NULL) { + *reason = bgp_path_selection_local_configured; return 0; - if (exist->peer->su_remote == NULL) + } + if (exist->peer->su_remote == NULL) { + *reason = bgp_path_selection_local_configured; return 1; + } ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote); if (ret == 1) { + *reason = bgp_path_selection_neighbor_ip; if (debug) zlog_debug( "%s: %s loses to %s due to Neighor IP comparison", @@ -1033,6 +1074,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (ret == -1) { + *reason = bgp_path_selection_neighbor_ip; if (debug) zlog_debug( "%s: %s wins over %s due to Neighor IP comparison", @@ -1040,6 +1082,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, return 1; } + *reason = bgp_path_selection_default; if (debug) zlog_debug("%s: %s wins over %s due to nothing left to compare", pfx_buf, new_buf, exist_buf); @@ -1053,12 +1096,13 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, * This version is compatible with */ int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new, struct bgp_path_info *exist, char *pfx_buf, - afi_t afi, safi_t safi) + afi_t afi, safi_t safi, + enum bgp_path_selection_reason *reason) { int paths_eq; int ret; ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf, - afi, safi); + afi, safi, reason); if (paths_eq) ret = 0; @@ -1955,7 +1999,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, if (bgp_path_info_cmp( bgp, pi2, new_select, &paths_eq, mpath_cfg, debug, - pfx_buf, afi, safi)) { + pfx_buf, afi, safi, + &rn->reason)) { bgp_path_info_unset_flag( rn, new_select, BGP_PATH_DMED_SELECTED); @@ -2028,7 +2073,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK); if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg, - debug, pfx_buf, afi, safi)) { + debug, pfx_buf, afi, safi, &rn->reason)) { new_select = pi; } } @@ -2084,7 +2129,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, } bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, - mpath_cfg, debug, pfx_buf, afi, safi); + mpath_cfg, debug, pfx_buf, afi, safi, + &rn->reason); if (paths_eq) { if (debug) diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 0d16ffc90c35..f71508445097 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -588,7 +588,8 @@ extern void bgp_path_info_restore(struct bgp_node *rn, extern int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new, struct bgp_path_info *exist, - char *pfx_buf, afi_t afi, safi_t safi); + char *pfx_buf, afi_t afi, safi_t safi, + enum bgp_path_selection_reason *reason); extern void bgp_attr_add_gshut_community(struct attr *attr); extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 040e83a8cd9e..b3542e7848a9 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -42,6 +42,31 @@ struct bgp_table { uint64_t version; }; +enum bgp_path_selection_reason { + bgp_path_selection_none, + bgp_path_selection_first, + bgp_path_selection_evpn_sticky_mac, + bgp_path_selection_evpn_seq, + bgp_path_selection_evpn_lower_ip, + bgp_path_selection_weight, + bgp_path_selection_local_pref, + bgp_path_selection_local_route, + bgp_path_selection_confed_as_path, + bgp_path_selection_as_path, + bgp_path_selection_origin, + bgp_path_selection_med, + bgp_path_selection_peer, + bgp_path_selection_confed, + bgp_path_selection_igp_metric, + bgp_path_selection_older, + bgp_path_selection_router_id, + bgp_path_selection_cluster_length, + bgp_path_selection_stale, + bgp_path_selection_local_configured, + bgp_path_selection_neighbor_ip, + bgp_path_selection_default, +}; + struct bgp_node { /* * CAUTION @@ -72,6 +97,8 @@ struct bgp_node { #define BGP_NODE_REGISTERED_FOR_LABEL (1 << 3) struct bgp_addpath_node_data tx_addpath; + + enum bgp_path_selection_reason reason; }; /* diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index d67361620db8..ad0900c2b854 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -1984,11 +1984,14 @@ static void rfapiBgpInfoAttachSorted(struct agg_node *rn, for (prev = NULL, next = rn->info; next; prev = next, next = next->next) { + enum bgp_path_selection_reason reason; + if (!bgp || (!CHECK_FLAG(info_new->flags, BGP_PATH_REMOVED) && CHECK_FLAG(next->flags, BGP_PATH_REMOVED)) || bgp_path_info_cmp_compatible(bgp, info_new, next, - pfx_buf, afi, safi) + pfx_buf, afi, safi, + &reason) == -1) { /* -1 if 1st is better */ break; } From 0dc8ee70624c5b018bbbe81f47536b80eda771eb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 May 2019 21:11:02 -0400 Subject: [PATCH 3/3] bgpd: Display best path selection reason As part of detailed bgp route detail, include the reason why a route was selected as best path. robot# show bgp ipv4 uni 223.255.254.0 BGP routing table entry for 223.255.254.0/24 Paths: (1 available, best #1, table default) Advertised to non peer-group peers: annie(192.168.201.136) 64539 15096 6939 7473 3758 55415 192.168.201.136 from annie(192.168.201.136) (192.168.201.136) Origin IGP, valid, external, bestpath-from-AS 64539, best (First path received) Last update: Wed May 15 21:15:48 2019 Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index d24a152f1385..f3a69d4b25a4 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -7868,6 +7868,79 @@ static void route_vty_out_tx_ids(struct vty *vty, } } +static const char *bgp_path_selection_reason2str( + enum bgp_path_selection_reason reason) +{ + switch (reason) { + case bgp_path_selection_none: + return "Nothing to Select"; + break; + case bgp_path_selection_first: + return "First path received"; + break; + case bgp_path_selection_evpn_sticky_mac: + return "EVPN Sticky Mac"; + break; + case bgp_path_selection_evpn_seq: + return "EVPN sequence number"; + break; + case bgp_path_selection_evpn_lower_ip: + return "EVPN lower IP"; + break; + case bgp_path_selection_weight: + return "Weight"; + break; + case bgp_path_selection_local_pref: + return "Local Pref"; + break; + case bgp_path_selection_local_route: + return "Local Route"; + break; + case bgp_path_selection_confed_as_path: + return "Confederation based AS Path"; + break; + case bgp_path_selection_as_path: + return "AS Path"; + break; + case bgp_path_selection_origin: + return "Origin"; + break; + case bgp_path_selection_med: + return "MED"; + break; + case bgp_path_selection_peer: + return "Peer Type"; + break; + case bgp_path_selection_confed: + return "Confed Peer Type"; + break; + case bgp_path_selection_igp_metric: + return "IGP Metric"; + break; + case bgp_path_selection_older: + return "Older Path"; + break; + case bgp_path_selection_router_id: + return "Router ID"; + break; + case bgp_path_selection_cluster_length: + return "Cluser length"; + break; + case bgp_path_selection_stale: + return "Path Staleness"; + break; + case bgp_path_selection_local_configured: + return "Locally configured route"; + break; + case bgp_path_selection_neighbor_ip: + return "Neighbor IP"; + break; + case bgp_path_selection_default: + return "Nothing left to compare"; + break; + } +} + void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_node *bn, struct bgp_path_info *path, afi_t afi, safi_t safi, json_object *json_paths) @@ -8463,8 +8536,14 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, json_object_new_object(); json_object_boolean_true_add(json_bestpath, "overall"); - } else + json_object_string_add(json_bestpath, + "selectionReason", + bgp_path_selection_reason2str(bn->reason)); + } else { vty_out(vty, ", best"); + vty_out(vty, " (%s)", + bgp_path_selection_reason2str(bn->reason)); + } } if (json_bestpath)