diff options
Diffstat (limited to 'bgpd/bgp_route.c')
| -rw-r--r-- | bgpd/bgp_route.c | 786 |
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); |
