forked from Mirror/frr
Merge pull request #17431 from krishna-samy/bgpd_json_commits
bgpd: show json output changes to optimize various show commands
This commit is contained in:
commit
c9c9608c70
|
@ -3108,6 +3108,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
|
|||
afi_t afi;
|
||||
safi_t safi;
|
||||
uint32_t prefix_cnt, path_cnt;
|
||||
int first = true;
|
||||
|
||||
afi = AFI_L2VPN;
|
||||
safi = SAFI_EVPN;
|
||||
|
@ -3132,8 +3133,15 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
|
|||
prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
|
||||
sizeof(rd_str), bgp->asnotation);
|
||||
|
||||
if (json)
|
||||
if (json) {
|
||||
if (first) {
|
||||
vty_out(vty, "\"%s\":", rd_str);
|
||||
first = false;
|
||||
} else {
|
||||
vty_out(vty, ",\"%s\":", rd_str);
|
||||
}
|
||||
json_rd = json_object_new_object();
|
||||
}
|
||||
|
||||
rd_header = 1;
|
||||
|
||||
|
@ -3247,18 +3255,18 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
|
|||
}
|
||||
|
||||
if (json) {
|
||||
if (add_rd_to_json)
|
||||
json_object_object_add(json, rd_str, json_rd);
|
||||
else {
|
||||
if (add_rd_to_json) {
|
||||
vty_json_no_pretty(vty, json_rd);
|
||||
} else {
|
||||
vty_out(vty, "{}");
|
||||
json_object_free(json_rd);
|
||||
json_rd = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (json) {
|
||||
json_object_int_add(json, "numPrefix", prefix_cnt);
|
||||
json_object_int_add(json, "numPaths", path_cnt);
|
||||
vty_out(vty, ",\"numPrefix\":%u", prefix_cnt);
|
||||
vty_out(vty, ",\"numPaths\":%u", path_cnt);
|
||||
} else {
|
||||
if (prefix_cnt == 0) {
|
||||
vty_out(vty, "No EVPN prefixes %sexist\n",
|
||||
|
@ -3276,20 +3284,18 @@ int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
|
|||
{
|
||||
json_object *json = NULL;
|
||||
|
||||
if (use_json)
|
||||
if (use_json) {
|
||||
json = json_object_new_object();
|
||||
vty_out(vty, "{\n");
|
||||
}
|
||||
|
||||
evpn_show_all_routes(vty, bgp, type, json, detail, false);
|
||||
|
||||
if (use_json)
|
||||
/*
|
||||
* We are using no_pretty here because under extremely high
|
||||
* settings (lots of routes with many different paths) this can
|
||||
* save several minutes of output when FRR is run on older cpu's
|
||||
* or more underperforming routers out there. So for route
|
||||
* scale, we need to use no_pretty json.
|
||||
*/
|
||||
vty_json_no_pretty(vty, json);
|
||||
if (use_json) {
|
||||
vty_out(vty, "}\n");
|
||||
json_object_free(json);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -4940,8 +4946,10 @@ DEFUN(show_bgp_l2vpn_evpn_route,
|
|||
if (!bgp)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (uj)
|
||||
if (uj) {
|
||||
json = json_object_new_object();
|
||||
vty_out(vty, "{\n");
|
||||
}
|
||||
|
||||
if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
|
||||
return CMD_WARNING;
|
||||
|
@ -4954,13 +4962,10 @@ DEFUN(show_bgp_l2vpn_evpn_route,
|
|||
|
||||
evpn_show_all_routes(vty, bgp, type, json, detail, self_orig);
|
||||
|
||||
/*
|
||||
* This is an extremely expensive operation at scale
|
||||
* and as such we need to save as much time as is
|
||||
* possible.
|
||||
*/
|
||||
if (uj)
|
||||
vty_json_no_pretty(vty, json);
|
||||
if (uj) {
|
||||
vty_out(vty, "}\n");
|
||||
json_object_free(json);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
@ -5017,10 +5022,20 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd,
|
|||
if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
|
||||
return CMD_WARNING;
|
||||
|
||||
if (rd_all)
|
||||
if (rd_all) {
|
||||
if (uj)
|
||||
vty_out(vty, "{\n");
|
||||
|
||||
evpn_show_all_routes(vty, bgp, type, json, 1, false);
|
||||
else
|
||||
|
||||
if (uj) {
|
||||
vty_out(vty, "}\n");
|
||||
json_object_free(json);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
evpn_show_route_rd(vty, bgp, &prd, type, json);
|
||||
}
|
||||
|
||||
if (uj)
|
||||
vty_json(vty, json);
|
||||
|
|
|
@ -970,9 +970,8 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
|
|||
json_object_object_add(json, "nexthops", json_gates);
|
||||
}
|
||||
|
||||
static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
|
||||
struct bgp_nexthop_cache *bnc, bool specific,
|
||||
json_object *json)
|
||||
static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp, struct bgp_nexthop_cache *bnc,
|
||||
bool detail, bool uj)
|
||||
{
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
time_t tbuf;
|
||||
|
@ -983,10 +982,10 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
|
|||
|
||||
peer = (struct peer *)bnc->nht_info;
|
||||
|
||||
if (json)
|
||||
if (uj)
|
||||
json_nexthop = json_object_new_object();
|
||||
if (bnc->srte_color) {
|
||||
if (json)
|
||||
if (uj)
|
||||
json_object_int_add(json_nexthop, "srteColor",
|
||||
bnc->srte_color);
|
||||
else
|
||||
|
@ -994,7 +993,7 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
|
|||
}
|
||||
inet_ntop(bnc->prefix.family, &bnc->prefix.u.prefix, buf, sizeof(buf));
|
||||
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
|
||||
if (json) {
|
||||
if (uj) {
|
||||
json_object_boolean_true_add(json_nexthop, "valid");
|
||||
json_object_boolean_true_add(json_nexthop, "complete");
|
||||
json_object_int_add(json_nexthop, "igpMetric",
|
||||
|
@ -1022,7 +1021,7 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
|
|||
}
|
||||
bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
|
||||
} else if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE)) {
|
||||
if (json) {
|
||||
if (uj) {
|
||||
json_object_boolean_true_add(json_nexthop, "valid");
|
||||
json_object_boolean_false_add(json_nexthop, "complete");
|
||||
json_object_int_add(json_nexthop, "igpMetric",
|
||||
|
@ -1042,7 +1041,7 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
|
|||
}
|
||||
bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
|
||||
} else {
|
||||
if (json) {
|
||||
if (uj) {
|
||||
json_object_boolean_false_add(json_nexthop, "valid");
|
||||
json_object_boolean_false_add(json_nexthop, "complete");
|
||||
json_object_int_add(json_nexthop, "pathCount",
|
||||
|
@ -1074,8 +1073,8 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
|
|||
}
|
||||
}
|
||||
tbuf = time(NULL) - (monotime(NULL) - bnc->last_update);
|
||||
if (json) {
|
||||
if (!specific) {
|
||||
if (uj) {
|
||||
if (detail) {
|
||||
json_last_update = json_object_new_object();
|
||||
json_object_int_add(json_last_update, "epoch", tbuf);
|
||||
json_object_string_add(json_last_update, "string",
|
||||
|
@ -1090,22 +1089,25 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
|
|||
}
|
||||
|
||||
/* show paths dependent on nexthop, if needed. */
|
||||
if (specific)
|
||||
if (detail)
|
||||
bgp_show_nexthop_paths(vty, bgp, bnc, json_nexthop);
|
||||
if (json)
|
||||
json_object_object_add(json, buf, json_nexthop);
|
||||
|
||||
if (uj) {
|
||||
vty_out(vty, "\"%s\":", buf);
|
||||
vty_json_no_pretty(vty, json_nexthop);
|
||||
}
|
||||
}
|
||||
|
||||
static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
|
||||
bool import_table, json_object *json, afi_t afi,
|
||||
bool detail)
|
||||
static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, bool import_table, bool uj,
|
||||
afi_t afi, bool detail)
|
||||
{
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
struct bgp_nexthop_cache_head(*tree)[AFI_MAX];
|
||||
json_object *json_afi = NULL;
|
||||
bool found = false;
|
||||
bool firstafi = true;
|
||||
bool firstnh = true;
|
||||
|
||||
if (!json) {
|
||||
if (!uj) {
|
||||
if (import_table)
|
||||
vty_out(vty, "Current BGP import check cache:\n");
|
||||
else
|
||||
|
@ -1117,34 +1119,42 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
|
|||
tree = &bgp->nexthop_cache_table;
|
||||
|
||||
if (afi == AFI_IP || afi == AFI_IP6) {
|
||||
if (json)
|
||||
json_afi = json_object_new_object();
|
||||
if (uj)
|
||||
vty_out(vty, "%s:{", (afi == AFI_IP) ? "\"ipv4\"" : "\"ipv6\"");
|
||||
frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc) {
|
||||
bgp_show_nexthop(vty, bgp, bnc, detail, json_afi);
|
||||
if (uj)
|
||||
vty_out(vty, "%s", firstnh ? "" : ",");
|
||||
bgp_show_nexthop(vty, bgp, bnc, detail, uj);
|
||||
found = true;
|
||||
firstnh = false;
|
||||
}
|
||||
if (found && json)
|
||||
json_object_object_add(
|
||||
json, (afi == AFI_IP) ? "ipv4" : "ipv6",
|
||||
json_afi);
|
||||
if (found && uj)
|
||||
vty_out(vty, "}");
|
||||
return;
|
||||
}
|
||||
|
||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||
if (json && (afi == AFI_IP || afi == AFI_IP6))
|
||||
json_afi = json_object_new_object();
|
||||
frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc)
|
||||
bgp_show_nexthop(vty, bgp, bnc, detail, json_afi);
|
||||
if (json && (afi == AFI_IP || afi == AFI_IP6))
|
||||
json_object_object_add(
|
||||
json, (afi == AFI_IP) ? "ipv4" : "ipv6",
|
||||
json_afi);
|
||||
if (afi != AFI_IP && afi != AFI_IP6)
|
||||
continue;
|
||||
if (uj)
|
||||
vty_out(vty, "%s%s:{", firstafi ? "" : ",",
|
||||
(afi == AFI_IP) ? "\"ipv4\"" : "\"ipv6\"");
|
||||
firstafi = false;
|
||||
firstnh = true;
|
||||
frr_each (bgp_nexthop_cache, &(*tree)[afi], bnc) {
|
||||
if (uj)
|
||||
vty_out(vty, "%s", firstnh ? "" : ",");
|
||||
bgp_show_nexthop(vty, bgp, bnc, detail, uj);
|
||||
firstnh = false;
|
||||
}
|
||||
|
||||
if (uj)
|
||||
vty_out(vty, "}");
|
||||
}
|
||||
}
|
||||
|
||||
static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
|
||||
const char *nhopip_str, bool import_table,
|
||||
json_object *json, afi_t afi, bool detail)
|
||||
static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name, const char *nhopip_str,
|
||||
bool import_table, bool uj, afi_t afi, bool detail)
|
||||
{
|
||||
struct bgp *bgp;
|
||||
|
||||
|
@ -1153,7 +1163,7 @@ static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
|
|||
else
|
||||
bgp = bgp_get_default();
|
||||
if (!bgp) {
|
||||
if (!json)
|
||||
if (!uj)
|
||||
vty_out(vty, "%% No such BGP instance exist\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
@ -1163,61 +1173,57 @@ static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
|
|||
struct bgp_nexthop_cache_head (*tree)[AFI_MAX];
|
||||
struct bgp_nexthop_cache *bnc;
|
||||
bool found = false;
|
||||
json_object *json_afi = NULL;
|
||||
|
||||
if (!str2prefix(nhopip_str, &nhop)) {
|
||||
if (!json)
|
||||
if (!uj)
|
||||
vty_out(vty, "nexthop address is malformed\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
tree = import_table ? &bgp->import_check_table
|
||||
: &bgp->nexthop_cache_table;
|
||||
if (json)
|
||||
json_afi = json_object_new_object();
|
||||
if (uj)
|
||||
vty_out(vty, "%s:{",
|
||||
(family2afi(nhop.family) == AFI_IP) ? "\"ipv4\"" : "\"ipv6\"");
|
||||
frr_each (bgp_nexthop_cache, &(*tree)[family2afi(nhop.family)],
|
||||
bnc) {
|
||||
if (prefix_cmp(&bnc->prefix, &nhop))
|
||||
continue;
|
||||
bgp_show_nexthop(vty, bgp, bnc, true, json_afi);
|
||||
bgp_show_nexthop(vty, bgp, bnc, true, uj);
|
||||
found = true;
|
||||
}
|
||||
if (json)
|
||||
json_object_object_add(
|
||||
json,
|
||||
(family2afi(nhop.family) == AFI_IP) ? "ipv4"
|
||||
: "ipv6",
|
||||
json_afi);
|
||||
if (!found && !json)
|
||||
if (!found && !uj)
|
||||
vty_out(vty, "nexthop %s does not have entry\n",
|
||||
nhopip_str);
|
||||
|
||||
if (uj)
|
||||
vty_out(vty, "}");
|
||||
} else
|
||||
bgp_show_nexthops(vty, bgp, import_table, json, afi, detail);
|
||||
bgp_show_nexthops(vty, bgp, import_table, uj, afi, detail);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void bgp_show_all_instances_nexthops_vty(struct vty *vty,
|
||||
json_object *json, afi_t afi,
|
||||
bool detail)
|
||||
static void bgp_show_all_instances_nexthops_vty(struct vty *vty, bool uj, afi_t afi, bool detail)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct bgp *bgp;
|
||||
const char *inst_name;
|
||||
json_object *json_instance = NULL;
|
||||
bool firstinst = true;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
|
||||
inst_name = (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
|
||||
? VRF_DEFAULT_NAME
|
||||
: bgp->name;
|
||||
if (json)
|
||||
json_instance = json_object_new_object();
|
||||
if (uj)
|
||||
vty_out(vty, "%s\"%s\":{", firstinst ? "" : ",", inst_name);
|
||||
|
||||
else
|
||||
vty_out(vty, "\nInstance %s:\n", inst_name);
|
||||
|
||||
bgp_show_nexthops(vty, bgp, false, json_instance, afi, detail);
|
||||
|
||||
if (json)
|
||||
json_object_object_add(json, inst_name, json_instance);
|
||||
bgp_show_nexthops(vty, bgp, false, uj, afi, detail);
|
||||
firstinst = false;
|
||||
if (uj)
|
||||
vty_out(vty, "}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1241,20 +1247,18 @@ DEFPY (show_ip_bgp_nexthop,
|
|||
JSON_STR)
|
||||
{
|
||||
int rc = 0;
|
||||
json_object *json = NULL;
|
||||
afi_t afiz = AFI_UNSPEC;
|
||||
|
||||
if (uj)
|
||||
json = json_object_new_object();
|
||||
vty_out(vty, "{\n");
|
||||
|
||||
if (afi)
|
||||
afiz = bgp_vty_afi_from_str(afi);
|
||||
|
||||
rc = show_ip_bgp_nexthop_table(vty, vrf, nhop_str, false, json, afiz,
|
||||
detail);
|
||||
rc = show_ip_bgp_nexthop_table(vty, vrf, nhop_str, false, uj, afiz, detail);
|
||||
|
||||
if (uj)
|
||||
vty_json(vty, json);
|
||||
vty_out(vty, "}\n");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -1271,16 +1275,14 @@ DEFPY (show_ip_bgp_import_check,
|
|||
JSON_STR)
|
||||
{
|
||||
int rc = 0;
|
||||
json_object *json = NULL;
|
||||
|
||||
if (uj)
|
||||
json = json_object_new_object();
|
||||
vty_out(vty, "{\n");
|
||||
|
||||
rc = show_ip_bgp_nexthop_table(vty, vrf, NULL, true, json, AFI_UNSPEC,
|
||||
detail);
|
||||
rc = show_ip_bgp_nexthop_table(vty, vrf, NULL, true, uj, AFI_UNSPEC, detail);
|
||||
|
||||
if (uj)
|
||||
vty_json(vty, json);
|
||||
vty_out(vty, "}\n");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -1298,19 +1300,18 @@ DEFPY (show_ip_bgp_instance_all_nexthop,
|
|||
"Show detailed information\n"
|
||||
JSON_STR)
|
||||
{
|
||||
json_object *json = NULL;
|
||||
afi_t afiz = AFI_UNSPEC;
|
||||
|
||||
if (uj)
|
||||
json = json_object_new_object();
|
||||
vty_out(vty, "{");
|
||||
|
||||
if (afi)
|
||||
afiz = bgp_vty_afi_from_str(afi);
|
||||
|
||||
bgp_show_all_instances_nexthops_vty(vty, json, afiz, detail);
|
||||
bgp_show_all_instances_nexthops_vty(vty, uj, afiz, detail);
|
||||
|
||||
if (uj)
|
||||
vty_json(vty, json);
|
||||
vty_out(vty, "}");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
|
105
bgpd/bgp_route.c
105
bgpd/bgp_route.c
|
@ -15106,6 +15106,8 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
|
|||
json_object *json = NULL;
|
||||
json_object *json_ar = NULL;
|
||||
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
|
||||
bool first = true;
|
||||
struct update_subgroup *subgrp;
|
||||
|
||||
/* Init BGP headers here so they're only displayed once
|
||||
* even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
|
||||
|
@ -15174,6 +15176,28 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
|
|||
else
|
||||
table = bgp->rib[afi][safi];
|
||||
|
||||
subgrp = peer_subgroup(peer, afi, safi);
|
||||
if (use_json) {
|
||||
if (type == bgp_show_adj_route_advertised || type == bgp_show_adj_route_received) {
|
||||
if (header1) {
|
||||
int version = table ? table->version : 0;
|
||||
vty_out(vty, "\"bgpTableVersion\":%d", version);
|
||||
vty_out(vty, ",\"bgpLocalRouterId\":\"%pI4\"", &bgp->router_id);
|
||||
vty_out(vty, ",\"defaultLocPrf\":%u", bgp->default_local_pref);
|
||||
vty_out(vty, ",\"localAS\":%u", bgp->as);
|
||||
if (type == bgp_show_adj_route_advertised && subgrp &&
|
||||
CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
|
||||
vty_out(vty, ",\"bgpOriginatingDefaultNetwork\":\"%s\"",
|
||||
(afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
|
||||
}
|
||||
|
||||
if (type == bgp_show_adj_route_advertised)
|
||||
vty_out(vty, ",\"advertisedRoutes\": ");
|
||||
if (type == bgp_show_adj_route_received)
|
||||
vty_out(vty, ",\"receivedRoutes\": ");
|
||||
}
|
||||
}
|
||||
|
||||
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
|
||||
|| (safi == SAFI_EVPN)) {
|
||||
|
||||
|
@ -15192,6 +15216,7 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
|
|||
json_routes = json_object_new_object();
|
||||
|
||||
const struct prefix_rd *prd;
|
||||
|
||||
prd = (const struct prefix_rd *)bgp_dest_get_prefix(
|
||||
dest);
|
||||
|
||||
|
@ -15205,34 +15230,56 @@ static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
|
|||
&filtered_count_per_rd);
|
||||
|
||||
/* Don't include an empty RD in the output! */
|
||||
if (json_routes && (output_count_per_rd > 0))
|
||||
json_object_object_add(json_ar, rd_str,
|
||||
json_routes);
|
||||
if (json_routes && (output_count_per_rd > 0) && use_json) {
|
||||
if (type == bgp_show_adj_route_advertised ||
|
||||
type == bgp_show_adj_route_received) {
|
||||
if (first) {
|
||||
vty_out(vty, "\"%s\":", rd_str);
|
||||
first = false;
|
||||
} else {
|
||||
vty_out(vty, ",\"%s\":", rd_str);
|
||||
}
|
||||
vty_json_no_pretty(vty, json_routes);
|
||||
} else {
|
||||
json_object_object_add(json_ar, rd_str, json_routes);
|
||||
}
|
||||
}
|
||||
|
||||
output_count += output_count_per_rd;
|
||||
filtered_count += filtered_count_per_rd;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
|
||||
json, json_ar, show_flags, &header1, &header2,
|
||||
rd_str, match, &output_count, &filtered_count);
|
||||
|
||||
if (use_json) {
|
||||
if (type == bgp_show_adj_route_advertised)
|
||||
json_object_object_add(json, "advertisedRoutes",
|
||||
json_ar);
|
||||
else
|
||||
json_object_object_add(json, "receivedRoutes", json_ar);
|
||||
json_object_int_add(json, "totalPrefixCounter", output_count);
|
||||
json_object_int_add(json, "filteredPrefixCounter",
|
||||
filtered_count);
|
||||
if (use_json) {
|
||||
if (type == bgp_show_adj_route_advertised ||
|
||||
type == bgp_show_adj_route_received) {
|
||||
vty_json_no_pretty(vty, json_ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is an extremely expensive operation at scale
|
||||
* and non-pretty reduces memory footprint significantly.
|
||||
*/
|
||||
vty_json_no_pretty(vty, json);
|
||||
} else if (output_count > 0) {
|
||||
if (use_json) {
|
||||
if (type == bgp_show_adj_route_advertised || type == bgp_show_adj_route_received) {
|
||||
vty_out(vty, ",\"totalPrefixCounter\":%lu", output_count);
|
||||
vty_out(vty, ",\"filteredPrefixCounter\":%lu", filtered_count);
|
||||
json_object_free(json);
|
||||
} else {
|
||||
/* for bgp_show_adj_route_filtered & bgp_show_adj_route_bestpath type */
|
||||
json_object_object_add(json, "receivedRoutes", json_ar);
|
||||
json_object_int_add(json, "totalPrefixCounter", output_count);
|
||||
json_object_int_add(json, "filteredPrefixCounter", filtered_count);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is an extremely expensive operation at scale
|
||||
* and non-pretty reduces memory footprint significantly.
|
||||
*/
|
||||
if ((type != bgp_show_adj_route_advertised) && (type != bgp_show_adj_route_received))
|
||||
vty_json_no_pretty(vty, json);
|
||||
} else if (output_count > 0) {
|
||||
if (!match && filtered_count > 0)
|
||||
vty_out(vty,
|
||||
"\nTotal number of prefixes %ld (%ld filtered)\n",
|
||||
|
@ -15335,6 +15382,7 @@ DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
|
|||
uint16_t show_flags = 0;
|
||||
struct listnode *node;
|
||||
struct bgp *abgp;
|
||||
int ret;
|
||||
|
||||
if (detail || prefix_str)
|
||||
SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
|
||||
|
@ -15376,9 +15424,22 @@ DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
|
|||
else if (argv_find(argv, argc, "filtered-routes", &idx))
|
||||
type = bgp_show_adj_route_filtered;
|
||||
|
||||
if (!all)
|
||||
return peer_adj_routes(vty, peer, afi, safi, type, route_map,
|
||||
prefix_str ? prefix : NULL, show_flags);
|
||||
if (!all) {
|
||||
if (uj)
|
||||
if (type == bgp_show_adj_route_advertised ||
|
||||
type == bgp_show_adj_route_received)
|
||||
vty_out(vty, "{\n");
|
||||
|
||||
ret = peer_adj_routes(vty, peer, afi, safi, type, route_map,
|
||||
prefix_str ? prefix : NULL, show_flags);
|
||||
if (uj)
|
||||
if (type == bgp_show_adj_route_advertised ||
|
||||
type == bgp_show_adj_route_received)
|
||||
vty_out(vty, "}\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (uj)
|
||||
vty_out(vty, "{\n");
|
||||
|
||||
|
|
|
@ -11476,6 +11476,72 @@ DEFPY (show_bgp_vrfs,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY(show_bgp_router,
|
||||
show_bgp_router_cmd,
|
||||
"show bgp router [json]",
|
||||
SHOW_STR
|
||||
BGP_STR
|
||||
"Overall BGP information\n"
|
||||
JSON_STR)
|
||||
{
|
||||
char timebuf[MONOTIME_STRLEN];
|
||||
time_t unix_timestamp;
|
||||
bool uj = use_json(argc, argv);
|
||||
json_object *json = NULL;
|
||||
|
||||
if (uj)
|
||||
json = json_object_new_object();
|
||||
|
||||
time_to_string(bm->start_time, timebuf);
|
||||
|
||||
if (uj) {
|
||||
unix_timestamp = time(NULL) - (monotime(NULL) - bm->start_time);
|
||||
json_object_int_add(json, "bgpStartedAt", unix_timestamp);
|
||||
json_object_boolean_add(json, "bgpStartedGracefully",
|
||||
CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_RESTART));
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(bm->flags, BM_FLAG_GRACEFUL_RESTART)) {
|
||||
if (!uj)
|
||||
vty_out(vty, "BGP started gracefully at %s", timebuf);
|
||||
else
|
||||
json_object_boolean_add(json, "grComplete",
|
||||
CHECK_FLAG(bm->flags, BM_FLAG_GR_COMPLETE));
|
||||
|
||||
if (CHECK_FLAG(bm->flags, BM_FLAG_GR_COMPLETE)) {
|
||||
time_to_string(bm->gr_completion_time, timebuf);
|
||||
if (uj) {
|
||||
unix_timestamp = time(NULL) -
|
||||
(monotime(NULL) - bm->gr_completion_time);
|
||||
json_object_int_add(json, "grCompletedAt", unix_timestamp);
|
||||
} else
|
||||
vty_out(vty, "Graceful restart completed at %s", timebuf);
|
||||
} else {
|
||||
if (!uj)
|
||||
vty_out(vty, "Graceful restart is in progress\n");
|
||||
}
|
||||
} else {
|
||||
if (!uj)
|
||||
vty_out(vty, "BGP started at %s", timebuf);
|
||||
}
|
||||
|
||||
if (uj) {
|
||||
json_object_boolean_add(json, "bgpInMaintenanceMode",
|
||||
(CHECK_FLAG(bm->flags, BM_FLAG_MAINTENANCE_MODE)));
|
||||
json_object_int_add(json, "bgpInstanceCount", listcount(bm->bgp));
|
||||
|
||||
vty_json(vty, json);
|
||||
} else {
|
||||
if (CHECK_FLAG(bm->flags, BM_FLAG_MAINTENANCE_MODE))
|
||||
vty_out(vty, "BGP is in Maintenance mode (BGP GSHUT is in effect)\n");
|
||||
|
||||
vty_out(vty, "Number of BGP instances (including default): %d\n",
|
||||
listcount(bm->bgp));
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_bgp_mac_hash,
|
||||
show_bgp_mac_hash_cmd,
|
||||
"show bgp mac hash",
|
||||
|
@ -21927,6 +21993,9 @@ void bgp_vty_init(void)
|
|||
/* "show [ip] bgp vrfs" commands. */
|
||||
install_element(VIEW_NODE, &show_bgp_vrfs_cmd);
|
||||
|
||||
/* Some overall BGP information */
|
||||
install_element(VIEW_NODE, &show_bgp_router_cmd);
|
||||
|
||||
/* Community-list. */
|
||||
community_list_vty();
|
||||
|
||||
|
|
|
@ -4350,6 +4350,10 @@ displays IPv6 routing table.
|
|||
If ``detail`` option is specified after ``json``, more verbose JSON output
|
||||
will be displayed.
|
||||
|
||||
.. clicmd:: show bgp router [json]
|
||||
|
||||
This command displays information related BGP router and Graceful Restart.
|
||||
|
||||
Some other commands provide additional options for filtering the output.
|
||||
|
||||
.. clicmd:: show [ip] bgp regexp LINE
|
||||
|
|
|
@ -187,6 +187,16 @@ def test_bgp_administrative_reset_gr():
|
|||
"""
|
||||
)
|
||||
|
||||
def _bgp_verify_show_bgp_router_json():
|
||||
output = json.loads(r1.vtysh_cmd("show bgp router json"))
|
||||
expected = {
|
||||
"bgpStartedAt": "*",
|
||||
"bgpStartedGracefully": False,
|
||||
"bgpInMaintenanceMode": False,
|
||||
"bgpInstanceCount": 1,
|
||||
}
|
||||
return topotest.json_cmp(output, expected)
|
||||
|
||||
step("Initial BGP converge")
|
||||
test_func = functools.partial(_bgp_converge)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||
|
@ -205,6 +215,11 @@ def test_bgp_administrative_reset_gr():
|
|||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||
assert result is None, "Failed to send Administrative Reset notification from R2"
|
||||
|
||||
step("Check show bgp router json")
|
||||
test_func = functools.partial(_bgp_verify_show_bgp_router_json)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||
assert result is None, "Invalid BGP router details"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
|
|
Loading…
Reference in a new issue