summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn_vty.c69
-rw-r--r--bgpd/bgp_nexthop.c149
-rw-r--r--bgpd/bgp_nexthop.h2
-rw-r--r--bgpd/bgp_route.c103
-rw-r--r--bgpd/bgp_updgrp_adv.c95
-rw-r--r--bgpd/bgp_vty.c69
-rw-r--r--bgpd/bgpd.c4
-rw-r--r--doc/developer/building-frr-for-alpine.rst4
-rw-r--r--doc/user/bgp.rst4
-rw-r--r--lib/route_types.txt2
-rw-r--r--ospfd/ospf_vty.c12
-rw-r--r--tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py15
-rw-r--r--tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py14
-rw-r--r--tests/topotests/mgmt_oper/oper.py17
-rw-r--r--tests/topotests/mgmt_oper/test_oper.py9
-rw-r--r--zebra/zebra_nb_config.c15
-rw-r--r--zebra/zebra_routemap.c9
17 files changed, 393 insertions, 199 deletions
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index d9dfc4c5eb..dc6e0d33c2 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -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);
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 140e1baef7..ed689c8bac 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -979,9 +979,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;
@@ -992,10 +991,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
@@ -1003,7 +1002,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",
@@ -1031,7 +1030,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",
@@ -1051,7 +1050,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",
@@ -1083,8 +1082,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",
@@ -1099,22 +1098,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
@@ -1126,34 +1128,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;
@@ -1162,7 +1172,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;
}
@@ -1172,61 +1182,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, "}");
}
}
@@ -1250,20 +1256,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;
}
@@ -1280,16 +1284,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;
}
@@ -1307,19 +1309,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;
}
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 6a4a02dcc8..5679c215b1 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -82,7 +82,7 @@ struct bgp_nexthop_cache {
* L3 unreachable | VALID = 0 | VALID = 0
* | INCOMPLETE = 0 | INCOMPLETE = 0
*/
-#define BGP_NEXTHOP_EVPN_INCOMPLETE (1 << 7)
+#define BGP_NEXTHOP_EVPN_INCOMPLETE (1 << 8)
uint32_t srte_color;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0f899d9617..5ac1d26603 100644
--- a/bgpd/bgp_route.c
+++ b/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 ||
+ type == bgp_show_adj_route_received) {
+ vty_json_no_pretty(vty, json_ar);
+ }
+ }
+ }
+
if (use_json) {
- if (type == bgp_show_adj_route_advertised)
- json_object_object_add(json, "advertisedRoutes",
- json_ar);
- else
+ 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.
- */
- vty_json_no_pretty(vty, json);
- } else if (output_count > 0) {
+ 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");
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index a1bf9a4c61..8f816eb30d 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -228,64 +228,67 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg)
afi2str(afi), safi2str(safi), ctx->dest);
UPDGRP_FOREACH_SUBGRP (updgrp, subgrp) {
- /* withdraw stale addpath without waiting for the coalesce timer timeout.
- * Otherwise, since adj->addpath_tx_id is overwritten, the code never
- * notice anymore it has to do a withdrawal.
- */
- if (addpath_capable)
- subgrp_withdraw_stale_addpath(ctx, subgrp);
- /*
- * Skip the subgroups that have coalesce timer running. We will
- * walk the entire prefix table for those subgroups when the
- * coalesce timer fires.
- */
- if (!subgrp->t_coalesce) {
-
- /* An update-group that uses addpath */
- if (addpath_capable) {
- subgrp_announce_addpath_best_selected(ctx->dest,
- subgrp);
+ /* An update-group that uses addpath */
+ if (addpath_capable) {
+ /* Send withdrawals without waiting for coalesting timer
+ * to expire.
+ */
+ if (subgrp->t_coalesce) {
+ subgrp_withdraw_stale_addpath(ctx, subgrp);
- /* Process the bestpath last so the "show [ip]
- * bgp neighbor x.x.x.x advertised"
- * output shows the attributes from the bestpath
- */
- if (ctx->pi)
- subgroup_process_announce_selected(
- subgrp, ctx->pi, ctx->dest, afi,
- safi,
- bgp_addpath_id_for_peer(
- peer, afi, safi,
- &ctx->pi->tx_addpath));
+ goto done;
}
- /* An update-group that does not use addpath */
- else {
- if (ctx->pi) {
- subgroup_process_announce_selected(
- subgrp, ctx->pi, ctx->dest, afi,
- safi,
- bgp_addpath_id_for_peer(
- peer, afi, safi,
- &ctx->pi->tx_addpath));
- } else {
- /* Find the addpath_tx_id of the path we
- * had advertised and
- * send a withdraw */
- RB_FOREACH_SAFE (adj, bgp_adj_out_rb,
- &ctx->dest->adj_out,
+
+ subgrp_withdraw_stale_addpath(ctx, subgrp);
+ subgrp_announce_addpath_best_selected(ctx->dest, subgrp);
+
+ /* Process the bestpath last so the
+ * "show [ip] bgp neighbor x.x.x.x advertised" output shows
+ * the attributes from the bestpath.
+ */
+ if (ctx->pi)
+ subgroup_process_announce_selected(
+ subgrp, ctx->pi, ctx->dest, afi, safi,
+ bgp_addpath_id_for_peer(peer, afi, safi,
+ &ctx->pi->tx_addpath));
+ } else {
+ /* Send withdrawals without waiting for coalesting timer
+ * to expire.
+ */
+ if (subgrp->t_coalesce) {
+ if (!ctx->pi || CHECK_FLAG(ctx->pi->flags, BGP_PATH_UNUSEABLE)) {
+ RB_FOREACH_SAFE (adj, bgp_adj_out_rb, &ctx->dest->adj_out,
adj_next) {
if (adj->subgroup == subgrp) {
subgroup_process_announce_selected(
- subgrp, NULL,
- ctx->dest, afi,
- safi,
+ subgrp, NULL, ctx->dest, afi, safi,
adj->addpath_tx_id);
}
}
}
+
+ goto done;
+ }
+
+ if (ctx->pi) {
+ subgroup_process_announce_selected(
+ subgrp, ctx->pi, ctx->dest, afi, safi,
+ bgp_addpath_id_for_peer(peer, afi, safi,
+ &ctx->pi->tx_addpath));
+ } else {
+ RB_FOREACH_SAFE (adj, bgp_adj_out_rb, &ctx->dest->adj_out,
+ adj_next) {
+ if (adj->subgroup == subgrp) {
+ subgroup_process_announce_selected(subgrp, NULL,
+ ctx->dest, afi,
+ safi,
+ adj->addpath_tx_id);
+ }
+ }
}
}
+done:
/* Notify BGP Conditional advertisement */
bgp_notify_conditional_adv_scanner(subgrp);
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 550adf93db..40b2847c6f 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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();
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 2f234e3a5a..eda6bc31d2 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -6686,7 +6686,7 @@ int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi,
SET_FLAG(member->af_flags[afi][safi],
PEER_FLAG_ALLOWAS_IN_ORIGIN);
member->allowas_in[afi][safi] = 0;
- peer_on_policy_change(peer, afi, safi, 0);
+ peer_on_policy_change(member, afi, safi, 0);
}
} else {
if (member->allowas_in[afi][safi] != allow_num
@@ -6695,7 +6695,7 @@ int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi,
UNSET_FLAG(member->af_flags[afi][safi],
PEER_FLAG_ALLOWAS_IN_ORIGIN);
member->allowas_in[afi][safi] = allow_num;
- peer_on_policy_change(peer, afi, safi, 0);
+ peer_on_policy_change(member, afi, safi, 0);
}
}
}
diff --git a/doc/developer/building-frr-for-alpine.rst b/doc/developer/building-frr-for-alpine.rst
index 68e58c9d76..a5ce636ebb 100644
--- a/doc/developer/building-frr-for-alpine.rst
+++ b/doc/developer/building-frr-for-alpine.rst
@@ -47,11 +47,11 @@ Build apk packages
./docker/alpine/build.sh
-This will put the apk packages in:
+This will put the apk packages into the architecture folder in:
::
- ./docker/pkgs/apk/x86_64/
+ ./docker/alpine/pkgs/apk/
Usage
-----
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index dafcac7c84..3642681765 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -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
diff --git a/lib/route_types.txt b/lib/route_types.txt
index 93cbc36e97..b5f8b6fdf3 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -88,7 +88,7 @@ ZEBRA_ROUTE_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP", vr
ZEBRA_ROUTE_NHG, zebra, none, '-', 0, 0, 0, "Nexthop Group", none
ZEBRA_ROUTE_SRTE, srte, none, '-', 0, 0, 0, "SR-TE", none
ZEBRA_ROUTE_TABLE_DIRECT, table-direct, zebra, 't', 1, 1, 1, "Table-Direct", zebra
-ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-", none
+ZEBRA_ROUTE_ALL, any, none, '-', 0, 0, 0, "-", none
## help strings
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 27528f6594..95e8b179d8 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -10258,8 +10258,10 @@ DEFUN (ospf_external_route_aggregation,
tag = strtoul(argv[idx + 2]->arg, NULL, 10);
ret = ospf_asbr_external_aggregator_set(ospf, &p, tag);
- if (ret == OSPF_INVALID)
- vty_out(vty, "Invalid configuration!!\n");
+ if (ret == OSPF_FAILURE) {
+ vty_out(vty, "%% Failed to set summary-address!\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
return CMD_SUCCESS;
}
@@ -10611,8 +10613,10 @@ DEFUN (ospf_external_route_aggregation_no_adrvertise,
}
ret = ospf_asbr_external_rt_no_advertise(ospf, &p);
- if (ret == OSPF_INVALID)
- vty_out(vty, "Invalid configuration!!\n");
+ if (ret == OSPF_FAILURE) {
+ vty_out(vty, "%% Failed to set summary-address!\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
return CMD_SUCCESS;
}
diff --git a/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py b/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py
index 5d8338d6eb..7e39b83d8f 100644
--- a/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py
+++ b/tests/topotests/bgp_gr_notification/test_bgp_gr_notification.py
@@ -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:]
diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
index 3932c29b98..ee7e00b323 100644
--- a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
+++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
@@ -232,6 +232,20 @@ def test_local_vs_non_local():
assert False, "Route 60.0.0.0/24 should not have fibPending"
+def test_ip_protocol_any_fib_filter():
+ # "Filtered route of source protocol any should not get installed in fib"
+
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd("conf\nno ip protocol bgp")
+ r2.vtysh_cmd("conf\nip protocol any route-map LIMIT")
+ test_bgp_route()
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/mgmt_oper/oper.py b/tests/topotests/mgmt_oper/oper.py
index bca452d011..6e1866382b 100644
--- a/tests/topotests/mgmt_oper/oper.py
+++ b/tests/topotests/mgmt_oper/oper.py
@@ -62,7 +62,7 @@ def disable_debug(router):
router.vtysh_cmd("no debug northbound callbacks configuration")
-@retry(retry_timeout=30, initial_wait=1)
+@retry(retry_timeout=30, initial_wait=0.1)
def _do_oper_test(tgen, qr, seconds_left=None):
r1 = tgen.gears["r1"].net
@@ -113,6 +113,7 @@ def _do_oper_test(tgen, qr, seconds_left=None):
"-------DIFF---------\n%s\n---------DIFF----------",
pprint.pformat(cmpout),
)
+ cmpout = str(cmpout)
else:
cmpout = tt_json_cmp(ojson, ejson, exact=True)
if cmpout and ejson_alt is not None:
@@ -186,6 +187,20 @@ def addrgen(a, count, step=1):
@retry(retry_timeout=30, initial_wait=0.1)
+def check_kernel_net(r1, net, vrf):
+ addr = ipaddress.ip_network(net)
+ vrfstr = f" vrf {vrf}" if vrf else ""
+ if addr.version == 6:
+ kernel = r1.cmd_raises(f"ip -6 route show{vrfstr}")
+ else:
+ kernel = r1.cmd_raises(f"ip -4 route show{vrfstr}")
+
+ nentries = len(re.findall("\n", kernel))
+ logging.info("checking kernel routing table%s: (%s entries)", vrfstr, nentries)
+ assert str(net) in kernel, f"Failed to find '{net}' in {nentries} entries"
+
+
+@retry(retry_timeout=30, initial_wait=0.1)
def check_kernel_32(r1, start_addr, count, vrf, step=1):
start = ipaddress.ip_address(start_addr)
vrfstr = f" vrf {vrf}" if vrf else ""
diff --git a/tests/topotests/mgmt_oper/test_oper.py b/tests/topotests/mgmt_oper/test_oper.py
index 23529bc75e..0d346b5b7c 100644
--- a/tests/topotests/mgmt_oper/test_oper.py
+++ b/tests/topotests/mgmt_oper/test_oper.py
@@ -15,7 +15,7 @@ import math
import pytest
from lib.topogen import Topogen
-from oper import check_kernel_32, do_oper_test
+from oper import check_kernel_32, check_kernel_net, do_oper_test
pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd]
@@ -85,10 +85,17 @@ def test_oper(tgen):
]
r1 = tgen.gears["r1"].net
+
check_kernel_32(r1, "11.11.11.11", 1, "")
check_kernel_32(r1, "12.12.12.12", 1, "")
check_kernel_32(r1, "13.13.13.13", 1, "red")
check_kernel_32(r1, "14.14.14.14", 1, "red")
+
+ check_kernel_net(r1, "2001:1111::/64", "")
+ check_kernel_net(r1, "2002:2222::/64", "")
+ check_kernel_net(r1, "2003:333::/64", "red")
+ check_kernel_net(r1, "2004:4444::/64", "red")
+
do_oper_test(tgen, query_results)
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index ec151360bd..d99010547f 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -3358,10 +3358,7 @@ int lib_vrf_zebra_filter_protocol_create(struct nb_cb_create_args *args)
const char *proto = yang_dnode_get_string(args->dnode, "protocol");
int rtype;
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
+ rtype = proto_name2num(proto);
if (args->event == NB_EV_VALIDATE)
if (rtype < 0) {
@@ -3387,10 +3384,7 @@ int lib_vrf_zebra_filter_protocol_destroy(struct nb_cb_destroy_args *args)
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
+ rtype = proto_name2num(proto);
/* deleting an existing entry, it can't be invalid */
assert(rtype >= 0);
@@ -3418,10 +3412,7 @@ void lib_vrf_zebra_filter_protocol_apply_finish(
yang_afi_safi_identity2value(afi_safi, &afi, &safi);
- if (strcasecmp(proto, "any") == 0)
- rtype = ZEBRA_ROUTE_MAX;
- else
- rtype = proto_name2num(proto);
+ rtype = proto_name2num(proto);
/* finishing apply for a validated entry, it can't be invalid */
assert(rtype >= 0);
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 29bbf6023d..73ffa09c16 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -114,11 +114,6 @@ static void show_vrf_proto_rm(struct vty *vty, struct zebra_vrf *zvrf,
vty_out(vty, "%-24s : none\n", zebra_route_string(i));
}
- if (PROTO_RM_NAME(zvrf, af_type, i))
- vty_out(vty, "%-24s : %-10s\n", "any",
- PROTO_RM_NAME(zvrf, af_type, i));
- else
- vty_out(vty, "%-24s : none\n", "any");
}
static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf,
@@ -1222,8 +1217,8 @@ route_map_result_t zebra_route_map_check(afi_t family, struct route_entry *re,
return RMAP_DENYMATCH;
}
if (!rmap) {
- rm_name = PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX);
- rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
+ rm_name = PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_ALL);
+ rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_ALL);
if (rm_name && !rmap)
return RMAP_DENYMATCH;