Skip to content

Commit

Permalink
zebra, lib: add recursive support for protocol nhid
Browse files Browse the repository at this point in the history
In sharpd, configuring a nexthop-group with an IP nexthop that is not
directly connected does not create a NHG context in zebra:

> ubuntu2204(config)# interface loop1
> ubuntu2204(config-if)# ip address 192.0.2.1/24
> ubuntu2204(config-if)# exi
> ubuntu2204(config)# ip route 192.168.0.0/24 192.0.2.100
> ubuntu2204(config)# nexthop-group ABCD
> ubuntu2204(config-nh-group)# nexthop 192.168.0.100
> 2024/01/17 16:36:23 SHARP: [Y2G2F-ZTW6M] nhg_add: nhg 181818169 not sent: no valid nexthops
> ubuntu2204(config-nh-group)# do show nexthop-group rib 181818169
> Nexthop Group ID: 181818169 does not exist

Nexthops with an undefined interface index are neither handled
in ZEBRA, nor in SHARPD.

On the other hand, if we had created a route pointing to the same
nexthop (by using ZEBRA_ROUTE_ADD zapi), the next-hop would have been
installed, thanks to the ALLOW_RECURSION flag embedded in the zapi_route
structure.

Add the support for recursivity in nexthop groups by introducing
a flags attribute in the nexthop group structure. Define the
NEXTHOP_GROUP_ALLOW_RECURSION value, which will be used by ZEBRA to
check for the next-hop group recursivity. This flag is not used by
default.

This flag control is mandatory, as the recursivity may not be allowed
by protocols like eBGP single-hop.

Signed-off-by: Philippe Guibert <[email protected]>
  • Loading branch information
pguibert6WIND committed Jan 24, 2024
1 parent 11c700e commit c77981d
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 7 deletions.
4 changes: 4 additions & 0 deletions lib/nexthop_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ struct nexthop_group {
struct nexthop *nexthop;

struct nhg_resilience nhgr;

/* nexthop group flags */
#define NEXTHOP_GROUP_ALLOW_RECURSION (1 << 1)
uint8_t flags;
};

struct nexthop_group *nexthop_group_new(void);
Expand Down
2 changes: 2 additions & 0 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,8 @@ static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
stream_putl(s, api_nhg->resilience.idle_timer);
stream_putl(s, api_nhg->resilience.unbalanced_timer);

stream_putc(s, api_nhg->flags);

if (cmd == ZEBRA_NHG_ADD) {
/* Nexthops */
zapi_nexthop_group_sort(api_nhg->nexthops,
Expand Down
3 changes: 3 additions & 0 deletions lib/zclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,9 @@ struct zapi_nhg {

uint16_t backup_nexthop_num;
struct zapi_nexthop backup_nexthops[MULTIPATH_NUM];

/* nexthop group flags */
uint8_t flags;
};

/*
Expand Down
1 change: 1 addition & 0 deletions sharpd/sharp_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ void nhg_add(uint32_t id, const struct nexthop_group *nhg,

api_nhg.id = id;

api_nhg.flags = nhg->flags;
api_nhg.resilience = nhg->nhgr;

for (ALL_NEXTHOPS_PTR(nhg, nh)) {
Expand Down
3 changes: 3 additions & 0 deletions zebra/zapi_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,8 @@ static int zapi_nhg_decode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
STREAM_GETL(s, api_nhg->resilience.idle_timer);
STREAM_GETL(s, api_nhg->resilience.unbalanced_timer);

STREAM_GETC(s, api_nhg->flags);

/* Nexthops */
STREAM_GETW(s, api_nhg->nexthop_num);

Expand Down Expand Up @@ -2013,6 +2015,7 @@ static void zread_nhg_add(ZAPI_HANDLER_ARGS)
nhe = zebra_nhg_alloc();
nhe->id = api_nhg.id;
nhe->type = api_nhg.proto;
nhe->nhg.flags = api_nhg.flags;
nhe->zapi_instance = client->instance;
nhe->zapi_session = client->session_id;

Expand Down
25 changes: 18 additions & 7 deletions zebra/zebra_nhg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2346,8 +2346,10 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe,
* if specified) - i.e., we cannot have a nexthop NH1 is
* resolved by a route NH1. The exception is if the route is a
* host route.
* This control will not work by using nexthop groups, and will
* have to be handled at protocol level
*/
if (prefix_same(&rn->p, top))
if (top && prefix_same(&rn->p, top))
if (((afi == AFI_IP)
&& (rn->p.prefixlen != IPV4_MAX_BITLEN))
|| ((afi == AFI_IP6)
Expand Down Expand Up @@ -3365,7 +3367,7 @@ struct nhg_hash_entry *zebra_nhg_proto_add(struct nhg_hash_entry *nhe,
struct nexthop *newhop;
bool replace = false;
int ret = 0, type;
uint32_t id, session;
uint32_t id, session, api_message = 0;
uint16_t instance;

id = nhe->id;
Expand Down Expand Up @@ -3413,14 +3415,23 @@ struct nhg_hash_entry *zebra_nhg_proto_add(struct nhg_hash_entry *nhe,
return NULL;
}

if (!newhop->ifindex) {
if (!newhop->ifindex &&
!CHECK_FLAG(nhg->flags, NEXTHOP_GROUP_ALLOW_RECURSION)) {
if (IS_ZEBRA_DEBUG_NHG)
zlog_debug(
"%s: id %u, nexthop without ifindex is not supported",
__func__, id);
zlog_debug("%s: id %u, nexthop without ifindex and allow-recursion is not supported",
__func__, id);
return NULL;
}
SET_FLAG(newhop->flags, NEXTHOP_FLAG_ACTIVE);

/* Check that the route may be recursively resolved */
if (CHECK_FLAG(nhg->flags, NEXTHOP_GROUP_ALLOW_RECURSION))
api_message = ZEBRA_FLAG_ALLOW_RECURSION;

if (nexthop_active(newhop, nhe, NULL, 0, api_message, NULL,
newhop->vrf_id))
SET_FLAG(newhop->flags, NEXTHOP_FLAG_ACTIVE);
else
UNSET_FLAG(newhop->flags, NEXTHOP_FLAG_ACTIVE);
}

zebra_nhe_init(&lookup, afi, nhg->nexthop);
Expand Down

0 comments on commit c77981d

Please sign in to comment.