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.c786
1 files changed, 536 insertions, 250 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 9a3ab0d8ee..09eb6fcf82 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -71,7 +71,7 @@
#include "bgpd/bgp_mac.h"
#include "bgpd/bgp_network.h"
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
#include "bgpd/rfapi/vnc_import_bgp.h"
#include "bgpd/rfapi/vnc_export_bgp.h"
@@ -1560,6 +1560,8 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
afi_t afi;
safi_t safi;
int samepeer_safe = 0; /* for synthetic mplsvpns routes */
+ bool nh_reset = false;
+ uint64_t cum_bw;
if (DISABLE_BGP_ANNOUNCE)
return false;
@@ -1577,7 +1579,7 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
: pi->attr;
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
&& ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
|| (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
@@ -1923,8 +1925,7 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
* benefit from consistent behavior across different BGP
* implementations.
*/
- if (peer->bgp->ebgp_requires_policy
- == DEFAULT_EBGP_POLICY_ENABLED)
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
if (!bgp_outbound_policy_exists(peer, filter))
return false;
@@ -1934,7 +1935,7 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
* and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
* and obsoletes RFC 6472.
*/
- if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
+ if (peer->bgp->reject_as_sets)
if (aspath_check_as_sets(attr->aspath))
return false;
@@ -1983,12 +1984,14 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
PEER_FLAG_FORCE_NEXTHOP_SELF)) {
if (!reflect
|| CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_FORCE_NEXTHOP_SELF))
+ PEER_FLAG_FORCE_NEXTHOP_SELF)) {
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
: p->family),
attr);
+ nh_reset = true;
+ }
} else if (peer->sort == BGP_PEER_EBGP) {
/* Can also reset the nexthop if announcing to EBGP, but
* only if
@@ -1999,22 +2002,26 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if ((p->family == AF_INET) &&
(!bgp_subgrp_multiaccess_check_v4(
piattr->nexthop,
- subgrp, from)))
+ subgrp, from))) {
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
: p->family),
attr);
+ nh_reset = true;
+ }
if ((p->family == AF_INET6) &&
(!bgp_subgrp_multiaccess_check_v6(
piattr->mp_nexthop_global,
- subgrp, from)))
+ subgrp, from))) {
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
: p->family),
attr);
+ nh_reset = true;
+ }
@@ -2032,6 +2039,7 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
"%s: BGP_PATH_ANNC_NH_SELF, family=%s",
__func__, family2str(family));
subgroup_announce_reset_nhop(family, attr);
+ nh_reset = true;
}
}
@@ -2044,10 +2052,25 @@ bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
* the same interface.
*/
if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
- if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global))
+ if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
subgroup_announce_reset_nhop(AF_INET6, attr);
+ nh_reset = true;
+ }
}
+ /*
+ * When the next hop is set to ourselves, if all multipaths have
+ * link-bandwidth announce the cumulative bandwidth as that makes
+ * the most sense. However, don't modify if the link-bandwidth has
+ * been explicitly set by user policy.
+ */
+ if (nh_reset &&
+ bgp_path_info_mpath_chkwtd(bgp, pi) &&
+ (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
+ !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
+ attr->ecommunity = ecommunity_replace_linkbw(
+ bgp->as, attr->ecommunity, cum_bw);
+
return true;
}
@@ -2394,7 +2417,8 @@ bool bgp_zebra_has_route_changed(struct bgp_node *rn,
* when the best path has an attribute change anyway.
*/
if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
- || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG))
+ || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
+ || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
return true;
/*
@@ -2419,6 +2443,54 @@ struct bgp_process_queue {
unsigned int queued;
};
+static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
+ safi_t safi, struct bgp_node *rn,
+ struct bgp_path_info *new_select,
+ struct bgp_path_info *old_select)
+{
+ const struct prefix *p = bgp_node_get_prefix(rn);
+
+ if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
+ return;
+
+ if (advertise_type5_routes(bgp, afi) && new_select
+ && is_route_injectable_into_evpn(new_select)) {
+
+ /* apply the route-map */
+ if (bgp->adv_cmd_rmap[afi][safi].map) {
+ route_map_result_t ret;
+ struct bgp_path_info rmap_path;
+ struct bgp_path_info_extra rmap_path_extra;
+ struct attr dummy_attr;
+
+ dummy_attr = *new_select->attr;
+
+ /* Fill temp path_info */
+ prep_for_rmap_apply(&rmap_path, &rmap_path_extra, rn,
+ new_select, new_select->peer,
+ &dummy_attr);
+
+ RESET_FLAG(dummy_attr.rmap_change_flags);
+
+ ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
+ p, RMAP_BGP, &rmap_path);
+
+ if (ret == RMAP_DENYMATCH) {
+ bgp_attr_flush(&dummy_attr);
+ bgp_evpn_withdraw_type5_route(bgp, p, afi,
+ safi);
+ } else
+ bgp_evpn_advertise_type5_route(
+ bgp, p, &dummy_attr, afi, safi);
+ } else {
+ bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
+ afi, safi);
+ }
+ } else if (advertise_type5_routes(bgp, afi) && old_select
+ && is_route_injectable_into_evpn(old_select))
+ bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
+}
+
/*
* old_select = The old best path
* new_select = the new best path
@@ -2547,7 +2619,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
&& !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
&& !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
if (bgp_zebra_has_route_changed(rn, old_select)) {
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
vnc_import_bgp_add_route(bgp, p, old_select);
vnc_import_bgp_exterior_add_route(bgp, p, old_select);
#endif
@@ -2563,12 +2635,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
bgp, afi, safi);
}
}
- UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
- bgp_zebra_clear_route_change_flags(rn);
/* If there is a change of interest to peers, reannounce the
* route. */
if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
+ || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
|| CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) {
group_announce_route(bgp, afi, safi, rn, new_select);
@@ -2583,6 +2654,15 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
}
+ /* advertise/withdraw type-5 routes */
+ if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
+ || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
+ bgp_process_evpn_route_injection(
+ bgp, afi, safi, rn, old_select, old_select);
+
+ UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
+ UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
+ bgp_zebra_clear_route_change_flags(rn);
UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED);
return;
}
@@ -2613,9 +2693,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED);
bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED);
UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
+ UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (old_select != new_select) {
if (old_select) {
@@ -2668,53 +2749,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
}
}
- /* advertise/withdraw type-5 routes */
- if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
- const struct prefix *p = bgp_node_get_prefix(rn);
-
- if (advertise_type5_routes(bgp, afi) &&
- new_select &&
- is_route_injectable_into_evpn(new_select)) {
-
- /* apply the route-map */
- if (bgp->adv_cmd_rmap[afi][safi].map) {
- route_map_result_t ret;
- struct bgp_path_info rmap_path;
- struct bgp_path_info_extra rmap_path_extra;
- struct attr dummy_attr;
-
- dummy_attr = *new_select->attr;
-
- /* Fill temp path_info */
- prep_for_rmap_apply(
- &rmap_path, &rmap_path_extra,
- rn, new_select, new_select->peer,
- &dummy_attr);
-
- RESET_FLAG(dummy_attr.rmap_change_flags);
-
- ret = route_map_apply(
- bgp->adv_cmd_rmap[afi][safi].map,
- p, RMAP_BGP, &rmap_path);
- if (ret == RMAP_DENYMATCH) {
- bgp_attr_flush(&dummy_attr);
- bgp_evpn_withdraw_type5_route(
- bgp, p, afi, safi);
- } else
- bgp_evpn_advertise_type5_route(
- bgp, p, &dummy_attr,
- afi, safi);
- } else {
- bgp_evpn_advertise_type5_route(bgp, p,
- new_select->attr,
- afi, safi);
-
- }
- } else if (advertise_type5_routes(bgp, afi) &&
- old_select &&
- is_route_injectable_into_evpn(old_select))
- bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
- }
+ bgp_process_evpn_route_injection(bgp, afi, safi, rn, new_select,
+ old_select);
/* Clear any route change flags. */
bgp_zebra_clear_route_change_flags(rn);
@@ -3090,7 +3126,7 @@ static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi,
return;
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) {
struct bgp_node *prn = NULL;
struct bgp_table *table = NULL;
@@ -3202,7 +3238,7 @@ static bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
uint8_t type, uint8_t stype,
struct attr *attr, struct bgp_node *rn)
{
- bool ret = 0;
+ bool ret = false;
/* Only validated for unicast and multicast currently. */
/* Also valid for EVPN where the nexthop is an IP address. */
@@ -3221,6 +3257,10 @@ static bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
/* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
* there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
* it is not an IPv6 link-local address.
+ *
+ * If we receive an UPDATE with nexthop length set to 32 bytes
+ * we shouldn't discard an UPDATE if it's set to (::).
+ * The link-local (2st) is validated along the code path later.
*/
if (attr->mp_nexthop_len) {
switch (attr->mp_nexthop_len) {
@@ -3234,7 +3274,6 @@ static bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
- case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
ret = (IN6_IS_ADDR_UNSPECIFIED(&attr->mp_nexthop_global)
|| IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
@@ -3243,6 +3282,13 @@ static bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
|| bgp_nexthop_self(bgp, afi, type, stype,
attr, rn));
break;
+ case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
+ ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
+ || IN6_IS_ADDR_MULTICAST(
+ &attr->mp_nexthop_global)
+ || bgp_nexthop_self(bgp, afi, type, stype, attr,
+ rn));
+ break;
default:
ret = true;
@@ -3277,7 +3323,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
uint8_t pi_type = 0;
uint8_t pi_sub_type = 0;
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
int vnc_implicit_withdraw = 0;
#endif
int same_attr = 0;
@@ -3376,7 +3422,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
* benefit from consistent behavior across different BGP
* implementations.
*/
- if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED)
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
if (!bgp_inbound_policy_exists(peer,
&peer->filter[afi][safi])) {
reason = "inbound policy missing";
@@ -3389,7 +3435,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
* and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
* and obsoletes RFC 6472.
*/
- if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED)
+ if (peer->bgp->reject_as_sets)
if (aspath_check_as_sets(attr->aspath)) {
reason =
"as-path contains AS_SET or AS_CONFED_SET type;";
@@ -3577,7 +3623,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
bgp_damp_withdraw(pi, rn, afi, safi, 1);
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) {
struct bgp_node *prn = NULL;
struct bgp_table *table = NULL;
@@ -3667,7 +3713,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
}
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST)) {
if (vnc_implicit_withdraw) {
@@ -3750,7 +3796,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
} else
bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID);
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) {
struct bgp_node *prn = NULL;
struct bgp_table *table = NULL;
@@ -3801,7 +3847,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
vpn_leak_to_vrf_update(bgp, pi);
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if (SAFI_MPLS_VPN == safi) {
mpls_label_t label_decoded = decode_label(label);
@@ -3910,7 +3956,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* route_node_get lock */
bgp_unlock_node(rn);
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) {
struct bgp_node *prn = NULL;
struct bgp_table *table = NULL;
@@ -3950,7 +3996,7 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
vpn_leak_to_vrf_update(bgp, new);
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if (SAFI_MPLS_VPN == safi) {
mpls_label_t label_decoded = decode_label(label);
@@ -4007,7 +4053,7 @@ filtered:
bgp_unlock_node(rn);
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
/*
* Filtered update is treated as an implicit withdrawal (see
* bgp_rib_remove()
@@ -4032,7 +4078,7 @@ int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct bgp_node *rn;
struct bgp_path_info *pi;
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
0);
@@ -4530,7 +4576,7 @@ void bgp_clear_route_all(struct peer *peer)
FOREACH_AFI_SAFI (afi, safi)
bgp_clear_route(peer, afi, safi);
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
rfapiProcessPeerDown(peer);
#endif
}
@@ -4918,7 +4964,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
struct attr attr;
struct attr *attr_new;
route_map_result_t ret;
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
int vnc_implicit_withdraw = 0;
#endif
@@ -5000,7 +5046,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp_path_info_restore(rn, pi);
else
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST)) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
@@ -5019,7 +5065,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp_attr_unintern(&pi->attr);
pi->attr = attr_new;
pi->uptime = bgp_clock();
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST)) {
if (vnc_implicit_withdraw) {
@@ -5188,7 +5234,7 @@ static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
/* Withdraw static BGP route from routing table. */
if (pi) {
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
rfapiProcessWithdraw(
pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
1); /* Kill, since it is an administrative change */
@@ -5215,7 +5261,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
struct attr *attr_new;
struct attr attr = {0};
struct bgp_path_info *pi;
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
mpls_label_t label = 0;
#endif
uint32_t num_labels = 0;
@@ -5317,7 +5363,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
bgp_attr_unintern(&pi->attr);
pi->attr = attr_new;
pi->uptime = bgp_clock();
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
if (pi->extra)
label = decode_label(&pi->extra->label[0]);
#endif
@@ -5330,7 +5376,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
vpn_leak_to_vrf_update(bgp, pi);
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
pi->attr, afi, safi, pi->type,
pi->sub_type, &label);
@@ -5351,7 +5397,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
new->extra->label[0] = bgp_static->label;
new->extra->num_labels = num_labels;
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
label = decode_label(&bgp_static->label);
#endif
@@ -5370,7 +5416,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
vpn_leak_to_vrf_update(bgp, new);
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
safi, new->type, new->sub_type, &label);
#endif
@@ -6854,7 +6900,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
* subsumed by the previously aggregated route) without AS_SET
* or AS_CONFED_SET in the updates.
*/
- if (bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) {
+ if (bgp->reject_as_sets) {
if (as_set == AGGREGATE_AS_SET) {
as_set_new = AGGREGATE_AS_UNSET;
zlog_warn(
@@ -7503,11 +7549,12 @@ static void route_vty_short_status_out(struct vty *vty,
vty_out(vty, " ");
}
-static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
+static char *bgp_nexthop_hostname(struct peer *peer,
+ struct bgp_nexthop_cache *bnc)
{
if (peer->hostname
- && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)
- && !(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
+ && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME) && bnc
+ && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
return peer->hostname;
return NULL;
}
@@ -7529,7 +7576,8 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
bool nexthop_othervrf = false;
vrf_id_t nexthop_vrfid = VRF_DEFAULT;
const char *nexthop_vrfname = VRF_DEFAULT_NAME;
- char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
+ char *nexthop_hostname =
+ bgp_nexthop_hostname(path->peer, path->nexthop);
if (json_paths)
json_path = json_object_new_object();
@@ -7819,32 +7867,19 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
/* MED/Metric */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
- if (json_paths) {
-
- /*
- * Adding "metric" field to match with corresponding
- * CLI. "med" will be deprecated in future.
- */
- json_object_int_add(json_path, "med", attr->med);
+ if (json_paths)
json_object_int_add(json_path, "metric", attr->med);
- } else
+ else
vty_out(vty, "%10u", attr->med);
else if (!json_paths)
vty_out(vty, " ");
/* Local Pref */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
- if (json_paths) {
-
- /*
- * Adding "locPrf" field to match with corresponding
- * CLI. "localPref" will be deprecated in future.
- */
- json_object_int_add(json_path, "localpref",
- attr->local_pref);
+ if (json_paths)
json_object_int_add(json_path, "locPrf",
- attr->local_pref);
- } else
+ attr->local_pref);
+ else
vty_out(vty, "%7u", attr->local_pref);
else if (!json_paths)
vty_out(vty, " ");
@@ -7863,17 +7898,10 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
/* Print aspath */
if (attr->aspath) {
- if (json_paths) {
-
- /*
- * Adding "path" field to match with corresponding
- * CLI. "aspath" will be deprecated in future.
- */
- json_object_string_add(json_path, "aspath",
- attr->aspath->str);
+ if (json_paths)
json_object_string_add(json_path, "path",
- attr->aspath->str);
- } else
+ attr->aspath->str);
+ else
aspath_print_vty(vty, "%s", attr->aspath, " ");
}
@@ -7936,7 +7964,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
vty_out(vty, "%s\n", attr->ecommunity->str);
}
-#if ENABLE_BGP_VNC
+#ifdef ENABLE_BGP_VNC
/* prints an additional line, indented, with VNC info, if
* present */
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
@@ -8016,34 +8044,16 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
json_object_int_add(json_net, "metric",
attr->med);
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
-
- /*
- * Adding "locPrf" field to match with
- * corresponding CLI. "localPref" will be
- * deprecated in future.
- */
- json_object_int_add(json_net, "localPref",
- attr->local_pref);
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
json_object_int_add(json_net, "locPrf",
- attr->local_pref);
- }
+ attr->local_pref);
json_object_int_add(json_net, "weight", attr->weight);
/* Print aspath */
- if (attr->aspath) {
-
- /*
- * Adding "path" field to match with
- * corresponding CLI. "localPref" will be
- * deprecated in future.
- */
- json_object_string_add(json_net, "asPath",
- attr->aspath->str);
+ if (attr->aspath)
json_object_string_add(json_net, "path",
- attr->aspath->str);
- }
+ attr->aspath->str);
/* Print origin */
json_object_string_add(json_net, "bgpOriginCode",
@@ -8308,7 +8318,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
mac = ecom_mac2str((char *)routermac->val);
if (mac) {
if (!json_path) {
- vty_out(vty, "/%s", (char *)mac);
+ vty_out(vty, "/%s", mac);
} else {
json_object_string_add(json_overlay, "rmac",
mac);
@@ -8638,7 +8648,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
bool nexthop_self =
CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
int i;
- char *nexthop_hostname = bgp_nexthop_hostname(path->peer, attr);
+ char *nexthop_hostname =
+ bgp_nexthop_hostname(path->peer, path->nexthop);
if (json_paths) {
json_path = json_object_new_object();
@@ -9077,21 +9088,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
bgp_origin_long_str[attr->origin]);
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
- if (json_paths) {
- /*
- * Adding "metric" field to match with
- * corresponding CLI. "med" will be
- * deprecated in future.
- */
- json_object_int_add(json_path, "med", attr->med);
+ if (json_paths)
json_object_int_add(json_path, "metric", attr->med);
- } else
+ else
vty_out(vty, ", metric %u", attr->med);
}
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
if (json_paths)
- json_object_int_add(json_path, "localpref",
+ json_object_int_add(json_path, "locPrf",
attr->local_pref);
else
vty_out(vty, ", localpref %u", attr->local_pref);
@@ -10291,7 +10296,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
}
} else if (safi == SAFI_EVPN) {
struct bgp_node *longest_pfx;
- bool is_exact_pfxlen_match = FALSE;
+ bool is_exact_pfxlen_match = false;
for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
const struct prefix *rn_p = bgp_node_get_prefix(rn);
@@ -10303,7 +10308,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
continue;
longest_pfx = NULL;
- is_exact_pfxlen_match = FALSE;
+ is_exact_pfxlen_match = false;
/*
* Search through all the prefixes for a match. The
* pfx's are enumerated in ascending order of pfxlens.
@@ -10325,7 +10330,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
bgp_evpn_get_type5_prefixlen(
rm_p);
if (type5_pfxlen == match.prefixlen) {
- is_exact_pfxlen_match = TRUE;
+ is_exact_pfxlen_match = true;
bgp_unlock_node(rm);
break;
}
@@ -10552,45 +10557,177 @@ DEFUN (show_ip_bgp_large_community,
}
static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
- safi_t safi);
+ safi_t safi, struct json_object *json);
+
+
+DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
+ SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
+ "Display number of prefixes for all afi/safi\n" JSON_STR)
+{
+ bool uj = use_json(argc, argv);
+ struct bgp *bgp = NULL;
+ safi_t safi;
+ afi_t afi;
+ int idx = 0;
+ struct json_object *json_all = NULL;
+ struct json_object *json_afi_safi = NULL;
+
+ bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+ &bgp, false);
+ if (!bgp)
+ return CMD_WARNING;
+
+ if (uj)
+ json_all = json_object_new_object();
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ /*
+ * So limit output to those afi/safi pairs that
+ * actually have something interesting in them
+ */
+ if (strmatch(get_afi_safi_str(afi, safi, true),
+ "Unknown")) {
+ continue;
+ }
+ if (uj) {
+ json_afi_safi = json_object_new_array();
+ json_object_object_add(
+ json_all,
+ get_afi_safi_str(afi, safi, true),
+ json_afi_safi);
+ } else {
+ json_afi_safi = NULL;
+ }
+ bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
+ }
+
+ if (uj) {
+ vty_out(vty, "%s",
+ json_object_to_json_string_ext(
+ json_all, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json_all);
+ }
+
+ return CMD_SUCCESS;
+}
/* BGP route print out function without JSON */
-DEFUN (show_ip_bgp,
- show_ip_bgp_cmd,
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
+DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
+ show_ip_bgp_l2vpn_evpn_statistics_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_INSTANCE_HELP_STR
+ L2VPN_HELP_STR
+ EVPN_HELP_STR
+ "BGP RIB advertisement statistics\n"
+ JSON_STR)
+{
+ afi_t afi;
+ safi_t safi;
+ struct bgp *bgp = NULL;
+ int idx = 0, ret;
+ bool uj = use_json(argc, argv);
+ struct json_object *json_afi_safi = NULL, *json = NULL;
+
+ bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+ &bgp, false);
+ if (!idx)
+ return CMD_WARNING;
+
+ if (uj)
+ json_afi_safi = json_object_new_array();
+ else
+ json_afi_safi = NULL;
+
+ ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
+
+ if (uj) {
+ json = json_object_new_object();
+ json_object_object_add(json, get_afi_safi_str(afi, safi, true),
+ json_afi_safi);
+ vty_out(vty, "%s", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+ return ret;
+}
+
+/* BGP route print out function without JSON */
+DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
+ " [" BGP_SAFI_WITH_LABEL_CMD_STR
+ "]]\
+ statistics [json]",
+ SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR
+ "BGP RIB advertisement statistics\n" JSON_STR)
+{
+ afi_t afi;
+ safi_t safi;
+ struct bgp *bgp = NULL;
+ int idx = 0, ret;
+ bool uj = use_json(argc, argv);
+ struct json_object *json_afi_safi = NULL, *json = NULL;
+
+ bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+ &bgp, false);
+ if (!idx)
+ return CMD_WARNING;
+
+ if (uj)
+ json_afi_safi = json_object_new_array();
+ else
+ json_afi_safi = NULL;
+
+ ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
+
+ if (uj) {
+ json = json_object_new_object();
+ json_object_object_add(json, get_afi_safi_str(afi, safi, true),
+ json_afi_safi);
+ vty_out(vty, "%s",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+ return ret;
+}
+
+/* BGP route print out function without JSON */
+DEFUN(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>\
|route-map WORD\
|prefix-list WORD\
|filter-list WORD\
- |statistics\
|community-list <(1-500)|WORD> [exact-match]\
|A.B.C.D/M longer-prefixes\
|X:X::X:X/M longer-prefixes\
- >",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_INSTANCE_HELP_STR
- BGP_AFI_HELP_STR
- BGP_SAFI_WITH_LABEL_HELP_STR
- "Display detailed information about dampening\n"
- "Display detail of configured dampening parameters\n"
- "Display routes matching the route-map\n"
- "A route-map to match on\n"
- "Display routes conforming to the prefix-list\n"
- "Prefix-list name\n"
- "Display routes conforming to the filter-list\n"
- "Regular expression access list name\n"
- "BGP RIB advertisement statistics\n"
- "Display routes matching the community-list\n"
- "community-list number\n"
- "community-list name\n"
- "Exact match of the communities\n"
- "IPv4 prefix\n"
- "Display route and more specific routes\n"
- "IPv6 prefix\n"
- "Display route and more specific routes\n")
+ >",
+ SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
+ BGP_SAFI_WITH_LABEL_HELP_STR
+ "Display detailed information about dampening\n"
+ "Display detail of configured dampening parameters\n"
+ "Display routes matching the route-map\n"
+ "A route-map to match on\n"
+ "Display routes conforming to the prefix-list\n"
+ "Prefix-list name\n"
+ "Display routes conforming to the filter-list\n"
+ "Regular expression access list name\n"
+ "Display routes matching the community-list\n"
+ "community-list number\n"
+ "community-list name\n"
+ "Exact match of the communities\n"
+ "IPv4 prefix\n"
+ "Display route and more specific routes\n"
+ "IPv6 prefix\n"
+ "Display route and more specific routes\n")
{
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
@@ -10616,9 +10753,6 @@ DEFUN (show_ip_bgp,
return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
safi, bgp_show_type_filter_list);
- if (argv_find(argv, argc, "statistics", &idx))
- return bgp_table_stats(vty, bgp, afi, safi);
-
if (argv_find(argv, argc, "route-map", &idx))
return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
safi, bgp_show_type_route_map);
@@ -11028,22 +11162,33 @@ enum bgp_stats {
BGP_STATS_MAX,
};
-static const char *const table_stats_strs[] = {
- [BGP_STATS_PREFIXES] = "Total Prefixes",
- [BGP_STATS_TOTPLEN] = "Average prefix length",
- [BGP_STATS_RIB] = "Total Advertisements",
- [BGP_STATS_UNAGGREGATEABLE] = "Unaggregateable prefixes",
- [BGP_STATS_MAX_AGGREGATEABLE] =
- "Maximum aggregateable prefixes",
- [BGP_STATS_AGGREGATES] = "BGP Aggregate advertisements",
- [BGP_STATS_SPACE] = "Address space advertised",
- [BGP_STATS_ASPATH_COUNT] = "Advertisements with paths",
- [BGP_STATS_ASPATH_MAXHOPS] = "Longest AS-Path (hops)",
- [BGP_STATS_ASPATH_MAXSIZE] = "Largest AS-Path (bytes)",
- [BGP_STATS_ASPATH_TOTHOPS] = "Average AS-Path length (hops)",
- [BGP_STATS_ASPATH_TOTSIZE] = "Average AS-Path size (bytes)",
- [BGP_STATS_ASN_HIGHEST] = "Highest public ASN",
- [BGP_STATS_MAX] = NULL,
+#define TABLE_STATS_IDX_VTY 0
+#define TABLE_STATS_IDX_JSON 1
+
+static const char *table_stats_strs[][2] = {
+ [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
+ [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
+ [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
+ [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
+ "unaggregateablePrefixes"},
+ [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
+ "maximumAggregateablePrefixes"},
+ [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
+ "bgpAggregateAdvertisements"},
+ [BGP_STATS_SPACE] = {"Address space advertised",
+ "addressSpaceAdvertised"},
+ [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
+ "advertisementsWithPaths"},
+ [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
+ "longestAsPath"},
+ [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
+ "largestAsPath"},
+ [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
+ "averageAsPathLengthHops"},
+ [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
+ "averageAsPathSizeBytes"},
+ [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
+ [BGP_STATS_MAX] = {NULL, NULL}
};
struct bgp_table_stats {
@@ -11168,7 +11313,9 @@ static int bgp_table_stats_walker(struct thread *t)
ts->counts[BGP_STATS_MAXBITLEN] = space;
for (rn = top; rn; rn = bgp_route_next(rn)) {
- if (ts->table->safi == SAFI_MPLS_VPN) {
+ if (ts->table->safi == SAFI_MPLS_VPN
+ || ts->table->safi == SAFI_ENCAP
+ || ts->table->safi == SAFI_EVPN) {
struct bgp_table *table;
table = bgp_node_get_bgp_table_info(rn);
@@ -11188,18 +11335,36 @@ static int bgp_table_stats_walker(struct thread *t)
}
static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
- safi_t safi)
+ safi_t safi, struct json_object *json_array)
{
struct bgp_table_stats ts;
unsigned int i;
+ int ret = CMD_SUCCESS;
+ char temp_buf[20];
+ struct json_object *json = NULL;
+
+ if (json_array)
+ json = json_object_new_object();
if (!bgp->rib[afi][safi]) {
- vty_out(vty, "%% No RIB exist's for the AFI(%d)/SAFI(%d)\n",
- afi, safi);
- return CMD_WARNING;
+ char warning_msg[50];
+
+ snprintf(warning_msg, sizeof(warning_msg),
+ "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
+ safi);
+
+ if (!json)
+ vty_out(vty, "%s\n", warning_msg);
+ else
+ json_object_string_add(json, "warning", warning_msg);
+
+ ret = CMD_WARNING;
+ goto end_table_stats;
}
- vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
+ if (!json)
+ vty_out(vty, "BGP %s RIB statistics\n",
+ get_afi_safi_str(afi, safi, false));
/* labeled-unicast routes live in the unicast table */
if (safi == SAFI_LABELED_UNICAST)
@@ -11210,7 +11375,8 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
for (i = 0; i < BGP_STATS_MAX; i++) {
- if (!table_stats_strs[i])
+ if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
+ || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
continue;
switch (i) {
@@ -11225,54 +11391,166 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
#endif
case BGP_STATS_ASPATH_TOTHOPS:
case BGP_STATS_ASPATH_TOTSIZE:
- vty_out(vty, "%-30s: ", table_stats_strs[i]);
- vty_out(vty, "%12.2f",
- ts.counts[i]
- ? (float)ts.counts[i]
- / (float)ts.counts
+ if (!json) {
+ snprintf(
+ temp_buf, sizeof(temp_buf), "%12.2f",
+ ts.counts[i]
+ ? (float)ts.counts[i]
+ / (float)ts.counts
+ [BGP_STATS_ASPATH_COUNT]
+ : 0);
+ vty_out(vty, "%-30s: %s",
+ table_stats_strs[i]
+ [TABLE_STATS_IDX_VTY],
+ temp_buf);
+ } else {
+ json_object_double_add(
+ json,
+ table_stats_strs[i]
+ [TABLE_STATS_IDX_JSON],
+ ts.counts[i]
+ ? (double)ts.counts[i]
+ / (double)ts.counts
[BGP_STATS_ASPATH_COUNT]
- : 0);
+ : 0);
+ }
break;
case BGP_STATS_TOTPLEN:
- vty_out(vty, "%-30s: ", table_stats_strs[i]);
- vty_out(vty, "%12.2f",
- ts.counts[i]
- ? (float)ts.counts[i]
- / (float)ts.counts
+ if (!json) {
+ snprintf(
+ temp_buf, sizeof(temp_buf), "%12.2f",
+ ts.counts[i]
+ ? (float)ts.counts[i]
+ / (float)ts.counts
+ [BGP_STATS_PREFIXES]
+ : 0);
+ vty_out(vty, "%-30s: %s",
+ table_stats_strs[i]
+ [TABLE_STATS_IDX_VTY],
+ temp_buf);
+ } else {
+ json_object_double_add(
+ json,
+ table_stats_strs[i]
+ [TABLE_STATS_IDX_JSON],
+ ts.counts[i]
+ ? (double)ts.counts[i]
+ / (double)ts.counts
[BGP_STATS_PREFIXES]
- : 0);
+ : 0);
+ }
break;
case BGP_STATS_SPACE:
- vty_out(vty, "%-30s: ", table_stats_strs[i]);
- vty_out(vty, "%12g\n", ts.total_space);
-
+ if (!json) {
+ snprintf(temp_buf, sizeof(temp_buf), "%12g",
+ ts.total_space);
+ vty_out(vty, "%-30s: %s\n",
+ table_stats_strs[i]
+ [TABLE_STATS_IDX_VTY],
+ temp_buf);
+ } else {
+ json_object_double_add(
+ json,
+ table_stats_strs[i]
+ [TABLE_STATS_IDX_JSON],
+ (double)ts.total_space);
+ }
if (afi == AFI_IP6) {
- vty_out(vty, "%30s: ", "/32 equivalent ");
- vty_out(vty, "%12g\n",
- ts.total_space * pow(2.0, -128 + 32));
- vty_out(vty, "%30s: ", "/48 equivalent ");
- vty_out(vty, "%12g\n",
- ts.total_space * pow(2.0, -128 + 48));
+ if (!json) {
+ snprintf(temp_buf, sizeof(temp_buf),
+ "%12g",
+ ts.total_space
+ * pow(2.0, -128 + 32));
+ vty_out(vty, "%30s: %s\n",
+ "/32 equivalent %s\n",
+ temp_buf);
+ } else {
+ json_object_double_add(
+ json, "/32equivalent",
+ (double)(ts.total_space
+ * pow(2.0,
+ -128 + 32)));
+ }
+ if (!json) {
+ snprintf(temp_buf, sizeof(temp_buf),
+ "%12g",
+ ts.total_space
+ * pow(2.0, -128 + 48));
+ vty_out(vty, "%30s: %s\n",
+ "/48 equivalent %s\n",
+ temp_buf);
+ } else {
+ json_object_double_add(
+ json, "/48equivalent",
+ (double)(ts.total_space
+ * pow(2.0,
+ -128 + 48)));
+ }
} else {
- vty_out(vty, "%30s: ", "% announced ");
- vty_out(vty, "%12.2f\n",
- ts.total_space * 100. * pow(2.0, -32));
- vty_out(vty, "%30s: ", "/8 equivalent ");
- vty_out(vty, "%12.2f\n",
- ts.total_space * pow(2.0, -32 + 8));
- vty_out(vty, "%30s: ", "/24 equivalent ");
- vty_out(vty, "%12.2f\n",
- ts.total_space * pow(2.0, -32 + 24));
+ if (!json) {
+ snprintf(temp_buf, sizeof(temp_buf),
+ "%12.2f",
+ ts.total_space * 100.
+ * pow(2.0, -32));
+ vty_out(vty, "%30s: %s\n",
+ "% announced ", temp_buf);
+ } else {
+ json_object_double_add(
+ json, "%announced",
+ (double)(ts.total_space * 100.
+ * pow(2.0, -32)));
+ }
+ if (!json) {
+ snprintf(temp_buf, sizeof(temp_buf),
+ "%12.2f",
+ ts.total_space
+ * pow(2.0, -32 + 8));
+ vty_out(vty, "%30s: %s\n",
+ "/8 equivalent ", temp_buf);
+ } else {
+ json_object_double_add(
+ json, "/8equivalent",
+ (double)(ts.total_space
+ * pow(2.0, -32 + 8)));
+ }
+ if (!json) {
+ snprintf(temp_buf, sizeof(temp_buf),
+ "%12.2f",
+ ts.total_space
+ * pow(2.0, -32 + 24));
+ vty_out(vty, "%30s: %s\n",
+ "/24 equivalent ", temp_buf);
+ } else {
+ json_object_double_add(
+ json, "/24equivalent",
+ (double)(ts.total_space
+ * pow(2.0, -32 + 24)));
+ }
}
break;
default:
- vty_out(vty, "%-30s: ", table_stats_strs[i]);
- vty_out(vty, "%12llu", ts.counts[i]);
+ if (!json) {
+ snprintf(temp_buf, sizeof(temp_buf), "%12llu",
+ ts.counts[i]);
+ vty_out(vty, "%-30s: %s",
+ table_stats_strs[i]
+ [TABLE_STATS_IDX_VTY],
+ temp_buf);
+ } else {
+ json_object_int_add(
+ json,
+ table_stats_strs[i]
+ [TABLE_STATS_IDX_JSON],
+ ts.counts[i]);
+ }
}
-
- vty_out(vty, "\n");
+ if (!json)
+ vty_out(vty, "\n");
}
- return CMD_SUCCESS;
+end_table_stats:
+ if (json)
+ json_object_array_add(json_array, json);
+ return ret;
}
enum bgp_pcounts {
@@ -11610,8 +11888,8 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
struct bgp_table *table;
struct bgp_adj_in *ain;
struct bgp_adj_out *adj;
- unsigned long output_count;
- unsigned long filtered_count;
+ unsigned long output_count = 0;
+ unsigned long filtered_count = 0;
struct bgp_node *rn;
int header1 = 1;
struct bgp *bgp;
@@ -11901,6 +12179,12 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
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)
@@ -12284,7 +12568,7 @@ static int bgp_distance_set(struct vty *vty, const char *distance_str,
distance = atoi(distance_str);
/* Get BGP distance node. */
- rn = bgp_node_get(bgp_distance_table[afi][safi], (struct prefix *)&p);
+ rn = bgp_node_get(bgp_distance_table[afi][safi], &p);
bdistance = bgp_node_get_bgp_distance_info(rn);
if (bdistance)
bgp_unlock_node(rn);
@@ -12325,8 +12609,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str,
return CMD_WARNING_CONFIG_FAILED;
}
- rn = bgp_node_lookup(bgp_distance_table[afi][safi],
- (struct prefix *)&p);
+ rn = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
if (!rn) {
vty_out(vty, "Can't find specified prefix\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -13149,9 +13432,12 @@ void bgp_route_init(void)
/* IPv4 labeled-unicast configuration. */
install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
install_element(VIEW_NODE, &show_ip_bgp_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
install_element(VIEW_NODE,
&show_ip_bgp_instance_neighbor_advertised_route_cmd);