bgpd: JSON support for show ip bgp vrf all update-group

Ticket:#3229030
Testing Done: UT

Changes:

 - JSON support for the update group command.

Testing:

torc-11# show ip bgp vrf all ipv6 update-groups json

torc-12# show bgp vrf all update-groups json
{
  "default":{
    "2":{
      "groupCreateTime":{
        "epoch":1669225617,
        "epochString":"Wed Nov 23 17:46:57 2022\n"
      },
      "afi":"IPv6",
      "safi":"unicast",
      "outRouteMap":"MY_ORIGIN_ASPATH_ONLY",
      "minRouteAdvInt":0,
      "subGroup":[
        {
          "subGroupId":2,
          "groupCreateTime":{
            "epoch":1669225617,
            "epochString":"Wed Nov 23 17:46:57 2022\n"
          },
          "statistics":{
            "joinEvents":2,
            "pruneEvents":0,
            "mergeEvents":0,
            "splitEvents":0,
            "switchEvents":0,
            "peerRefreshEvents":0,
            "mergeCheckEvents":2
          },
          "coalesceTime":1100,
          "version":12,
          "packetQueueInfo":{
            "qeueueLen":0,
            "queuedTotal":1,
            "queueHwmLen":1,
            "totalEnqueued":1
          },
          "adjListCount":1,
          "needsRefresh":false,
          "peers":[
            "uplink_1",
            "uplink_2"
          ]
        }
      ]
    }
  }
}
{
  "sym_3":{
  }
}
{
  "sym_5":{
  }
}
{
  "sym_2":{
  }
}
{
  "sym_4":{
  }
}
{
  "sym_1":{
  }
}

Co-authored-by: Chirag Shah <chirag@nvidia.com>
Signed-off-by: Ashwini Reddy <ashred@nvidia.com>
This commit is contained in:
Ashwini Reddy 2022-11-07 11:53:48 -08:00 committed by Chirag Shah
parent a86afb3e0e
commit fa5a9276d1
4 changed files with 274 additions and 81 deletions

View File

