Merge pull request #8052 from ton31337/feature/show_bgp_peer-groups_json

This commit is contained in:
Quentin Young 2021-03-17 15:08:00 -04:00 committed by GitHub
commit 263e82b308
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 240 additions and 50 deletions

View File

@ -24,6 +24,7 @@
#include "lib/json.h" #include "lib/json.h"
#include "lib_errors.h" #include "lib_errors.h"
#include "lib/zclient.h" #include "lib/zclient.h"
#include "lib/printfrr.h"
#include "prefix.h" #include "prefix.h"
#include "plist.h" #include "plist.h"
#include "buffer.h" #include "buffer.h"
@ -15464,7 +15465,8 @@ DEFPY(show_ip_bgp_instance_updgrps_adj_s,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group) static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group,
json_object *json)
{ {
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct prefix *range; struct prefix *range;
@ -15473,64 +15475,143 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
const char *peer_status; const char *peer_status;
const char *af_str;
int lr_count; int lr_count;
int dynamic; int dynamic;
int af_cfgd; bool af_cfgd;
json_object *json_peer_group = NULL;
json_object *json_peer_group_afc = NULL;
json_object *json_peer_group_members = NULL;
json_object *json_peer_group_dynamic = NULL;
json_object *json_peer_group_dynamic_af = NULL;
json_object *json_peer_group_ranges = NULL;
conf = group->conf; conf = group->conf;
if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) { if (json) {
vty_out(vty, "\nBGP peer-group %s, remote AS %u\n", json_peer_group = json_object_new_object();
group->name, conf->as); json_peer_group_afc = json_object_new_array();
} else if (conf->as_type == AS_INTERNAL) {
vty_out(vty, "\nBGP peer-group %s, remote AS %u\n",
group->name, group->bgp->as);
} else {
vty_out(vty, "\nBGP peer-group %s\n", group->name);
} }
if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL)) if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) {
vty_out(vty, " Peer-group type is internal\n"); if (json)
else json_object_int_add(json_peer_group, "remoteAs",
vty_out(vty, " Peer-group type is external\n"); conf->as);
else
vty_out(vty, "\nBGP peer-group %s, remote AS %u\n",
group->name, conf->as);
} else if (conf->as_type == AS_INTERNAL) {
if (json)
json_object_int_add(json_peer_group, "remoteAs",
group->bgp->as);
else
vty_out(vty, "\nBGP peer-group %s, remote AS %u\n",
group->name, group->bgp->as);
} else {
if (!json)
vty_out(vty, "\nBGP peer-group %s\n", group->name);
}
if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL)) {
if (json)
json_object_string_add(json_peer_group, "type",
"internal");
else
vty_out(vty, " Peer-group type is internal\n");
} else {
if (json)
json_object_string_add(json_peer_group, "type",
"external");
else
vty_out(vty, " Peer-group type is external\n");
}
/* Display AFs configured. */ /* Display AFs configured. */
vty_out(vty, " Configured address-families:"); if (!json)
vty_out(vty, " Configured address-families:");
FOREACH_AFI_SAFI (afi, safi) { FOREACH_AFI_SAFI (afi, safi) {
if (conf->afc[afi][safi]) { if (conf->afc[afi][safi]) {
af_cfgd = 1; af_cfgd = true;
vty_out(vty, " %s;", get_afi_safi_str(afi, safi, false)); if (json)
json_object_array_add(
json_peer_group_afc,
json_object_new_string(get_afi_safi_str(
afi, safi, false)));
else
vty_out(vty, " %s;",
get_afi_safi_str(afi, safi, false));
} }
} }
if (!af_cfgd)
vty_out(vty, " none\n"); if (json) {
else json_object_object_add(json_peer_group,
vty_out(vty, "\n"); "addressFamiliesConfigured",
json_peer_group_afc);
} else {
if (!af_cfgd)
vty_out(vty, " none\n");
else
vty_out(vty, "\n");
}
/* Display listen ranges (for dynamic neighbors), if any */ /* Display listen ranges (for dynamic neighbors), if any */
for (afi = AFI_IP; afi < AFI_MAX; afi++) { for (afi = AFI_IP; afi < AFI_MAX; afi++) {
if (afi == AFI_IP)
af_str = "IPv4";
else if (afi == AFI_IP6)
af_str = "IPv6";
else
af_str = "???";
lr_count = listcount(group->listen_range[afi]); lr_count = listcount(group->listen_range[afi]);
if (lr_count) { if (lr_count) {
vty_out(vty, " %d %s listen range(s)\n", lr_count, if (json) {
af_str); if (!json_peer_group_dynamic)
json_peer_group_dynamic =
json_object_new_object();
json_peer_group_dynamic_af =
json_object_new_object();
json_peer_group_ranges =
json_object_new_array();
json_object_int_add(json_peer_group_dynamic_af,
"count", lr_count);
} else {
vty_out(vty, " %d %s listen range(s)\n",
lr_count, afi2str(afi));
}
for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, for (ALL_LIST_ELEMENTS(group->listen_range[afi], node,
nnode, range)) nnode, range)) {
vty_out(vty, " %pFX\n", range); if (json) {
char buf[BUFSIZ];
snprintfrr(buf, sizeof(buf), "%pFX",
range);
json_object_array_add(
json_peer_group_ranges,
json_object_new_string(buf));
} else {
vty_out(vty, " %pFX\n", range);
}
}
if (json) {
json_object_object_add(
json_peer_group_dynamic_af, "ranges",
json_peer_group_ranges);
json_object_object_add(
json_peer_group_dynamic, afi2str(afi),
json_peer_group_dynamic_af);
}
} }
} }
if (json_peer_group_dynamic)
json_object_object_add(json_peer_group, "dynamicRanges",
json_peer_group_dynamic);
/* Display group members and their status */ /* Display group members and their status */
if (listcount(group->peer)) { if (listcount(group->peer)) {
vty_out(vty, " Peer-group members:\n"); if (json)
json_peer_group_members = json_object_new_object();
else
vty_out(vty, " Peer-group members:\n");
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN) if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)
|| CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN)) || CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN))
@ -15543,65 +15624,106 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
peer->status, NULL); peer->status, NULL);
dynamic = peer_dynamic_neighbor(peer); dynamic = peer_dynamic_neighbor(peer);
vty_out(vty, " %s %s %s \n", peer->host,
dynamic ? "(dynamic)" : "", peer_status); if (json) {
json_object *json_peer_group_member =
json_object_new_object();
json_object_string_add(json_peer_group_member,
"status", peer_status);
if (dynamic)
json_object_boolean_true_add(
json_peer_group_member,
"dynamic");
json_object_object_add(json_peer_group_members,
peer->host,
json_peer_group_member);
} else {
vty_out(vty, " %s %s %s \n", peer->host,
dynamic ? "(dynamic)" : "",
peer_status);
}
} }
if (json)
json_object_object_add(json_peer_group, "members",
json_peer_group_members);
} }
if (json)
json_object_object_add(json, group->name, json_peer_group);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
static int bgp_show_peer_group_vty(struct vty *vty, const char *name, static int bgp_show_peer_group_vty(struct vty *vty, const char *name,
const char *group_name) const char *group_name, bool uj)
{ {
struct bgp *bgp; struct bgp *bgp;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct peer_group *group; struct peer_group *group;
bool found = false; bool found = false;
json_object *json = NULL;
if (uj)
json = json_object_new_object();
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default(); bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
if (!bgp) { if (!bgp) {
vty_out(vty, "%% BGP instance not found\n"); if (uj) {
vty_out(vty, "%s\n",
json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
} else {
vty_out(vty, "%% BGP instance not found\n");
}
return CMD_WARNING; return CMD_WARNING;
} }
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) { for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
if (group_name) { if (group_name) {
if (strmatch(group->name, group_name)) { if (strmatch(group->name, group_name)) {
bgp_show_one_peer_group(vty, group); bgp_show_one_peer_group(vty, group, json);
found = true; found = true;
break; break;
} }
} else { } else {
bgp_show_one_peer_group(vty, group); bgp_show_one_peer_group(vty, group, json);
} }
} }
if (group_name && !found) if (group_name && !found && !uj)
vty_out(vty, "%% No such peer-group\n"); vty_out(vty, "%% No such peer-group\n");
if (uj) {
vty_out(vty, "%s\n",
json_object_to_json_string_ext(
json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (show_ip_bgp_peer_groups, DEFUN(show_ip_bgp_peer_groups, show_ip_bgp_peer_groups_cmd,
show_ip_bgp_peer_groups_cmd, "show [ip] bgp [<view|vrf> VIEWVRFNAME] peer-group [PGNAME] [json]",
"show [ip] bgp [<view|vrf> VIEWVRFNAME] peer-group [PGNAME]", SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
SHOW_STR "Detailed information on BGP peer groups\n"
IP_STR "Peer group name\n" JSON_STR)
BGP_STR
BGP_INSTANCE_HELP_STR
"Detailed information on BGP peer groups\n"
"Peer group name\n")
{ {
char *vrf, *pg; char *vrf, *pg;
int idx = 0; int idx = 0;
bool uj = use_json(argc, argv);
vrf = argv_find(argv, argc, "VIEWVRFNAME", &idx) ? argv[idx]->arg vrf = argv_find(argv, argc, "VIEWVRFNAME", &idx) ? argv[idx]->arg
: NULL; : NULL;
pg = argv_find(argv, argc, "PGNAME", &idx) ? argv[idx]->arg : NULL; pg = argv_find(argv, argc, "PGNAME", &idx) ? argv[idx]->arg : NULL;
return bgp_show_peer_group_vty(vty, vrf, pg); return bgp_show_peer_group_vty(vty, vrf, pg, uj);
} }

View File

@ -1667,6 +1667,74 @@ and will share updates.
should not be reflected back to the peer. This command only is only should not be reflected back to the peer. This command only is only
meaningful when there is a single peer defined in the peer-group. meaningful when there is a single peer defined in the peer-group.
.. clicmd:: show [ip] bgp peer-group [json]
This command displays configured BGP peer-groups.
.. code-block:: frr
exit1-debian-9# show bgp peer-group
BGP peer-group test1, remote AS 65001
Peer-group type is external
Configured address-families: IPv4 Unicast; IPv6 Unicast;
1 IPv4 listen range(s)
192.168.100.0/24
2 IPv6 listen range(s)
2001:db8:1::/64
2001:db8:2::/64
Peer-group members:
192.168.200.1 Active
2001:db8::1 Active
BGP peer-group test2
Peer-group type is external
Configured address-families: IPv4 Unicast;
Optional ``json`` parameter is used to display JSON output.
.. code-block:: frr
{
"test1":{
"remoteAs":65001,
"type":"external",
"addressFamiliesConfigured":[
"IPv4 Unicast",
"IPv6 Unicast"
],
"dynamicRanges":{
"IPv4":{
"count":1,
"ranges":[
"192.168.100.0\/24"
]
},
"IPv6":{
"count":2,
"ranges":[
"2001:db8:1::\/64",
"2001:db8:2::\/64"
]
}
},
"members":{
"192.168.200.1":{
"status":"Active"
},
"2001:db8::1":{
"status":"Active"
}
}
},
"test2":{
"type":"external",
"addressFamiliesConfigured":[
"IPv4 Unicast"
]
}
}
Capability Negotiation Capability Negotiation
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^