Merge pull request #8679 from louis-oui/bgp-summary-filter

bgpd: add show bgp summary filter by neighbor or AS
This commit is contained in:
Donatas Abraitis 2021-05-27 13:57:14 +03:00 committed by GitHub
commit b8fd5ba1d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 283 additions and 106 deletions

View File

@ -4309,24 +4309,30 @@ DEFPY(show_bgp_l2vpn_evpn_nh,
/* /*
* Display EVPN neighbor summary. * Display EVPN neighbor summary.
*/ */
DEFUN(show_bgp_l2vpn_evpn_summary, DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
show_bgp_l2vpn_evpn_summary_cmd, "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [wide] [json]",
"show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [wide] [json]", SHOW_STR BGP_STR
SHOW_STR
BGP_STR
"bgp vrf\n" "bgp vrf\n"
"vrf name\n" "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
L2VPN_HELP_STR
EVPN_HELP_STR
"Summary of BGP neighbor status\n" "Summary of BGP neighbor status\n"
"Show only sessions in Established state\n" "Show only sessions in Established state\n"
"Show only sessions not in Established state\n" "Show only sessions not in Established state\n"
"Increase table width for longer output\n" "Show only the specified neighbor session\n"
JSON_STR) "Neighbor to display information about\n"
"Neighbor to display information about\n"
"Neighbor on BGP configured interface\n"
"Show only the specified remote AS sessions\n"
"AS number\n"
"Internal (iBGP) AS sessions\n"
"External (eBGP) AS sessions\n"
"Increase table width for longer output\n" JSON_STR)
{ {
int idx_vrf = 0; int idx_vrf = 0;
int idx = 0; int idx = 0;
char *vrf = NULL; char *vrf = NULL;
char *neighbor = NULL;
as_t as = 0; /* 0 means AS filter not set */
int as_type = AS_UNSPECIFIED;
uint8_t show_flags = 0; uint8_t show_flags = 0;
if (argv_find(argv, argc, "vrf", &idx_vrf)) if (argv_find(argv, argc, "vrf", &idx_vrf))
@ -4338,13 +4344,27 @@ DEFUN(show_bgp_l2vpn_evpn_summary,
if (argv_find(argv, argc, "established", &idx)) if (argv_find(argv, argc, "established", &idx))
SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED); SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
if (argv_find(argv, argc, "neighbor", &idx))
neighbor = argv[idx + 1]->arg;
if (argv_find(argv, argc, "remote-as", &idx)) {
if (argv[idx + 1]->arg[0] == 'i')
as_type = AS_INTERNAL;
else if (argv[idx + 1]->arg[0] == 'e')
as_type = AS_EXTERNAL;
else
as = (as_t)atoi(argv[idx + 1]->arg);
}
if (argv_find(argv, argc, "wide", &idx)) if (argv_find(argv, argc, "wide", &idx))
SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE); SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
if (use_json(argc, argv)) if (use_json(argc, argv))
SET_FLAG(show_flags, BGP_SHOW_OPT_JSON); SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, show_flags); return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, neighbor,
as_type, as, show_flags);
} }
int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc) int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)

View File

