From 96c81f66717110e0bf77f5dfa043d9862896d495 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Wed, 12 May 2021 18:54:11 +0200 Subject: [PATCH] bgpd: add terse display option on show bgp summary Add a terse option to show bgp summary to shorten output. Do not show the following information about the BGP instances: the number of RIB entries, the table version and the used memory. The "terse" option can be used in combination with the "remote-as", "neighbor", "failed" and "established" filters, and with the "wide" option as well. Before patch: ubuntu# show bgp summary remote-as 123456 IPv4 Unicast Summary (VRF default): BGP router identifier X.X.X.X, local AS number XXX vrf-id 0 BGP table version 0 RIB entries 3, using 552 bytes of memory Peers 5, using 3635 KiB of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc 10.200.200.2 4 123456 81432 4 0 56092 0 00:00:13 572106 0 N/A Displayed neighbors 1 Total number of neighbors 4 IPv6 Unicast Summary (VRF default): BGP router identifier X.X.X.X, local AS number XXX vrf-id 0 BGP table version 0 RIB entries 3, using 552 bytes of memory Peers 5, using 3635 KiB of memory Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc % No matching neighbor Total number of neighbors 5 After patch: ubuntu# show bgp summary remote-as 123456 terse IPv4 Unicast Summary (VRF default): BGP router identifier X.X.X.X, local AS number XXX vrf-id 0 Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc 10.200.200.2 4 123456 81432 4 0 56092 0 00:00:13 572106 0 N/A Displayed neighbors 1 Total number of neighbors 4 IPv6 Unicast Summary (VRF default): BGP router identifier X.X.X.X, local AS number XXX vrf-id 1 % No matching neighbor Signed-off-by: Louis Scalbert --- bgpd/bgp_damp.c | 2 +- bgpd/bgp_damp.h | 2 +- bgpd/bgp_evpn_vty.c | 8 +- bgpd/bgp_route.c | 48 +++--- bgpd/bgp_route.h | 1 + bgpd/bgp_vty.c | 158 +++++++++++------- bgpd/bgp_vty.h | 2 +- doc/user/bgp.rst | 7 + .../test_all_protocol_startup.py | 50 ++++-- 9 files changed, 171 insertions(+), 107 deletions(-) diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 3db142b8cf..07c70d5aae 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -822,7 +822,7 @@ static int bgp_print_dampening_parameters(struct bgp *bgp, struct vty *vty, } int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi, - uint8_t show_flags) + uint16_t show_flags) { struct bgp *bgp; diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h index 3c8f138d6a..c03a0cc5c9 100644 --- a/bgpd/bgp_damp.h +++ b/bgpd/bgp_damp.h @@ -166,7 +166,7 @@ extern const char *bgp_damp_reuse_time_vty(struct vty *vty, safi_t safi, bool use_json, json_object *json); extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t, - uint8_t); + uint16_t); extern void bgp_peer_damp_enable(struct peer *peer, afi_t afi, safi_t safi, time_t half, unsigned int reuse, unsigned int suppress, time_t max); diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index fb3ba2c0ec..192ead6fd4 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -4310,7 +4310,7 @@ DEFPY(show_bgp_l2vpn_evpn_nh, * Display EVPN neighbor summary. */ DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd, - "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [|remote-as <(1-4294967295)|internal|external>>] [wide] [json]", + "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json]", SHOW_STR BGP_STR "bgp vrf\n" "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR @@ -4325,6 +4325,7 @@ DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd, "AS number\n" "Internal (iBGP) AS sessions\n" "External (eBGP) AS sessions\n" + "Shorten the information on BGP instances\n" "Increase table width for longer output\n" JSON_STR) { int idx_vrf = 0; @@ -4333,7 +4334,7 @@ DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd, char *neighbor = NULL; as_t as = 0; /* 0 means AS filter not set */ int as_type = AS_UNSPECIFIED; - uint8_t show_flags = 0; + uint16_t show_flags = 0; if (argv_find(argv, argc, "vrf", &idx_vrf)) vrf = argv[++idx_vrf]->arg; @@ -4357,6 +4358,9 @@ DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd, as = (as_t)atoi(argv[idx + 1]->arg); } + if (argv_find(argv, argc, "terse", &idx)) + SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE); + if (argv_find(argv, argc, "wide", &idx)) SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c61aedb560..36fd537c4d 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -10569,13 +10569,13 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr, 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, uint8_t show_flags); + safi_t safi, uint16_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, char *rd, int is_last, unsigned long *output_cum, unsigned long *total_cum, - unsigned long *json_header_depth, uint8_t show_flags, + unsigned long *json_header_depth, uint16_t show_flags, enum rpki_states rpki_target_state) { struct bgp_path_info *pi; @@ -10994,7 +10994,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, unsigned long json_header_depth = 0; struct bgp_table *itable; bool show_msg; - uint8_t show_flags = 0; + uint16_t show_flags = 0; show_msg = (!use_json && type == bgp_show_type_normal); @@ -11036,7 +11036,7 @@ int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, } static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, enum bgp_show_type type, void *output_arg, - uint8_t show_flags, enum rpki_states rpki_target_state) + uint16_t show_flags, enum rpki_states rpki_target_state) { struct bgp_table *table; unsigned long json_header_depth = 0; @@ -11076,7 +11076,7 @@ static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi, } static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi, - safi_t safi, uint8_t show_flags) + safi_t safi, uint16_t show_flags) { struct listnode *node, *nnode; struct bgp *bgp; @@ -11582,7 +11582,7 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, int i; char *str; int first = 0; - uint8_t show_flags = 0; + uint16_t show_flags = 0; int ret; if (uj) @@ -11625,7 +11625,7 @@ 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; + uint16_t show_flags = 0; if (uj) SET_FLAG(show_flags, BGP_SHOW_OPT_JSON); @@ -11705,7 +11705,7 @@ DEFUN (show_ip_bgp_large_community, bool exact_match = 0; struct bgp *bgp = NULL; bool uj = use_json(argc, argv); - uint8_t show_flags = 0; + uint16_t show_flags = 0; if (uj) { argc--; @@ -11909,7 +11909,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd, int exact_match = 0; struct bgp *bgp = NULL; int idx = 0; - uint8_t show_flags = 0; + uint16_t show_flags = 0; /* [ [all]] */ if (all) { @@ -12022,7 +12022,7 @@ DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd, char *prefix_version = NULL; char *bgp_community_alias = NULL; bool first = true; - uint8_t show_flags = 0; + uint16_t show_flags = 0; enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED; if (uj) { @@ -12343,7 +12343,7 @@ DEFPY (show_ip_bgp_instance_all, safi_t safi = SAFI_UNICAST; struct bgp *bgp = NULL; int idx = 0; - uint8_t show_flags = 0; + uint16_t show_flags = 0; if (uj) { argc--; @@ -12368,7 +12368,7 @@ static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr, { regex_t *regex; int rc; - uint8_t show_flags = 0; + uint16_t show_flags = 0; if (use_json) SET_FLAG(show_flags, BGP_SHOW_OPT_JSON); @@ -12396,7 +12396,7 @@ static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp, safi_t safi, enum bgp_show_type type) { struct prefix_list *plist; - uint8_t show_flags = 0; + uint16_t show_flags = 0; plist = prefix_list_lookup(afi, prefix_list_str); if (plist == NULL) { @@ -12414,7 +12414,7 @@ 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; + uint16_t show_flags = 0; as_list = as_list_lookup(filter); if (as_list == NULL) { @@ -12432,7 +12432,7 @@ 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; + uint16_t show_flags = 0; rmap = route_map_lookup_by_name(rmap_str); if (!rmap) { @@ -12446,7 +12446,7 @@ static int bgp_show_route_map(struct vty *vty, struct bgp *bgp, static int bgp_show_community(struct vty *vty, struct bgp *bgp, const char *comstr, int exact, afi_t afi, - safi_t safi, uint8_t show_flags) + safi_t safi, uint16_t show_flags) { struct community *com; int ret = 0; @@ -12471,7 +12471,7 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, safi_t safi) { struct community_list *list; - uint8_t show_flags = 0; + uint16_t show_flags = 0; list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER); if (list == NULL) { @@ -12491,7 +12491,7 @@ static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp, { int ret; struct prefix *p; - uint8_t show_flags = 0; + uint16_t show_flags = 0; p = prefix_new(); @@ -13284,7 +13284,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, const char *rmap_name, json_object *json, json_object *json_ar, json_object *json_scode, json_object *json_ocode, - uint8_t show_flags, int *header1, int *header2, char *rd_str, + uint16_t show_flags, int *header1, int *header2, char *rd_str, unsigned long *output_count, unsigned long *filtered_count) { struct bgp_adj_in *ain; @@ -13494,7 +13494,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_adj_route_type type, - const char *rmap_name, uint8_t show_flags) + const char *rmap_name, uint16_t show_flags) { struct bgp *bgp; struct bgp_table *table; @@ -13685,7 +13685,7 @@ DEFPY (show_ip_bgp_instance_neighbor_bestpath_route, struct peer *peer; enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath; int idx = 0; - uint8_t show_flags = 0; + uint16_t show_flags = 0; if (uj) SET_FLAG(show_flags, BGP_SHOW_OPT_JSON); @@ -13741,7 +13741,7 @@ DEFPY (show_ip_bgp_instance_neighbor_advertised_route, enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised; int idx = 0; bool first = true; - uint8_t show_flags = 0; + uint16_t show_flags = 0; if (uj) { argc--; @@ -13923,7 +13923,7 @@ static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, enum bgp_show_type type, bool use_json) { - uint8_t show_flags = 0; + uint16_t show_flags = 0; if (use_json) SET_FLAG(show_flags, BGP_SHOW_OPT_JSON); @@ -13968,7 +13968,7 @@ 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; + uint16_t show_flags = 0; if (uj) { argc--; diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 6d6008ff55..990faa6d51 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -591,6 +591,7 @@ DECLARE_HOOK(bgp_process, #define BGP_SHOW_OPT_ESTABLISHED (1 << 5) #define BGP_SHOW_OPT_FAILED (1 << 6) #define BGP_SHOW_OPT_DETAIL (1 << 7) +#define BGP_SHOW_OPT_TERSE (1 << 8) /* Prototypes. */ extern void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 760a260b12..f024a3460f 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -10734,7 +10734,7 @@ static bool bgp_show_summary_is_peer_filtered(struct peer *peer, /* Show BGP peer's summary information. */ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, struct peer *fpeer, int as_type, as_t as, - uint8_t show_flags) + uint16_t show_flags) { struct peer *peer; struct listnode *node, *nnode; @@ -10756,6 +10756,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, bool show_established = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED); bool show_wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE); + bool show_terse = CHECK_FLAG(show_flags, BGP_SHOW_OPT_TERSE); /* labeled-unicast routes are installed in the unicast table so in order * to @@ -10854,7 +10855,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, json_object_free(json); } else { vty_out(vty, "%% No failed BGP neighbors found\n"); - vty_out(vty, "\nTotal number of neighbors %d\n", count); } return CMD_SUCCESS; } @@ -11017,63 +11017,75 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, json_object_boolean_true_add( json, "dampeningEnabled"); } else { - if (bgp_maxmed_onstartup_configured(bgp) - && bgp->maxmed_active) - vty_out(vty, - "Max-med on-startup active\n"); - if (bgp->v_maxmed_admin) - vty_out(vty, - "Max-med administrative active\n"); + if (!show_terse) { + if (bgp_maxmed_onstartup_configured(bgp) + && bgp->maxmed_active) + vty_out(vty, + "Max-med on-startup active\n"); + if (bgp->v_maxmed_admin) + vty_out(vty, + "Max-med administrative active\n"); - vty_out(vty, "BGP table version %" PRIu64 "\n", - bgp_table_version(bgp->rib[afi][safi])); + vty_out(vty, + "BGP table version %" PRIu64 + "\n", + bgp_table_version( + bgp->rib[afi][safi])); - ents = bgp_table_count(bgp->rib[afi][safi]); - vty_out(vty, - "RIB entries %ld, using %s of memory\n", - ents, - mtype_memstr( - memstrbuf, sizeof(memstrbuf), - ents - * sizeof(struct - bgp_dest))); - - /* Peer related usage */ - ents = bgp->af_peer_count[afi][safi]; - vty_out(vty, "Peers %ld, using %s of memory\n", - ents, - mtype_memstr( - memstrbuf, sizeof(memstrbuf), - ents * sizeof(struct peer))); + ents = bgp_table_count( + bgp->rib[afi][safi]); + vty_out(vty, + "RIB entries %ld, using %s of memory\n", + ents, + mtype_memstr( + memstrbuf, + sizeof(memstrbuf), + ents + * sizeof( + struct + bgp_dest))); - if ((ents = listcount(bgp->group))) + /* Peer related usage */ + ents = bgp->af_peer_count[afi][safi]; vty_out(vty, - "Peer groups %ld, using %s of memory\n", + "Peers %ld, using %s of memory\n", ents, mtype_memstr( memstrbuf, sizeof(memstrbuf), - ents * sizeof(struct - peer_group))); + ents + * sizeof( + struct + peer))); - if (CHECK_FLAG(bgp->af_flags[afi][safi], - BGP_CONFIG_DAMPENING)) - vty_out(vty, "Dampening enabled.\n"); - vty_out(vty, "\n"); + if ((ents = listcount(bgp->group))) + vty_out(vty, + "Peer groups %ld, using %s of memory\n", + ents, + mtype_memstr( + memstrbuf, + sizeof(memstrbuf), + ents + * sizeof( + struct + peer_group))); + + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_DAMPENING)) + vty_out(vty, + "Dampening enabled.\n"); + } + if (show_failed) { + vty_out(vty, "\n"); - /* Subtract 8 here because 'Neighbor' is - * 8 characters */ - vty_out(vty, "Neighbor"); - vty_out(vty, "%*s", max_neighbor_width - 8, - " "); - if (show_failed) + /* Subtract 8 here because 'Neighbor' is + * 8 characters */ + vty_out(vty, "Neighbor"); + vty_out(vty, "%*s", + max_neighbor_width - 8, " "); vty_out(vty, BGP_SHOW_SUMMARY_HEADER_FAILED); - else - vty_out(vty, - show_wide - ? BGP_SHOW_SUMMARY_HEADER_ALL_WIDE - : BGP_SHOW_SUMMARY_HEADER_ALL); + } } } @@ -11259,6 +11271,23 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, filtered_count++; continue; } + + if ((count - filtered_count) == 1) { + /* display headline before the first + * neighbor line */ + vty_out(vty, "\n"); + + /* Subtract 8 here because 'Neighbor' is + * 8 characters */ + vty_out(vty, "Neighbor"); + vty_out(vty, "%*s", + max_neighbor_width - 8, " "); + vty_out(vty, + show_wide + ? BGP_SHOW_SUMMARY_HEADER_ALL_WIDE + : BGP_SHOW_SUMMARY_HEADER_ALL); + } + memset(dn_flag, '\0', sizeof(dn_flag)); if (peer_dynamic_neighbor(peer)) { dn_flag[0] = '*'; @@ -11396,19 +11425,20 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, json_object_free(json); } else { if (count) { - if (show_failed) - vty_out(vty, "\nDisplayed neighbors %d", - failed_count); - else if (as_type != AS_UNSPECIFIED || as || fpeer - || show_established) { - if (filtered_count == count) - vty_out(vty, - "%% No matching neighbor\n"); - else + if (filtered_count == count) + vty_out(vty, "\n%% No matching neighbor\n"); + else { + if (show_failed) + vty_out(vty, "\nDisplayed neighbors %d", + failed_count); + else if (as_type != AS_UNSPECIFIED || as + || fpeer || show_established) vty_out(vty, "\nDisplayed neighbors %d", count - filtered_count); + + vty_out(vty, "\nTotal number of neighbors %d\n", + count); } - vty_out(vty, "\nTotal number of neighbors %d\n", count); } else { vty_out(vty, "No %s neighbor is configured\n", get_afi_safi_str(afi, safi, false)); @@ -11426,7 +11456,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi, int safi, struct peer *fpeer, int as_type, - as_t as, uint8_t show_flags) + as_t as, uint16_t show_flags) { int is_first = 1; int afi_wildcard = (afi == AFI_MAX); @@ -11499,7 +11529,7 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, safi_t safi, const char *neighbor, int as_type, as_t as, - uint8_t show_flags) + uint16_t show_flags) { struct listnode *node, *nnode; struct bgp *bgp; @@ -11542,7 +11572,7 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, safi_t safi, const char *neighbor, int as_type, - as_t as, uint8_t show_flags) + as_t as, uint16_t show_flags) { struct bgp *bgp; bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); @@ -11604,7 +11634,7 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd, "show [ip] bgp [ VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR - "]] [all$all] summary [established|failed] [|remote-as <(1-4294967295)|internal|external>>] [wide] [json$uj]", + "]] [all$all] summary [established|failed] [|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json$uj]", 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" @@ -11619,6 +11649,7 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd, "AS number\n" "Internal (iBGP) AS sessions\n" "External (eBGP) AS sessions\n" + "Shorten the information on BGP instances\n" "Increase table width for longer output\n" JSON_STR) { char *vrf = NULL; @@ -11626,7 +11657,7 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd, safi_t safi = SAFI_MAX; as_t as = 0; /* 0 means AS filter not set */ int as_type = AS_UNSPECIFIED; - uint8_t show_flags = 0; + uint16_t show_flags = 0; int idx = 0; @@ -11661,6 +11692,9 @@ DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd, as = (as_t)atoi(argv[idx + 1]->arg); } + if (argv_find(argv, argc, "terse", &idx)) + SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE); + if (argv_find(argv, argc, "wide", &idx)) SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE); diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 2531488d0d..04a47f6f62 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -186,7 +186,7 @@ int bgp_vty_find_and_parse_bgp(struct vty *vty, struct cmd_token **argv, int argc, struct bgp **bgp, bool use_json); extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, safi_t safi, const char *neighbor, int as_type, - as_t as, uint8_t show_flags); + as_t as, uint16_t show_flags); extern int bgp_clear_star_soft_in(const char *name, char *errmsg, size_t errmsg_len); extern int bgp_clear_star_soft_out(const char *name, char *errmsg, diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 202df373ed..a43dd46e26 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -3297,6 +3297,13 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`. address-family. The remote-as filter can be used in combination with the failed, established filters. +.. clicmd:: show bgp [afi] [safi] [all] summary terse [json] + + Shorten the output. Do not show the following information about the BGP + instances: the number of RIB entries, the table version and the used memory. + The ``terse`` option can be used in combination with the remote-as, neighbor, + failed and established filters, and with the ``wide`` option as well. + .. clicmd:: show bgp [afi] [safi] [neighbor [PEER] [routes|advertised-routes|received-routes] [json] This command shows information on a specific BGP peer of the relevant diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py index dea054b8bc..2d75428f1a 100644 --- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py +++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py @@ -906,17 +906,25 @@ def test_bgp_summary(): # Read expected result from file expected_original = open(refTableFile).read().rstrip() - for filter in ["", "remote-as internal", "remote-as external", + for arguments in ["", "remote-as internal", "remote-as external", "remote-as 100", "remote-as 123", "neighbor 192.168.7.10", "neighbor 192.168.7.10", "neighbor fc00:0:0:8::1000", - "neighbor 10.0.0.1"]: + "neighbor 10.0.0.1", + "terse", + "remote-as internal terse", + "remote-as external terse", + "remote-as 100 terse", "remote-as 123 terse", + "neighbor 192.168.7.10 terse", "neighbor 192.168.7.10 terse", + "neighbor fc00:0:0:8::1000 terse", + "neighbor 10.0.0.1 terse"]: # Actual output from router actual = ( net["r%s" % i] - .cmd('vtysh -c "show ip bgp summary ' + filter + '" 2> /dev/null') + .cmd('vtysh -c "show ip bgp summary ' + arguments + '" 2> /dev/null') .rstrip() ) + # Mask out "using XXiXX bytes" portion. They are random... actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) # Mask out "using XiXXX KiB" portion. They are random... @@ -948,30 +956,36 @@ def test_bgp_summary(): ) expected = expected_original - # apply filters on expected output - if "internal" in filter or "remote-as 100" in filter: + # apply argumentss on expected output + if "internal" in arguments or "remote-as 100" in arguments: expected = re.sub(r".+\s+200\s+.+", "", expected) - elif "external" in filter: + elif "external" in arguments: expected = re.sub(r".+\s+100\s+.+Active.+", "", expected) - elif "remote-as 123" in filter: + elif "remote-as 123" in arguments: expected = re.sub( r"(192.168.7.(1|2)0|fc00:0:0:8::(1|2)000).+Active.+", "", expected ) + expected = re.sub(r"\nNeighbor.+Desc", "", expected) expected = expected + "% No matching neighbor\n" - elif "192.168.7.10" in filter: + elif "192.168.7.10" in arguments: expected = re.sub( r"(192.168.7.20|fc00:0:0:8::(1|2)000).+Active.+", "", expected ) - elif "fc00:0:0:8::1000" in filter: + elif "fc00:0:0:8::1000" in arguments: expected = re.sub( r"(192.168.7.(1|2)0|fc00:0:0:8::2000).+Active.+", "", expected ) - elif "10.0.0.1" in filter: + elif "10.0.0.1" in arguments: expected = "No such neighbor in VRF default" + if "terse" in arguments: + expected = re.sub(r"BGP table version .+", "", expected) + expected = re.sub(r"RIB entries .+", "", expected) + expected = re.sub(r"Peers [0-9]+, using .+", "", expected) + # Strip empty lines actual = actual.lstrip().rstrip() expected = expected.lstrip().rstrip() @@ -979,13 +993,17 @@ def test_bgp_summary(): expected = re.sub(r"\n+", "\n", expected) # reapply initial formatting - actual = re.sub(r"KiB of memory\n", "KiB of memory\n\n", actual) - expected = re.sub(r"KiB of memory\n", "KiB of memory\n\n", expected) + if "terse" in arguments: + actual = re.sub(r" vrf-id 0\n", " vrf-id 0\n\n", actual) + expected = re.sub(r" vrf-id 0\n", " vrf-id 0\n\n", expected) + else: + actual = re.sub(r"KiB of memory\n", "KiB of memory\n\n", actual) + expected = re.sub(r"KiB of memory\n", "KiB of memory\n\n", expected) # realign expected neighbor columns if needed try: - idx_actual = re.search(r"\n(Neighbor\s+V\s+)", actual).group(1).find("V") - idx_expected = re.search(r"\n(Neighbor\s+V\s+)", expected).group(1).find("V") + idx_actual = re.search(r"(Neighbor\s+V\s+)", actual).group(1).find("V") + idx_expected = re.search(r"(Neighbor\s+V\s+)", expected).group(1).find("V") idx_diff = idx_expected - idx_actual if idx_diff > 0: # Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd @@ -1003,8 +1021,8 @@ def test_bgp_summary(): diff = topotest.get_textdiff( actual, expected, - title1="actual SHOW IP BGP SUMMARY " + filter.upper() , - title2="expected SHOW IP BGP SUMMARY " + filter.upper(), + title1="actual SHOW IP BGP SUMMARY " + arguments.upper() , + title2="expected SHOW IP BGP SUMMARY " + arguments.upper(), ) # Empty string if it matches, otherwise diff contains unified diff -- 2.39.5