summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_vty.c218
-rw-r--r--doc/user/bgp.rst68
2 files changed, 238 insertions, 48 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 46a017f914..4b012430d9 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -24,6 +24,7 @@
#include "lib/json.h"
#include "lib_errors.h"
#include "lib/zclient.h"
+#include "lib/printfrr.h"
#include "prefix.h"
#include "plist.h"
#include "buffer.h"
@@ -15464,7 +15465,8 @@ DEFPY(show_ip_bgp_instance_updgrps_adj_s,
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 prefix *range;
@@ -15473,64 +15475,143 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
afi_t afi;
safi_t safi;
const char *peer_status;
- const char *af_str;
int lr_count;
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;
+ if (json) {
+ json_peer_group = json_object_new_object();
+ json_peer_group_afc = json_object_new_array();
+ }
+
if (conf->as_type == AS_SPECIFIED || conf->as_type == AS_EXTERNAL) {
- vty_out(vty, "\nBGP peer-group %s, remote AS %u\n",
- group->name, conf->as);
+ if (json)
+ json_object_int_add(json_peer_group, "remoteAs",
+ 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) {
- vty_out(vty, "\nBGP peer-group %s, remote AS %u\n",
- group->name, group->bgp->as);
+ 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 {
- vty_out(vty, "\nBGP peer-group %s\n", group->name);
+ if (!json)
+ vty_out(vty, "\nBGP peer-group %s\n", group->name);
}
- if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL))
- vty_out(vty, " Peer-group type is internal\n");
- else
- vty_out(vty, " Peer-group type is external\n");
+ 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. */
- vty_out(vty, " Configured address-families:");
+ if (!json)
+ vty_out(vty, " Configured address-families:");
+
FOREACH_AFI_SAFI (afi, safi) {
if (conf->afc[afi][safi]) {
- af_cfgd = 1;
- vty_out(vty, " %s;", get_afi_safi_str(afi, safi, false));
+ af_cfgd = true;
+ 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");
- else
- vty_out(vty, "\n");
+
+ if (json) {
+ json_object_object_add(json_peer_group,
+ "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 */
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]);
if (lr_count) {
- vty_out(vty, " %d %s listen range(s)\n", lr_count,
- af_str);
-
+ if (json) {
+ 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,
- nnode, range))
- vty_out(vty, " %pFX\n", range);
+ nnode, 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 */
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)) {
if (CHECK_FLAG(peer->flags, PEER_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);
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;
}
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 listnode *node, *nnode;
struct peer_group *group;
bool found = false;
+ json_object *json = NULL;
+
+ if (uj)
+ json = json_object_new_object();
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
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;
}
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
if (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;
break;
}
} 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");
+ 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;
}
-DEFUN (show_ip_bgp_peer_groups,
- show_ip_bgp_peer_groups_cmd,
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] peer-group [PGNAME]",
- SHOW_STR
- IP_STR
- BGP_STR
- BGP_INSTANCE_HELP_STR
- "Detailed information on BGP peer groups\n"
- "Peer group name\n")
+DEFUN(show_ip_bgp_peer_groups, show_ip_bgp_peer_groups_cmd,
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] peer-group [PGNAME] [json]",
+ SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
+ "Detailed information on BGP peer groups\n"
+ "Peer group name\n" JSON_STR)
{
char *vrf, *pg;
int idx = 0;
+ bool uj = use_json(argc, argv);
vrf = argv_find(argv, argc, "VIEWVRFNAME", &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);
}
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index da6c0d9824..a121595972 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1667,6 +1667,74 @@ and will share updates.
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.
+.. 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
^^^^^^^^^^^^^^^^^^^^^^