diff options
33 files changed, 635 insertions, 385 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index b83c7b1908..f17842366a 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -719,6 +719,7 @@ babel_interface_close_all(void) { struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct interface *ifp = NULL; + int type; FOR_ALL_INTERFACES(vrf, ifp) { if(!if_up(ifp)) @@ -740,8 +741,14 @@ babel_interface_close_all(void) flushbuf(ifp); usleep(roughly(10000)); gettime(&babel_now); + babel_enable_if_delete(ifp->name); interface_reset(ifp); } + /* Disable babel redistribution */ + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type, 0, VRF_DEFAULT); + zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP6, type, 0, VRF_DEFAULT); + } } /* return "true" if address is one of our ipv6 addresses */ 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 5fda5701f3..ed689c8bac 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -869,6 +869,9 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, ? bnc->ifindex_ipv6_ll : nexthop->ifindex, bgp->vrf_id)); + json_object_int_add(json_gate, "ifindex", + bnc->ifindex_ipv6_ll ? bnc->ifindex_ipv6_ll + : nexthop->ifindex); break; case NEXTHOP_TYPE_IPV4: json_object_string_addf(json_gate, "ip", "%pI4", @@ -882,6 +885,9 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, ? bnc->ifindex_ipv6_ll : nexthop->ifindex, bgp->vrf_id)); + json_object_int_add(json_gate, "ifindex", + bnc->ifindex_ipv6_ll ? bnc->ifindex_ipv6_ll + : nexthop->ifindex); break; case NEXTHOP_TYPE_IPV4_IFINDEX: json_object_string_addf(json_gate, "ip", "%pI4", @@ -893,6 +899,9 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, ? bnc->ifindex_ipv6_ll : nexthop->ifindex, bgp->vrf_id)); + json_object_int_add(json_gate, "ifindex", + bnc->ifindex_ipv6_ll ? bnc->ifindex_ipv6_ll + : nexthop->ifindex); break; case NEXTHOP_TYPE_BLACKHOLE: json_object_boolean_true_add(json_gate, @@ -926,13 +935,13 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, vty_out(vty, " gate %pI6", &nexthop->gate.ipv6); if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX && bnc->ifindex_ipv6_ll) - vty_out(vty, ", if %s\n", - ifindex2ifname(bnc->ifindex_ipv6_ll, - bgp->vrf_id)); + vty_out(vty, ", if %s, ifindex %d\n", + ifindex2ifname(bnc->ifindex_ipv6_ll, bgp->vrf_id), + bnc->ifindex_ipv6_ll); else if (nexthop->ifindex) - vty_out(vty, ", if %s\n", - ifindex2ifname(nexthop->ifindex, - bgp->vrf_id)); + vty_out(vty, ", if %s, ifindex %d\n", + ifindex2ifname(nexthop->ifindex, bgp->vrf_id), + nexthop->ifindex); else vty_out(vty, "\n"); break; @@ -941,22 +950,22 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, vty_out(vty, " gate %pI4", &nexthop->gate.ipv4); if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX && bnc->ifindex_ipv6_ll) - vty_out(vty, ", if %s\n", - ifindex2ifname(bnc->ifindex_ipv6_ll, - bgp->vrf_id)); + vty_out(vty, ", if %s, ifindex %d\n", + ifindex2ifname(bnc->ifindex_ipv6_ll, bgp->vrf_id), + bnc->ifindex_ipv6_ll); else if (nexthop->ifindex) - vty_out(vty, ", if %s\n", - ifindex2ifname(nexthop->ifindex, - bgp->vrf_id)); + vty_out(vty, ", if %s, ifindex %d\n", + ifindex2ifname(nexthop->ifindex, bgp->vrf_id), + nexthop->ifindex); else vty_out(vty, "\n"); break; case NEXTHOP_TYPE_IFINDEX: - vty_out(vty, " if %s\n", - ifindex2ifname(bnc->ifindex_ipv6_ll - ? bnc->ifindex_ipv6_ll - : nexthop->ifindex, - bgp->vrf_id)); + vty_out(vty, " if %s, ifindex %d\n", + ifindex2ifname(bnc->ifindex_ipv6_ll ? bnc->ifindex_ipv6_ll + : nexthop->ifindex, + bgp->vrf_id), + bnc->ifindex_ipv6_ll ? bnc->ifindex_ipv6_ll : nexthop->ifindex); break; case NEXTHOP_TYPE_BLACKHOLE: vty_out(vty, " blackhole\n"); @@ -970,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; @@ -983,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 @@ -994,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", @@ -1022,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", @@ -1042,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", @@ -1074,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", @@ -1090,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 @@ -1117,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; @@ -1153,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; } @@ -1163,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, "}"); } } @@ -1241,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; } @@ -1271,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; } @@ -1298,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 bd2fda56fc..5ac1d26603 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -11975,14 +11975,13 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t sa continue; } - if (type == bgp_show_type_rpki) { - if (dest_p->family == AF_INET - || dest_p->family == AF_INET6) - rpki_curr_state = hook_call( - bgp_rpki_prefix_status, - pi->peer, pi->attr, dest_p); - if (rpki_target_state != RPKI_NOT_BEING_USED - && rpki_curr_state != rpki_target_state) + if ((dest_p->family == AF_INET || dest_p->family == AF_INET6) && + (detail_routes || detail_json || type == bgp_show_type_rpki)) { + rpki_curr_state = hook_call(bgp_rpki_prefix_status, pi->peer, + pi->attr, dest_p); + if (type == bgp_show_type_rpki && + rpki_target_state != RPKI_NOT_BEING_USED && + rpki_curr_state != rpki_target_state) continue; } @@ -12213,7 +12212,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t sa route_vty_out_detail(vty, bgp, dest, dest_p, pi, family2afi(dest_p->family), safi, - RPKI_NOT_BEING_USED, json_paths, NULL); + rpki_curr_state, json_paths, NULL); } else { route_vty_out(vty, dest_p, pi, display, safi, json_paths, wide); @@ -15107,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). @@ -15175,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)) { @@ -15193,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); @@ -15206,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", @@ -15336,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); @@ -15377,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"); @@ -15778,6 +15838,28 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str, return CMD_SUCCESS; } +void bgp_address_family_distance_delete(void) +{ + afi_t afi = AFI_UNSPEC; + safi_t safi = SAFI_UNSPEC; + struct bgp_dest *dest = NULL; + struct bgp_distance *bdistance = NULL; + + FOREACH_AFI_SAFI (afi, safi) { + for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest; + dest = bgp_route_next(dest)) { + if (!bgp_dest_has_bgp_path_info_data(dest)) + continue; + bdistance = bgp_dest_get_bgp_distance_info(dest); + XFREE(MTYPE_AS_LIST, bdistance->access_list); + bgp_distance_free(bdistance); + + bgp_dest_set_bgp_distance_info(dest, NULL); + bgp_dest_unlock_node(dest); + } + } +} + /* Apply BGP information to distance method. */ uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo, afi_t afi, safi_t safi, struct bgp *bgp) diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index bde0580d6c..474e229575 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -831,6 +831,7 @@ extern void bgp_redistribute_withdraw(struct bgp *, afi_t, int, unsigned short); extern void bgp_static_add(struct bgp *); extern void bgp_static_delete(struct bgp *); +extern void bgp_address_family_distance_delete(void); extern void bgp_static_redo_import_check(struct bgp *); extern void bgp_purge_static_redist_routes(struct bgp *bgp); extern void bgp_static_update(struct bgp *bgp, const struct prefix *p, 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 2da77c314d..c6b09481b6 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -11488,6 +11488,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", @@ -21939,6 +22005,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 f0b4f6c262..05bc804db4 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -4244,6 +4244,14 @@ int bgp_delete(struct bgp *bgp) } } + /* Clean BGP address family parameters */ + bgp_mh_info->ead_evi_rx = BGP_EVPN_MH_EAD_EVI_RX_DEF; + bgp_evpn_switch_ead_evi_rx(); + bgp_mh_info->ead_evi_tx = BGP_EVPN_MH_EAD_EVI_TX_DEF; + bgp_mh_info->evi_per_es_frag = BGP_EVPN_MAX_EVI_PER_ES_FRAG; + + bgp_address_family_distance_delete(); + return 0; } @@ -6682,7 +6690,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 @@ -6691,7 +6699,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/isisd/isis_circuit.c b/isisd/isis_circuit.c index 9a967bc1e3..9ea2cfd0a1 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -1008,45 +1008,40 @@ void isis_circuit_print_json(struct isis_circuit *circuit, circuit_t2string(level)); if (circuit->area->newmetric) json_object_int_add(level_json, "metric", - circuit->te_metric[0]); + circuit->te_metric[level - 1]); else json_object_int_add(level_json, "metric", - circuit->metric[0]); + circuit->metric[level - 1]); if (!circuit->is_passive) { - json_object_int_add(level_json, - "active-neighbors", - circuit->upadjcount[0]); - json_object_int_add(level_json, - "hello-interval", - circuit->hello_interval[0]); + json_object_int_add(level_json, "active-neighbors", + circuit->upadjcount[level - 1]); + json_object_int_add(level_json, "hello-interval", + circuit->hello_interval[level - 1]); hold_json = json_object_new_object(); json_object_object_add(level_json, "holddown", hold_json); - json_object_int_add( - hold_json, "count", - circuit->hello_multiplier[0]); + json_object_int_add(hold_json, "count", + circuit->hello_multiplier[level - 1]); json_object_string_add( hold_json, "pad", isis_hello_padding2string( circuit->pad_hellos)); json_object_int_add(level_json, "cnsp-interval", - circuit->csnp_interval[0]); + circuit->csnp_interval[level - 1]); json_object_int_add(level_json, "psnp-interval", - circuit->psnp_interval[0]); + circuit->psnp_interval[level - 1]); if (circuit->circ_type == CIRCUIT_T_BROADCAST) { lan_prio_json = json_object_new_object(); json_object_object_add(level_json, "lan", lan_prio_json); - json_object_int_add( - lan_prio_json, "priority", - circuit->priority[0]); - json_object_string_add( - lan_prio_json, "is-dis", - (circuit->u.bc.is_dr[0] - ? "yes" - : "no")); + json_object_int_add(lan_prio_json, "priority", + circuit->priority[level - 1]); + json_object_string_add(lan_prio_json, "is-dis", + (circuit->u.bc.is_dr[level - 1] + ? "yes" + : "no")); } } json_object_array_add(levels_json, level_json); 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_abr.c b/ospfd/ospf_abr.c index 93779991b5..eed1bfcb30 100644 --- a/ospfd/ospf_abr.c +++ b/ospfd/ospf_abr.c @@ -1823,7 +1823,7 @@ static void ospf_abr_nssa_type7_default_create(struct ospf *ospf, "Announcing Type-7 default route into NSSA area %pI4", &area->area_id); - /* Prepare the extrenal_info for aggregator */ + /* Prepare the external_info for aggregator */ memset(&ei, 0, sizeof(struct external_info)); ei.p.family = AF_INET; ei.p.prefixlen = 0; diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index 738ac6d8cf..aa11467027 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -492,7 +492,7 @@ static void ospf_aggr_handle_external_info(void *data) ei->to_be_processed = true; if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) - zlog_debug("%s: Handle extrenal route(%pI4/%d)", __func__, + zlog_debug("%s: Handle external route(%pI4/%d)", __func__, &ei->p.prefix, ei->p.prefixlen); assert(ospf); @@ -571,7 +571,7 @@ static void ospf_external_aggr_delete(struct ospf *ospf, struct route_node *rn) } struct ospf_external_aggr_rt * -ospf_extrenal_aggregator_lookup(struct ospf *ospf, struct prefix_ipv4 *p) +ospf_external_aggregator_lookup(struct ospf *ospf, struct prefix_ipv4 *p) { struct route_node *rn; struct ospf_external_aggr_rt *summary_rt = NULL; @@ -617,7 +617,7 @@ void ospf_unlink_ei_from_aggr(struct ospf *ospf, { if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) zlog_debug( - "%s: Unlinking extrenal route(%pI4/%d) from aggregator(%pI4/%d), external route count:%ld", + "%s: Unlinking external route(%pI4/%d) from aggregator(%pI4/%d), external route count:%ld", __func__, &ei->p.prefix, ei->p.prefixlen, &aggr->p.prefix, aggr->p.prefixlen, OSPF_EXTERNAL_RT_COUNT(aggr)); @@ -648,7 +648,7 @@ static void ospf_link_ei_to_aggr(struct ospf_external_aggr_rt *aggr, { if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR)) zlog_debug( - "%s: Linking extrenal route(%pI4/%d) to aggregator(%pI4/%d)", + "%s: Linking external route(%pI4/%d) to aggregator(%pI4/%d)", __func__, &ei->p.prefix, ei->p.prefixlen, &aggr->p.prefix, aggr->p.prefixlen); (void)hash_get(aggr->match_extnl_hash, ei, hash_alloc_intern); @@ -703,7 +703,7 @@ struct ospf_lsa *ospf_originate_summary_lsa(struct ospf *ospf, return NULL; } - /* Prepare the extrenal_info for aggregator */ + /* Prepare the external_info for aggregator */ memset(&ei_aggr, 0, sizeof(ei_aggr)); ei_aggr.p = aggr->p; ei_aggr.tag = aggr->tag; @@ -1063,7 +1063,7 @@ static void ospf_handle_external_aggr_update(struct ospf *ospf) aggr->action = OSPF_ROUTE_AGGR_NONE; - /* Prepare the extrenal_info for aggregator */ + /* Prepare the external_info for aggregator */ memset(&ei_aggr, 0, sizeof(ei_aggr)); ei_aggr.p = aggr->p; ei_aggr.tag = aggr->tag; @@ -1176,7 +1176,7 @@ int ospf_asbr_external_aggregator_set(struct ospf *ospf, struct prefix_ipv4 *p, { struct ospf_external_aggr_rt *aggregator; - aggregator = ospf_extrenal_aggregator_lookup(ospf, p); + aggregator = ospf_external_aggregator_lookup(ospf, p); if (aggregator) { if (CHECK_FLAG(aggregator->flags, @@ -1236,7 +1236,7 @@ int ospf_asbr_external_rt_no_advertise(struct ospf *ospf, struct prefix_ipv4 *p) struct ospf_external_aggr_rt *aggr; route_tag_t tag = 0; - aggr = ospf_extrenal_aggregator_lookup(ospf, p); + aggr = ospf_external_aggregator_lookup(ospf, p); if (aggr) { if (CHECK_FLAG(aggr->flags, OSPF_EXTERNAL_AGGRT_NO_ADVERTISE)) return OSPF_SUCCESS; diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index 648a5a11ae..0b3b695f3e 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -144,7 +144,7 @@ extern int ospf_external_aggregator_timer_set(struct ospf *ospf, extern void ospf_external_aggrigator_free(struct ospf_external_aggr_rt *aggr); extern struct ospf_external_aggr_rt * -ospf_extrenal_aggregator_lookup(struct ospf *ospf, struct prefix_ipv4 *p); +ospf_external_aggregator_lookup(struct ospf *ospf, struct prefix_ipv4 *p); void ospf_unset_all_aggr_flag(struct ospf *ospf); diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index e3398af74b..bcb35315d8 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -325,7 +325,7 @@ static void ospf_process_self_originated_lsa(struct ospf *ospf, LSA_REFRESH_FORCE, false); } else { aggr = (struct ospf_external_aggr_rt *) - ospf_extrenal_aggregator_lookup(ospf, &p); + ospf_external_aggregator_lookup(ospf, &p); if (aggr) { struct external_info ei_aggr; diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 7354223397..ac53f3a19f 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -4064,7 +4064,7 @@ struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa) ospf, lsa, ei, LSA_REFRESH_FORCE, false); else { aggr = (struct ospf_external_aggr_rt *) - ospf_extrenal_aggregator_lookup(ospf, &p); + ospf_external_aggregator_lookup(ospf, &p); if (aggr) { struct external_info ei_aggr; 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/ospfd/ospfd.c b/ospfd/ospfd.c index d72afec1e4..90330d368d 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -843,7 +843,7 @@ static void ospf_finish_final(struct ospf *ospf) ospf_distance_reset(ospf); route_table_finish(ospf->distance_table); - /* Release extrenal Aggregator table */ + /* Release external Aggregator table */ for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) { struct ospf_external_aggr_rt *aggr; diff --git a/staticd/static_nht.c b/staticd/static_nht.c index 6be598434d..06d27c6f59 100644 --- a/staticd/static_nht.c +++ b/staticd/static_nht.c @@ -21,6 +21,7 @@ static void static_nht_update_path(struct static_path *pn, struct prefix *nhp, uint32_t nh_num, vrf_id_t nh_vrf_id) { struct static_nexthop *nh; + bool route_changed = false; frr_each(static_nexthop_list, &pn->nexthop_list, nh) { if (nh->nh_vrf_id != nh_vrf_id) @@ -42,8 +43,10 @@ static void static_nht_update_path(struct static_path *pn, struct prefix *nhp, nh->nh_valid = !!nh_num; if (nh->state == STATIC_START) - static_zebra_route_add(pn, true); + route_changed = true; } + if (route_changed) + static_zebra_route_add(pn, true); } static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp, 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_rpki_topo1/r2/bgp_rpki_valid.json b/tests/topotests/bgp_rpki_topo1/r2/bgp_rpki_valid.json new file mode 100644 index 0000000000..016c019d10 --- /dev/null +++ b/tests/topotests/bgp_rpki_topo1/r2/bgp_rpki_valid.json @@ -0,0 +1,70 @@ +{ + "vrfId": 0, + "vrfName": "default", + "tableVersion": 3, + "routerId": "192.0.2.2", + "defaultLocPrf": 100, + "localAS": 65002, + "routes": { + "198.51.100.0/24": [ + { + "origin": "IGP", + "metric": 0, + "valid": true, + "version": 2, + "rpkiValidationState": "valid", + "bestpath": { + "overall": true, + "selectionReason": "First path received" + }, + "nexthops": [ + { + "ip": "192.0.2.1", + "hostname": "r1", + "afi": "ipv4", + "metric": 0, + "accessible": true, + "used": true + } + ], + "peer": { + "peerId": "192.0.2.1", + "routerId": "192.0.2.1", + "hostname": "r1", + "type": "external" + } + } + ], + "203.0.113.0/24": [ + { + "origin": "IGP", + "metric": 0, + "valid": true, + "version": 3, + "rpkiValidationState": "valid", + "bestpath": { + "overall": true, + "selectionReason": "First path received" + }, + "nexthops": [ + { + "ip": "192.0.2.1", + "hostname": "r1", + "afi": "ipv4", + "metric": 0, + "accessible": true, + "used": true + } + ], + "peer": { + "peerId": "192.0.2.1", + "routerId": "192.0.2.1", + "hostname": "r1", + "type": "external" + } + } + ] + }, + "totalRoutes": 3, + "totalPaths": 3 +}
\ No newline at end of file diff --git a/tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py b/tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py index 7b40bbdae8..5b775aa6cb 100644 --- a/tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py +++ b/tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py @@ -101,6 +101,16 @@ def show_rpki_prefixes(rname, expected, vrf=None): return topotest.json_cmp(output, expected) +def show_rpki_valid(rname, expected, vrf=None): + tgen = get_topogen() + + cmd = "show bgp ipv4 detail json" + + output = json.loads(tgen.gears[rname].vtysh_cmd(cmd)) + + return topotest.json_cmp(output, expected) + + def show_bgp_ipv4_table_rpki(rname, rpki_state, expected, vrf=None): tgen = get_topogen() @@ -123,6 +133,25 @@ def show_bgp_ipv4_table_rpki(rname, rpki_state, expected, vrf=None): return topotest.json_cmp(output, expected) +def test_show_bgp_rpki_prefixes_valid(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ["r1", "r3"]: + logger.info("{}: checking if rtrd is running".format(rname)) + if rtrd_process[rname].poll() is not None: + pytest.skip(tgen.errors) + + rname = "r2" + expected = open(os.path.join(CWD, "{}/bgp_rpki_valid.json".format(rname))).read() + expected_json = json.loads(expected) + test_func = functools.partial(show_rpki_valid, rname, expected_json) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Failed to see RPKI on {}".format(rname) + + def test_show_bgp_rpki_prefixes(): tgen = get_topogen() 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/tools/frr-reload.py b/tools/frr-reload.py index 2bb364f32b..dba50b3c53 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -270,7 +270,7 @@ ctx_keywords = { "mpls ldp": {"address-family ": {"interface ": {}}}, "l2vpn ": {"member pseudowire ": {}}, "key chain ": {"key ": {}}, - "vrf ": {}, + "vrf ": {"rpki": {}}, "interface ": {"link-params": {}}, "pseudowire ": {}, "segment-routing": { @@ -279,7 +279,11 @@ ctx_keywords = { "policy ": {"candidate-path ": {}}, "pcep": {"pcc": {}, "pce ": {}, "pce-config ": {}}, }, - "srv6": {"locators": {"locator ": {}}, "encapsulation": {}}, + "srv6": { + "locators": {"locator ": {}}, + "encapsulation": {}, + "formats": {"format": {}}, + }, }, "nexthop-group ": {}, "route-map ": {}, diff --git a/zebra/dpdk/zebra_dplane_dpdk.c b/zebra/dpdk/zebra_dplane_dpdk.c index ae1a3743ce..0a898c1923 100644 --- a/zebra/dpdk/zebra_dplane_dpdk.c +++ b/zebra/dpdk/zebra_dplane_dpdk.c @@ -330,14 +330,11 @@ static void zd_dpdk_rule_update(struct zebra_dplane_ctx *ctx) op = dplane_ctx_get_op(ctx); - switch (op) { - case DPLANE_OP_RULE_ADD: + if (op == DPLANE_OP_RULE_ADD) { atomic_fetch_add_explicit(&dpdk_stat->rule_adds, 1, memory_order_relaxed); zd_dpdk_rule_add(ctx); - break; - - case DPLANE_OP_RULE_UPDATE: + } else if (op == DPLANE_OP_RULE_UPDATE) { /* delete old rule and install new one */ atomic_fetch_add_explicit(&dpdk_stat->rule_adds, 1, memory_order_relaxed); @@ -346,62 +343,12 @@ static void zd_dpdk_rule_update(struct zebra_dplane_ctx *ctx) zd_dpdk_rule_del(ctx, dplane_ctx_rule_get_ifname(ctx), in_ifindex, dp_flow_ptr); zd_dpdk_rule_add(ctx); - break; - - case DPLANE_OP_RULE_DELETE: + } else if (op == DPLANE_OP_RULE_DELETE) { atomic_fetch_add_explicit(&dpdk_stat->rule_dels, 1, memory_order_relaxed); in_ifindex = dplane_ctx_get_ifindex(ctx); dp_flow_ptr = dplane_ctx_rule_get_dp_flow_ptr(ctx); - zd_dpdk_rule_del(ctx, dplane_ctx_rule_get_ifname(ctx), - in_ifindex, dp_flow_ptr); - break; - - case DPLANE_OP_NONE: - case DPLANE_OP_ROUTE_INSTALL: - case DPLANE_OP_ROUTE_UPDATE: - case DPLANE_OP_ROUTE_DELETE: - case DPLANE_OP_ROUTE_NOTIFY: - case DPLANE_OP_NH_INSTALL: - case DPLANE_OP_NH_UPDATE: - case DPLANE_OP_NH_DELETE: - case DPLANE_OP_LSP_INSTALL: - case DPLANE_OP_LSP_UPDATE: - case DPLANE_OP_LSP_DELETE: - case DPLANE_OP_LSP_NOTIFY: - case DPLANE_OP_PW_INSTALL: - case DPLANE_OP_PW_UNINSTALL: - case DPLANE_OP_SYS_ROUTE_ADD: - case DPLANE_OP_SYS_ROUTE_DELETE: - case DPLANE_OP_ADDR_INSTALL: - case DPLANE_OP_ADDR_UNINSTALL: - case DPLANE_OP_MAC_INSTALL: - case DPLANE_OP_MAC_DELETE: - case DPLANE_OP_NEIGH_INSTALL: - case DPLANE_OP_NEIGH_UPDATE: - case DPLANE_OP_NEIGH_DELETE: - case DPLANE_OP_VTEP_ADD: - case DPLANE_OP_VTEP_DELETE: - case DPLANE_OP_NEIGH_DISCOVER: - case DPLANE_OP_BR_PORT_UPDATE: - case DPLANE_OP_IPTABLE_ADD: - case DPLANE_OP_IPTABLE_DELETE: - case DPLANE_OP_IPSET_ADD: - case DPLANE_OP_IPSET_DELETE: - case DPLANE_OP_IPSET_ENTRY_ADD: - case DPLANE_OP_IPSET_ENTRY_DELETE: - case DPLANE_OP_NEIGH_IP_INSTALL: - case DPLANE_OP_NEIGH_IP_DELETE: - case DPLANE_OP_NEIGH_TABLE_UPDATE: - case DPLANE_OP_GRE_SET: - case DPLANE_OP_INTF_ADDR_ADD: - case DPLANE_OP_INTF_ADDR_DEL: - case DPLANE_OP_INTF_NETCONFIG: - case DPLANE_OP_INTF_INSTALL: - case DPLANE_OP_INTF_UPDATE: - case DPLANE_OP_INTF_DELETE: - case DPLANE_OP_VLAN_INSTALL, - break; + zd_dpdk_rule_del(ctx, dplane_ctx_rule_get_ifname(ctx), in_ifindex, dp_flow_ptr); } } @@ -410,62 +357,13 @@ static void zd_dpdk_rule_update(struct zebra_dplane_ctx *ctx) */ static void zd_dpdk_process_update(struct zebra_dplane_ctx *ctx) { - switch (dplane_ctx_get_op(ctx)) { + enum dplane_op_e op; - case DPLANE_OP_RULE_ADD: - case DPLANE_OP_RULE_UPDATE: - case DPLANE_OP_RULE_DELETE: + op = dplane_ctx_get_op(ctx); + if (op == DPLANE_OP_RULE_ADD || op == DPLANE_OP_RULE_UPDATE || op == DPLANE_OP_RULE_DELETE) zd_dpdk_rule_update(ctx); - break; - case DPLANE_OP_NONE: - case DPLANE_OP_ROUTE_INSTALL: - case DPLANE_OP_ROUTE_UPDATE: - case DPLANE_OP_ROUTE_DELETE: - case DPLANE_OP_ROUTE_NOTIFY: - case DPLANE_OP_NH_INSTALL: - case DPLANE_OP_NH_UPDATE: - case DPLANE_OP_NH_DELETE: - case DPLANE_OP_LSP_INSTALL: - case DPLANE_OP_LSP_UPDATE: - case DPLANE_OP_LSP_DELETE: - case DPLANE_OP_LSP_NOTIFY: - case DPLANE_OP_PW_INSTALL: - case DPLANE_OP_PW_UNINSTALL: - case DPLANE_OP_SYS_ROUTE_ADD: - case DPLANE_OP_SYS_ROUTE_DELETE: - case DPLANE_OP_ADDR_INSTALL: - case DPLANE_OP_ADDR_UNINSTALL: - case DPLANE_OP_MAC_INSTALL: - case DPLANE_OP_MAC_DELETE: - case DPLANE_OP_NEIGH_INSTALL: - case DPLANE_OP_NEIGH_UPDATE: - case DPLANE_OP_NEIGH_DELETE: - case DPLANE_OP_VTEP_ADD: - case DPLANE_OP_VTEP_DELETE: - case DPLANE_OP_NEIGH_DISCOVER: - case DPLANE_OP_BR_PORT_UPDATE: - case DPLANE_OP_IPTABLE_ADD: - case DPLANE_OP_IPTABLE_DELETE: - case DPLANE_OP_IPSET_ADD: - case DPLANE_OP_IPSET_DELETE: - case DPLANE_OP_IPSET_ENTRY_ADD: - case DPLANE_OP_IPSET_ENTRY_DELETE: - case DPLANE_OP_NEIGH_IP_INSTALL: - case DPLANE_OP_NEIGH_IP_DELETE: - case DPLANE_OP_NEIGH_TABLE_UPDATE: - case DPLANE_OP_GRE_SET: - case DPLANE_OP_INTF_ADDR_ADD: - case DPLANE_OP_INTF_ADDR_DEL: - case DPLANE_OP_INTF_NETCONFIG: - case DPLANE_OP_INTF_INSTALL: - case DPLANE_OP_INTF_UPDATE: - case DPLANE_OP_INTF_DELETE: - case DPLANE_OP_VLAN_INSTALL, - atomic_fetch_add_explicit(&dpdk_stat->ignored_updates, 1, - memory_order_relaxed); - - break; - } + else + atomic_fetch_add_explicit(&dpdk_stat->ignored_updates, 1, memory_order_relaxed); } diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c index f9009dabb7..3fd84b5257 100644 --- a/zebra/zebra_evpn_mac.c +++ b/zebra/zebra_evpn_mac.c @@ -1323,6 +1323,7 @@ int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr, uint32_t flags, bool force) { int state = ZEBRA_NEIGH_ACTIVE; + struct zebra_vrf *zvrf; if (!force) { if (CHECK_FLAG(flags, ZEBRA_MAC_LOCAL_INACTIVE) && @@ -1330,12 +1331,14 @@ int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr, /* the host was not advertised - nothing to delete */ return 0; - /* MAC is LOCAL and DUP_DETECTED, this local mobility event - * is not known to bgpd. Upon receiving local delete - * ask bgp to reinstall the best route (remote entry). + /* Duplicate detect action is freeze enabled and + * Local MAC is duplicate deteced, this local + * mobility event is not known to bgpd. + * Upon receiving local delete ask bgp to reinstall + * the best route (remote entry). */ - if (CHECK_FLAG(flags, ZEBRA_MAC_LOCAL) && - CHECK_FLAG(flags, ZEBRA_MAC_DUPLICATE)) + zvrf = zebra_vrf_get_evpn(); + if (zvrf && zvrf->dad_freeze && CHECK_FLAG(flags, ZEBRA_MAC_DUPLICATE)) state = ZEBRA_NEIGH_INACTIVE; } 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_nhg.c b/zebra/zebra_nhg.c index e61c158ca9..a32fc2bb14 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -1056,6 +1056,7 @@ static struct nhg_ctx *nhg_ctx_init(uint32_t id, struct nexthop *nh, struct nh_g static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe, bool valid) { struct nhg_connected *rb_node_dep; + bool dependent_valid = valid; if (valid) SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); @@ -1071,6 +1072,7 @@ static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe, bool valid) /* Update validity of nexthops depending on it */ frr_each (nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) { + dependent_valid = valid; if (!valid) { /* * Grab the first nexthop from the depending nexthop group @@ -1080,16 +1082,22 @@ static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe, bool valid) struct nexthop *nexthop = rb_node_dep->nhe->nhg.nexthop; while (nexthop) { - if (nexthop_same(nexthop, nhe->nhg.nexthop)) - break; - + if (nexthop_same(nexthop, nhe->nhg.nexthop)) { + /* Invalid Nexthop */ + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } else { + /* + * If other nexthops in the nexthop + * group are valid then we can continue + * to use this nexthop group as valid + */ + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) + dependent_valid = true; + } nexthop = nexthop->next; } - - if (nexthop) - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); } - zebra_nhg_set_valid(rb_node_dep->nhe, valid); + zebra_nhg_set_valid(rb_node_dep->nhe, dependent_valid); } } 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; |
