Skip to content

Commit

Permalink
zebra: return fully-resolved route to NHT clients
Browse files Browse the repository at this point in the history
When a nexthop being tracked is resolved to a recursive route at the
first level of recursion, several parameters (such as the prefix,
metric and protocol type) of the recursive route are sent to clients,
along with the fully-resolved nexthop.

This creates an inconsistency or de-coupling between the route and its
nexthop, that is, the fully-resolved nexthop would belong to a different
route that is non-recursive. Thus the update message to clients would
contain parameters like prefix, metric and protocl type from a recursive
route, and the nexthop from a non-recursive route.

In particular, the protocol type and the metric fields in the update
message no longer reflect the property of the fully-resolved nexthop
in the meesage. It would be diffcult for a client to make sense of
these parameters.

As an example, when the nexthop being tracked is resolved to a BGP
route, instead of further resolving to an IGP route and getting its
metric, the MED value of the BGP route would be taken as the metric
and given to BGP for bestpath calculation, resulting in	incorrect
route selection.

The fix is to always calculate and return the fully-resolved route to
clients so that the route parameters like protocol type, distance,
metric and the resolved nexthops are consistent.

When a nht nexthop is resolved recursively, associate the nht nexthop
with each of the recursive routes so that the nht entry is re-evaluated
when there is a change to any of the dependent routes.

Signed-off-by: Enke Chen <[email protected]>
  • Loading branch information
enkechen-panw committed Jan 13, 2025
1 parent 5a1d69d commit af49397
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 86 deletions.
25 changes: 22 additions & 3 deletions zebra/rib.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ DECLARE_MTYPE(RE);

PREDECL_LIST(rnh_list);

struct rnh;
struct rnh_item {
struct rnh_list_item next;
struct rnh *rnh;
struct prefix resolved_route;
};

/* Nexthop structure. */
struct rnh {
uint8_t flags;
Expand All @@ -50,7 +57,6 @@ struct rnh {
uint32_t seqno;

struct route_entry *state;
struct prefix resolved_route;
struct list *client_list;

/* pseudowires dependent on this nh */
Expand All @@ -63,7 +69,20 @@ struct rnh {
*/
int filtered[ZEBRA_ROUTE_MAX];

struct rnh_list_item rnh_list_item;
/* Level of recursions in nht */
#define ZEBRA_NHT_RECURSION_MAX 8

/*
* For a resolved rnh that has a valid route entry ("state"), the array
* contains one or more routes (multiples in case of recursion). The one
* indexed by (resolved_count - 1) corresponds to the fully-resolved
* route.
*
* For an unresolved rnh, the resolved_count is 1 and the item is queued
* to 0.0.0.0/0, or 0::0/0.
*/
uint8_t resolved_count;
struct rnh_item rnh_item[ZEBRA_NHT_RECURSION_MAX];
};

#define DISTANCE_INFINITY 255
Expand Down Expand Up @@ -233,7 +252,7 @@ typedef struct rib_dest_t_ {

} rib_dest_t;

DECLARE_LIST(rnh_list, struct rnh, rnh_list_item);
DECLARE_LIST(rnh_list, struct rnh_item, next);
DECLARE_LIST(re_list, struct route_entry, next);

#define RIB_ROUTE_QUEUED(x) (1 << (x))
Expand Down
2 changes: 1 addition & 1 deletion zebra/zapi_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ static int zsend_nexthop_lookup(struct zserv *client, struct ipaddr *addr, struc
stream_putw(s, 0);
nhg = rib_get_fib_nhg(re);
for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
if (rnh_nexthop_valid(re, nexthop))
if (rnh_nexthop_valid(re, nexthop, false))
num += zserv_encode_nexthop(s, nexthop);
}

Expand Down
4 changes: 3 additions & 1 deletion zebra/zebra_rib.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,7 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq,
bool rt_delete)
{
rib_dest_t *dest = rib_dest_from_rnode(rn);
struct rnh_item *rnh_item;
struct rnh *rnh;

/*
Expand Down Expand Up @@ -813,7 +814,8 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq,
* nht resolution and as such we need to call the
* nexthop tracking evaluation code
*/
frr_each_safe(rnh_list, &dest->nht, rnh) {
frr_each_safe(rnh_list, &dest->nht, rnh_item) {
rnh = rnh_item->rnh;
struct zebra_vrf *zvrf =
zebra_vrf_lookup_by_id(rnh->vrf_id);
struct prefix *p = &rnh->node->p;
Expand Down
Loading

0 comments on commit af49397

Please sign in to comment.