Skip to content

Commit

Permalink
*: add srte color support in nhg
Browse files Browse the repository at this point in the history
The nexthop group CLI can not configure color support.
Add a new option under nexthop command to configure an
srte color:

> nexthop-group 1
> [..]
>  nexthop 192.0.2.100 color 100

Add srte color support for nhg:
- Add NEXTHOP_GROUP_MESSAGE_COLOR support in NHG.
- Add ZAPI_NEXTHOP_MESSAGE_SRTE support in ZAPI.
- When checking for nexthop active, an SRTE policy with
the (color, nexthop ip) tuple will be looked ip.

Add a NHG sharp test for SRTE color:
- a NHG matching an SRTE policy is configured
- NHG sharp is extended to watch a given NHT color
> sharp watch nexthop 172.31.0.200 color 1
- Upon NHT call back, the NHG is re-added, and updates
the nexthop.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
  • Loading branch information
pguibert6WIND committed Jan 3, 2024
1 parent 887133c commit e5b4063
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 29 deletions.
2 changes: 1 addition & 1 deletion doc/user/nexthop_groups.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ listing of ECMP nexthops used to forward packets.
sub-mode where you can specify individual nexthops. To exit this mode type
exit or end as per normal conventions for leaving a sub-mode.

.. clicmd:: nexthop [A.B.C.D|X:X::X:XX] [interface [onlink]] [nexthop-vrf NAME] [label LABELS]
.. clicmd:: nexthop [A.B.C.D|X:X::X:XX] [interface [onlink]] [nexthop-vrf NAME] [label LABELS] [color (1-4294967295)]

Create a v4 or v6 nexthop. All normal rules for creating nexthops that you
are used to are allowed here. The syntax was intentionally kept the same as
Expand Down
76 changes: 60 additions & 16 deletions lib/nexthop_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct nexthop_hold {
vni_t vni;
uint32_t weight;
char *backup_str;
uint32_t color;
};

