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.c601
1 files changed, 407 insertions, 194 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 87e03d205f..f9e655b4e7 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -93,10 +93,14 @@
#include "bgpd/bgp_route_clippy.c"
#endif
+DEFINE_HOOK(bgp_snmp_update_stats,
+ (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
+ (rn, pi, added))
+
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
-const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
+
/* PMSI strings. */
#define PMSI_TNLTYPE_STR_NO_INFO "No info"
#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
@@ -208,9 +212,6 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
return;
e = *extra;
- if (e->damp_info)
- bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
- e->damp_info->safi);
e->damp_info = NULL;
if (e->parent) {
@@ -405,6 +406,7 @@ void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
bgp_dest_lock_node(dest);
peer_lock(pi->peer); /* bgp_path_info peer reference */
bgp_dest_set_defer_flag(dest, false);
+ hook_call(bgp_snmp_update_stats, dest, pi, true);
}
/* Do the actual removal of info from RIB, for use by bgp_process
@@ -420,6 +422,7 @@ void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
bgp_path_info_mpath_dequeue(pi);
bgp_path_info_unlock(pi);
+ hook_call(bgp_snmp_update_stats, dest, pi, false);
bgp_dest_unlock_node(dest);
}
@@ -1839,7 +1842,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* If community is not disabled check the no-export and local. */
if (!transparent && bgp_community_filter(peer, piattr)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
- zlog_debug("%s: community filter check fail", __func__);
+ zlog_debug("%s: community filter check fail for %pFX",
+ __func__, p);
return false;
}
@@ -2755,7 +2759,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
== BGP_ROUTE_REDISTRIBUTE) {
if (CHECK_FLAG(
dest->flags,
- BGP_NODE_REGISTERED_FOR_LABEL))
+ BGP_NODE_REGISTERED_FOR_LABEL)
+ || CHECK_FLAG(
+ dest->flags,
+ BGP_NODE_LABEL_REQUESTED))
bgp_unregister_for_label(dest);
label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
&dest->local_label);
@@ -2765,10 +2772,13 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
new_select);
}
} else if (CHECK_FLAG(dest->flags,
- BGP_NODE_REGISTERED_FOR_LABEL)) {
+ BGP_NODE_REGISTERED_FOR_LABEL)
+ || CHECK_FLAG(dest->flags,
+ BGP_NODE_LABEL_REQUESTED)) {
bgp_unregister_for_label(dest);
}
- } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
+ } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
+ || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
bgp_unregister_for_label(dest);
}
@@ -3325,14 +3335,16 @@ static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
/* apply dampening, if result is suppressed, we'll be retaining
* the bgp_path_info in the RIB for historical reference.
*/
- if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP)
- if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
- == BGP_DAMP_SUPPRESSED) {
- bgp_aggregate_decrement(peer->bgp, p, pi, afi,
- safi);
- return;
+ if (peer->sort == BGP_PEER_EBGP) {
+ if (get_active_bdc_from_pi(pi, afi, safi)) {
+ if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
+ == BGP_DAMP_SUPPRESSED) {
+ bgp_aggregate_decrement(peer->bgp, p, pi, afi,
+ safi);
+ return;
+ }
}
+ }
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) {
@@ -3500,6 +3512,36 @@ bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
return ret;
}
+static void bgp_attr_add_no_export_community(struct attr *attr)
+{
+ struct community *old;
+ struct community *new;
+ struct community *merge;
+ struct community *no_export;
+
+ old = attr->community;
+ no_export = community_str2com("no-export");
+
+ assert(no_export);
+
+ if (old) {
+ merge = community_merge(community_dup(old), no_export);
+
+ if (!old->refcnt)
+ community_free(&old);
+
+ new = community_uniq_sort(merge);
+ community_free(&merge);
+ } else {
+ new = community_dup(no_export);
+ }
+
+ community_free(&no_export);
+
+ attr->community = new;
+ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
+}
+
int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct attr *attr, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd, mpls_label_t *label,
@@ -3692,6 +3734,20 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (peer->sort == BGP_PEER_EBGP) {
+ /* rfc7999:
+ * A BGP speaker receiving an announcement tagged with the
+ * BLACKHOLE community SHOULD add the NO_ADVERTISE or
+ * NO_EXPORT community as defined in RFC1997, or a
+ * similar community, to prevent propagation of the
+ * prefix outside the local AS. The community to prevent
+ * propagation SHOULD be chosen according to the operator's
+ * routing policy.
+ */
+ if (new_attr.community
+ && community_include(new_attr.community,
+ COMMUNITY_BLACKHOLE))
+ bgp_attr_add_no_export_community(&new_attr);
+
/* If we receive the graceful-shutdown community from an eBGP
* peer we must lower local-preference */
if (new_attr.community
@@ -3749,7 +3805,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Same attribute comes in. */
if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
- && attrhash_cmp(pi->attr, attr_new)
+ && same_attr
&& (!has_valid_label
|| memcmp(&(bgp_path_info_extra_get(pi))->label, label,
num_labels * sizeof(mpls_label_t))
@@ -3757,8 +3813,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
&& (overlay_index_equal(
afi, pi,
evpn == NULL ? NULL : &evpn->gw_ip))) {
- if (CHECK_FLAG(bgp->af_flags[afi][safi],
- BGP_CONFIG_DAMPENING)
+ if (get_active_bdc_from_pi(pi, afi, safi)
&& peer->sort == BGP_PEER_EBGP
&& CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
if (bgp_debug_update(peer, p, NULL, 1)) {
@@ -3852,11 +3907,11 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
/* Update bgp route dampening information. */
- if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
+ if (get_active_bdc_from_pi(pi, afi, safi)
&& peer->sort == BGP_PEER_EBGP) {
/* This is implicit withdraw so we should update
- dampening
- information. */
+ * dampening information.
+ */
if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
bgp_damp_withdraw(pi, dest, afi, safi, 1);
}
@@ -3979,7 +4034,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
#endif
/* Update bgp route dampening information. */
- if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
+ if (get_active_bdc_from_pi(pi, afi, safi)
&& peer->sort == BGP_PEER_EBGP) {
/* Now we do normal update dampening. */
ret = bgp_damp_update(pi, dest, afi, safi);
@@ -4013,7 +4068,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
- pi, NULL, connected)
+ safi, pi, NULL, connected)
|| CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
bgp_path_info_set_flag(dest, pi,
BGP_PATH_VALID);
@@ -4158,7 +4213,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
- if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
+ if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
connected)
|| CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
@@ -4595,8 +4650,10 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
continue;
/* graceful restart STALE flag set. */
- if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
- && peer->nsf[afi][safi]
+ if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
+ && peer->nsf[afi][safi])
+ || CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_ENHANCED_REFRESH))
&& !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
&& !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
@@ -4847,7 +4904,7 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
struct bgp_path_info *pi;
struct bgp_table *table;
- if (safi == SAFI_MPLS_VPN) {
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
dest = bgp_route_next(dest)) {
struct bgp_dest *rm;
@@ -4886,6 +4943,81 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
}
}
+void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
+{
+ struct bgp_dest *dest, *ndest;
+ struct bgp_path_info *pi;
+ struct bgp_table *table;
+
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
+ for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
+ dest = bgp_route_next(dest)) {
+ table = bgp_dest_get_bgp_table_info(dest);
+ if (!table)
+ continue;
+
+ for (ndest = bgp_table_top(table); ndest;
+ ndest = bgp_route_next(ndest)) {
+ for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
+ pi = pi->next) {
+ if (pi->peer != peer)
+ continue;
+
+ if ((CHECK_FLAG(
+ peer->af_sflags[afi][safi],
+ PEER_STATUS_ENHANCED_REFRESH))
+ && !CHECK_FLAG(pi->flags,
+ BGP_PATH_STALE)
+ && !CHECK_FLAG(
+ pi->flags,
+ BGP_PATH_UNUSEABLE)) {
+ if (bgp_debug_neighbor_events(
+ peer))
+ zlog_debug(
+ "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
+ peer->host,
+ afi2str(afi),
+ safi2str(safi),
+ bgp_dest_get_prefix(
+ ndest));
+
+ bgp_path_info_set_flag(
+ ndest, pi,
+ BGP_PATH_STALE);
+ }
+ }
+ }
+ }
+ } else {
+ for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
+ dest = bgp_route_next(dest)) {
+ for (pi = bgp_dest_get_bgp_path_info(dest); pi;
+ pi = pi->next) {
+ if (pi->peer != peer)
+ continue;
+
+ if ((CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_ENHANCED_REFRESH))
+ && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
+ && !CHECK_FLAG(pi->flags,
+ BGP_PATH_UNUSEABLE)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
+ peer->host,
+ afi2str(afi),
+ safi2str(safi),
+ bgp_dest_get_prefix(
+ dest));
+
+ bgp_path_info_set_flag(dest, pi,
+ BGP_PATH_STALE);
+ }
+ }
+ }
+ }
+}
+
bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
if (peer->sort == BGP_PEER_IBGP)
@@ -5319,7 +5451,8 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp_nexthop = pi->extra->bgp_orig;
if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
- afi, pi, NULL, 0))
+ afi, safi, pi, NULL,
+ 0))
bgp_path_info_set_flag(dest, pi,
BGP_PATH_VALID);
else {
@@ -5371,7 +5504,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
/* Nexthop reachability check. */
if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
&& (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
- if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
+ if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
else {
if (BGP_DEBUG(nht, NHT)) {
@@ -6576,6 +6709,9 @@ static void bgp_aggregate_install(
if (!attr) {
bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
+ if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
+ zlog_debug("%s: %pFX null attribute", __func__,
+ p);
return;
}
@@ -7094,6 +7230,13 @@ static void bgp_add_route_to_aggregate(struct bgp *bgp,
struct ecommunity *ecommunity = NULL;
struct lcommunity *lcommunity = NULL;
+ /* If the bgp instance is being deleted or self peer is deleted
+ * then do not create aggregate route
+ */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
+ || (bgp->peer_self == NULL))
+ return;
+
/* ORIGIN attribute: If at least one route among routes that are
* aggregated has ORIGIN with the value INCOMPLETE, then the
* aggregated route must have the ORIGIN attribute with the value
@@ -7210,6 +7353,13 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
struct lcommunity *lcommunity = NULL;
unsigned long match = 0;
+ /* If the bgp instance is being deleted or self peer is deleted
+ * then do not create aggregate route
+ */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
+ || (bgp->peer_self == NULL))
+ return;
+
if (BGP_PATH_HOLDDOWN(pi))
return;
@@ -7406,6 +7556,13 @@ int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
struct bgp_dest *dest;
struct bgp_aggregate *aggregate;
+ /* If the bgp instance is being deleted or self peer is deleted
+ * then do not create aggregate route
+ */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
+ || (bgp->peer_self == NULL))
+ return 0;
+
apply_mask(prefix);
/* Old configuration check. */
dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
@@ -8115,7 +8272,7 @@ bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
case bgp_path_selection_router_id:
return "Router ID";
case bgp_path_selection_cluster_length:
- return "Cluser length";
+ return "Cluster length";
case bgp_path_selection_stale:
return "Path Staleness";
case bgp_path_selection_local_configured:
@@ -9508,22 +9665,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
inet_ntop(AF_INET,
&attr->aggregator_addr,
buf, sizeof(buf)));
- if (attr->aggregator_as == BGP_AS_ZERO)
- json_object_boolean_true_add(
- json_path, "aggregatorAsMalformed");
- else
- json_object_boolean_false_add(
- json_path, "aggregatorAsMalformed");
} else {
- if (attr->aggregator_as == BGP_AS_ZERO)
- vty_out(vty,
- ", (aggregated by %u(malformed) %pI4)",
- attr->aggregator_as,
- &attr->aggregator_addr);
- else
- vty_out(vty, ", (aggregated by %u %pI4)",
- attr->aggregator_as,
- &attr->aggregator_addr);
+ vty_out(vty, ", (aggregated by %u %pI4)",
+ attr->aggregator_as, &attr->aggregator_addr);
}
}
@@ -10129,7 +10273,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
}
if (path->extra && path->extra->damp_info)
- bgp_damp_info_vty(vty, path, afi, safi, json_path);
+ bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
/* Remote Label */
if (path->extra && bgp_is_valid_label(&path->extra->label[0])
@@ -10261,6 +10405,24 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
str, label2vni(&attr->label));
}
+ /* Output some debug about internal state of the dest flags */
+ if (json_paths) {
+ if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
+ json_object_boolean_true_add(json_path, "processScheduled");
+ if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
+ json_object_boolean_true_add(json_path, "userCleared");
+ if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
+ json_object_boolean_true_add(json_path, "labelChanged");
+ if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
+ json_object_boolean_true_add(json_path, "registeredForLabel");
+ if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
+ json_object_boolean_true_add(json_path, "selectDefered");
+ if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
+ json_object_boolean_true_add(json_path, "fibInstalled");
+ if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
+ json_object_boolean_true_add(json_path, "fibPending");
+ }
+
/* We've constructed the json object for this path, add it to the json
* array of paths
*/
@@ -11163,8 +11325,13 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
vty,
use_json,
json_paths);
- if (use_json && display)
- json_object_object_add(json, "paths", json_paths);
+ if (use_json) {
+ if (display)
+ json_object_object_add(json, "paths",
+ json_paths);
+ else
+ json_object_free(json_paths);
+ }
} else {
if ((dest = bgp_node_match(rib, &match)) != NULL) {
const struct prefix *dest_p = bgp_dest_get_prefix(dest);
@@ -11739,10 +11906,6 @@ DEFPY (show_ip_bgp_json,
? AFI_IP
: AFI_IP6;
FOREACH_SAFI (safi) {
- if (strmatch(get_afi_safi_str(afi, safi, true),
- "Unknown"))
- continue;
-
if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
continue;
@@ -11773,10 +11936,6 @@ DEFPY (show_ip_bgp_json,
} else {
/* show <ip> bgp all: for each AFI and SAFI*/
FOREACH_AFI_SAFI (afi, safi) {
- if (strmatch(get_afi_safi_str(afi, safi, true),
- "Unknown"))
- continue;
-
if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
continue;
@@ -12148,22 +12307,6 @@ struct bgp_table_stats {
double total_space;
};
-#if 0
-#define TALLY_SIGFIG 100000
-static unsigned long
-ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
-{
- unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
- unsigned long res = (newtot * TALLY_SIGFIG) / count;
- unsigned long ret = newtot / count;
-
- if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
- return ret + 1;
- else
- return ret;
-}
-#endif
-
static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
struct bgp_table_stats *ts, unsigned int space)
{
@@ -12178,13 +12321,6 @@ static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
ts->counts[BGP_STATS_PREFIXES]++;
ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
-#if 0
- ts->counts[BGP_STATS_AVGPLEN]
- = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
- ts->counts[BGP_STATS_AVGPLEN],
- rn_p->prefixlen);
-#endif
-
/* check if the prefix is included by any other announcements */
while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
pdest = bgp_dest_parent_nolock(pdest);
@@ -12221,16 +12357,6 @@ static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
-#if 0
- ts->counts[BGP_STATS_ASPATH_AVGHOPS]
- = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
- ts->counts[BGP_STATS_ASPATH_AVGHOPS],
- hops);
- ts->counts[BGP_STATS_ASPATH_AVGSIZE]
- = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
- ts->counts[BGP_STATS_ASPATH_AVGSIZE],
- size);
-#endif
if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
}
@@ -12340,15 +12466,6 @@ static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
continue;
switch (i) {
-#if 0
- case BGP_STATS_ASPATH_AVGHOPS:
- case BGP_STATS_ASPATH_AVGSIZE:
- case BGP_STATS_AVGPLEN:
- vty_out (vty, "%-30s: ", table_stats_strs[i]);
- vty_out (vty, "%12.2f",
- (float)ts.counts[i] / (float)TALLY_SIGFIG);
- break;
-#endif
case BGP_STATS_ASPATH_TOTHOPS:
case BGP_STATS_ASPATH_TOTSIZE:
if (!json) {
@@ -12651,6 +12768,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
"No such neighbor or address family");
vty_out(vty, "%s\n", json_object_to_json_string(json));
json_object_free(json);
+ json_object_free(json_loop);
} else
vty_out(vty, "%% No such neighbor or address family\n");
@@ -12903,51 +13021,29 @@ static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
}
}
-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, json_object *json,
- uint8_t show_flags)
+static void
+show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
+ afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
+ const char *rmap_name, json_object *json, json_object *json_ar,
+ json_object *json_scode, json_object *json_ocode,
+ uint8_t show_flags, int *header1, int *header2, char *rd_str,
+ unsigned long *output_count, unsigned long *filtered_count)
{
- struct bgp_table *table;
struct bgp_adj_in *ain;
struct bgp_adj_out *adj;
- unsigned long output_count = 0;
- unsigned long filtered_count = 0;
struct bgp_dest *dest;
- int header1 = 1;
struct bgp *bgp;
- int header2 = 1;
struct attr attr;
int ret;
struct update_subgroup *subgrp;
- json_object *json_scode = NULL;
- json_object *json_ocode = NULL;
- json_object *json_ar = NULL;
struct peer_af *paf;
bool route_filtered;
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
-
- if (use_json) {
- json_scode = json_object_new_object();
- json_ocode = json_object_new_object();
- json_ar = json_object_new_object();
-
- json_object_string_add(json_scode, "suppressed", "s");
- json_object_string_add(json_scode, "damped", "d");
- json_object_string_add(json_scode, "history", "h");
- json_object_string_add(json_scode, "valid", "*");
- json_object_string_add(json_scode, "best", ">");
- json_object_string_add(json_scode, "multipath", "=");
- json_object_string_add(json_scode, "internal", "i");
- json_object_string_add(json_scode, "ribFailure", "r");
- json_object_string_add(json_scode, "stale", "S");
- json_object_string_add(json_scode, "removed", "R");
-
- json_object_string_add(json_ocode, "igp", "i");
- json_object_string_add(json_ocode, "egp", "e");
- json_object_string_add(json_ocode, "incomplete", "?");
- }
+ bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
+ || (safi == SAFI_EVPN))
+ ? true
+ : false;
bgp = peer->bgp;
@@ -12961,13 +13057,6 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
return;
}
- /* labeled-unicast routes live in the unicast table */
- if (safi == SAFI_LABELED_UNICAST)
- table = bgp->rib[afi][SAFI_UNICAST];
- else
- table = bgp->rib[afi][safi];
-
- output_count = filtered_count = 0;
subgrp = peer_subgroup(peer, afi, safi);
if (type == bgp_show_adj_route_advertised && subgrp
@@ -13011,7 +13100,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
vty_out(vty, "Originating default network %s\n\n",
(afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
}
- header1 = 0;
+ *header1 = 0;
}
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
@@ -13021,9 +13110,23 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
if (ain->peer != peer)
continue;
- show_adj_route_header(
- vty, bgp, table, &header1, &header2,
- json, json_scode, json_ocode, wide);
+ show_adj_route_header(vty, bgp, table, header1,
+ header2, json, json_scode,
+ json_ocode, wide);
+
+ if ((safi == SAFI_MPLS_VPN)
+ || (safi == SAFI_ENCAP)
+ || (safi == SAFI_EVPN)) {
+ if (use_json)
+ json_object_string_add(
+ json_ar, "rd", rd_str);
+ else if (show_rd && rd_str) {
+ vty_out(vty,
+ "Route Distinguisher: %s\n",
+ rd_str);
+ show_rd = false;
+ }
+ }
attr = *ain->attr;
route_filtered = false;
@@ -13049,14 +13152,14 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
continue;
}
- if (type == bgp_show_adj_route_received &&
- (route_filtered || ret == RMAP_DENY))
- filtered_count++;
+ if (type == bgp_show_adj_route_received
+ && (route_filtered || ret == RMAP_DENY))
+ (*filtered_count)++;
route_vty_out_tmp(vty, rn_p, &attr, safi,
use_json, json_ar, wide);
bgp_attr_undup(&attr, ain->attr);
- output_count++;
+ (*output_count)++;
}
} else if (type == bgp_show_adj_route_advertised) {
RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
@@ -13064,10 +13167,10 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
if (paf->peer != peer || !adj->attr)
continue;
- show_adj_route_header(
- vty, bgp, table, &header1,
- &header2, json, json_scode,
- json_ocode, wide);
+ 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);
@@ -13078,13 +13181,29 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
rmap_name);
if (ret != RMAP_DENY) {
+ if ((safi == SAFI_MPLS_VPN)
+ || (safi == SAFI_ENCAP)
+ || (safi == SAFI_EVPN)) {
+ if (use_json)
+ json_object_string_add(
+ json_ar,
+ "rd",
+ rd_str);
+ else if (show_rd
+ && rd_str) {
+ vty_out(vty,
+ "Route Distinguisher: %s\n",
+ rd_str);
+ show_rd = false;
+ }
+ }
route_vty_out_tmp(
vty, rn_p, &attr, safi,
use_json, json_ar,
wide);
- output_count++;
+ (*output_count)++;
} else {
- filtered_count++;
+ (*filtered_count)++;
}
bgp_attr_undup(&attr, adj->attr);
@@ -13092,9 +13211,9 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
} 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);
+ 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) {
@@ -13108,46 +13227,67 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
bgp_dest_get_prefix(dest),
pi->attr, safi, use_json,
json_ar, wide);
- output_count++;
+ (*output_count)++;
}
}
}
-
- if (use_json) {
- json_object_object_add(json, "advertisedRoutes", json_ar);
- json_object_int_add(json, "totalPrefixCounter", output_count);
- json_object_int_add(json, "filteredPrefixCounter",
- filtered_count);
-
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
-
- if (!output_count && !filtered_count) {
- json_object_free(json_scode);
- json_object_free(json_ocode);
- }
-
- json_object_free(json);
- } else if (output_count > 0) {
- if (filtered_count > 0)
- vty_out(vty,
- "\nTotal number of prefixes %ld (%ld filtered)\n",
- output_count, filtered_count);
- else
- vty_out(vty, "\nTotal number of prefixes %ld\n",
- output_count);
- }
}
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, uint8_t show_flags)
{
+ struct bgp *bgp;
+ struct bgp_table *table;
json_object *json = NULL;
+ json_object *json_scode = NULL;
+ json_object *json_ocode = NULL;
+ json_object *json_ar = NULL;
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
- if (use_json)
+ /* Init BGP headers here so they're only displayed once
+ * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
+ */
+ int header1 = 1;
+ int header2 = 1;
+
+ /*
+ * Initialize variables for each RD
+ * All prefixes under an RD is aggregated within "json_routes"
+ */
+ char rd_str[BUFSIZ] = {0};
+ json_object *json_routes = NULL;
+
+
+ /* For 2-tier tables, prefix counts need to be
+ * maintained across multiple runs of show_adj_route()
+ */
+ unsigned long output_count_per_rd;
+ unsigned long filtered_count_per_rd;
+ unsigned long output_count = 0;
+ unsigned long filtered_count = 0;
+
+ if (use_json) {
json = json_object_new_object();
+ json_ar = json_object_new_object();
+ json_scode = json_object_new_object();
+ json_ocode = json_object_new_object();
+
+ json_object_string_add(json_scode, "suppressed", "s");
+ json_object_string_add(json_scode, "damped", "d");
+ json_object_string_add(json_scode, "history", "h");
+ json_object_string_add(json_scode, "valid", "*");
+ json_object_string_add(json_scode, "best", ">");
+ json_object_string_add(json_scode, "multipath", "=");
+ json_object_string_add(json_scode, "internal", "i");
+ json_object_string_add(json_scode, "ribFailure", "r");
+ json_object_string_add(json_scode, "stale", "S");
+ json_object_string_add(json_scode, "removed", "R");
+
+ json_object_string_add(json_ocode, "igp", "i");
+ json_object_string_add(json_ocode, "egp", "e");
+ json_object_string_add(json_ocode, "incomplete", "?");
+ }
if (!peer || !peer->afc[afi][safi]) {
if (use_json) {
@@ -13179,7 +13319,84 @@ 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, json, show_flags);
+ bgp = peer->bgp;
+
+ /* labeled-unicast routes live in the unicast table */
+ if (safi == SAFI_LABELED_UNICAST)
+ table = bgp->rib[afi][SAFI_UNICAST];
+ else
+ table = bgp->rib[afi][safi];
+
+ if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
+ || (safi == SAFI_EVPN)) {
+
+ struct bgp_dest *dest;
+
+ for (dest = bgp_table_top(table); dest;
+ dest = bgp_route_next(dest)) {
+ table = bgp_dest_get_bgp_table_info(dest);
+ if (!table)
+ continue;
+
+ output_count_per_rd = 0;
+ filtered_count_per_rd = 0;
+
+ if (use_json)
+ json_routes = json_object_new_object();
+
+ const struct prefix_rd *prd;
+ prd = (const struct prefix_rd *)bgp_dest_get_prefix(
+ dest);
+
+ prefix_rd2str(prd, rd_str, sizeof(rd_str));
+
+ show_adj_route(vty, peer, table, afi, safi, type,
+ rmap_name, json, json_routes, json_scode,
+ json_ocode, show_flags, &header1,
+ &header2, rd_str, &output_count_per_rd,
+ &filtered_count_per_rd);
+
+ /* Don't include an empty RD in the output! */
+ if (json_routes && (output_count_per_rd > 0))
+ json_object_object_add(json_ar, rd_str,
+ json_routes);
+
+ output_count += output_count_per_rd;
+ filtered_count += filtered_count_per_rd;
+ }
+ } else
+ show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
+ json, json_ar, json_scode, json_ocode,
+ show_flags, &header1, &header2, rd_str,
+ &output_count, &filtered_count);
+
+ if (use_json) {
+ json_object_object_add(json, "advertisedRoutes", json_ar);
+ json_object_int_add(json, "totalPrefixCounter", output_count);
+ json_object_int_add(json, "filteredPrefixCounter",
+ filtered_count);
+
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+
+ if (!output_count && !filtered_count) {
+ json_object_free(json_scode);
+ json_object_free(json_ocode);
+ }
+
+ if (json)
+ json_object_free(json);
+
+ } else if (output_count > 0) {
+ if (filtered_count > 0)
+ vty_out(vty,
+ "\nTotal number of prefixes %ld (%ld filtered)\n",
+ output_count, filtered_count);
+ else
+ vty_out(vty, "\nTotal number of prefixes %ld\n",
+ output_count);
+ }
return CMD_SUCCESS;
}
@@ -13318,10 +13535,6 @@ DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
: AFI_IP6;
FOREACH_SAFI (safi) {
- if (strmatch(get_afi_safi_str(afi, safi, true),
- "Unknown"))
- continue;
-
if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
continue;
@@ -13341,10 +13554,6 @@ DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
}
} else {
FOREACH_AFI_SAFI (afi, safi) {
- if (strmatch(get_afi_safi_str(afi, safi, true),
- "Unknown"))
- continue;
-
if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
continue;
@@ -14077,7 +14286,8 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
if (pi->extra && pi->extra->damp_info) {
pi_temp = pi->next;
bgp_damp_info_free(
- pi->extra->damp_info,
+ &pi->extra->damp_info,
+ &bgp->damp[afi][safi],
1, afi, safi);
pi = pi_temp;
} else
@@ -14099,7 +14309,8 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
if (pi->extra && pi->extra->damp_info) {
pi_temp = pi->next;
bgp_damp_info_free(
- pi->extra->damp_info,
+ &pi->extra->damp_info,
+ &bgp->damp[afi][safi],
1, afi, safi);
pi = pi_temp;
} else
@@ -14122,7 +14333,9 @@ DEFUN (clear_ip_bgp_dampening,
BGP_STR
"Clear route flap dampening information\n")
{
- bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_damp_info_clean(&bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
+ SAFI_UNICAST);
return CMD_SUCCESS;
}