zebra: Further handle route replace semantics

When an upper level protocol is installing a route X that needs to be
route replaced and at the same time the same or another protocol installs a
different route that depends on route X for nexthop resolution can leave
us with a state where the route is not accepted because zebra is still
really early in the route replace semantics ( route X is still on the work
Queue to be processed ) then the dependent route would not be installed.
This came up in the bgp_default_originate test cases frequently.

Further extendd the ROUTE_ENTR_ROUTE_REPLACING flag to cover this case
as well.  This has come up because the early route processing queueing
that was implemented late last year.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
This commit is contained in:
Donald Sharp 2023-07-17 10:00:32 -04:00
parent 33b1b8a04c
commit af80201876
2 changed files with 14 additions and 9 deletions

View File

@ -2366,17 +2366,18 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
if (is_default_prefix(&rn->p)
&& !rnh_resolve_via_default(zvrf, p.family)) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
" :%s: Resolved against default route",
__func__);
zlog_debug(" :%s: %pFX Resolved against default route",
__func__, &p);
return 0;
}
dest = rib_dest_from_rnode(rn);
if (dest && dest->selected_fib
&& !CHECK_FLAG(dest->selected_fib->status,
ROUTE_ENTRY_REMOVED)
&& dest->selected_fib->type != ZEBRA_ROUTE_TABLE)
if (dest && dest->selected_fib &&
(!CHECK_FLAG(dest->selected_fib->status,
ROUTE_ENTRY_REMOVED) ||
CHECK_FLAG(dest->selected_fib->status,
ROUTE_ENTRY_ROUTE_REPLACING)) &&
dest->selected_fib->type != ZEBRA_ROUTE_TABLE)
match = dest->selected_fib;
/* If there is no selected route or matched route is EGP, go up
@ -2388,7 +2389,6 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
} while (rn && rn->info == NULL);
if (rn)
route_lock_node(rn);
continue;
}

View File

@ -2824,8 +2824,13 @@ static void process_subq_early_route_add(struct zebra_early_route *ere)
rib_addnode(rn, re, 1);
/* Free implicit route.*/
if (same)
if (same) {
rib_dest_t *dest = rn->info;
if (same == dest->selected_fib)
SET_FLAG(same->status, ROUTE_ENTRY_ROUTE_REPLACING);
rib_delnode(rn, same);
}
/* See if we can remove some RE entries that are queued for
* removal, but won't be considered in rib processing.