@ -10685,8 +10685,35 @@ static char *bgp_peer_description_stripped(char *desc, uint32_t size)
return stripped; return stripped;
} }
/* Determine whether var peer should be filtered out of the summary. */
static bool bgp_show_summary_is_peer_filtered(struct peer *peer,
struct peer *fpeer, int as_type,
as_t as)
{
/* filter neighbor XXXX */
if (fpeer && fpeer != peer)
return true;
/* filter remote-as (internal|external) */
if (as_type != AS_UNSPECIFIED) {
if (peer->as_type == AS_SPECIFIED) {
if (as_type == AS_INTERNAL) {
if (peer->as != peer->local_as)
return true;
} else if (peer->as == peer->local_as)
return true;
} else if (as_type != peer->as_type)
return true;
} else if (as && as != peer->as) /* filter remote-as XXX */
return true;
return false;
}
/* Show BGP peer's summary information. */ /* Show BGP peer's summary information. */
static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, 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) uint8_t show_flags)
{ {
struct peer *peer; struct peer *peer;
@ -10723,6 +10750,12 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
json = json_object_new_object(); json = json_object_new_object();
json_peers = json_object_new_object(); json_peers = json_object_new_object();
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (bgp_show_summary_is_peer_filtered(peer, fpeer,
as_type, as)) {
count++;
continue;
}
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
continue; continue;
@ -10742,6 +10775,12 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
* characters are needed for the Neighbor column * characters are needed for the Neighbor column
*/ */
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (bgp_show_summary_is_peer_filtered(peer, fpeer,
as_type, as)) {
count++;
continue;
}
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
continue; continue;
@ -11025,6 +11064,10 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
if (use_json) { if (use_json) {
json_peer = NULL; json_peer = NULL;
if (bgp_show_summary_is_peer_filtered(peer, fpeer,
as_type, as))
continue;
if (show_failed && if (show_failed &&
bgp_has_peer_failed(peer, afi, safi)) { bgp_has_peer_failed(peer, afi, safi)) {
json_peer = json_object_new_object(); json_peer = json_object_new_object();
@ -11174,6 +11217,9 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
json_object_object_add(json_peers, peer->host, json_object_object_add(json_peers, peer->host,
json_peer); json_peer);
} else { } else {
if (bgp_show_summary_is_peer_filtered(peer, fpeer,
as_type, as))
continue;
if (show_failed && if (show_failed &&
bgp_has_peer_failed(peer, afi, safi)) { bgp_has_peer_failed(peer, afi, safi)) {
bgp_show_failed_summary(vty, bgp, peer, NULL, bgp_show_failed_summary(vty, bgp, peer, NULL,
@ -11183,7 +11229,6 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
if (show_established if (show_established
&& bgp_has_peer_failed(peer, afi, safi)) && bgp_has_peer_failed(peer, afi, safi))
continue; continue;
memset(dn_flag, '\0', sizeof(dn_flag)); memset(dn_flag, '\0', sizeof(dn_flag));
if (peer_dynamic_neighbor(peer)) { if (peer_dynamic_neighbor(peer)) {
dn_flag[0] = '*'; dn_flag[0] = '*';
@ -11336,7 +11381,8 @@ 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, static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
int safi, uint8_t show_flags) int safi, struct peer *fpeer, int as_type,
as_t as, uint8_t show_flags)
{ {
int is_first = 1; int is_first = 1;
int afi_wildcard = (afi == AFI_MAX); int afi_wildcard = (afi == AFI_MAX);
@ -11380,8 +11426,8 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
false)); false));
} }
} }
bgp_show_summary(vty, bgp, afi, safi, bgp_show_summary(vty, bgp, afi, safi, fpeer,
show_flags); as_type, as, show_flags);
} }
safi++; safi++;
if (!safi_wildcard) if (!safi_wildcard)
@ -11403,10 +11449,14 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
} }
static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi, static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
safi_t safi, uint8_t show_flags) safi_t safi,
const char *neighbor,
int as_type, as_t as,
uint8_t show_flags)
{ {
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct bgp *bgp; struct bgp *bgp;
struct peer *fpeer = NULL;
int is_first = 1; int is_first = 1;
bool nbr_output = false; bool nbr_output = false;
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
@ -11432,7 +11482,14 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
? VRF_DEFAULT_NAME ? VRF_DEFAULT_NAME
: bgp->name); : bgp->name);
} }
bgp_show_summary_afi_safi(vty, bgp, afi, safi, show_flags); if (neighbor) {
fpeer = peer_lookup_in_view(vty, bgp, neighbor,
use_json);
if (!fpeer)
continue;
}
bgp_show_summary_afi_safi(vty, bgp, afi, safi, fpeer, as_type,
as, show_flags);
} }
if (use_json) if (use_json)
@ -11442,15 +11499,18 @@ 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, int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
safi_t safi, uint8_t show_flags) safi_t safi, const char *neighbor, int as_type,
as_t as, uint8_t show_flags)
{ {
struct bgp *bgp; struct bgp *bgp;
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON); bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
struct peer *fpeer = NULL;
if (name) { if (name) {
if (strmatch(name, "all")) { if (strmatch(name, "all")) {
bgp_show_all_instances_summary_vty(vty, afi, safi, bgp_show_all_instances_summary_vty(vty, afi, safi,
show_flags); neighbor, as_type,
as, show_flags);
return CMD_SUCCESS; return CMD_SUCCESS;
} else { } else {
bgp = bgp_lookup_by_name(name); bgp = bgp_lookup_by_name(name);
@ -11464,17 +11524,30 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
return CMD_WARNING; return CMD_WARNING;
} }
bgp_show_summary_afi_safi(vty, bgp, afi, safi, if (neighbor) {
show_flags); fpeer = peer_lookup_in_view(vty, bgp, neighbor,
use_json);
if (!fpeer)
return CMD_WARNING;
}
bgp_show_summary_afi_safi(vty, bgp, afi, safi, fpeer,
as_type, as, show_flags);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
} }
bgp = bgp_get_default(); bgp = bgp_get_default();
if (bgp) if (bgp) {
bgp_show_summary_afi_safi(vty, bgp, afi, safi, show_flags); if (neighbor) {
else { fpeer = peer_lookup_in_view(vty, bgp, neighbor,
use_json);
if (!fpeer)
return CMD_WARNING;
}
bgp_show_summary_afi_safi(vty, bgp, afi, safi, fpeer, as_type,
as, show_flags);
} else {
if (use_json) if (use_json)
vty_out(vty, "{}\n"); vty_out(vty, "{}\n");
else else
@ -11486,25 +11559,31 @@ int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
} }
/* `show [ip] bgp summary' commands. */ /* `show [ip] bgp summary' commands. */
DEFPY (show_ip_bgp_summary, DEFPY(show_ip_bgp_summary, show_ip_bgp_summary_cmd,
show_ip_bgp_summary_cmd, "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] summary [established|failed] [wide] [json$uj]", " [" BGP_SAFI_WITH_LABEL_CMD_STR
SHOW_STR "]] [all$all] summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [wide] [json$uj]",
IP_STR SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
BGP_STR BGP_SAFI_WITH_LABEL_HELP_STR
BGP_INSTANCE_HELP_STR "Display the entries for all address families\n"
BGP_AFI_HELP_STR "Summary of BGP neighbor status\n"
BGP_SAFI_WITH_LABEL_HELP_STR "Show only sessions in Established state\n"
"Display the entries for all address families\n" "Show only sessions not in Established state\n"
"Summary of BGP neighbor status\n" "Show only the specified neighbor session\n"
"Show only sessions in Established state\n" "Neighbor to display information about\n"
"Show only sessions not in Established state\n" "Neighbor to display information about\n"
"Increase table width for longer output\n" "Neighbor on BGP configured interface\n"
JSON_STR) "Show only the specified remote AS sessions\n"
"AS number\n"
"Internal (iBGP) AS sessions\n"
"External (eBGP) AS sessions\n"
"Increase table width for longer output\n" JSON_STR)
{ {
char *vrf = NULL; char *vrf = NULL;
afi_t afi = AFI_MAX; afi_t afi = AFI_MAX;
safi_t safi = SAFI_MAX; 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; uint8_t show_flags = 0;
int idx = 0; int idx = 0;
@ -11531,13 +11610,23 @@ DEFPY (show_ip_bgp_summary,
if (argv_find(argv, argc, "established", &idx)) if (argv_find(argv, argc, "established", &idx))
SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED); SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
if (argv_find(argv, argc, "remote-as", &idx)) {
if (argv[idx + 1]->arg[0] == 'i')
as_type = AS_INTERNAL;
else if (argv[idx + 1]->arg[0] == 'e')
as_type = AS_EXTERNAL;
else
as = (as_t)atoi(argv[idx + 1]->arg);
}
if (argv_find(argv, argc, "wide", &idx)) if (argv_find(argv, argc, "wide", &idx))
SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE); SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
if (argv_find(argv, argc, "json", &idx)) if (argv_find(argv, argc, "json", &idx))
SET_FLAG(show_flags, BGP_SHOW_OPT_JSON); SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
return bgp_show_summary_vty(vty, vrf, afi, safi, show_flags); return bgp_show_summary_vty(vty, vrf, afi, safi, neighbor, as_type, as,
show_flags);
} }
const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json) const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json)

