summaryrefslogtreecommitdiff
path: root/bgpd/bgp_route.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_route.c')
-rw-r--r--bgpd/bgp_route.c780
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);