diff options
Diffstat (limited to 'bgpd/bgp_route.c')
| -rw-r--r-- | bgpd/bgp_route.c | 780 |
1 files changed, 485 insertions, 295 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 19e398fc88..3a627b4486 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -79,6 +79,7 @@ #include "bgpd/bgp_encap_types.h" #include "bgpd/bgp_encap_tlv.h" #include "bgpd/bgp_evpn.h" +#include "bgpd/bgp_evpn_mh.h" #include "bgpd/bgp_evpn_vty.h" #include "bgpd/bgp_flowspec.h" #include "bgpd/bgp_flowspec_util.h" @@ -544,6 +545,11 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, uint32_t new_mm_seq; uint32_t exist_mm_seq; int nh_cmp; + esi_t *exist_esi; + esi_t *new_esi; + bool same_esi; + bool old_proxy; + bool new_proxy; *paths_eq = 0; @@ -620,6 +626,47 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } } + new_esi = bgp_evpn_attr_get_esi(newattr); + exist_esi = bgp_evpn_attr_get_esi(existattr); + if (bgp_evpn_is_esi_valid(new_esi) && + !memcmp(new_esi, exist_esi, sizeof(esi_t))) { + same_esi = true; + } else { + same_esi = false; + } + + /* If both paths have the same non-zero ES and + * one path is local it wins. + * PS: Note the local path wins even if the remote + * has the higher MM seq. The local path's + * MM seq will be fixed up to match the highest + * rem seq, subsequently. + */ + if (same_esi) { + char esi_buf[ESI_STR_LEN]; + + if (bgp_evpn_is_path_local(bgp, new)) { + *reason = bgp_path_selection_evpn_local_path; + if (debug) + zlog_debug( + "%s: %s wins over %s as ES %s is same and local", + pfx_buf, new_buf, exist_buf, + esi_to_str(new_esi, esi_buf, + sizeof(esi_buf))); + return 1; + } + if (bgp_evpn_is_path_local(bgp, exist)) { + *reason = bgp_path_selection_evpn_local_path; + if (debug) + zlog_debug( + "%s: %s loses to %s as ES %s is same and local", + pfx_buf, new_buf, exist_buf, + esi_to_str(new_esi, esi_buf, + sizeof(esi_buf))); + return 0; + } + } + new_mm_seq = mac_mobility_seqnum(newattr); exist_mm_seq = mac_mobility_seqnum(existattr); @@ -643,6 +690,30 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, return 0; } + /* if the sequence numbers and ESI are the same and one path + * is non-proxy it wins (over proxy) + */ + new_proxy = bgp_evpn_attr_is_proxy(newattr); + old_proxy = bgp_evpn_attr_is_proxy(existattr); + if (same_esi && bgp_evpn_attr_is_local_es(newattr) && + old_proxy != new_proxy) { + if (!new_proxy) { + *reason = bgp_path_selection_evpn_non_proxy; + if (debug) + zlog_debug( + "%s: %s wins over %s, same seq/es and non-proxy", + pfx_buf, new_buf, exist_buf); + return 1; + } + + *reason = bgp_path_selection_evpn_non_proxy; + if (debug) + zlog_debug( + "%s: %s loses to %s, same seq/es and non-proxy", + pfx_buf, new_buf, exist_buf); + return 0; + } + /* * if sequence numbers are the same path with the lowest IP * wins @@ -1175,6 +1246,17 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, return 1; } + +int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, + struct bgp_path_info *exist, int *paths_eq) +{ + enum bgp_path_selection_reason reason; + char pfx_buf[PREFIX2STR_BUFFER]; + + return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf, + AFI_L2VPN, SAFI_EVPN, &reason); +} + /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist * is preferred, or 0 if they are the same (usually will only occur if * multipath is enabled @@ -1644,8 +1726,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi); if (!bgp_is_valid_label(&label)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) - zlog_debug("u%" PRIu64 ":s%" PRIu64 - " %s/%d is filtered - no label (%p)", + zlog_debug("u%" PRIu64 ":s%" PRIu64" %s/%d is filtered - no label (%p)", subgrp->update_group->id, subgrp->id, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), @@ -1690,8 +1771,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( - "%s [Update:SEND] %s originator-id is same as " - "remote router-id", + "%s [Update:SEND] %s originator-id is same as remote router-id", onlypeer->host, prefix2str(p, buf, sizeof(buf))); return false; @@ -1729,8 +1809,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, && aspath_loop_check(piattr->aspath, onlypeer->as)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( - "%s [Update:SEND] suppress announcement to peer AS %u " - "that is part of AS path.", + "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.", onlypeer->host, onlypeer->as); return false; } @@ -1740,8 +1819,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, if (aspath_loop_check(piattr->aspath, bgp->confed_id)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( - "%s [Update:SEND] suppress announcement to peer AS %u" - " is AS path.", + "%s [Update:SEND] suppress announcement to peer AS %u is AS path.", peer->host, bgp->confed_id); return false; } @@ -2978,26 +3056,52 @@ static int bgp_maximum_prefix_restart_timer(struct thread *thread) return 0; } +static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi, + safi_t safi) +{ + uint32_t count = 0; + struct bgp_dest *dest; + struct bgp_adj_in *ain; + struct bgp_table *table = peer->bgp->rib[afi][safi]; + + for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) { + for (ain = dest->adj_in; ain; ain = ain->next) { + const struct prefix *rn_p = bgp_dest_get_prefix(dest); + struct attr attr = {}; + + if (bgp_input_filter(peer, rn_p, &attr, afi, safi) + == FILTER_DENY) + count++; + } + } + + return count; +} + bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, int always) { iana_afi_t pkt_afi; iana_safi_t pkt_safi; + uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_FORCE)) + ? bgp_filtered_routes_count(peer, afi, safi) + + peer->pcount[afi][safi] + : peer->pcount[afi][safi]; if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) return false; - if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) { + if (pcount > peer->pmax[afi][safi]) { if (CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT) && !always) return false; zlog_info( - "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32 - " exceed, limit %" PRIu32, - get_afi_safi_str(afi, safi, false), peer->host, - peer->pcount[afi][safi], peer->pmax[afi][safi]); + "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u", + get_afi_safi_str(afi, safi, false), peer->host, pcount, + peer->pmax[afi][safi]); SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); if (CHECK_FLAG(peer->af_flags[afi][safi], @@ -3048,18 +3152,16 @@ bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); - if (peer->pcount[afi][safi] - > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) { + if (pcount > (pcount * peer->pmax_threshold[afi][safi] / 100)) { if (CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD) && !always) return false; zlog_info( - "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32 - ", max %" PRIu32, - get_afi_safi_str(afi, safi, false), peer->host, - peer->pcount[afi][safi], peer->pmax[afi][safi]); + "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u", + get_afi_safi_str(afi, safi, false), peer->host, pcount, + peer->pmax[afi][safi]); SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); } else @@ -3178,19 +3280,10 @@ struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance, } static void overlay_index_update(struct attr *attr, - struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) { if (!attr) return; - - if (eth_s_id == NULL) { - memset(&(attr->evpn_overlay.eth_s_id), 0, - sizeof(struct eth_segment_id)); - } else { - memcpy(&(attr->evpn_overlay.eth_s_id), eth_s_id, - sizeof(struct eth_segment_id)); - } if (gw_ip == NULL) { memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr)); } else { @@ -3200,20 +3293,17 @@ static void overlay_index_update(struct attr *attr, } static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path, - struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) { - struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote; union gw_addr *path_gw_ip, *path_gw_ip_remote; union { - struct eth_segment_id esi; + esi_t esi; union gw_addr ip; } temp; if (afi != AFI_L2VPN) return true; - path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id); path_gw_ip = &(path->attr->evpn_overlay.gw_ip); if (gw_ip == NULL) { @@ -3222,17 +3312,7 @@ static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path, } else path_gw_ip_remote = gw_ip; - if (eth_s_id == NULL) { - memset(&temp, 0, sizeof(temp)); - path_eth_s_id_remote = &temp.esi; - } else - path_eth_s_id_remote = eth_s_id; - - if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr))) - return false; - - return !memcmp(path_eth_s_id, path_eth_s_id_remote, - sizeof(struct eth_segment_id)); + return !!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)); } /* Check if received nexthop is valid or not. */ @@ -3512,6 +3592,12 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, attr_new = bgp_attr_intern(&new_attr); + /* If maximum prefix count is configured and current prefix + * count exeed it. + */ + if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) + return -1; + /* If the update is implicit withdraw. */ if (pi) { pi->uptime = bgp_clock(); @@ -3527,7 +3613,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, num_labels * sizeof(mpls_label_t)) == 0) && (overlay_index_equal( - afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id, + afi, pi, evpn == NULL ? NULL : &evpn->gw_ip))) { if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) @@ -3752,7 +3838,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, /* Update Overlay Index */ if (afi == AFI_L2VPN) { overlay_index_update( - pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id, + pi->attr, evpn == NULL ? NULL : &evpn->gw_ip); } @@ -3797,13 +3883,9 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, BGP_PATH_VALID); else { if (BGP_DEBUG(nht, NHT)) { - char buf1[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET, - (const void *)&attr_new - ->nexthop, - buf1, INET6_ADDRSTRLEN); - zlog_debug("%s(%s): NH unresolved", - __func__, buf1); + zlog_debug("%s(%pI4): NH unresolved", + __func__, + (in_addr_t *)&attr_new->nexthop); } bgp_path_info_unset_flag(dest, pi, BGP_PATH_VALID); @@ -3922,7 +4004,6 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, /* Update Overlay Index */ if (afi == AFI_L2VPN) { overlay_index_update(new->attr, - evpn == NULL ? NULL : &evpn->eth_s_id, evpn == NULL ? NULL : &evpn->gw_ip); } /* Nexthop reachability check. */ @@ -3987,11 +4068,6 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, } #endif - /* If maximum prefix count is configured and current prefix - count exeed it. */ - if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) - return -1; - /* If this is an EVPN route, process for import. */ if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID)) bgp_evpn_import_route(bgp, afi, safi, p, new); @@ -5311,7 +5387,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p, else if (bgp_static->gatewayIp.family == AF_INET6) memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6), sizeof(struct in6_addr)); - overlay_index_update(&attr, bgp_static->eth_s_id, &add); + memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t)); if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) { struct bgp_encap_type_vxlan bet; memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan)); @@ -5362,7 +5438,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p, if (pi) { memset(&add, 0, sizeof(union gw_addr)); if (attrhash_cmp(pi->attr, attr_new) - && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add) + && overlay_index_equal(afi, pi, &add) && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { bgp_dest_unlock_node(dest); bgp_attr_unintern(&attr_new); @@ -5866,7 +5942,7 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, if (esi) { bgp_static->eth_s_id = XCALLOC(MTYPE_ATTR, - sizeof(struct eth_segment_id)); + sizeof(esi_t)); str2esi(esi, bgp_static->eth_s_id); } if (routermac) { @@ -7417,7 +7493,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type, /* Static function to display route. */ static void route_vty_out_route(const struct prefix *p, struct vty *vty, - json_object *json) + json_object *json, bool wide) { int len = 0; char buf[BUFSIZ]; @@ -7472,7 +7548,7 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty, } if (!json) { - len = 17 - len; + len = wide ? (45 - len) : (17 - len); if (len < 1) vty_out(vty, "\n%*s", 20, " "); else @@ -7575,7 +7651,7 @@ static char *bgp_nexthop_hostname(struct peer *peer, /* called from terminal list command */ void route_vty_out(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, - json_object *json_paths) + json_object *json_paths, bool wide) { int len; struct attr *attr = path->attr; @@ -7592,6 +7668,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, const char *nexthop_vrfname = VRF_DEFAULT_NAME; char *nexthop_hostname = bgp_nexthop_hostname(path->peer, path->nexthop); + char esi_buf[ESI_STR_LEN]; if (json_paths) json_path = json_object_new_object(); @@ -7602,11 +7679,11 @@ void route_vty_out(struct vty *vty, const struct prefix *p, if (!json_paths) { /* print prefix and mask */ if (!display) - route_vty_out_route(p, vty, json_path); + route_vty_out_route(p, vty, json_path, wide); else - vty_out(vty, "%*s", 17, " "); + vty_out(vty, "%*s", (wide ? 45 : 17), " "); } else { - route_vty_out_route(p, vty, json_path); + route_vty_out_route(p, vty, json_path, wide); } /* @@ -7696,7 +7773,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, else len = vty_out(vty, "%s%s", nexthop, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -7726,7 +7803,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, len = vty_out(vty, "%pI4%s", &attr->nexthop, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -7762,7 +7839,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, &attr->nexthop, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -7793,7 +7870,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, len = vty_out(vty, "%pI4%s", &attr->nexthop, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -7866,10 +7943,9 @@ void route_vty_out(struct vty *vty, const struct prefix *p, if (path->peer->conf_if) { len = vty_out(vty, "%s", path->peer->conf_if); - len = 16 - len; /* len of IPv6 - addr + max - len of def - ifname */ + /* len of IPv6 addr + max len of def + * ifname */ + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); @@ -7888,7 +7964,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, &attr->mp_nexthop_local, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); @@ -7906,7 +7982,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, &attr->mp_nexthop_global, vrf_id_str); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); @@ -7920,10 +7996,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p, if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) if (json_paths) json_object_int_add(json_path, "metric", attr->med); + else if (wide) + vty_out(vty, "%7u", attr->med); else vty_out(vty, "%10u", attr->med); - else if (!json_paths) - vty_out(vty, " "); + else if (!json_paths) { + if (wide) + vty_out(vty, "%*s", 7, " "); + else + vty_out(vty, "%*s", 10, " "); + } /* Local Pref */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) @@ -7964,6 +8046,11 @@ void route_vty_out(struct vty *vty, const struct prefix *p, vty_out(vty, "%s", bgp_origin_str[attr->origin]); if (json_paths) { + if (bgp_evpn_is_esi_valid(&attr->esi)) { + json_object_string_add(json_path, "esi", + esi_to_str(&attr->esi, + esi_buf, sizeof(esi_buf))); + } if (safi == SAFI_EVPN && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) { json_ext_community = json_object_new_object(); @@ -8009,10 +8096,18 @@ void route_vty_out(struct vty *vty, const struct prefix *p, } else { vty_out(vty, "\n"); - if (safi == SAFI_EVPN && - attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) { - vty_out(vty, "%*s", 20, " "); - vty_out(vty, "%s\n", attr->ecommunity->str); + if (safi == SAFI_EVPN) { + if (bgp_evpn_is_esi_valid(&attr->esi)) { + vty_out(vty, "%*s", 20, " "); + vty_out(vty, "ESI:%s\n", + esi_to_str(&attr->esi, + esi_buf, sizeof(esi_buf))); + } + if (attr->flag & + ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) { + vty_out(vty, "%*s", 20, " "); + vty_out(vty, "%s\n", attr->ecommunity->str); + } } #ifdef ENABLE_BGP_VNC @@ -8027,7 +8122,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, /* called from terminal list command */ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, struct attr *attr, safi_t safi, bool use_json, - json_object *json_ar) + json_object *json_ar, bool wide) { json_object *json_status = NULL; json_object *json_net = NULL; @@ -8059,7 +8154,7 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, json_object_string_add(json_net, "network", buff); } } else - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, NULL, wide); /* Print attribute */ if (attr) { @@ -8120,6 +8215,9 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, vty_out(vty, "%-16s", inet_ntoa( attr->mp_nexthop_global_in)); + else if (wide) + vty_out(vty, "%-41s", + inet_ntoa(attr->nexthop)); else vty_out(vty, "%-16s", inet_ntoa(attr->nexthop)); @@ -8132,7 +8230,7 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, inet_ntop(AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); - len = 16 - len; + len = wide ? (41 - len) : (16 - len); if (len < 1) vty_out(vty, "\n%*s", 36, " "); else @@ -8140,7 +8238,12 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p, } if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) - vty_out(vty, "%10u", attr->med); + if (wide) + vty_out(vty, "%7u", attr->med); + else + vty_out(vty, "%10u", attr->med); + else if (wide) + vty_out(vty, " "); else vty_out(vty, " "); @@ -8191,7 +8294,7 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p, /* print prefix and mask */ if (json == NULL) { if (!display) - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, NULL, false); else vty_out(vty, "%*s", 17, " "); } @@ -8288,7 +8391,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, /* print prefix and mask */ if (!display) - route_vty_out_route(p, vty, json_path); + route_vty_out_route(p, vty, json_path, false); else vty_out(vty, "%*s", 17, " "); @@ -8337,15 +8440,6 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, } } - char *str = esi2str(&(attr->evpn_overlay.eth_s_id)); - - if (!json_path) - vty_out(vty, "%s", str); - else - json_object_string_add(json_overlay, "esi", str); - - XFREE(MTYPE_TMP, str); - if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) { inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf, BUFSIZ); @@ -8403,7 +8497,7 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p, /* print prefix and mask */ if (!use_json) { if (!display) - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, NULL, false); else vty_out(vty, "%*s", 17, " "); } @@ -8474,7 +8568,7 @@ static void flap_route_vty_out(struct vty *vty, const struct prefix *p, /* print prefix and mask */ if (!use_json) { if (!display) - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, NULL, false); else vty_out(vty, "%*s", 17, " "); } @@ -8629,6 +8723,10 @@ static const char *bgp_path_selection_reason2str( return "EVPN sequence number"; case bgp_path_selection_evpn_lower_ip: return "EVPN lower IP"; + case bgp_path_selection_evpn_local_path: + return "EVPN local ES path"; + case bgp_path_selection_evpn_non_proxy: + return "EVPN non proxy"; case bgp_path_selection_weight: return "Weight"; case bgp_path_selection_local_pref: @@ -8667,9 +8765,67 @@ static const char *bgp_path_selection_reason2str( return "Invalid (internal error)"; } -void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, - struct bgp_path_info *path, afi_t afi, safi_t safi, - json_object *json_paths) +static void route_vty_out_detail_es_info(struct vty *vty, + struct attr *attr, json_object *json_path) +{ + char esi_buf[ESI_STR_LEN]; + bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL); + bool peer_router = !!CHECK_FLAG(attr->es_flags, + ATTR_ES_PEER_ROUTER); + bool peer_active = !!CHECK_FLAG(attr->es_flags, + ATTR_ES_PEER_ACTIVE); + bool peer_proxy = !!CHECK_FLAG(attr->es_flags, + ATTR_ES_PEER_PROXY); + + esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf)); + if (json_path) { + json_object *json_es_info = NULL; + + json_object_string_add( + json_path, "esi", + esi_buf); + if (es_local || bgp_evpn_attr_is_sync(attr)) { + json_es_info = json_object_new_object(); + if (es_local) + json_object_boolean_true_add( + json_es_info, "localEs"); + if (peer_active) + json_object_boolean_true_add( + json_es_info, "peerActive"); + if (peer_proxy) + json_object_boolean_true_add( + json_es_info, "peerProxy"); + if (peer_router) + json_object_boolean_true_add( + json_es_info, "peerRouter"); + if (attr->mm_sync_seqnum) + json_object_int_add( + json_es_info, "peerSeq", + attr->mm_sync_seqnum); + json_object_object_add( + json_path, "es_info", + json_es_info); + } + } else { + if (bgp_evpn_attr_is_sync(attr)) + vty_out(vty, + " ESI %s %s peer-info: (%s%s%sMM: %d)\n", + esi_buf, + es_local ? "local-es":"", + peer_proxy ? "proxy " : "", + peer_active ? "active ":"", + peer_router ? "router ":"", + attr->mm_sync_seqnum); + else + vty_out(vty, " ESI %s %s\n", + esi_buf, + es_local ? "local-es":""); + } +} + +void route_vty_out_detail(struct vty *vty, struct bgp *bgp, + struct bgp_dest *bn, struct bgp_path_info *path, + afi_t afi, safi_t safi, json_object *json_paths) { char buf[INET6_ADDRSTRLEN]; char buf1[BUFSIZ]; @@ -9139,6 +9295,11 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, "used"); } + if (safi == SAFI_EVPN && + bgp_evpn_is_esi_valid(&attr->esi)) { + route_vty_out_detail_es_info(vty, attr, json_path); + } + /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid, * Int/Ext/Local, Atomic, best */ if (json_paths) @@ -9589,7 +9750,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, void *output_arg, bool use_json, char *rd, int is_last, unsigned long *output_cum, unsigned long *total_cum, - unsigned long *json_header_depth) + unsigned long *json_header_depth, bool wide) { struct bgp_path_info *pi; struct bgp_dest *dest; @@ -9598,7 +9759,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, unsigned long output_count = 0; unsigned long total_count = 0; struct prefix *p; - char buf2[BUFSIZ]; json_object *json_paths = NULL; int first = 1; @@ -9607,8 +9767,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, if (use_json && !*json_header_depth) { vty_out(vty, - "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64 - ",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n" + "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n" " \"localAS\": %u,\n \"routes\": { ", bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id, bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT @@ -9793,8 +9952,7 @@ 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, vrf id ", + vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ", table->version, inet_ntoa(bgp->router_id)); if (bgp->vrf_id == VRF_UNKNOWN) @@ -9815,7 +9973,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, || type == bgp_show_type_flap_neighbor) vty_out(vty, BGP_SHOW_FLAP_HEADER); else - vty_out(vty, BGP_SHOW_HEADER); + vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE + : BGP_SHOW_HEADER)); header = 0; } if (rd != NULL && !display && !output_count) { @@ -9836,7 +9995,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, json_paths); else route_vty_out(vty, dest_p, pi, display, safi, - json_paths); + json_paths, wide); display++; } @@ -9863,11 +10022,10 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, dest_p->u.prefix_flowspec .prefixlen); } else { - prefix2str(dest_p, buf2, sizeof(buf2)); if (first) - vty_out(vty, "\"%s\": ", buf2); + vty_out(vty, "\"%pFX\": ", dest_p); else - vty_out(vty, ",\"%s\": ", buf2); + vty_out(vty, ",\"%pFX\": ", dest_p); } vty_out(vty, "%s", json_object_to_json_string_ext( @@ -9944,7 +10102,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, prefix_rd2str(&prd, rd, sizeof(rd)); bgp_show_table(vty, bgp, safi, itable, type, output_arg, use_json, rd, next == NULL, &output_cum, - &total_cum, &json_header_depth); + &total_cum, &json_header_depth, false); if (next == NULL) show_msg = false; } @@ -9961,7 +10119,8 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, 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, bool use_json) + enum bgp_show_type type, void *output_arg, bool use_json, + bool wide) { struct bgp_table *table; unsigned long json_header_depth = 0; @@ -9995,11 +10154,12 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, safi = SAFI_UNICAST; return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json, - NULL, 1, NULL, NULL, &json_header_depth); + NULL, 1, NULL, NULL, &json_header_depth, wide); } static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, - safi_t safi, bool use_json) + safi_t safi, bool use_json, + bool wide) { struct listnode *node, *nnode; struct bgp *bgp; @@ -10028,7 +10188,7 @@ static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, : bgp->name); } bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL, - use_json); + use_json, wide); } if (use_json) @@ -10515,8 +10675,8 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, return bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_lcommunity_exact - : bgp_show_type_lcommunity), - lcom, uj); + : bgp_show_type_lcommunity), + lcom, uj, false); } static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, @@ -10535,8 +10695,8 @@ static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, return bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_lcommunity_list_exact - : bgp_show_type_lcommunity_list), - list, uj); + : bgp_show_type_lcommunity_list), + list, uj, false); } DEFUN (show_ip_bgp_large_community_list, @@ -10615,9 +10775,11 @@ DEFUN (show_ip_bgp_large_community, exact_match, afi, safi, uj); } else return bgp_show(vty, bgp, afi, safi, - bgp_show_type_lcommunity_all, NULL, uj); + bgp_show_type_lcommunity_all, NULL, uj, false); } +static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, struct json_object *json_array); static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, struct json_object *json); @@ -10637,7 +10799,7 @@ DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd, bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, &bgp, false); - if (!bgp) + if (!idx) return CMD_WARNING; if (uj) @@ -10837,7 +10999,7 @@ DEFUN(show_ip_bgp, show_ip_bgp_cmd, } /* BGP route print out function with JSON */ -DEFUN (show_ip_bgp_json, +DEFPY (show_ip_bgp_json, show_ip_bgp_json_cmd, "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ [cidr-only\ @@ -10847,7 +11009,7 @@ DEFUN (show_ip_bgp_json, |accept-own|accept-own-nexthop|route-filter-v6\ |route-filter-v4|route-filter-translated-v6\ |route-filter-translated-v4] [exact-match]\ - ] [json]", + ] [json$uj | wide$wide]", SHOW_STR IP_STR BGP_STR @@ -10875,7 +11037,8 @@ DEFUN (show_ip_bgp_json, "RT translated VPNv6 route filtering (well-known community)\n" "RT translated VPNv4 route filtering (well-known community)\n" "Exact match of the communities\n" - JSON_STR) + JSON_STR + "Increase table width for longer prefixes\n") { afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; @@ -10883,7 +11046,6 @@ DEFUN (show_ip_bgp_json, struct bgp *bgp = NULL; int idx = 0; int exact_match = 0; - bool uj = use_json(argc, argv); if (uj) argc--; @@ -10895,16 +11057,17 @@ DEFUN (show_ip_bgp_json, if (argv_find(argv, argc, "cidr-only", &idx)) return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only, - NULL, uj); + NULL, uj, wide); if (argv_find(argv, argc, "dampening", &idx)) { if (argv_find(argv, argc, "dampened-paths", &idx)) return bgp_show(vty, bgp, afi, safi, - bgp_show_type_dampend_paths, NULL, uj); + bgp_show_type_dampend_paths, NULL, uj, + wide); else if (argv_find(argv, argc, "flap-statistics", &idx)) return bgp_show(vty, bgp, afi, safi, - bgp_show_type_flap_statistics, NULL, - uj); + bgp_show_type_flap_statistics, NULL, uj, + wide); } if (argv_find(argv, argc, "community", &idx)) { @@ -10930,17 +11093,16 @@ DEFUN (show_ip_bgp_json, exact_match, afi, safi, uj); else return (bgp_show(vty, bgp, afi, safi, - bgp_show_type_community_all, NULL, - uj)); + bgp_show_type_community_all, NULL, uj, + wide)); } - return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj); + return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj, wide); } DEFUN (show_ip_bgp_route, show_ip_bgp_route_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]" - "<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]<A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [<bestpath|multipath>] [json]", SHOW_STR IP_STR BGP_STR @@ -11046,22 +11208,22 @@ DEFUN (show_ip_bgp_regexp, bgp_show_type_regexp, uj); } -DEFUN (show_ip_bgp_instance_all, +DEFPY (show_ip_bgp_instance_all, show_ip_bgp_instance_all_cmd, - "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json]", + "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_ALL_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_WITH_LABEL_HELP_STR - JSON_STR) + JSON_STR + "Increase table width for longer prefixes\n") { afi_t afi = AFI_IP; safi_t safi = SAFI_UNICAST; struct bgp *bgp = NULL; int idx = 0; - bool uj = use_json(argc, argv); if (uj) argc--; @@ -11071,7 +11233,7 @@ DEFUN (show_ip_bgp_instance_all, if (!idx) return CMD_WARNING; - bgp_show_all_instances_routes_vty(vty, afi, safi, uj); + bgp_show_all_instances_routes_vty(vty, afi, safi, uj, wide); return CMD_SUCCESS; } @@ -11094,7 +11256,7 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr, return CMD_WARNING; } - rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json); + rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json, false); bgp_regex_free(regex); return rc; } @@ -11112,7 +11274,7 @@ static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp, return CMD_WARNING; } - return bgp_show(vty, bgp, afi, safi, type, plist, 0); + return bgp_show(vty, bgp, afi, safi, type, plist, 0, false); } static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp, @@ -11128,7 +11290,7 @@ static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp, return CMD_WARNING; } - return bgp_show(vty, bgp, afi, safi, type, as_list, 0); + return bgp_show(vty, bgp, afi, safi, type, as_list, 0, false); } static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, @@ -11143,7 +11305,7 @@ static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, return CMD_WARNING; } - return bgp_show(vty, bgp, afi, safi, type, rmap, 0); + return bgp_show(vty, bgp, afi, safi, type, rmap, 0, false); } static int bgp_show_community(struct vty *vty, struct bgp *bgp, @@ -11162,7 +11324,7 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp, ret = bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_community_exact : bgp_show_type_community), - com, use_json); + com, use_json, false); community_free(&com); return ret; @@ -11183,7 +11345,7 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, return bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_community_list_exact : bgp_show_type_community_list), - list, 0); + list, 0, false); } static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, @@ -11201,7 +11363,7 @@ static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, return CMD_WARNING; } - ret = bgp_show(vty, bgp, afi, safi, type, p, 0); + ret = bgp_show(vty, bgp, afi, safi, type, p, 0, false); prefix_free(&p); return ret; } @@ -11396,8 +11558,18 @@ static int bgp_table_stats_walker(struct thread *t) return 0; } -static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, struct json_object *json_array) +static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi, + struct json_object *json_array) +{ + struct listnode *node, *nnode; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) + bgp_table_stats_single(vty, bgp, afi, safi, json_array); +} + +static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, struct json_object *json_array) { struct bgp_table_stats ts; unsigned int i; @@ -11425,8 +11597,10 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, } if (!json) - vty_out(vty, "BGP %s RIB statistics\n", - get_afi_safi_str(afi, safi, false)); + vty_out(vty, "BGP %s RIB statistics (%s)\n", + get_afi_safi_str(afi, safi, false), bgp->name_pretty); + else + json_object_string_add(json, "instance", bgp->name_pretty); /* labeled-unicast routes live in the unicast table */ if (safi == SAFI_LABELED_UNICAST) @@ -11615,6 +11789,17 @@ end_table_stats: return ret; } +static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, struct json_object *json_array) +{ + if (!bgp) { + bgp_table_stats_all(vty, afi, safi, json_array); + return CMD_SUCCESS; + } + + return bgp_table_stats_single(vty, bgp, afi, safi, json_array); +} + enum bgp_pcounts { PCOUNT_ADJ_IN = 0, PCOUNT_DAMPED, @@ -11624,6 +11809,7 @@ enum bgp_pcounts { PCOUNT_VALID, PCOUNT_ALL, PCOUNT_COUNTED, + PCOUNT_BPATH_SELECTED, PCOUNT_PFCNT, /* the figure we display to users */ PCOUNT_MAX, }; @@ -11637,6 +11823,7 @@ static const char *const pcount_strs[] = { [PCOUNT_VALID] = "Valid", [PCOUNT_ALL] = "All RIB", [PCOUNT_COUNTED] = "PfxCt counted", + [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected", [PCOUNT_PFCNT] = "Useable", [PCOUNT_MAX] = NULL, }; @@ -11677,6 +11864,8 @@ static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc) pc->count[PCOUNT_VALID]++; if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) pc->count[PCOUNT_PFCNT]++; + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) + pc->count[PCOUNT_BPATH_SELECTED]++; if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) { pc->count[PCOUNT_COUNTED]++; @@ -11790,7 +11979,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, get_afi_safi_str(afi, safi, false)); } - vty_out(vty, "PfxCt: %" PRIu32 "\n", peer->pcount[afi][safi]); + vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]); vty_out(vty, "\nCounts from RIB table walk:\n\n"); for (i = 0; i < PCOUNT_MAX; i++) @@ -11809,8 +11998,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, DEFUN (show_ip_bgp_instance_neighbor_prefix_counts, show_ip_bgp_instance_neighbor_prefix_counts_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] " - "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]", SHOW_STR IP_STR BGP_STR @@ -11941,10 +12129,56 @@ DEFUN (show_bgp_l2vpn_evpn_route_prefix, use_json(argc, argv)); } +static void show_adj_route_header(struct vty *vty, struct bgp *bgp, + struct bgp_table *table, int *header1, + int *header2, json_object *json, + json_object *json_scode, + json_object *json_ocode, bool wide) +{ + uint64_t version = table ? table->version : 0; + + if (*header1) { + if (json) { + json_object_int_add(json, "bgpTableVersion", version); + 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); + json_object_object_add(json, "bgpOriginCodes", + json_ocode); + } else { + vty_out(vty, + "BGP table version is %" PRIu64 ", local router ID is %s, vrf id ", + 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, "Default local pref %u, ", + bgp->default_local_pref); + vty_out(vty, "local AS %u\n", bgp->as); + vty_out(vty, BGP_SHOW_SCODE_HEADER); + vty_out(vty, BGP_SHOW_NCODE_HEADER); + vty_out(vty, BGP_SHOW_OCODE_HEADER); + } + *header1 = 0; + } + if (*header2) { + if (!json) + vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE + : BGP_SHOW_HEADER)); + *header2 = 0; + } +} + static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, const char *rmap_name, bool use_json, - json_object *json) + json_object *json, bool wide) { struct bgp_table *table; struct bgp_adj_in *ain; @@ -12024,8 +12258,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, json, "bgpOriginatingDefaultNetwork", (afi == AFI_IP) ? "0.0.0.0/0" : "::/0"); } else { - vty_out(vty, "BGP table version is %" PRIu64 - ", local router ID is %s, vrf id ", + vty_out(vty, "BGP table version is %" PRIu64", 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); @@ -12052,58 +12285,9 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, if (ain->peer != peer) continue; - if (header1) { - if (use_json) { - json_object_int_add( - json, "bgpTableVersion", - 0); - 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); - json_object_object_add( - json, "bgpOriginCodes", - json_ocode); - } else { - vty_out(vty, - "BGP table version is 0, local router ID is %s, vrf id ", - 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, - "Default local pref %u, ", - bgp->default_local_pref); - vty_out(vty, "local AS %u\n", - bgp->as); - vty_out(vty, - BGP_SHOW_SCODE_HEADER); - vty_out(vty, - BGP_SHOW_NCODE_HEADER); - vty_out(vty, - BGP_SHOW_OCODE_HEADER); - } - header1 = 0; - } - if (header2) { - if (!use_json) - vty_out(vty, BGP_SHOW_HEADER); - header2 = 0; - } + show_adj_route_header( + vty, bgp, table, &header1, &header2, + json, json_scode, json_ocode, wide); attr = *ain->attr; route_filtered = false; @@ -12134,7 +12318,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, filtered_count++; route_vty_out_tmp(vty, rn_p, &attr, safi, - use_json, json_ar); + use_json, json_ar, wide); bgp_attr_undup(&attr, ain->attr); output_count++; } @@ -12144,71 +12328,10 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, if (paf->peer != peer || !adj->attr) continue; - if (header1) { - if (use_json) { - json_object_int_add( - json, - "bgpTableVersion", - table->version); - 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); - json_object_object_add( - json, - "bgpOriginCodes", - json_ocode); - } else { - vty_out(vty, - "BGP table version is %" PRIu64 - ", 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, - "Default local pref %u, ", - bgp->default_local_pref - ); - vty_out(vty, - "local AS %u\n", - bgp->as); - vty_out(vty, - BGP_SHOW_SCODE_HEADER); - vty_out(vty, - BGP_SHOW_NCODE_HEADER); - vty_out(vty, - BGP_SHOW_OCODE_HEADER); - } - header1 = 0; - } - if (header2) { - if (!use_json) - vty_out(vty, - BGP_SHOW_HEADER); - header2 = 0; - } + show_adj_route_header( + vty, bgp, table, &header1, + &header2, json, json_scode, + json_ocode, wide); const struct prefix *rn_p = bgp_dest_get_prefix(dest); @@ -12221,7 +12344,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, if (ret != RMAP_DENY) { route_vty_out_tmp( vty, rn_p, &attr, safi, - use_json, json_ar); + use_json, json_ar, + wide); output_count++; } else { filtered_count++; @@ -12229,6 +12353,27 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, bgp_attr_undup(&attr, adj->attr); } + } else if (type == bgp_show_adj_route_bestpath) { + struct bgp_path_info *pi; + + show_adj_route_header(vty, bgp, table, &header1, + &header2, json, json_scode, + json_ocode, wide); + + for (pi = bgp_dest_get_bgp_path_info(dest); pi; + pi = pi->next) { + if (pi->peer != peer) + continue; + + if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) + continue; + + route_vty_out_tmp(vty, + bgp_dest_get_prefix(dest), + pi->attr, safi, use_json, + json_ar, wide); + output_count++; + } } } @@ -12260,7 +12405,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, - const char *rmap_name, bool use_json) + const char *rmap_name, bool use_json, bool wide) { json_object *json = NULL; @@ -12297,15 +12442,57 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi, return CMD_WARNING; } - show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json); + show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json, + wide); return CMD_SUCCESS; } -DEFUN (show_ip_bgp_instance_neighbor_advertised_route, +DEFPY (show_ip_bgp_instance_neighbor_bestpath_route, + show_ip_bgp_instance_neighbor_bestpath_route_cmd, + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [json$uj | wide$wide]", + SHOW_STR + IP_STR + BGP_STR + BGP_INSTANCE_HELP_STR + BGP_AFI_HELP_STR + BGP_SAFI_WITH_LABEL_HELP_STR + "Detailed information on TCP and BGP neighbor connections\n" + "Neighbor to display information about\n" + "Neighbor to display information about\n" + "Neighbor on BGP configured interface\n" + "Display the routes selected by best path\n" + JSON_STR + "Increase table width for longer prefixes\n") +{ + afi_t afi = AFI_IP6; + safi_t safi = SAFI_UNICAST; + char *rmap_name = NULL; + char *peerstr = NULL; + struct bgp *bgp = NULL; + struct peer *peer; + enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath; + int idx = 0; + + bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi, + &bgp, uj); + + if (!idx) + return CMD_WARNING; + + argv_find(argv, argc, "neighbors", &idx); + peerstr = argv[++idx]->arg; + + peer = peer_lookup_in_view(vty, bgp, peerstr, uj); + if (!peer) + return CMD_WARNING; + + return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj, wide); +} + +DEFPY (show_ip_bgp_instance_neighbor_advertised_route, show_ip_bgp_instance_neighbor_advertised_route_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] " - "neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]", SHOW_STR IP_STR BGP_STR @@ -12321,7 +12508,8 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, "Display the filtered routes received from neighbor\n" "Route-map to modify the attributes\n" "Name of the route map\n" - JSON_STR) + JSON_STR + "Increase table width for longer prefixes\n") { afi_t afi = AFI_IP6; safi_t safi = SAFI_UNICAST; @@ -12331,7 +12519,6 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, struct peer *peer; enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised; int idx = 0; - bool uj = use_json(argc, argv); if (uj) argc--; @@ -12359,7 +12546,7 @@ DEFUN (show_ip_bgp_instance_neighbor_advertised_route, if (argv_find(argv, argc, "route-map", &idx)) rmap_name = argv[++idx]->arg; - return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj); + return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj, wide); } DEFUN (show_ip_bgp_neighbor_received_prefix_filter, @@ -12467,7 +12654,8 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer, return CMD_WARNING; } - return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json); + return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json, + false); } DEFUN (show_ip_bgp_flowspec_routes_detailed, @@ -12496,13 +12684,13 @@ DEFUN (show_ip_bgp_flowspec_routes_detailed, if (!idx) return CMD_WARNING; - return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj); + return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj, + false); } DEFUN (show_ip_bgp_neighbor_routes, show_ip_bgp_neighbor_routes_cmd, - "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] " - "neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]", + "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> <flap-statistics|dampened-routes|routes> [json]", SHOW_STR IP_STR BGP_STR @@ -13286,6 +13474,7 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, char buf[PREFIX_STRLEN * 2]; char buf2[SU_ADDRSTRLEN]; char rdbuf[RD_ADDRSTRLEN]; + char esi_buf[ESI_BYTES]; /* Network configuration. */ for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest; @@ -13301,13 +13490,13 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, continue; char *macrouter = NULL; - char *esi = NULL; if (bgp_static->router_mac) macrouter = prefix_mac2str( bgp_static->router_mac, NULL, 0); if (bgp_static->eth_s_id) - esi = esi2str(bgp_static->eth_s_id); + esi_to_str(bgp_static->eth_s_id, + esi_buf, sizeof(esi_buf)); p = bgp_dest_get_prefix(dest); prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest); @@ -13338,11 +13527,10 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n", buf, rdbuf, p->u.prefix_evpn.prefix_addr.eth_tag, - decode_label(&bgp_static->label), esi, buf2, + decode_label(&bgp_static->label), esi_buf, buf2, macrouter); XFREE(MTYPE_TMP, macrouter); - XFREE(MTYPE_TMP, esi); } } } @@ -13511,6 +13699,8 @@ void bgp_route_init(void) install_element(VIEW_NODE, &show_ip_bgp_instance_neighbor_advertised_route_cmd); + install_element(VIEW_NODE, + &show_ip_bgp_instance_neighbor_bestpath_route_cmd); install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd); install_element(VIEW_NODE, &show_ip_bgp_neighbor_received_prefix_filter_cmd); |
