mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-08 14:34:22 +00:00
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:
commit
b8fd5ba1d7
@ -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)
|
||||||
|
147
bgpd/bgp_vty.c
147
bgpd/bgp_vty.c
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user