struct nexthop_group_hooks {
Expand All @@ -51,7 +52,7 @@ nexthop_group_cmd_compare(const struct nexthop_group_cmd *nhgc1,
RB_GENERATE(nhgc_entry_head, nexthop_group_cmd, nhgc_entry,
nexthop_group_cmd_compare)

static struct nhgc_entry_head nhgc_entries;
struct nhgc_entry_head nhgc_entries;

static inline int
nexthop_group_cmd_compare(const struct nexthop_group_cmd *nhgc1,
Expand Down Expand Up @@ -721,6 +722,23 @@ DEFPY(nexthop_group_ibgp,
return CMD_SUCCESS;
}

static void nhgc_configure_color(struct nexthop_group_cmd *nhgc, bool enable)
{
if (enable ==
!!CHECK_FLAG(nhgc->nhg.message, NEXTHOP_GROUP_MESSAGE_SRTE))
return;

if (enable)
SET_FLAG(nhgc->nhg.message, NEXTHOP_GROUP_MESSAGE_SRTE);
else
UNSET_FLAG(nhgc->nhg.message, NEXTHOP_GROUP_MESSAGE_SRTE);

SET_FLAG(nhgc->nhg.flags, NEXTHOP_GROUP_RESET_NHG);
if (nhg_hooks.modify)
nhg_hooks.modify(nhgc);
UNSET_FLAG(nhgc->nhg.flags, NEXTHOP_GROUP_RESET_NHG);
}

DEFPY(no_nexthop_group_backup, no_nexthop_group_backup_cmd,
"no backup-group [WORD$name]",
NO_STR
Expand Down Expand Up @@ -778,12 +796,11 @@ DEFPY(no_nexthop_group_resilience,
return CMD_SUCCESS;
}

static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc,
const char *nhvrf_name,
const union sockunion *addr,
const char *intf, bool onlink,
const char *labels, const uint32_t weight,
const char *backup_str)
static void
nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc, const char *nhvrf_name,
const union sockunion *addr, const char *intf,
bool onlink, const char *labels, const uint32_t weight,
const char *backup_str, const uint32_t color)
{
struct nexthop_hold *nh;

Expand All @@ -802,6 +819,8 @@ static void nexthop_group_save_nhop(struct nexthop_group_cmd *nhgc,

nh->weight = weight;

nh->color = color;

if (backup_str)
nh->backup_str = XSTRDUP(MTYPE_TMP, backup_str);

Expand Down Expand Up @@ -850,8 +869,8 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
const union sockunion *addr,
const char *intf, bool onlink,
const char *name, const char *labels,
vni_t vni, int *lbl_ret,
uint32_t weight, const char *backup_str)
vni_t vni, int *lbl_ret, uint32_t weight,
const char *backup_str, uint32_t color)
{
int ret = 0;
struct vrf *vrf;
Expand Down Expand Up @@ -918,6 +937,7 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
}

nhop->weight = weight;
nhop->srte_color = color;

if (backup_str) {
/* Parse backup indexes */
Expand All @@ -939,9 +959,11 @@ static bool nexthop_group_parse_nexthop(struct nexthop *nhop,
static bool nexthop_group_parse_nhh(struct nexthop *nhop,
const struct nexthop_hold *nhh)
{
return (nexthop_group_parse_nexthop(
nhop, nhh->addr, nhh->intf, nhh->onlink, nhh->nhvrf_name,
nhh->labels, nhh->vni, NULL, nhh->weight, nhh->backup_str));
return (nexthop_group_parse_nexthop(nhop, nhh->addr, nhh->intf,
nhh->onlink, nhh->nhvrf_name,
nhh->labels, nhh->vni, NULL,
nhh->weight, nhh->backup_str,
nhh->color));
}

DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
Expand All @@ -956,6 +978,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
|vni (1-16777215) \
|weight (1-255) \
|backup-idx WORD \
|color (1-4294967295) \
}]",
NO_STR
"Specify one of the nexthops in this ECMP group\n"
Expand All @@ -973,7 +996,9 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
"Weight to be used by the nexthop for purposes of ECMP\n"
"Weight value to be used\n"
"Specify backup nexthop indexes in another group\n"
"One or more indexes in the range (0-254) separated by ','\n")
"One or more indexes in the range (0-254) separated by ','\n"
SRTE_STR
SRTE_COLOR_STR)
{
VTY_DECLVAR_CONTEXT(nexthop_group_cmd, nhgc);
struct nexthop nhop;
Expand All @@ -982,7 +1007,9 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
bool legal;
int num;
uint8_t backups[NEXTHOP_MAX_BACKUPS];
bool yes = !no;
bool yes = !no, color_config = false;
struct nexthop_hold *nhh;
struct listnode *node;

/* Pre-parse backup string to validate */
if (backup_idx) {
Expand All @@ -995,7 +1022,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,

legal = nexthop_group_parse_nexthop(&nhop, addr, intf, !!onlink,
vrf_name, label, vni, &lbl_ret,
weight, backup_idx);
weight, backup_idx, color);

if (nhop.type == NEXTHOP_TYPE_IPV6
&& IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) {
Expand Down Expand Up @@ -1058,10 +1085,18 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,

/* Save config always */
nexthop_group_save_nhop(nhgc, vrf_name, addr, intf, !!onlink,
label, weight, backup_idx);
label, weight, backup_idx, color);
if (color)
nhgc_configure_color(nhgc, true);

if (legal && nhg_hooks.add_nexthop)
nhg_hooks.add_nexthop(nhgc, nh);
} else {
for (ALL_LIST_ELEMENTS_RO(nhgc->nhg_list, node, nhh)) {
if (nhh->color)
color_config = true;
}
nhgc_configure_color(nhgc, color_config);
}

return CMD_SUCCESS;
Expand Down Expand Up @@ -1134,6 +1169,9 @@ void nexthop_group_write_nexthop(struct vty *vty, const struct nexthop *nh)
if (nh->weight)
vty_out(vty, " weight %u", nh->weight);

if (nh->srte_color)
vty_out(vty, " color %u", nh->srte_color);

if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
vty_out(vty, " backup-idx %d", nh->backup_idx[0]);

Expand Down Expand Up @@ -1191,6 +1229,9 @@ void nexthop_group_json_nexthop(json_object *j, const struct nexthop *nh)
if (nh->weight)
json_object_int_add(j, "weight", nh->weight);

if (nh->srte_color)
json_object_int_add(j, "color", nh->srte_color);