View File

@ -185,7 +185,8 @@ extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
int bgp_vty_find_and_parse_bgp(struct vty *vty, struct cmd_token **argv, int bgp_vty_find_and_parse_bgp(struct vty *vty, struct cmd_token **argv,
int argc, struct bgp **bgp, bool use_json); int argc, struct bgp **bgp, bool use_json);
extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi, extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
safi_t safi, uint8_t show_flags); safi_t safi, const char *neighbor, int as_type,
as_t as, uint8_t show_flags);
extern int bgp_clear_star_soft_in(const char *name, char *errmsg, extern int bgp_clear_star_soft_in(const char *name, char *errmsg,
size_t errmsg_len); size_t errmsg_len);
extern int bgp_clear_star_soft_out(const char *name, char *errmsg, extern int bgp_clear_star_soft_out(const char *name, char *errmsg,

View File

@ -3284,6 +3284,19 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
Show a bgp peer summary for peers that are succesfully exchanging routes Show a bgp peer summary for peers that are succesfully exchanging routes
for the specified address family, and subsequent address-family. for the specified address family, and subsequent address-family.
.. clicmd:: show bgp [afi] [safi] [all] summary neighbor [PEER] [json]
Show a bgp summary for the specified peer, address family, and
subsequent address-family. The neighbor filter can be used in combination
with the failed, established filters.
.. clicmd:: show bgp [afi] [safi] [all] summary remote-as <internal|external|ASN> [json]
Show a bgp peer summary for the specified remote-as ASN or type (``internal``
for iBGP and ``external`` for eBGP sessions), address family, and subsequent
address-family. The remote-as filter can be used in combination with the
failed, established filters.
.. clicmd:: show bgp [afi] [safi] [neighbor [PEER] [routes|advertised-routes|received-routes] [json] .. 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 This command shows information on a specific BGP peer of the relevant

View File

@ -904,74 +904,128 @@ def test_bgp_summary():
refTableFile = "%s/r%s/show_ip_bgp_summary.ref" % (thisDir, i) refTableFile = "%s/r%s/show_ip_bgp_summary.ref" % (thisDir, i)
if os.path.isfile(refTableFile): if os.path.isfile(refTableFile):
# Read expected result from file # Read expected result from file
expected = open(refTableFile).read().rstrip() expected_original = open(refTableFile).read().rstrip()
# Fix newlines (make them all the same)
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
# Actual output from router for filter in ["", "remote-as internal", "remote-as external",
actual = ( "remote-as 100", "remote-as 123",
net["r%s" % i] "neighbor 192.168.7.10", "neighbor 192.168.7.10",
.cmd('vtysh -c "show ip bgp summary" 2> /dev/null') "neighbor fc00:0:0:8::1000",
.rstrip() "neighbor 10.0.0.1"]:
) # Actual output from router
# Mask out "using XXiXX bytes" portion. They are random... actual = (
actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual) net["r%s" % i]
# Mask out "using XiXXX KiB" portion. They are random... .cmd('vtysh -c "show ip bgp summary ' + filter + '" 2> /dev/null')
actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual) .rstrip()
#
# Remove extra summaries which exist with newer versions
#
# Remove summary lines (changed recently)
actual = re.sub(r"Total number.*", "", actual)
actual = re.sub(r"Displayed.*", "", actual)
# Remove IPv4 Unicast Summary (Title only)
actual = re.sub(r"IPv4 Unicast Summary:", "", actual)
# Remove IPv4 Multicast Summary (all of it)
actual = re.sub(r"IPv4 Multicast Summary:", "", actual)
actual = re.sub(r"No IPv4 Multicast neighbor is configured", "", actual)
# Remove IPv4 VPN Summary (all of it)
actual = re.sub(r"IPv4 VPN Summary:", "", actual)
actual = re.sub(r"No IPv4 VPN neighbor is configured", "", actual)
# Remove IPv4 Encap Summary (all of it)
actual = re.sub(r"IPv4 Encap Summary:", "", actual)
actual = re.sub(r"No IPv4 Encap neighbor is configured", "", actual)
# Remove Unknown Summary (all of it)
actual = re.sub(r"Unknown Summary:", "", actual)
actual = re.sub(r"No Unknown neighbor is configured", "", actual)
actual = re.sub(r"IPv4 labeled-unicast Summary:", "", actual)
actual = re.sub(
r"No IPv4 labeled-unicast neighbor is configured", "", actual
)
# Strip empty lines
actual = actual.lstrip()
actual = actual.rstrip()
#
# Fix newlines (make them all the same)
actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
# Generate Diff
diff = topotest.get_textdiff(
actual,
expected,
title1="actual SHOW IP BGP SUMMARY",
title2="expected SHOW IP BGP SUMMARY",
)
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write(
"r%s failed SHOW IP BGP SUMMARY check:\n%s\n" % (i, diff)
) )
failures += 1 # Mask out "using XXiXX bytes" portion. They are random...
else: actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual)
print("r%s ok" % i) # Mask out "using XiXXX KiB" portion. They are random...
actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual)
assert failures == 0, "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % ( # Remove extra summaries which exist with newer versions
i,
diff, # Remove summary lines (changed recently)
) actual = re.sub(r"Total number.*", "", actual)
actual = re.sub(r"Displayed.*", "", actual)
# Remove IPv4 Unicast Summary (Title only)
actual = re.sub(r"IPv4 Unicast Summary:", "", actual)
# Remove IPv4 Multicast Summary (all of it)
actual = re.sub(r"IPv4 Multicast Summary:", "", actual)
actual = re.sub(r"No IPv4 Multicast neighbor is configured", "", actual)
# Remove IPv4 VPN Summary (all of it)
actual = re.sub(r"IPv4 VPN Summary:", "", actual)
actual = re.sub(r"No IPv4 VPN neighbor is configured", "", actual)
# Remove IPv4 Encap Summary (all of it)
actual = re.sub(r"IPv4 Encap Summary:", "", actual)
actual = re.sub(r"No IPv4 Encap neighbor is configured", "", actual)
# Remove Unknown Summary (all of it)
actual = re.sub(r"Unknown Summary:", "", actual)
actual = re.sub(r"No Unknown neighbor is configured", "", actual)
actual = re.sub(r"IPv4 labeled-unicast Summary:", "", actual)
actual = re.sub(
r"No IPv4 labeled-unicast neighbor is configured", "", actual
)
expected = expected_original
# apply filters on expected output
if "internal" in filter or "remote-as 100" in filter:
expected = re.sub(r".+\s+200\s+.+", "", expected)
elif "external" in filter:
expected = re.sub(r".+\s+100\s+.+Active.+", "", expected)
elif "remote-as 123" in filter:
expected = re.sub(
r"(192.168.7.(1|2)0|fc00:0:0:8::(1|2)000).+Active.+",
"", expected
)
elif "192.168.7.10" in filter:
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:
expected = re.sub(
r"(192.168.7.(1|2)0|fc00:0:0:8::2000).+Active.+",
"", expected
)
elif "10.0.0.1" in filter:
expected = "No such neighbor in this view/vrf"
# Strip empty lines
actual = actual.lstrip().rstrip()
expected = expected.lstrip().rstrip()
actual = re.sub(r"\n+", "\n", actual)
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)
# 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_diff = idx_expected - idx_actual
if idx_diff > 0:
# Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
expected = re.sub(" " * idx_diff + "V ", "V ", expected)
# 192.168.7.10 4 100 0 0 0 0 0 never Active
expected = re.sub(" " * idx_diff + "4 ", "4 ", expected)
except AttributeError:
pass
# Fix newlines (make them all the same)
actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
# Generate Diff
diff = topotest.get_textdiff(
actual,
expected,
title1="actual SHOW IP BGP SUMMARY " + filter.upper() ,
title2="expected SHOW IP BGP SUMMARY " + filter.upper(),
)
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write(
"r%s failed SHOW IP BGP SUMMARY check:\n%s\n" % (i, diff)
)
failures += 1
else:
print("r%s ok" % i)
assert failures == 0, "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % (
i,
diff,
)
# Actual output from router
actual = (
net["r%s" % i]
.cmd('vtysh -c "show ip bgp summary" 2> /dev/null')
.rstrip()
)
# Make sure that all daemons are running # Make sure that all daemons are running
for i in range(1, 2): for i in range(1, 2):