@ -677,6 +677,15 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
struct bgp_filter *filter;
struct peer *peer = UPDGRP_PEER(updgrp);
int match = 0;
json_object *json_updgrp = NULL;
json_object *json_subgrps = NULL;
json_object *json_subgrp = NULL;
json_object *json_time = NULL;
json_object *json_subgrp_time = NULL;
json_object *json_subgrp_event = NULL;
json_object *json_peers = NULL;
json_object *json_pkt_info = NULL;
time_t epoch_tbuf, tbuf;
if (!ctx)
return CMD_SUCCESS;
@ -703,79 +712,232 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
vty = ctx->vty;
vty_out(vty, "Update-group %" PRIu64 ":\n", updgrp->id);
vty_out(vty, " Created: %s", timestamp_string(updgrp->uptime));
filter = &updgrp->conf->filter[updgrp->afi][updgrp->safi];
if (filter->map[RMAP_OUT].name)
vty_out(vty, " Outgoing route map: %s\n",
filter->map[RMAP_OUT].name);
vty_out(vty, " MRAI value (seconds): %d\n", updgrp->conf->v_routeadv);
if (updgrp->conf->change_local_as)
vty_out(vty, " Local AS %u%s%s\n",
updgrp->conf->change_local_as,
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_NO_PREPEND)
? " no-prepend"
: "",
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_REPLACE_AS)
? " replace-as"
: "");
if (ctx->uj) {
json_updgrp = json_object_new_object();
/* Display json o/p */
tbuf = monotime(NULL);
tbuf -= updgrp->uptime;
epoch_tbuf = time(NULL) - tbuf;
json_time = json_object_new_object();
json_object_int_add(json_time, "epoch", epoch_tbuf);
json_object_string_add(json_time, "epochString",
ctime(&epoch_tbuf));
json_object_object_add(json_updgrp, "groupCreateTime",
json_time);
json_object_string_add(json_updgrp, "afi",
afi2str(updgrp->afi));
json_object_string_add(json_updgrp, "safi",
safi2str(updgrp->safi));
} else {
vty_out(vty, "Update-group %" PRIu64 ":\n", updgrp->id);
vty_out(vty, " Created: %s", timestamp_string(updgrp->uptime));
}
filter = &updgrp->conf->filter[updgrp->afi][updgrp->safi];
if (filter->map[RMAP_OUT].name) {
if (ctx->uj)
json_object_string_add(json_updgrp, "outRouteMap",
filter->map[RMAP_OUT].name);
else
vty_out(vty, " Outgoing route map: %s\n",
filter->map[RMAP_OUT].name);
}
if (ctx->uj)
json_object_int_add(json_updgrp, "minRouteAdvInt",
updgrp->conf->v_routeadv);
else
vty_out(vty, " MRAI value (seconds): %d\n",
updgrp->conf->v_routeadv);
if (updgrp->conf->change_local_as) {
if (ctx->uj) {
json_object_int_add(json_updgrp, "localAs",
updgrp->conf->change_local_as);
json_object_boolean_add(
json_updgrp, "noPrepend",
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_NO_PREPEND));
json_object_boolean_add(
json_updgrp, "replaceLocalAs",
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_REPLACE_AS));
} else {
vty_out(vty, " Local AS %u%s%s\n",
updgrp->conf->change_local_as,
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_NO_PREPEND)
? " no-prepend"
: "",
CHECK_FLAG(updgrp->conf->flags,
PEER_FLAG_LOCAL_AS_REPLACE_AS)
? " replace-as"
: "");
}
}
json_subgrps = json_object_new_array();
UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
if (ctx->subgrp_id && (ctx->subgrp_id != subgrp->id))
continue;
vty_out(vty, "\n");
vty_out(vty, " Update-subgroup %" PRIu64 ":\n", subgrp->id);
vty_out(vty, " Created: %s",
timestamp_string(subgrp->uptime));
if (ctx->uj) {
json_subgrp = json_object_new_object();
json_object_int_add(json_subgrp, "subGroupId",
subgrp->id);
tbuf = monotime(NULL);
tbuf -= subgrp->uptime;
epoch_tbuf = time(NULL) - tbuf;
json_subgrp_time = json_object_new_object();
json_object_int_add(json_subgrp_time, "epoch",
epoch_tbuf);
json_object_string_add(json_subgrp_time, "epochString",
ctime(&epoch_tbuf));
json_object_object_add(json_subgrp, "groupCreateTime",
json_subgrp_time);
} else {
vty_out(vty, "\n");
vty_out(vty, " Update-subgroup %" PRIu64 ":\n",
subgrp->id);
vty_out(vty, " Created: %s",
timestamp_string(subgrp->uptime));
}
if (subgrp->split_from.update_group_id
|| subgrp->split_from.subgroup_id) {
vty_out(vty, " Split from group id: %" PRIu64 "\n",
subgrp->split_from.update_group_id);
vty_out(vty,
" Split from subgroup id: %" PRIu64 "\n",
subgrp->split_from.subgroup_id);
if (ctx->uj) {
json_object_int_add(
json_subgrp, "splitGroupId",
subgrp->split_from.update_group_id);
json_object_int_add(
json_subgrp, "splitSubGroupId",
subgrp->split_from.subgroup_id);
} else {
vty_out(vty,
" Split from group id: %" PRIu64
"\n",
subgrp->split_from.update_group_id);
vty_out(vty,
" Split from subgroup id: %" PRIu64
"\n",
subgrp->split_from.subgroup_id);
}
}
vty_out(vty, " Join events: %u\n", subgrp->join_events);
vty_out(vty, " Prune events: %u\n", subgrp->prune_events);
vty_out(vty, " Merge events: %u\n", subgrp->merge_events);
vty_out(vty, " Split events: %u\n", subgrp->split_events);
vty_out(vty, " Update group switch events: %u\n",
subgrp->updgrp_switch_events);
vty_out(vty, " Peer refreshes combined: %u\n",
subgrp->peer_refreshes_combined);
vty_out(vty, " Merge checks triggered: %u\n",
subgrp->merge_checks_triggered);
vty_out(vty, " Coalesce Time: %u%s\n",
(UPDGRP_INST(subgrp->update_group))->coalesce_time,
subgrp->t_coalesce ? "(Running)" : "");
vty_out(vty, " Version: %" PRIu64 "\n", subgrp->version);
vty_out(vty, " Packet queue length: %d\n",
bpacket_queue_length(SUBGRP_PKTQ(subgrp)));
vty_out(vty, " Total packets enqueued: %u\n",
subgroup_total_packets_enqueued(subgrp));
vty_out(vty, " Packet queue high watermark: %d\n",
bpacket_queue_hwm_length(SUBGRP_PKTQ(subgrp)));
vty_out(vty, " Adj-out list count: %u\n", subgrp->adj_count);
vty_out(vty, " Advertise list: %s\n",
advertise_list_is_empty(subgrp) ? "empty"
: "not empty");
vty_out(vty, " Flags: %s\n",
CHECK_FLAG(subgrp->flags, SUBGRP_FLAG_NEEDS_REFRESH)
? "R"
: "");
if (peer)
vty_out(vty, " Max packet size: %d\n",
peer->max_packet_size);
if (subgrp->peer_count > 0) {
vty_out(vty, " Peers:\n");
SUBGRP_FOREACH_PEER (subgrp, paf)
vty_out(vty, " - %s\n", paf->peer->host);
if (ctx->uj) {
json_subgrp_event = json_object_new_object();
json_object_int_add(json_subgrp_event, "joinEvents",
subgrp->join_events);
json_object_int_add(json_subgrp_event, "pruneEvents",
subgrp->prune_events);
json_object_int_add(json_subgrp_event, "mergeEvents",
subgrp->merge_events);
json_object_int_add(json_subgrp_event, "splitEvents",
subgrp->split_events);
json_object_int_add(json_subgrp_event, "switchEvents",
subgrp->updgrp_switch_events);
json_object_int_add(json_subgrp_event,
"peerRefreshEvents",
subgrp->peer_refreshes_combined);
json_object_int_add(json_subgrp_event,
"mergeCheckEvents",
subgrp->merge_checks_triggered);
json_object_object_add(json_subgrp, "statistics",
json_subgrp_event);
json_object_int_add(json_subgrp, "coalesceTime",
(UPDGRP_INST(subgrp->update_group))
->coalesce_time);
json_object_int_add(json_subgrp, "version",
subgrp->version);
json_pkt_info = json_object_new_object();
json_object_int_add(
json_pkt_info, "qeueueLen",
bpacket_queue_length(SUBGRP_PKTQ(subgrp)));
json_object_int_add(
json_pkt_info, "queuedTotal",
subgroup_total_packets_enqueued(subgrp));
json_object_int_add(
json_pkt_info, "queueHwmLen",
bpacket_queue_hwm_length(SUBGRP_PKTQ(subgrp)));
json_object_int_add(
json_pkt_info, "totalEnqueued",
subgroup_total_packets_enqueued(subgrp));
json_object_object_add(json_subgrp, "packetQueueInfo",
json_pkt_info);
json_object_int_add(json_subgrp, "adjListCount",
subgrp->adj_count);
json_object_boolean_add(
json_subgrp, "needsRefresh",
CHECK_FLAG(subgrp->flags,
SUBGRP_FLAG_NEEDS_REFRESH));
} else {
vty_out(vty, " Join events: %u\n",
subgrp->join_events);
vty_out(vty, " Prune events: %u\n",
subgrp->prune_events);
vty_out(vty, " Merge events: %u\n",
subgrp->merge_events);
vty_out(vty, " Split events: %u\n",
subgrp->split_events);
vty_out(vty, " Update group switch events: %u\n",
subgrp->updgrp_switch_events);
vty_out(vty, " Peer refreshes combined: %u\n",
subgrp->peer_refreshes_combined);
vty_out(vty, " Merge checks triggered: %u\n",
subgrp->merge_checks_triggered);
vty_out(vty, " Coalesce Time: %u%s\n",
(UPDGRP_INST(subgrp->update_group))
->coalesce_time,
subgrp->t_coalesce ? "(Running)" : "");
vty_out(vty, " Version: %" PRIu64 "\n",
subgrp->version);
vty_out(vty, " Packet queue length: %d\n",
bpacket_queue_length(SUBGRP_PKTQ(subgrp)));
vty_out(vty, " Total packets enqueued: %u\n",
subgroup_total_packets_enqueued(subgrp));
vty_out(vty, " Packet queue high watermark: %d\n",
bpacket_queue_hwm_length(SUBGRP_PKTQ(subgrp)));
vty_out(vty, " Adj-out list count: %u\n",
subgrp->adj_count);
vty_out(vty, " Advertise list: %s\n",
advertise_list_is_empty(subgrp) ? "empty"
: "not empty");
vty_out(vty, " Flags: %s\n",
CHECK_FLAG(subgrp->flags,
SUBGRP_FLAG_NEEDS_REFRESH)
? "R"
: "");
if (peer)
vty_out(vty, " Max packet size: %d\n",
peer->max_packet_size);
}
if (subgrp->peer_count > 0) {
if (ctx->uj) {
json_peers = json_object_new_array();
SUBGRP_FOREACH_PEER (subgrp, paf) {
json_object *peer =
json_object_new_string(
paf->peer->host);
json_object_array_add(json_peers, peer);
}
json_object_object_add(json_subgrp, "peers",
json_peers);
} else {
vty_out(vty, " Peers:\n");
SUBGRP_FOREACH_PEER (subgrp, paf)
vty_out(vty, " - %s\n",
paf->peer->host);
}
}
if (ctx->uj)
json_object_array_add(json_subgrps, json_subgrp);
}
if (ctx->uj) {
json_object_object_add(json_updgrp, "subGroup", json_subgrps);
json_object_object_addf(ctx->json_updategrps, json_updgrp,
"%" PRIu64, updgrp->id);
}
return UPDWALK_CONTINUE;
}
@ -1708,14 +1870,34 @@ void update_bgp_group_free(struct bgp *bgp)
}
void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi, struct vty *vty,
uint64_t subgrp_id)
uint64_t subgrp_id, bool uj)
{
struct updwalk_context ctx;
json_object *json_vrf_obj = NULL;
memset(&ctx, 0, sizeof(ctx));
ctx.vty = vty;
ctx.subgrp_id = subgrp_id;
ctx.uj = uj;
if (uj) {
ctx.json_updategrps = json_object_new_object();
json_vrf_obj = json_object_new_object();
}
update_group_af_walk(bgp, afi, safi, update_group_show_walkcb, &ctx);
if (uj) {
const char *vname;
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
vname = VRF_DEFAULT_NAME;
else
vname = bgp->name;
json_object_object_add(json_vrf_obj, vname,
ctx.json_updategrps);
vty_json(vty, json_vrf_obj);
}
}
/*

View File

@ -304,6 +304,8 @@ struct updwalk_context {
updgrp_walkcb cb;
void *context;
uint8_t flags;
bool uj;
json_object *json_updategrps;
#define UPDWALK_FLAGS_ADVQUEUE (1 << 0)
#define UPDWALK_FLAGS_ADVERTISED (1 << 1)
@ -365,7 +367,7 @@ extern void update_bgp_group_init(struct bgp *);
extern void udpate_bgp_group_free(struct bgp *);
extern void update_group_show(struct bgp *bgp, afi_t afi, safi_t safi,
struct vty *vty, uint64_t subgrp_id);
struct vty *vty, uint64_t subgrp_id, bool uj);
extern void update_group_show_stats(struct bgp *bgp, struct vty *vty);
extern void update_group_adjust_peer(struct peer_af *paf);
extern int update_group_adjust_soloness(struct peer *peer, int set);

View File

@ -15531,28 +15531,30 @@ DEFUN (show_ip_bgp_route_leak,
}
static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
safi_t safi)
safi_t safi, bool uj)
{
struct listnode *node, *nnode;
struct bgp *bgp;
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
vty_out(vty, "\nInstance %s:\n",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
? VRF_DEFAULT_NAME
: bgp->name);
update_group_show(bgp, afi, safi, vty, 0);
if (!uj)
vty_out(vty, "\nInstance %s:\n",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
? VRF_DEFAULT_NAME
: bgp->name);
update_group_show(bgp, afi, safi, vty, 0, uj);
}
}
static int bgp_show_update_groups(struct vty *vty, const char *name, int afi,
int safi, uint64_t subgrp_id)
int safi, uint64_t subgrp_id, bool uj)
{
struct bgp *bgp;
if (name) {
if (strmatch(name, "all")) {
bgp_show_all_instances_updgrps_vty(vty, afi, safi);
bgp_show_all_instances_updgrps_vty(vty, afi, safi, uj);
return CMD_SUCCESS;
} else {
bgp = bgp_lookup_by_name(name);
@ -15562,13 +15564,13 @@ static int bgp_show_update_groups(struct vty *vty, const char *name, int afi,
}
if (bgp)
update_group_show(bgp, afi, safi, vty, subgrp_id);
update_group_show(bgp, afi, safi, vty, subgrp_id, uj);
return CMD_SUCCESS;
}
DEFUN (show_ip_bgp_updgrps,
show_ip_bgp_updgrps_cmd,
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] update-groups [SUBGROUP-ID]",
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] update-groups [SUBGROUP-ID] [json]",
SHOW_STR
IP_STR
BGP_STR
@ -15576,7 +15578,8 @@ DEFUN (show_ip_bgp_updgrps,
BGP_AFI_HELP_STR
BGP_SAFI_WITH_LABEL_HELP_STR
"Detailed info about dynamic update groups\n"
"Specific subgroup to display detailed info for\n")
"Specific subgroup to display detailed info for\n"
JSON_STR)
{
char *vrf = NULL;
afi_t afi = AFI_IP6;
@ -15585,6 +15588,8 @@ DEFUN (show_ip_bgp_updgrps,
int idx = 0;
bool uj = use_json(argc, argv);
/* show [ip] bgp */
if (argv_find(argv, argc, "ip", &idx))
afi = AFI_IP;
@ -15606,19 +15611,22 @@ DEFUN (show_ip_bgp_updgrps,
if (argv[idx]->type == VARIABLE_TKN)
subgrp_id = strtoull(argv[idx]->arg, NULL, 10);
return (bgp_show_update_groups(vty, vrf, afi, safi, subgrp_id));
return (bgp_show_update_groups(vty, vrf, afi, safi, subgrp_id, uj));
}
DEFUN (show_bgp_instance_all_ipv6_updgrps,
show_bgp_instance_all_ipv6_updgrps_cmd,
"show [ip] bgp <view|vrf> all update-groups",
"show [ip] bgp <view|vrf> all update-groups [json]",
SHOW_STR
IP_STR
BGP_STR
BGP_INSTANCE_ALL_HELP_STR
"Detailed info about dynamic update groups\n")
"Detailed info about dynamic update groups\n"
JSON_STR)
{
bgp_show_all_instances_updgrps_vty(vty, AFI_IP6, SAFI_UNICAST);
bool uj = use_json(argc, argv);
bgp_show_all_instances_updgrps_vty(vty, AFI_IP6, SAFI_UNICAST, uj);
return CMD_SUCCESS;
}
@ -15635,7 +15643,7 @@ DEFUN (show_bgp_l2vpn_evpn_updgrps,
char *vrf = NULL;
uint64_t subgrp_id = 0;
bgp_show_update_groups(vty, vrf, AFI_L2VPN, SAFI_EVPN, subgrp_id);
bgp_show_update_groups(vty, vrf, AFI_L2VPN, SAFI_EVPN, subgrp_id, 0);
return CMD_SUCCESS;
}

View File

@ -296,7 +296,7 @@ the default route.
Allow IPv6 nexthop tracking to resolve via the default route. This parameter
is configured per-VRF, so the command is also available in the VRF subnode.
.. clicmd:: show ip nht [vrf NAME] [A.B.C.D|X:X::X:X] [mrib]
.. clicmd:: show ip nht [vrf NAME] [A.B.C.D|X:X::X:X] [mrib] [json]
Show nexthop tracking status for address resolution. If vrf is not specified
then display the default vrf. If ``all`` is specified show all vrf address
@ -305,6 +305,7 @@ the default route.
indicates that the operator wants to see the multicast rib address resolution
table. An alternative form of the command is ``show ip import-check`` and this
form of the command is deprecated at this point in time.
If the ``json`` option is specified, output is displayed in JSON format.
PBR dataplane programming
=========================