if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
json_backups = json_object_new_array();
for (i = 0; i < nh->backup_num; i++)
Expand Down Expand Up @@ -1228,6 +1269,9 @@ static void nexthop_group_write_nexthop_internal(struct vty *vty,
if (nh->weight)
vty_out(vty, " weight %u", nh->weight);

if (nh->color)
vty_out(vty, " color %u", nh->color);

if (nh->backup_str)
vty_out(vty, " backup-idx %s", nh->backup_str);

Expand Down
4 changes: 4 additions & 0 deletions lib/nexthop_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ struct nexthop_group {
#define NEXTHOP_GROUP_FORCE_NH_CONFIG (1 << 3)
#define NEXTHOP_GROUP_IBGP (1 << 4)
uint8_t flags;
/* nexthop group messages */
#define NEXTHOP_GROUP_MESSAGE_SRTE (1 << 1)
uint8_t message;
};

struct nexthop_group *nexthop_group_new(void);
Expand Down Expand Up @@ -106,6 +109,7 @@ RB_HEAD(nhgc_entry_head, nexthp_group_cmd);
RB_PROTOTYPE(nhgc_entry_head, nexthop_group_cmd, nhgc_entry,
nexthop_group_cmd_compare)
DECLARE_QOBJ_TYPE(nexthop_group_cmd);
extern struct nhgc_entry_head nhgc_entries;

/*
* Initialize nexthop_groups. If you are interested in when
Expand Down
9 changes: 7 additions & 2 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,7 @@ int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l)
static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
{
int i;
uint32_t api_message = 0;

if (cmd != ZEBRA_NHG_DEL && cmd != ZEBRA_NHG_ADD) {
flog_err(EC_LIB_ZAPI_ENCODE,
Expand All @@ -1174,6 +1175,9 @@ static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
stream_putl(s, api_nhg->resilience.unbalanced_timer);

stream_putc(s, api_nhg->flags);
stream_putc(s, api_nhg->message);
if (CHECK_FLAG(api_nhg->message, ZAPI_NEXTHOP_MESSAGE_SRTE))
SET_FLAG(api_message, ZAPI_MESSAGE_SRTE);

if (cmd == ZEBRA_NHG_ADD) {
/* Nexthops */
Expand All @@ -1183,14 +1187,15 @@ static int zapi_nhg_encode(struct stream *s, int cmd, struct zapi_nhg *api_nhg)
stream_putw(s, api_nhg->nexthop_num);

for (i = 0; i < api_nhg->nexthop_num; i++)
zapi_nexthop_encode(s, &api_nhg->nexthops[i], 0, 0);
zapi_nexthop_encode(s, &api_nhg->nexthops[i], 0,
api_message);

/* Backup nexthops */
stream_putw(s, api_nhg->backup_nexthop_num);

for (i = 0; i < api_nhg->backup_nexthop_num; i++)
zapi_nexthop_encode(s, &api_nhg->backup_nexthops[i], 0,
0);
api_message);
}

stream_putw_at(s, 0, stream_get_endp(s));
Expand Down
3 changes: 3 additions & 0 deletions lib/zclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,9 @@ struct zapi_nhg {

/* nexthop group flags */
uint8_t flags;
/* nexthop group message : definition from nexthop_group.h */
#define ZAPI_NEXTHOP_MESSAGE_SRTE NEXTHOP_GROUP_MESSAGE_SRTE
uint8_t message;
};

/*
Expand Down
2 changes: 2 additions & 0 deletions sharpd/sharp_nht.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ struct sharp_nh_tracker {
uint32_t nhop_num;

uint32_t updates;

uint32_t color;
};

extern struct sharp_nh_tracker *sharp_nh_tracker_get(struct prefix *p);
Expand Down
23 changes: 17 additions & 6 deletions sharpd/sharp_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ DEFPY(watch_redistribute, watch_redistribute_cmd,
}

DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
"sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
"sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected] [color (1-4294967295)]",
"Sharp routing Protocol\n"
"Watch for changes\n"
"The vrf we would like to watch if non-default\n"
Expand All @@ -64,11 +64,14 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
"The v6 nexthop to signal for watching\n"
"Watch for import check changes\n"
"The v6 prefix to signal for watching\n"
"Should the route be connected\n")
"Should the route be connected\n"
SRTE_STR
SRTE_COLOR_STR)
{
struct vrf *vrf;
struct prefix p;
bool type_import;
struct sharp_nh_tracker *nht;

if (!vrf_name)
vrf_name = VRF_DEFAULT_NAME;
Expand All @@ -91,15 +94,18 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
prefix_copy(&p, inhop);
}

sharp_nh_tracker_get(&p);
nht = sharp_nh_tracker_get(&p);
if (color)
nht->color = color;

sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
true, !!connected);

return CMD_SUCCESS;
}

DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
"sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
"sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected] [color (1-4294967295)]",
"Sharp routing Protocol\n"
"Watch for changes\n"
"The vrf we would like to watch if non-default\n"
Expand All @@ -108,11 +114,14 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
"The v4 address to signal for watching\n"
"Watch for import check changes\n"
"The v4 prefix for import check to watch\n"
"Should the route be connected\n")
"Should the route be connected\n"
SRTE_STR
SRTE_COLOR_STR)
{
struct vrf *vrf;
struct prefix p;
bool type_import;
struct sharp_nh_tracker *nht;

if (!vrf_name)
vrf_name = VRF_DEFAULT_NAME;
Expand All @@ -136,7 +145,9 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
prefix_copy(&p, inhop);
}

sharp_nh_tracker_get(&p);
nht = sharp_nh_tracker_get(&p);
if (color)
nht->color = color;
sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
true, !!connected);

Expand Down
Loading

0 comments on commit e5b4063

Please sign in to comment.