mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 09:22:03 +00:00
bgpd: Add JSON output for show ip bgp peer-group
command
``` exit1-debian-9# show bgp peer-group BGP peer-group test, remote AS 123 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 test3 Peer-group type is external Configured address-families: IPv4 Unicast; exit1-debian-9# exit1-debian-9# show bgp peer-group json { "test":{ "remoteAs":123, "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" } } }, "test3":{ "type":"external", "addressFamiliesConfigured":[ "IPv4 Unicast" ] } } ``` Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
parent
e319ed4c49
commit
6f4eacf315
222
bgpd/bgp_vty.c
222
bgpd/bgp_vty.c
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user