Skip to content

Commit

Permalink
zebra: add prefix evaluation at NHG updates
Browse files Browse the repository at this point in the history
When a BGP configuration receives and installs a prefix with multiple
nexthops, if a link down event happens, the nexthop resolution is not
propagated. The below example illustrates the 10.0.5.1 prefix, where
the resolution is given by BGP.

> # show ip nht
> [..]
> 10.0.5.1
>  resolved via bgp
>  via 10.0.7.2, r1-r2-eth2 (vrf default), weight 1
>  via 10.0.8.2, r1-r2-eth3 (vrf default), weight 1
>  via 10.0.9.2, r1-r2-eth4 (vrf default), weight 1
>  via 10.0.10.2, r1-r2-eth5 (vrf default), weight 1
>  Client list: pim(fd 45)

After the r1-r2-th2 and r1-r2-eth4 interfaces are down, the nht entry
for 10.0.5.1 is kept unchanged.

The problem is related to nexthop groups. When using an NHG_ADD to
refresh the BGP route, then NHT entry is not refreshed, and PIM is not
informed about the change.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
  • Loading branch information
pguibert6WIND committed May 31, 2024
1 parent b78d408 commit 1e64cc6
Showing 1 changed file with 84 additions and 0 deletions.
84 changes: 84 additions & 0 deletions zebra/zebra_rib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1961,7 +1961,89 @@ struct route_node *rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx)
}


static void zebra_rib_evaluate_prefix_nhg(struct hash_bucket *b, void *data)
{
struct zebra_router_table *zrt;
struct nhg_prefix_proto_nhgs *nhg_p = b->data;
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(nhg_p->vrf_id);
struct route_node *rn;
struct route_entry *re, *next;
rib_dest_t *dest;

if (!zvrf)
return;

zrt = zebra_router_find_zrt(zvrf, nhg_p->table_id, nhg_p->afi,
nhg_p->safi);

if (!zrt)
return;

if (nhg_p->src_prefix.family)
rn = srcdest_rnode_get(zrt->table, &nhg_p->prefix,
(const struct prefix_ipv6 *)&nhg_p
->src_prefix);
else
rn = srcdest_rnode_get(zrt->table, &nhg_p->prefix, NULL);
if (!rn)
return;

if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: => NHG updated, evaluating prefix %pRN",
__func__, rn);

RNODE_FOREACH_RE_SAFE (rn, re, next) {
/* re did not change, an, still selected */
dest = rib_dest_from_rnode(rn);
/* Redistribute if this is the selected re */
if (dest && re == dest->selected_fib)
redistribute_update(rn, re, re);
zebra_rib_evaluate_rn_nexthops(rn,
zebra_router_get_next_sequence(),
false);
zebra_rib_evaluate_mpls(rn);
}
}
/*
* update results processing after async dataplane update.
*/
static void rib_nhg_process_result(struct zebra_dplane_ctx *ctx)
{
enum dplane_op_e op;
enum zebra_dplane_result status;
uint32_t id;
struct nhg_hash_entry *nhe;

op = dplane_ctx_get_op(ctx);
status = dplane_ctx_get_status(ctx);

id = dplane_ctx_get_nhe_id(ctx);

if (op == DPLANE_OP_NH_DELETE) {
/* We already free'd the data, nothing to do */
return;
}

nhe = zebra_nhg_lookup_id(id);
if (!nhe) {
/* nothing to process, as there is no NHG add or update */
return;
}

if (status != ZEBRA_DPLANE_REQUEST_SUCCESS) {
/* no sucess, means that the attempt to change did not work */
return;
}

if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: Evaluating routes using updated nhe (%u)",
__func__, id);

/* We have to do them ALL */
if (nhe->prefix_proto_nhgs)
hash_iterate(nhe->prefix_proto_nhgs,
zebra_rib_evaluate_prefix_nhg, NULL);
}
/*
* Route-update results processing after async dataplane update.
*/
Expand Down Expand Up @@ -4929,6 +5011,8 @@ static void rib_process_dplane_results(struct event *thread)
case DPLANE_OP_NH_UPDATE:
case DPLANE_OP_NH_DELETE:
zebra_nhg_dplane_result(ctx);
if (dplane_ctx_get_notif_provider(ctx) == 0)
rib_nhg_process_result(ctx);
break;

case DPLANE_OP_LSP_INSTALL:
Expand Down

0 comments on commit 1e64cc6

Please sign in to comment.