unsigned refcount;
bpi = bgp_path_info_lock(bpi);
- refcount = bpi->net->lock - 1;
+ refcount = bgp_dest_get_lock_count(bpi->net) - 1;
bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
if (!refcount)
bpi->net = NULL;
if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug(
- "Route %pRN is in workqueue and being processed, not deferred.",
- bgp_dest_to_rnode(dest));
+ "Route %pBD is in workqueue and being processed, not deferred.",
+ dest);
return 0;
}
bgp->gr_info[afi][safi].route_list,
dest);
if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("DEFER route %pRN, dest %p, node %p",
+ zlog_debug("DEFER route %pBD, dest %p, node %p",
dest, dest, dest->rt_node);
return 0;
}
struct peer *onlypeer;
struct bgp *bgp;
struct attr *piattr;
- char buf[PREFIX_STRLEN];
route_map_result_t ret;
int transparent;
int reflect;
* though they can have peer pointers that reference other
* systems
*/
- prefix2str(p, buf, PREFIX_STRLEN);
- zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
- __func__, buf);
+ zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
+ __func__, p);
samepeer_safe = 1;
}
#endif
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
+ " %pFX is filtered - no label (%p)",
subgrp->update_group->id, subgrp->id,
- inet_ntop(p->family, &p->u.prefix,
- buf, SU_ADDRSTRLEN),
- p->prefixlen, &label);
+ p, &label);
return false;
}
}
&& (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",
- onlypeer->host,
- prefix2str(p, buf, sizeof(buf)));
+ "%s [Update:SEND] %pFX originator-id is same as remote router-id",
+ onlypeer->host, p);
return false;
}
if (bgp_debug_update(NULL, p,
subgrp->update_group, 0))
zlog_debug(
- "%s [Update:SEND] %s is filtered via ORF",
- peer->host,
- prefix2str(p, buf,
- sizeof(buf)));
+ "%s [Update:SEND] %pFX is filtered via ORF",
+ peer->host, p);
return false;
}
}
/* Output filter check. */
if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
- zlog_debug("%s [Update:SEND] %s is filtered",
- peer->host, prefix2str(p, buf, sizeof(buf)));
+ zlog_debug("%s [Update:SEND] %pFX is filtered",
+ peer->host, p);
return false;
}
if (ret == RMAP_DENYMATCH) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
- zlog_debug("%s [Update:SEND] %s is filtered by route-map",
- peer->host, prefix2str(p, buf, sizeof(buf)));
+ zlog_debug(
+ "%s [Update:SEND] %pFX is filtered by route-map",
+ peer->host, p);
bgp_attr_flush(attr);
return false;
if (aspath_check_as_zero(attr->aspath))
return false;
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+ if (bgp_in_graceful_shutdown(bgp)) {
if (peer->sort == BGP_PEER_IBGP
|| peer->sort == BGP_PEER_CONFED) {
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
new_select, path_buf);
- zlog_debug("%s: %s is the bestpath from AS %u",
- pfx_buf, path_buf,
- aspath_get_first_as(
- new_select->attr->aspath));
+ zlog_debug(
+ "%pBD: %s is the bestpath from AS %u",
+ dest, path_buf,
+ aspath_get_first_as(
+ new_select->attr->aspath));
}
}
}
else
snprintf(path_buf, sizeof(path_buf), "NONE");
zlog_debug(
- "%s: After path selection, newbest is %s oldbest was %s",
- pfx_buf, path_buf,
+ "%pBD: After path selection, newbest is %s oldbest was %s",
+ dest, path_buf,
old_select ? old_select->peer->host : "NONE");
}
if (pi == new_select) {
if (debug)
zlog_debug(
- "%s: %s is the bestpath, add to the multipath list",
- pfx_buf, path_buf);
+ "%pBD: %s is the bestpath, add to the multipath list",
+ dest, path_buf);
bgp_mp_list_add(&mp_list, pi);
continue;
}
if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
if (debug)
zlog_debug(
- "%s: %s has the same nexthop as the bestpath, skip it",
- pfx_buf, path_buf);
+ "%pBD: %s has the same nexthop as the bestpath, skip it",
+ dest, path_buf);
continue;
}
if (paths_eq) {
if (debug)
zlog_debug(
- "%s: %s is equivalent to the bestpath, add to the multipath list",
- pfx_buf, path_buf);
+ "%pBD: %s is equivalent to the bestpath, add to the multipath list",
+ dest, path_buf);
bgp_mp_list_add(&mp_list, pi);
}
}
debug = bgp_debug_bestpath(dest);
if (debug)
zlog_debug(
- "%s: bgp delete in progress, ignoring event, p=%pRN",
+ "%s: bgp delete in progress, ignoring event, p=%pBD",
__func__, dest);
return;
}
debug = bgp_debug_bestpath(dest);
if (debug)
- zlog_debug("%s: p=%pRN afi=%s, safi=%s start", __func__, dest,
+ zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
afi2str(afi), safi2str(safi));
/* The best path calculation for the route is deferred if
if (debug)
zlog_debug(
- "%s: p=%pRN afi=%s, safi=%s, old_select=%p, new_select=%p",
+ "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
__func__, dest, afi2str(afi), safi2str(safi),
old_select, new_select);
bool filtered = false;
struct bgp_dest *dest;
struct bgp_adj_in *ain;
+ struct attr attr = {};
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 = {};
+
+ attr = *ain->attr;
if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
== FILTER_DENY)
UNSET_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_PREFIX_LIMIT);
- if (pcount > (pcount * peer->pmax_threshold[afi][safi] / 100)) {
+ if (pcount
+ > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
if (CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_PREFIX_THRESHOLD)
&& !always)
(type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
: false;
- /* Only validated for unicast and multicast currently. */
- /* Also valid for EVPN where the nexthop is an IP address. */
- if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN)
+ /*
+ * Only validated for unicast and multicast currently.
+ * Also valid for EVPN where the nexthop is an IP address.
+ * If we are a bgp static route being checked then there is
+ * no need to check to see if the nexthop is martian as
+ * that it should be ok.
+ */
+ if (is_bgp_static_route ||
+ (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
return false;
/* If NEXT_HOP is present, validate it. */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
- if ((attr->nexthop.s_addr == INADDR_ANY && !is_bgp_static_route)
+ if (attr->nexthop.s_addr == INADDR_ANY
|| IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
|| bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
return true;
switch (attr->mp_nexthop_len) {
case BGP_ATTR_NHLEN_IPV4:
case BGP_ATTR_NHLEN_VPNV4:
- ret = ((attr->mp_nexthop_global_in.s_addr == INADDR_ANY
- && !is_bgp_static_route)
+ ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
|| IPV4_CLASS_DE(
ntohl(attr->mp_nexthop_global_in.s_addr))
|| bgp_nexthop_self(bgp, afi, type, stype, attr,
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
- ret = ((IN6_IS_ADDR_UNSPECIFIED(
+ ret = (IN6_IS_ADDR_UNSPECIFIED(
&attr->mp_nexthop_global)
- && !is_bgp_static_route)
|| IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
|| IN6_IS_ADDR_MULTICAST(
&attr->mp_nexthop_global)
/* If graceful-shutdown is configured then add the GSHUT
* community to all paths received from eBGP peers */
- } else if (CHECK_FLAG(peer->bgp->flags,
- BGP_FLAG_GRACEFUL_SHUTDOWN))
+ } else if (bgp_in_graceful_shutdown(peer->bgp))
bgp_attr_add_gshut_community(&new_attr);
}
goto filtered;
}
+ /* Update Overlay Index */
+ if (afi == AFI_L2VPN) {
+ overlay_index_update(&new_attr,
+ evpn == NULL ? NULL : &evpn->gw_ip);
+ }
+
attr_new = bgp_attr_intern(&new_attr);
/* If maximum prefix count is configured and current prefix
}
}
#endif
- /* Update Overlay Index */
- if (afi == AFI_L2VPN) {
- overlay_index_update(
- pi->attr,
- evpn == NULL ? NULL : &evpn->gw_ip);
- }
/* Update bgp route dampening information. */
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
return;
}
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
+ if (bgp_in_graceful_shutdown(bgp))
bgp_attr_add_gshut_community(&attr_tmp);
attr_new = bgp_attr_intern(&attr_tmp);
} else {
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
+ if (bgp_in_graceful_shutdown(bgp))
bgp_attr_add_gshut_community(&attr);
attr_new = bgp_attr_intern(&attr);
&& pi->sub_type == BGP_ROUTE_AGGREGATE)
break;
+ /*
+ * If we have paths with different MEDs, then don't install
+ * (or uninstall) the aggregate route.
+ */
+ if (aggregate->match_med && aggregate->med_mismatched)
+ goto uninstall_aggregate_route;
+
if (aggregate->count > 0) {
/*
* If the aggregate information has not changed
bgp_path_info_add(dest, new);
bgp_process(bgp, dest, afi, safi);
} else {
+ uninstall_aggregate_route:
for (pi = orig; pi; pi = pi->next)
if (pi->peer == bgp->peer_self
&& pi->type == ZEBRA_ROUTE_BGP
bgp_dest_unlock_node(dest);
}
+/**
+ * Check if the current path has different MED than other known paths.
+ *
+ * \returns `true` if the MED matched the others else `false`.
+ */
+static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
+ struct bgp *bgp, struct bgp_path_info *pi)
+{
+ uint32_t cur_med = bgp_med_value(pi->attr, bgp);
+
+ /* This is the first route being analyzed. */
+ if (!aggregate->med_initialized) {
+ aggregate->med_initialized = true;
+ aggregate->med_mismatched = false;
+ aggregate->med_matched_value = cur_med;
+ } else {
+ /* Check if routes with different MED showed up. */
+ if (cur_med != aggregate->med_matched_value)
+ aggregate->med_mismatched = true;
+ }
+
+ return !aggregate->med_mismatched;
+}
+
+/**
+ * Initializes and tests all routes in the aggregate address path for MED
+ * values.
+ *
+ * \returns `true` if all MEDs are the same otherwise `false`.
+ */
+static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
+ struct bgp *bgp, const struct prefix *p,
+ afi_t afi, safi_t safi)
+{
+ struct bgp_table *table = bgp->rib[afi][safi];
+ const struct prefix *dest_p;
+ struct bgp_dest *dest, *top;
+ struct bgp_path_info *pi;
+ bool med_matched = true;
+
+ aggregate->med_initialized = false;
+
+ top = bgp_node_get(table, p);
+ for (dest = bgp_node_get(table, p); dest;
+ dest = bgp_route_next_until(dest, top)) {
+ dest_p = bgp_dest_get_prefix(dest);
+ if (dest_p->prefixlen <= p->prefixlen)
+ continue;
+
+ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+ if (BGP_PATH_HOLDDOWN(pi))
+ continue;
+ if (pi->sub_type == BGP_ROUTE_AGGREGATE)
+ continue;
+ if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
+ med_matched = false;
+ break;
+ }
+ }
+ if (!med_matched)
+ break;
+ }
+ bgp_dest_unlock_node(top);
+
+ return med_matched;
+}
+
+/**
+ * Toggles the route suppression status for this aggregate address
+ * configuration.
+ */
+static void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
+ struct bgp *bgp,
+ const struct prefix *p, afi_t afi,
+ safi_t safi, bool suppress)
+{
+ struct bgp_table *table = bgp->rib[afi][safi];
+ struct bgp_path_info_extra *pie;
+ const struct prefix *dest_p;
+ struct bgp_dest *dest, *top;
+ struct bgp_path_info *pi;
+ bool toggle_suppression;
+
+ /* We've found a different MED we must revert any suppressed routes. */
+ top = bgp_node_get(table, p);
+ for (dest = bgp_node_get(table, p); dest;
+ dest = bgp_route_next_until(dest, top)) {
+ dest_p = bgp_dest_get_prefix(dest);
+ if (dest_p->prefixlen <= p->prefixlen)
+ continue;
+
+ toggle_suppression = false;
+ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+ if (BGP_PATH_HOLDDOWN(pi))
+ continue;
+ if (pi->sub_type == BGP_ROUTE_AGGREGATE)
+ continue;
+
+ /*
+ * On installation it is possible that pi->extra is
+ * set to NULL, otherwise it must exists.
+ */
+ assert(!suppress && pi->extra != NULL);
+
+ /* We are toggling suppression back. */
+ if (suppress) {
+ pie = bgp_path_info_extra_get(pi);
+ /* Suppress route if not suppressed already. */
+ pie->suppress++;
+ bgp_path_info_set_flag(dest, pi,
+ BGP_PATH_ATTR_CHANGED);
+ toggle_suppression = true;
+ continue;
+ }
+
+ pie = pi->extra;
+ assert(pie->suppress > 0);
+ pie->suppress--;
+ /* Install route if there is no more suppression. */
+ if (pie->suppress == 0) {
+ bgp_path_info_set_flag(dest, pi,
+ BGP_PATH_ATTR_CHANGED);
+ toggle_suppression = true;
+ }
+ }
+
+ if (toggle_suppression)
+ bgp_process(bgp, dest, afi, safi);
+ }
+ bgp_dest_unlock_node(top);
+}
+
+/**
+ * Aggregate address MED matching incremental test: this function is called
+ * when the initial aggregation occurred and we are only testing a single
+ * new path.
+ *
+ * In addition to testing and setting the MED validity it also installs back
+ * suppressed routes (if summary is configured).
+ *
+ * Must not be called in `bgp_aggregate_route`.
+ */
+static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
+ struct bgp *bgp, const struct prefix *p,
+ afi_t afi, safi_t safi,
+ struct bgp_path_info *pi, bool is_adding)
+{
+ /* MED matching disabled. */
+ if (!aggregate->match_med)
+ return;
+
+ /* Aggregation with different MED, nothing to do. */
+ if (aggregate->med_mismatched)
+ return;
+
+ /*
+ * Test the current entry:
+ *
+ * is_adding == true: if the new entry doesn't match then we must
+ * install all suppressed routes.
+ *
+ * is_adding == false: if the entry being removed was the last
+ * unmatching entry then we can suppress all routes.
+ */
+ if (!is_adding) {
+ if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
+ && aggregate->summary_only)
+ bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
+ safi, true);
+ } else
+ bgp_aggregate_med_match(aggregate, bgp, pi);
+
+ /* No mismatches, just quit. */
+ if (!aggregate->med_mismatched)
+ return;
+
+ /* Route summarization is disabled. */
+ if (!aggregate->summary_only)
+ return;
+
+ bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
+}
+
/* Update an aggregate as routes are added/removed from the BGP table */
void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
safi_t safi, struct bgp_aggregate *aggregate)
|| (bgp->peer_self == NULL))
return;
+ /* Initialize and test routes for MED difference. */
+ if (aggregate->match_med)
+ bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
+
/* 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
/*
* summary-only aggregate route suppress
* aggregated route announcements.
+ *
+ * MED matching:
+ * Don't create summaries if MED didn't match
+ * otherwise neither the specific routes and the
+ * aggregation will be announced.
*/
- if (aggregate->summary_only) {
+ if (aggregate->summary_only
+ && AGGREGATE_MED_VALID(aggregate)) {
(bgp_path_info_extra_get(pi))->suppress++;
bgp_path_info_set_flag(dest, pi,
BGP_PATH_ATTR_CHANGED);
if (pi->sub_type == BGP_ROUTE_AGGREGATE)
continue;
- if (aggregate->summary_only && pi->extra) {
+ if (aggregate->summary_only && pi->extra
+ && AGGREGATE_MED_VALID(aggregate)) {
pi->extra->suppress--;
if (pi->extra->suppress == 0) {
aggregate->count++;
- if (aggregate->summary_only)
+ /*
+ * This must be called before `summary` check to avoid
+ * "suppressing" twice.
+ */
+ if (aggregate->match_med)
+ bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
+ pinew, true);
+
+ if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
(bgp_path_info_extra_get(pinew))->suppress++;
switch (pinew->attr->origin) {
if (pi->sub_type == BGP_ROUTE_AGGREGATE)
return;
- if (aggregate->summary_only
- && pi->extra
- && pi->extra->suppress > 0) {
+ if (aggregate->summary_only && pi->extra && pi->extra->suppress > 0
+ && AGGREGATE_MED_VALID(aggregate)) {
pi->extra->suppress--;
if (pi->extra->suppress == 0) {
}
}
+ /*
+ * This must be called after `summary` check to avoid
+ * "unsuppressing" twice.
+ */
+ if (aggregate->match_med)
+ bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
+ true);
+
if (aggregate->count > 0)
aggregate->count--;
static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
safi_t safi, const char *rmap,
uint8_t summary_only, uint8_t as_set,
- uint8_t origin)
+ uint8_t origin, bool match_med)
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret;
/* Make aggregate address structure. */
aggregate = bgp_aggregate_new();
aggregate->summary_only = summary_only;
+ aggregate->match_med = match_med;
/* Network operators MUST NOT locally generate any new
* announcements containing AS_SET or AS_CONFED_SET. If they have
return CMD_SUCCESS;
}
-DEFUN (aggregate_address,
- aggregate_address_cmd,
- "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n"
- "Apply route map to aggregate network\n"
- "Name of route map\n"
- "BGP origin code\n"
- "Remote EGP\n"
- "Local IGP\n"
- "Unknown heritage\n")
-{
- int idx = 0;
- argv_find(argv, argc, "A.B.C.D/M", &idx);
- char *prefix = argv[idx]->arg;
- char *rmap = NULL;
+DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
+ "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
+ "as-set$as_set_s"
+ "|summary-only$summary_only"
+ "|route-map WORD$rmap_name"
+ "|origin <egp|igp|incomplete>$origin_s"
+ "|matching-MED-only$match_med"
+ "}",
+ NO_STR
+ "Configure BGP aggregate entries\n"
+ "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
+ "Generate AS set path information\n"
+ "Filter more specific routes from updates\n"
+ "Apply route map to aggregate network\n"
+ "Route map name\n"
+ "BGP origin code\n"
+ "Remote EGP\n"
+ "Local IGP\n"
+ "Unknown heritage\n"
+ "Only aggregate routes with matching MED\n")
+{
+ const char *prefix_s = NULL;
+ safi_t safi = bgp_node_safi(vty);
uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
- int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
- : AGGREGATE_AS_UNSET;
- idx = 0;
- int summary_only = argv_find(argv, argc, "summary-only", &idx)
- ? AGGREGATE_SUMMARY_ONLY
- : 0;
-
- idx = 0;
- argv_find(argv, argc, "WORD", &idx);
- if (idx)
- rmap = argv[idx]->arg;
-
- idx = 0;
- if (argv_find(argv, argc, "origin", &idx)) {
- if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
- origin = BGP_ORIGIN_IGP;
- if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
- origin = BGP_ORIGIN_EGP;
- if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
- origin = BGP_ORIGIN_INCOMPLETE;
- }
+ int as_set = AGGREGATE_AS_UNSET;
+ char prefix_buf[PREFIX2STR_BUFFER];
- return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
- summary_only, as_set, origin);
-}
-
-DEFUN (aggregate_address_mask,
- aggregate_address_mask_cmd,
- "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n"
- "Apply route map to aggregate network\n"
- "Name of route map\n"
- "BGP origin code\n"
- "Remote EGP\n"
- "Local IGP\n"
- "Unknown heritage\n")
-{
- int idx = 0;
- argv_find(argv, argc, "A.B.C.D", &idx);
- char *prefix = argv[idx]->arg;
- char *mask = argv[idx + 1]->arg;
- bool rmap_found;
- char *rmap = NULL;
- uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
- int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
- : AGGREGATE_AS_UNSET;
- idx = 0;
- int summary_only = argv_find(argv, argc, "summary-only", &idx)
- ? AGGREGATE_SUMMARY_ONLY
- : 0;
-
- rmap_found = argv_find(argv, argc, "WORD", &idx);
- if (rmap_found)
- rmap = argv[idx]->arg;
-
- char prefix_str[BUFSIZ];
- int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
-
- if (!ret) {
- vty_out(vty, "%% Inconsistent address and mask\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (addr_str) {
+ if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
+ == 0) {
+ vty_out(vty, "%% Inconsistent address and mask\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ prefix_s = prefix_buf;
+ } else
+ prefix_s = prefix_str;
- idx = 0;
- if (argv_find(argv, argc, "origin", &idx)) {
- if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
- origin = BGP_ORIGIN_IGP;
- if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
+ if (origin_s) {
+ if (strcmp(origin_s, "egp") == 0)
origin = BGP_ORIGIN_EGP;
- if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
+ else if (strcmp(origin_s, "igp") == 0)
+ origin = BGP_ORIGIN_IGP;
+ else if (strcmp(origin_s, "incomplete") == 0)
origin = BGP_ORIGIN_INCOMPLETE;
}
- return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
- rmap, summary_only, as_set, origin);
-}
-
-DEFUN (no_aggregate_address,
- no_aggregate_address_cmd,
- "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n"
- "Apply route map to aggregate network\n"
- "Name of route map\n"
- "BGP origin code\n"
- "Remote EGP\n"
- "Local IGP\n"
- "Unknown heritage\n")
+ if (as_set_s)
+ as_set = AGGREGATE_AS_SET;
+
+ /* Handle configuration removal, otherwise installation. */
+ if (no)
+ return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
+
+ return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
+ summary_only != NULL, as_set, origin,
+ match_med != NULL);
+}
+
+DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
+ "[no] aggregate-address X:X::X:X/M$prefix {"
+ "as-set$as_set_s"
+ "|summary-only$summary_only"
+ "|route-map WORD$rmap_name"
+ "|origin <egp|igp|incomplete>$origin_s"
+ "|matching-MED-only$match_med"
+ "}",
+ NO_STR
+ "Configure BGP aggregate entries\n"
+ "Aggregate prefix\n"
+ "Generate AS set path information\n"
+ "Filter more specific routes from updates\n"
+ "Apply route map to aggregate network\n"
+ "Route map name\n"
+ "BGP origin code\n"
+ "Remote EGP\n"
+ "Local IGP\n"
+ "Unknown heritage\n"
+ "Only aggregate routes with matching MED\n")
{
- int idx = 0;
- argv_find(argv, argc, "A.B.C.D/M", &idx);
- char *prefix = argv[idx]->arg;
- return bgp_aggregate_unset(vty, prefix, AFI_IP, bgp_node_safi(vty));
-}
-
-DEFUN (no_aggregate_address_mask,
- no_aggregate_address_mask_cmd,
- "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate address\n"
- "Aggregate mask\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n"
- "Apply route map to aggregate network\n"
- "Name of route map\n"
- "BGP origin code\n"
- "Remote EGP\n"
- "Local IGP\n"
- "Unknown heritage\n")
-{
- int idx = 0;
- argv_find(argv, argc, "A.B.C.D", &idx);
- char *prefix = argv[idx]->arg;
- char *mask = argv[idx + 1]->arg;
-
- char prefix_str[BUFSIZ];
- int ret = netmask_str2prefix_str(prefix, mask, prefix_str);
-
- if (!ret) {
- vty_out(vty, "%% Inconsistent address and mask\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return bgp_aggregate_unset(vty, prefix_str, AFI_IP, bgp_node_safi(vty));
-}
-
-DEFUN (ipv6_aggregate_address,
- ipv6_aggregate_address_cmd,
- "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n"
- "Apply route map to aggregate network\n"
- "Name of route map\n"
- "BGP origin code\n"
- "Remote EGP\n"
- "Local IGP\n"
- "Unknown heritage\n")
-{
- int idx = 0;
- argv_find(argv, argc, "X:X::X:X/M", &idx);
- char *prefix = argv[idx]->arg;
- char *rmap = NULL;
- bool rmap_found;
uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
- int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
- : AGGREGATE_AS_UNSET;
+ int as_set = AGGREGATE_AS_UNSET;
- idx = 0;
- int sum_only = argv_find(argv, argc, "summary-only", &idx)
- ? AGGREGATE_SUMMARY_ONLY
- : 0;
-
- rmap_found = argv_find(argv, argc, "WORD", &idx);
- if (rmap_found)
- rmap = argv[idx]->arg;
-
- idx = 0;
- if (argv_find(argv, argc, "origin", &idx)) {
- if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
- origin = BGP_ORIGIN_IGP;
- if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
+ if (origin_s) {
+ if (strcmp(origin_s, "egp") == 0)
origin = BGP_ORIGIN_EGP;
- if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
+ else if (strcmp(origin_s, "igp") == 0)
+ origin = BGP_ORIGIN_IGP;
+ else if (strcmp(origin_s, "incomplete") == 0)
origin = BGP_ORIGIN_INCOMPLETE;
}
- return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
- sum_only, as_set, origin);
-}
+ if (as_set_s)
+ as_set = AGGREGATE_AS_SET;
-DEFUN (no_ipv6_aggregate_address,
- no_ipv6_aggregate_address_cmd,
- "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
- NO_STR
- "Configure BGP aggregate entries\n"
- "Aggregate prefix\n"
- "Generate AS set path information\n"
- "Filter more specific routes from updates\n"
- "Filter more specific routes from updates\n"
- "Generate AS set path information\n"
- "Apply route map to aggregate network\n"
- "Name of route map\n"
- "BGP origin code\n"
- "Remote EGP\n"
- "Local IGP\n"
- "Unknown heritage\n")
-{
- int idx = 0;
- argv_find(argv, argc, "X:X::X:X/M", &idx);
- char *prefix = argv[idx]->arg;
- return bgp_aggregate_unset(vty, prefix, AFI_IP6, SAFI_UNICAST);
+ /* Handle configuration removal, otherwise installation. */
+ if (no)
+ return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
+ SAFI_UNICAST);
+
+ return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
+ rmap_name, summary_only != NULL, as_set,
+ origin, match_med != NULL);
}
/* Redistribute route treatment. */
}
}
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
+ if (bgp_in_graceful_shutdown(bgp))
bgp_attr_add_gshut_community(&attr_new);
bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
if (p->family == AF_INET) {
if (!json) {
- len = vty_out(
- vty, "%s/%d",
- inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
- p->prefixlen);
+ len = vty_out(vty, "%pFX", p);
} else {
json_object_string_add(json, "prefix",
inet_ntop(p->family,
}
} else if (p->family == AF_ETHERNET) {
prefix2str(p, buf, PREFIX_STRLEN);
- len = vty_out(vty, "%s", buf);
+ len = vty_out(vty, "%pFX", p);
} else if (p->family == AF_EVPN) {
if (!json)
- len = vty_out(
- vty, "%s",
- bgp_evpn_route2str((struct prefix_evpn *)p, buf,
- BUFSIZ));
+ len = vty_out(vty, "%s",
+ prefix2str((struct prefix_evpn *)p, buf,
+ BUFSIZ));
else
bgp_evpn_route2json((struct prefix_evpn *)p, json);
} else if (p->family == AF_FLOWSPEC) {
NLRI_STRING_FORMAT_MIN, json);
} else {
if (!json)
- len = vty_out(
- vty, "%s/%d",
- inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
- p->prefixlen);
+ len = vty_out(vty, "%pFX", p);
else {
json_object_string_add(json, "prefix",
inet_ntop(p->family,
}
if (safi == SAFI_EVPN) {
if (!json_paths) {
- bgp_evpn_route2str(
- (struct prefix_evpn *)
- bgp_dest_get_prefix(bn),
- buf2, sizeof(buf2));
+ prefix2str((struct prefix_evpn *)
+ bgp_dest_get_prefix(bn),
+ buf2, sizeof(buf2));
vty_out(vty, " Route %s", buf2);
if (tag_buf[0] != '\0')
vty_out(vty, " VNI %s", tag_buf);
pdest),
buf1, sizeof(buf1));
if (is_pi_family_evpn(parent_ri)) {
- bgp_evpn_route2str(
- (struct prefix_evpn *)
- bgp_dest_get_prefix(
- dest),
- buf2, sizeof(buf2));
+ prefix2str((struct prefix_evpn *)
+ bgp_dest_get_prefix(
+ dest),
+ buf2, sizeof(buf2));
vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
} else
vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
bool use_json);
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
const char *comstr, int exact, afi_t afi,
- safi_t safi, bool use_json);
+ safi_t safi, uint8_t show_flags);
static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
struct bgp_table *table, enum bgp_show_type type,
- void *output_arg, bool use_json, char *rd,
- int is_last, unsigned long *output_cum,
- unsigned long *total_cum,
- unsigned long *json_header_depth, bool wide)
+ void *output_arg, char *rd, int is_last,
+ unsigned long *output_cum, unsigned long *total_cum,
+ unsigned long *json_header_depth, uint8_t show_flags)
{
struct bgp_path_info *pi;
struct bgp_dest *dest;
struct prefix *p;
json_object *json_paths = NULL;
int first = 1;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
+ bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
if (output_cum && *output_cum != 0)
header = 0;
if (use_json && !*json_header_depth) {
+ if (all)
+ *json_header_depth = 1;
+ else {
+ vty_out(vty, "{\n");
+ *json_header_depth = 2;
+ }
+
vty_out(vty,
- "{\n \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\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
: bgp->name,
table->version, inet_ntoa(bgp->router_id),
bgp->default_local_pref, bgp->as);
- *json_header_depth = 2;
if (rd) {
vty_out(vty, " \"routeDistinguishers\" : {");
++*json_header_depth;
if (dest_p->family == AF_FLOWSPEC) {
char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
+
bgp_fs_nlri_get_string(
(unsigned char *)
dest_p->u.prefix_flowspec.ptr,
dest_p->u.prefix_flowspec.prefixlen,
- retstr, NLRI_STRING_FORMAT_MIN, NULL);
+ retstr, NLRI_STRING_FORMAT_MIN, NULL,
+ family2afi(dest_p->u
+ .prefix_flowspec.family));
if (first)
vty_out(vty, "\"%s/%d\": ", retstr,
dest_p->u.prefix_flowspec
unsigned long i;
for (i = 0; i < *json_header_depth; ++i)
vty_out(vty, " } ");
- vty_out(vty, "\n");
+ if (!all)
+ vty_out(vty, "\n");
}
} else {
if (is_last) {
unsigned long json_header_depth = 0;
struct bgp_table *itable;
bool show_msg;
+ uint8_t show_flags = 0;
show_msg = (!use_json && type == bgp_show_type_normal);
+ if (use_json)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+
for (dest = bgp_table_top(table); dest; dest = next) {
const struct prefix *dest_p = bgp_dest_get_prefix(dest);
memcpy(&prd, dest_p, sizeof(struct prefix_rd));
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, false);
+ rd, next == NULL, &output_cum,
+ &total_cum, &json_header_depth,
+ show_flags);
if (next == NULL)
show_msg = false;
}
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,
- bool wide)
+ enum bgp_show_type type, void *output_arg,
+ uint8_t show_flags)
{
struct bgp_table *table;
unsigned long json_header_depth = 0;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
if (bgp == NULL) {
bgp = bgp_get_default();
else if (safi == SAFI_LABELED_UNICAST)
safi = SAFI_UNICAST;
- return bgp_show_table(vty, bgp, safi, table, type, output_arg, use_json,
- NULL, 1, NULL, NULL, &json_header_depth, wide);
+ return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
+ NULL, NULL, &json_header_depth, show_flags);
}
static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
- safi_t safi, bool use_json,
- bool wide)
+ safi_t safi, uint8_t show_flags)
{
struct listnode *node, *nnode;
struct bgp *bgp;
int is_first = 1;
bool route_output = false;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
if (use_json)
vty_out(vty, "{\n");
: bgp->name);
}
bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
- use_json, wide);
+ show_flags);
}
if (use_json)
struct peer *peer;
struct listnode *node, *nnode;
char buf1[RD_ADDRSTRLEN];
- char buf2[INET6_ADDRSTRLEN];
char buf3[EVPN_ROUTE_STRLEN];
char prefix_str[BUFSIZ];
int count = 0;
if (!json) {
vty_out(vty, "BGP routing table entry for %s%s%s\n",
prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
- : "", prd ? ":" : "",
- bgp_evpn_route2str((struct prefix_evpn *)p,
- buf3, sizeof(buf3)));
+ : "",
+ prd ? ":" : "",
+ prefix2str((struct prefix_evpn *)p, buf3,
+ sizeof(buf3)));
} else {
json_object_string_add(json, "rd",
prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
}
} else {
if (!json) {
- vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
+ vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
- ? prefix_rd2str(prd, buf1,
- sizeof(buf1))
- : ""),
- safi == SAFI_MPLS_VPN ? ":" : "",
- inet_ntop(p->family, &p->u.prefix, buf2,
- INET6_ADDRSTRLEN),
- p->prefixlen);
+ ? prefix_rd2str(prd, buf1,
+ sizeof(buf1))
+ : ""),
+ safi == SAFI_MPLS_VPN ? ":" : "", p);
} else
json_object_string_add(json, "prefix",
int i;
char *str;
int first = 0;
+ uint8_t show_flags = 0;
+
+ if (uj)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
b = buffer_new(1024);
for (i = 0; i < argc; i++) {
return bgp_show(vty, bgp, afi, safi,
(exact ? bgp_show_type_lcommunity_exact
: bgp_show_type_lcommunity),
- lcom, uj, false);
+ lcom, show_flags);
}
static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
safi_t safi, bool uj)
{
struct community_list *list;
+ uint8_t show_flags = 0;
+
+ if (uj)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+
list = community_list_lookup(bgp_clist, lcom, 0,
LARGE_COMMUNITY_LIST_MASTER);
return bgp_show(vty, bgp, afi, safi,
(exact ? bgp_show_type_lcommunity_list_exact
: bgp_show_type_lcommunity_list),
- list, uj, false);
+ list, show_flags);
}
DEFUN (show_ip_bgp_large_community_list,
bool exact_match = 0;
struct bgp *bgp = NULL;
bool uj = use_json(argc, argv);
+ uint8_t show_flags = 0;
- if (uj)
- argc--;
+ if (uj) {
+ argc--;
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ }
- bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
- &bgp, uj);
- if (!idx)
- return CMD_WARNING;
+ bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+ &bgp, uj);
+ if (!idx)
+ return CMD_WARNING;
if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
if (argv_find(argv, argc, "exact-match", &idx))
exact_match, afi, safi, uj);
} else
return bgp_show(vty, bgp, afi, safi,
- bgp_show_type_lcommunity_all, NULL, uj, false);
+ bgp_show_type_lcommunity_all, NULL, show_flags);
}
static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
}
/* BGP route print out function without JSON */
-DEFUN(show_ip_bgp, show_ip_bgp_cmd,
+DEFPY(show_ip_bgp, show_ip_bgp_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
" [" BGP_SAFI_WITH_LABEL_CMD_STR
"]]\
- <dampening <parameters>\
+ <[all$all] dampening <parameters>\
|route-map WORD\
|prefix-list WORD\
|filter-list WORD\
>",
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
+ "Display the entries for all address families\n"
"Display detailed information about dampening\n"
"Display detail of configured dampening parameters\n"
"Display routes matching the route-map\n"
int exact_match = 0;
struct bgp *bgp = NULL;
int idx = 0;
+ uint8_t show_flags = 0;
+
+ /* [<ipv4|ipv6> [all]] */
+ if (all) {
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
+ if (argv_find(argv, argc, "ipv4", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
+
+ if (argv_find(argv, argc, "ipv6", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
+ }
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp, false);
if (argv_find(argv, argc, "dampening", &idx)) {
if (argv_find(argv, argc, "parameters", &idx))
- return bgp_show_dampening_parameters(vty, afi, safi);
+ return bgp_show_dampening_parameters(vty, afi, safi,
+ show_flags);
}
if (argv_find(argv, argc, "prefix-list", &idx))
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"]]\
+ [all$all]\
[cidr-only\
|dampening <flap-statistics|dampened-paths>\
|community [AA:NN|local-AS|no-advertise|no-export\
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
+ "Display the entries for all address families\n"
"Display only routes with non-natural netmasks\n"
"Display detailed information about dampening\n"
"Display flap statistics of routes\n"
struct bgp *bgp = NULL;
int idx = 0;
int exact_match = 0;
+ char *community = NULL;
+ bool first = true;
+ uint8_t show_flags = 0;
- if (uj)
+
+ if (uj) {
argc--;
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ }
+
+ /* [<ipv4|ipv6> [all]] */
+ if (all) {
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
+
+ if (argv_find(argv, argc, "ipv4", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
+
+ if (argv_find(argv, argc, "ipv6", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
+ }
+
+ if (wide)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp, uj);
return CMD_WARNING;
if (argv_find(argv, argc, "cidr-only", &idx))
- return bgp_show(vty, bgp, afi, safi, bgp_show_type_cidr_only,
- NULL, uj, wide);
+ sh_type = bgp_show_type_cidr_only;
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,
- wide);
+ sh_type = bgp_show_type_dampend_paths;
else if (argv_find(argv, argc, "flap-statistics", &idx))
- return bgp_show(vty, bgp, afi, safi,
- bgp_show_type_flap_statistics, NULL, uj,
- wide);
+ sh_type = bgp_show_type_flap_statistics;
}
if (argv_find(argv, argc, "community", &idx)) {
char *maybecomm = NULL;
- char *community = NULL;
if (idx + 1 < argc) {
if (argv[idx + 1]->type == VARIABLE_TKN)
if (argv_find(argv, argc, "exact-match", &idx))
exact_match = 1;
+ if (!community)
+ sh_type = bgp_show_type_community_all;
+ }
+
+ if (!all) {
+ /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
if (community)
return bgp_show_community(vty, bgp, community,
- exact_match, afi, safi, uj);
+ exact_match, afi, safi,
+ show_flags);
else
- return (bgp_show(vty, bgp, afi, safi,
- bgp_show_type_community_all, NULL, uj,
- wide));
- }
+ return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
+ show_flags);
+ } else {
+ /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
+ * AFI_IP6 */
- return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj, wide);
+ if (uj)
+ vty_out(vty, "{\n");
+
+ if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
+ || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
+ 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;
+
+ if (uj) {
+ if (first)
+ first = false;
+ else
+ vty_out(vty, ",\n");
+ vty_out(vty, "\"%s\":{\n",
+ get_afi_safi_str(afi, safi,
+ true));
+ } else
+ vty_out(vty,
+ "\nFor address family: %s\n",
+ get_afi_safi_str(afi, safi,
+ false));
+
+ if (community)
+ bgp_show_community(vty, bgp, community,
+ exact_match, afi,
+ safi, show_flags);
+ else
+ bgp_show(vty, bgp, afi, safi, sh_type,
+ NULL, show_flags);
+ if (uj)
+ vty_out(vty, "}\n");
+ }
+ } 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;
+
+ if (uj) {
+ if (first)
+ first = false;
+ else
+ vty_out(vty, ",\n");
+
+ vty_out(vty, "\"%s\":{\n",
+ get_afi_safi_str(afi, safi,
+ true));
+ } else
+ vty_out(vty,
+ "\nFor address family: %s\n",
+ get_afi_safi_str(afi, safi,
+ false));
+
+ if (community)
+ bgp_show_community(vty, bgp, community,
+ exact_match, afi,
+ safi, show_flags);
+ else
+ bgp_show(vty, bgp, afi, safi, sh_type,
+ NULL, show_flags);
+ if (uj)
+ vty_out(vty, "}\n");
+ }
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+ }
+ return CMD_SUCCESS;
}
DEFUN (show_ip_bgp_route,
safi_t safi = SAFI_UNICAST;
struct bgp *bgp = NULL;
int idx = 0;
+ uint8_t show_flags = 0;
- if (uj)
+ if (uj) {
argc--;
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ }
+
+ if (wide)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp, uj);
if (!idx)
return CMD_WARNING;
- bgp_show_all_instances_routes_vty(vty, afi, safi, uj, wide);
+ bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
return CMD_SUCCESS;
}
{
regex_t *regex;
int rc;
+ uint8_t show_flags = 0;
+
+ if (use_json)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
if (!config_bgp_aspath_validate(regstr)) {
vty_out(vty, "Invalid character in REGEX %s\n",
return CMD_WARNING;
}
- rc = bgp_show(vty, bgp, afi, safi, type, regex, use_json, false);
+ rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
bgp_regex_free(regex);
return rc;
}
safi_t safi, enum bgp_show_type type)
{
struct prefix_list *plist;
+ uint8_t show_flags = 0;
plist = prefix_list_lookup(afi, prefix_list_str);
if (plist == NULL) {
return CMD_WARNING;
}
- return bgp_show(vty, bgp, afi, safi, type, plist, 0, false);
+ return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
}
static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
enum bgp_show_type type)
{
struct as_list *as_list;
+ uint8_t show_flags = 0;
as_list = as_list_lookup(filter);
if (as_list == NULL) {
return CMD_WARNING;
}
- return bgp_show(vty, bgp, afi, safi, type, as_list, 0, false);
+ return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
}
static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
enum bgp_show_type type)
{
struct route_map *rmap;
+ uint8_t show_flags = 0;
rmap = route_map_lookup_by_name(rmap_str);
if (!rmap) {
return CMD_WARNING;
}
- return bgp_show(vty, bgp, afi, safi, type, rmap, 0, false);
+ return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
}
static int bgp_show_community(struct vty *vty, struct bgp *bgp,
const char *comstr, int exact, afi_t afi,
- safi_t safi, bool use_json)
+ safi_t safi, uint8_t show_flags)
{
struct community *com;
int ret = 0;
ret = bgp_show(vty, bgp, afi, safi,
(exact ? bgp_show_type_community_exact
: bgp_show_type_community),
- com, use_json, false);
+ com, show_flags);
community_free(&com);
return ret;
safi_t safi)
{
struct community_list *list;
+ uint8_t show_flags = 0;
list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
if (list == NULL) {
return bgp_show(vty, bgp, afi, safi,
(exact ? bgp_show_type_community_list_exact
: bgp_show_type_community_list),
- list, 0, false);
+ list, show_flags);
}
static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
{
int ret;
struct prefix *p;
+ uint8_t show_flags = 0;
p = prefix_new();
return CMD_WARNING;
}
- ret = bgp_show(vty, bgp, afi, safi, type, p, 0, false);
+ ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
prefix_free(&p);
return ret;
}
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, bool wide)
+ const char *rmap_name, json_object *json,
+ uint8_t show_flags)
{
struct bgp_table *table;
struct bgp_adj_in *ain;
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();
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, bool wide)
+ const char *rmap_name, uint8_t show_flags)
{
json_object *json = NULL;
+ bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
if (use_json)
json = json_object_new_object();
return CMD_WARNING;
}
- show_adj_route(vty, peer, afi, safi, type, rmap_name, use_json, json,
- wide);
+ show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
return CMD_SUCCESS;
}
struct peer *peer;
enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
int idx = 0;
+ uint8_t show_flags = 0;
+
+ if (uj)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+
+ if (wide)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp, uj);
if (!peer)
return CMD_WARNING;
- return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, uj, wide);
+ return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
+ show_flags);
}
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$uj | wide$wide]",
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] 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
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
+ "Display the entries for all address families\n"
"Detailed information on TCP and BGP neighbor connections\n"
"Neighbor to display information about\n"
"Neighbor to display information about\n"
struct peer *peer;
enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
int idx = 0;
+ bool first = true;
+ uint8_t show_flags = 0;
- if (uj)
+ if (uj) {
argc--;
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ }
+
+ if (all) {
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
+ if (argv_find(argv, argc, "ipv4", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
+
+ if (argv_find(argv, argc, "ipv6", &idx))
+ SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
+ }
+
+ if (wide)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp, uj);
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, wide);
+ if (!all)
+ return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
+ show_flags);
+ if (uj)
+ vty_out(vty, "{\n");
+
+ if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
+ || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
+ 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;
+
+ if (uj) {
+ if (first)
+ first = false;
+ else
+ vty_out(vty, ",\n");
+ vty_out(vty, "\"%s\":",
+ get_afi_safi_str(afi, safi, true));
+ } else
+ vty_out(vty, "\nFor address family: %s\n",
+ get_afi_safi_str(afi, safi, false));
+
+ peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
+ show_flags);
+ }
+ } 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;
+
+ if (uj) {
+ if (first)
+ first = false;
+ else
+ vty_out(vty, ",\n");
+ vty_out(vty, "\"%s\":",
+ get_afi_safi_str(afi, safi, true));
+ } else
+ vty_out(vty, "\nFor address family: %s\n",
+ get_afi_safi_str(afi, safi, false));
+
+ peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
+ show_flags);
+ }
+ }
+ if (uj)
+ vty_out(vty, "}\n");
+
+ return CMD_SUCCESS;
}
DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
afi_t afi, safi_t safi,
enum bgp_show_type type, bool use_json)
{
- /* labeled-unicast routes live in the unicast table */
- if (safi == SAFI_LABELED_UNICAST)
- safi = SAFI_UNICAST;
+ uint8_t show_flags = 0;
+
+ if (use_json)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
if (!peer || !peer->afc[afi][safi]) {
if (use_json) {
return CMD_WARNING;
}
- return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, use_json,
- false);
+ /* labeled-unicast routes live in the unicast table */
+ if (safi == SAFI_LABELED_UNICAST)
+ safi = SAFI_UNICAST;
+
+ return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
}
DEFUN (show_ip_bgp_flowspec_routes_detailed,
struct bgp *bgp = NULL;
int idx = 0;
bool uj = use_json(argc, argv);
+ uint8_t show_flags = 0;
- if (uj)
+ if (uj) {
argc--;
+ SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
+ }
bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
&bgp, uj);
if (!idx)
return CMD_WARNING;
- return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL, uj,
- false);
+ return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
+ show_flags);
}
DEFUN (show_ip_bgp_neighbor_routes,
const struct prefix_rd *prd;
struct bgp_static *bgp_static;
mpls_label_t label;
- char buf[SU_ADDRSTRLEN];
char rdbuf[RD_ADDRSTRLEN];
/* Network configuration. */
prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
label = decode_label(&bgp_static->label);
- vty_out(vty, " network %s/%d rd %s",
- inet_ntop(p->family, &p->u.prefix, buf,
- SU_ADDRSTRLEN),
- p->prefixlen, rdbuf);
+ vty_out(vty, " network %pFX rd %s", p, rdbuf);
if (safi == SAFI_MPLS_VPN)
vty_out(vty, " label %u", label);
const struct prefix *p;
struct bgp_static *bgp_static;
struct bgp_aggregate *bgp_aggregate;
- char buf[SU_ADDRSTRLEN];
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
bgp_config_write_network_vpn(vty, bgp, afi, safi);
p = bgp_dest_get_prefix(dest);
- vty_out(vty, " network %s/%d",
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ vty_out(vty, " network %pFX", p);
if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
vty_out(vty, " label-index %u",
p = bgp_dest_get_prefix(dest);
- vty_out(vty, " aggregate-address %s/%d",
- inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
- p->prefixlen);
+ vty_out(vty, " aggregate-address %pFX", p);
if (bgp_aggregate->as_set)
vty_out(vty, " as-set");
vty_out(vty, " origin %s",
bgp_origin2str(bgp_aggregate->origin));
+ if (bgp_aggregate->match_med)
+ vty_out(vty, " matching-MED-only");
+
vty_out(vty, "\n");
}
}
dest = bgp_route_next(dest)) {
bdistance = bgp_dest_get_bgp_distance_info(dest);
if (bdistance != NULL)
- vty_out(vty, " distance %d %pRN %s\n",
+ vty_out(vty, " distance %d %pBD %s\n",
bdistance->distance, dest,
bdistance->access_list ? bdistance->access_list
: "");
install_element(BGP_NODE, &bgp_network_cmd);
install_element(BGP_NODE, &no_bgp_table_map_cmd);
- install_element(BGP_NODE, &aggregate_address_cmd);
- install_element(BGP_NODE, &aggregate_address_mask_cmd);
- install_element(BGP_NODE, &no_aggregate_address_cmd);
- install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
+ install_element(BGP_NODE, &aggregate_addressv4_cmd);
/* IPv4 unicast configuration. */
install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
install_element(BGP_IPV4_NODE, &bgp_network_cmd);
install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
- install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
- install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
- install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
- install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
+ install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
/* IPv4 multicast configuration. */
install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
- install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
- install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
- install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
- install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
+ install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
/* IPv4 labeled-unicast configuration. */
install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
- install_element(BGP_IPV4L_NODE, &aggregate_address_cmd);
- install_element(BGP_IPV4L_NODE, &aggregate_address_mask_cmd);
- install_element(BGP_IPV4L_NODE, &no_aggregate_address_cmd);
- install_element(BGP_IPV4L_NODE, &no_aggregate_address_mask_cmd);
+ install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
install_element(VIEW_NODE, &show_ip_bgp_cmd);
install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
- install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
- install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
+ install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
/* IPv6 labeled unicast address family. */
install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
- install_element(BGP_IPV6L_NODE, &ipv6_aggregate_address_cmd);
- install_element(BGP_IPV6L_NODE, &no_ipv6_aggregate_address_cmd);
+ install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
install_element(BGP_NODE, &bgp_distance_cmd);
install_element(BGP_NODE, &no_bgp_distance_cmd);