diff --git a/lib/nexthop.c b/lib/nexthop.c index 0ac6c0ae1b..3c36dbf69a 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -36,6 +36,7 @@ DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop"); DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label"); +DEFINE_MTYPE_STATIC(LIB, NH_SEG6LOCAL, "Nexthop seg6local"); static int _nexthop_labels_cmp(const struct nexthop *nh1, const struct nexthop *nh2) @@ -66,6 +67,28 @@ static int _nexthop_labels_cmp(const struct nexthop *nh1, (nhl1->num_labels * sizeof(mpls_label_t))); } +static int _nexthop_seg6local_cmp(const struct nexthop *nh1, + const struct nexthop *nh2) +{ + if (nh1->nh_seg6local_action > nh2->nh_seg6local_action) + return 1; + + if (nh2->nh_seg6local_action < nh1->nh_seg6local_action) + return -1; + + if (!nh1->nh_seg6local_ctx && !nh2->nh_seg6local_ctx) + return 0; + + if (nh1->nh_seg6local_ctx && !nh2->nh_seg6local_ctx) + return 1; + + if (!nh1->nh_seg6local_ctx && nh2->nh_seg6local_ctx) + return -1; + + return memcmp(nh1->nh_seg6local_ctx, nh2->nh_seg6local_ctx, + sizeof(struct seg6local_context)); +} + int nexthop_g_addr_cmp(enum nexthop_types_t type, const union g_addr *addr1, const union g_addr *addr2) { @@ -199,6 +222,10 @@ int nexthop_cmp(const struct nexthop *next1, const struct nexthop *next2) return ret; ret = _nexthop_labels_cmp(next1, next2); + if (ret != 0) + return ret; + + ret = _nexthop_seg6local_cmp(next1, next2); return ret; } @@ -353,6 +380,7 @@ struct nexthop *nexthop_new(void) void nexthop_free(struct nexthop *nexthop) { nexthop_del_labels(nexthop); + nexthop_del_seg6local(nexthop); if (nexthop->resolved) nexthops_free(nexthop->resolved); XFREE(MTYPE_NEXTHOP, nexthop); @@ -523,6 +551,27 @@ void nexthop_del_labels(struct nexthop *nexthop) nexthop->nh_label_type = ZEBRA_LSP_NONE; } +void nexthop_add_seg6local(struct nexthop *nexthop, uint32_t action, + const struct seg6local_context *ctx) +{ + struct seg6local_context *nh_ctx; + + if (action == ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) + return; + + nh_ctx = XCALLOC(MTYPE_NH_SEG6LOCAL, sizeof(struct seg6local_context)); + if (ctx) + *nh_ctx = *ctx; + nexthop->nh_seg6local_action = action; + nexthop->nh_seg6local_ctx = nh_ctx; +} + +void nexthop_del_seg6local(struct nexthop *nexthop) +{ + XFREE(MTYPE_NH_SEG6LOCAL, nexthop->nh_seg6local_ctx); + nexthop->nh_seg6local_action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC; +} + const char *nexthop2str(const struct nexthop *nexthop, char *str, int size) { switch (nexthop->type) { @@ -668,6 +717,12 @@ uint32_t nexthop_hash_quick(const struct nexthop *nexthop) key = jhash_1word(nexthop->backup_idx[i], key); } + if (nexthop->nh_seg6local_ctx) { + key = jhash_1word(nexthop->nh_seg6local_action, key); + key = jhash(nexthop->nh_seg6local_ctx, + sizeof(nexthop->nh_seg6local_ctx), key); + } + return key; } @@ -720,6 +775,10 @@ void nexthop_copy_no_recurse(struct nexthop *copy, nexthop_add_labels(copy, nexthop->nh_label_type, nexthop->nh_label->num_labels, &nexthop->nh_label->label[0]); + + if (nexthop->nh_seg6local_ctx) + nexthop_add_seg6local(copy, nexthop->nh_seg6local_action, + nexthop->nh_seg6local_ctx); } void nexthop_copy(struct nexthop *copy, const struct nexthop *nexthop, diff --git a/lib/nexthop.h b/lib/nexthop.h index d6ea83cf06..7bddee8713 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -26,6 +26,7 @@ #include "prefix.h" #include "mpls.h" #include "vxlan.h" +#include "srv6.h" #ifdef __cplusplus extern "C" { @@ -139,6 +140,10 @@ struct nexthop { /* SR-TE color used for matching SR-TE policies */ uint32_t srte_color; + + /* SRv6 localsid info for Endpoint-behaviour */ + enum seg6local_action_t nh_seg6local_action; + struct seg6local_context *nh_seg6local_ctx; }; /* Utility to append one nexthop to another. */ @@ -157,6 +162,9 @@ void nexthops_free(struct nexthop *nexthop); void nexthop_add_labels(struct nexthop *nexthop, enum lsp_types_t ltype, uint8_t num_labels, const mpls_label_t *labels); void nexthop_del_labels(struct nexthop *); +void nexthop_add_seg6local(struct nexthop *nexthop, uint32_t action, + const struct seg6local_context *ctx); +void nexthop_del_seg6local(struct nexthop *nexthop); /* * Allocate a new nexthop object and initialize it from various args. diff --git a/lib/zclient.c b/lib/zclient.c index 3ea1789441..bf67392cbe 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -796,6 +796,19 @@ static int zapi_nexthop_labels_cmp(const struct zapi_nexthop *next1, return memcmp(next1->labels, next2->labels, next1->label_num); } +static int zapi_nexthop_seg6local_cmp(const struct zapi_nexthop *next1, + const struct zapi_nexthop *next2) +{ + if (next1->seg6local_action > next2->seg6local_action) + return 1; + + if (next1->seg6local_action < next2->seg6local_action) + return -1; + + return memcmp(&next1->seg6local_ctx, &next2->seg6local_ctx, + sizeof(struct seg6local_context)); +} + static int zapi_nexthop_cmp_no_labels(const struct zapi_nexthop *next1, const struct zapi_nexthop *next2) { @@ -896,6 +909,10 @@ static int zapi_nexthop_cmp(const void *item1, const void *item2) return ret; ret = zapi_nexthop_labels_cmp(next1, next2); + if (ret != 0) + return ret; + + ret = zapi_nexthop_seg6local_cmp(next1, next2); return ret; } @@ -992,6 +1009,12 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, stream_putc(s, api_nh->backup_idx[i]); } + if (CHECK_FLAG(api_flags, ZEBRA_FLAG_SEG6LOCAL_ROUTE)) { + stream_putl(s, api_nh->seg6local_action); + stream_write(s, &api_nh->seg6local_ctx, + sizeof(struct seg6local_context)); + } + done: return ret; } @@ -1273,6 +1296,12 @@ int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh, STREAM_GETC(s, api_nh->backup_idx[i]); } + if (CHECK_FLAG(api_flags, ZEBRA_FLAG_SEG6LOCAL_ROUTE)) { + STREAM_GETL(s, api_nh->seg6local_action); + STREAM_GET(&api_nh->seg6local_ctx, s, + sizeof(struct seg6local_context)); + } + /* Success */ ret = 0; @@ -1637,6 +1666,10 @@ struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh) memcpy(n->backup_idx, znh->backup_idx, n->backup_num); } + if (znh->seg6local_action != 0) + nexthop_add_seg6local(n, znh->seg6local_action, + &znh->seg6local_ctx); + return n; } @@ -1681,6 +1714,12 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh, memcpy(znh->backup_idx, nh->backup_idx, znh->backup_num); } + if (nh->nh_seg6local_action != 0 && nh->nh_seg6local_ctx != NULL) { + znh->seg6local_action = nh->nh_seg6local_action; + memcpy(&znh->seg6local_ctx, nh->nh_seg6local_ctx, + sizeof(struct seg6local_context)); + } + return 0; } diff --git a/lib/zclient.h b/lib/zclient.h index 8c27916542..3f5225f097 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -459,6 +459,10 @@ struct zapi_nexthop { /* SR-TE color. */ uint32_t srte_color; + + /* SRv6 localsid info for Endpoint-behaviour */ + uint32_t seg6local_action; + struct seg6local_context seg6local_ctx; }; /* @@ -555,6 +559,16 @@ struct zapi_route { * offload situation. */ #define ZEBRA_FLAG_OFFLOAD_FAILED 0x200 +/* + * This flag tells Zebra that the route is a seg6 route and should + * be treated specially. + */ +#define ZEBRA_FLAG_SEG6_ROUTE 0x400 +/* + * This flag tells Zebra that the route is a seg6local route and + * should be treated specially. + */ +#define ZEBRA_FLAG_SEG6LOCAL_ROUTE 0x800 /* The older XXX_MESSAGE flags live here */ uint32_t message;