From cb7775a9740d78ba81b5126fcb637102e4bad1d6 Mon Sep 17 00:00:00 2001 From: Hiroki Shirokura Date: Wed, 19 Aug 2020 09:46:33 +0900 Subject: [PATCH] lib: add new nexthop's attributes seg6local (step1) This commit is a part of #5853 works that add new nexthop's addional object for SRv6 routing about seg6local route. Before this commit, we can add MPLS info as additional object on nexthop. This commit make it add more support about seg6local routes. seg6local routes are ones of the LWT routing mechanism, so configuration of seg6local routes is performed by ZEBRA_ROUTE_SEND, it's same as MPLS configuration. Real configuration implementation isn't implemented at this commit. later commit add that. This commit add only nexthop additional object and some misc functions. Signed-off-by: Hiroki Shirokura --- lib/nexthop.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/nexthop.h | 8 +++++++ lib/zclient.c | 39 ++++++++++++++++++++++++++++++++++ lib/zclient.h | 14 ++++++++++++ 4 files changed, 120 insertions(+) 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;