]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Add support for SRv6 SIDs
authorCarmine Scarpitta <cscarpit@cisco.com>
Sat, 23 Mar 2024 12:42:19 +0000 (13:42 +0100)
committerCarmine Scarpitta <cscarpit@cisco.com>
Thu, 13 Jun 2024 12:54:16 +0000 (14:54 +0200)
Add a data structure to represent an SRv6 SID context and the related
management functions (allocate/free).

Signed-off-by: Carmine Scarpitta <cscarpit@cisco.com>
zebra/zebra_srv6.c
zebra/zebra_srv6.h

index e6b3c2a2522a1649e7fdb305c07bdc02ce2fd963..6e72440274865cca45c7501b1b4c39011c547d05 100644 (file)
@@ -37,6 +37,8 @@ DEFINE_MTYPE_STATIC(SRV6_MGR, ZEBRA_SRV6_SID_BLOCK, "SRv6 SID block");
 DEFINE_MTYPE_STATIC(SRV6_MGR, ZEBRA_SRV6_SID_FUNC, "SRv6 SID function");
 DEFINE_MTYPE_STATIC(SRV6_MGR, ZEBRA_SRV6_USID_WLIB,
                    "SRv6 uSID Wide LIB information");
+DEFINE_MTYPE_STATIC(SRV6_MGR, ZEBRA_SRV6_SID, "SRv6 SID");
+DEFINE_MTYPE_STATIC(SRV6_MGR, ZEBRA_SRV6_SID_CTX, "SRv6 SID context");
 
 /* define hooks for the basic API, so that it can be specialized or served
  * externally
@@ -94,6 +96,33 @@ static int zebra_srv6_cleanup(struct zserv *client)
        return 0;
 }
 
+/* --- Zebra SRv6 SID context management functions -------------------------- */
+
+struct zebra_srv6_sid_ctx *zebra_srv6_sid_ctx_alloc(void)
+{
+       struct zebra_srv6_sid_ctx *ctx = NULL;
+
+       ctx = XCALLOC(MTYPE_ZEBRA_SRV6_SID_CTX,
+                     sizeof(struct zebra_srv6_sid_ctx));
+
+       return ctx;
+}
+
+void zebra_srv6_sid_ctx_free(struct zebra_srv6_sid_ctx *ctx)
+{
+       XFREE(MTYPE_ZEBRA_SRV6_SID_CTX, ctx);
+}
+
+/**
+ * Free an SRv6 SID context.
+ *
+ * @param val SRv6 SID context to be freed
+ */
+void delete_zebra_srv6_sid_ctx(void *val)
+{
+       zebra_srv6_sid_ctx_free((struct zebra_srv6_sid_ctx *)val);
+}
+
 /* --- Zebra SRv6 SID format management functions --------------------------- */
 
 void srv6_sid_format_register(struct srv6_sid_format *format)
@@ -481,6 +510,58 @@ zebra_srv6_sid_block_lookup(struct prefix_ipv6 *prefix)
        return NULL;
 }
 
+/* --- Zebra SRv6 SID management functions ---------------------------------- */
+
+/**
+ * Alloc and fill an SRv6 SID.
+ *
+ * @param ctx Context associated with the SID to be created
+ * @param sid_value IPv6 address associated with the SID to be created
+ * @param locator Parent locator of the SID to be created
+ * @param sid_block Block from which the SID value has been allocated
+ * @param sid_func Function part of the SID to be created
+ * @param alloc_mode Allocation mode of the Function (dynamic vs explicit)
+ * @return The requested SID
+ */
+struct zebra_srv6_sid *
+zebra_srv6_sid_alloc(struct zebra_srv6_sid_ctx *ctx, struct in6_addr *sid_value,
+                    struct srv6_locator *locator,
+                    struct zebra_srv6_sid_block *sid_block, uint32_t sid_func,
+                    enum srv6_sid_alloc_mode alloc_mode)
+{
+       struct zebra_srv6_sid *sid;
+
+       if (!ctx || !sid_value)
+               return NULL;
+
+       sid = XCALLOC(MTYPE_ZEBRA_SRV6_SID, sizeof(struct zebra_srv6_sid));
+       sid->ctx = ctx;
+       sid->value = *sid_value;
+       sid->locator = locator;
+       sid->block = sid_block;
+       sid->func = sid_func;
+       sid->alloc_mode = alloc_mode;
+       sid->client_list = list_new();
+
+       return sid;
+}
+
+void zebra_srv6_sid_free(struct zebra_srv6_sid *sid)
+{
+       list_delete(&sid->client_list);
+       XFREE(MTYPE_ZEBRA_SRV6_SID, sid);
+}
+
+/**
+ * Free an SRv6 SID.
+ *
+ * @param val SRv6 SID to be freed
+ */
+void delete_zebra_srv6_sid(void *val)
+{
+       zebra_srv6_sid_free((struct zebra_srv6_sid *)val);
+}
+
 void zebra_srv6_locator_add(struct srv6_locator *locator)
 {
        struct zebra_srv6 *srv6 = zebra_srv6_get_default();
@@ -632,6 +713,10 @@ struct zebra_srv6 *zebra_srv6_get_default(void)
                format_uncompressed = create_srv6_sid_format_uncompressed();
                srv6_sid_format_register(format_uncompressed);
 
+               /* Init list to store SRv6 SIDs */
+               srv6.sids = list_new();
+               srv6.sids->del = delete_zebra_srv6_sid_ctx;
+
                /* Init list to store SRv6 SID blocks */
                srv6.sid_blocks = list_new();
                srv6.sid_blocks->del = delete_zebra_srv6_sid_block;
@@ -841,6 +926,7 @@ void zebra_srv6_terminate(void)
        struct srv6_locator *locator;
        struct srv6_sid_format *format;
        struct zebra_srv6_sid_block *block;
+       struct zebra_srv6_sid_ctx *sid_ctx;
 
        if (srv6.locators) {
                while (listcount(srv6.locators)) {
@@ -853,6 +939,18 @@ void zebra_srv6_terminate(void)
                list_delete(&srv6.locators);
        }
 
+       /* Free SRv6 SIDs */
+       if (srv6.sids) {
+               while (listcount(srv6.sids)) {
+                       sid_ctx = listnode_head(srv6.sids);
+
+                       listnode_delete(srv6.sids, sid_ctx);
+                       zebra_srv6_sid_ctx_free(sid_ctx);
+               }
+
+               list_delete(&srv6.sids);
+       }
+
        /* Free SRv6 SID blocks */
        if (srv6.sid_blocks) {
                while (listcount(srv6.sid_blocks)) {
index 0a8b58ce6183084f5c5c9c8c7973e829e74bdc8c..ad100925755feaf642cbdc1861071af675dc712c 100644 (file)
@@ -102,6 +102,96 @@ struct zebra_srv6_sid_block {
        } u;
 };
 
+/**
+ * The function part of an SRv6 SID can be allocated in one
+ * of the following ways:
+ *  - dynamic: allocate any available function
+ *  - explicit: allocate a specific function
+ */
+enum srv6_sid_alloc_mode {
+       SRV6_SID_ALLOC_MODE_UNSPEC = 0,
+       /* Dynamic SID allocation */
+       SRV6_SID_ALLOC_MODE_DYNAMIC = 1,
+       /* Explicit SID allocation */
+       SRV6_SID_ALLOC_MODE_EXPLICIT = 2,
+       SRV6_SID_ALLOC_MODE_MAX = 3,
+};
+
+/**
+ * Convert SID allocation mode to string.
+ *
+ * @param alloc_mode SID allocation mode
+ * @return String representing the allocation mode
+ */
+static inline const char *
+srv6_sid_alloc_mode2str(enum srv6_sid_alloc_mode alloc_mode)
+{
+       switch (alloc_mode) {
+       case SRV6_SID_ALLOC_MODE_EXPLICIT:
+               return "explicit";
+       case SRV6_SID_ALLOC_MODE_DYNAMIC:
+               return "dynamic";
+       case SRV6_SID_ALLOC_MODE_UNSPEC:
+               return "unspec";
+       case SRV6_SID_ALLOC_MODE_MAX:
+       default:
+               return "unknown";
+       }
+}
+
+/* SRv6 SID instance. */
+struct zebra_srv6_sid {
+       /*
+        * SID context associated with the SID.
+        * Defines behavior and attributes of the SID.
+        */
+       struct zebra_srv6_sid_ctx *ctx;
+
+       /* SID value (e.g. fc00:0:1:e000::) */
+       struct in6_addr value;
+
+       /* Pointer to the SRv6 locator from which the SID has been allocated */
+       struct srv6_locator *locator;
+
+       /* Pointer to the SRv6 block from which the SID has been allocated */
+       struct zebra_srv6_sid_block *block;
+
+       /*
+        * Function part of the SID
+        * Example:
+        *   SID = fc00:0:1:e000:: => func = e000
+        */
+       uint32_t func;
+
+       /* SID wide function. */
+       uint32_t wide_func;
+
+       /* SID allocation mode: dynamic or explicit */
+       enum srv6_sid_alloc_mode alloc_mode;
+
+       /* List of clients that are using the SID */
+       struct list *client_list;
+};
+
+/*
+ * Zebra SRv6 SID context.
+ * A context defines a behavior and (optionally) some behavior-specific
+ * attributes. Client daemons (bgp, isis, ...) ask SRv6 Manager to allocate
+ * a SID for a particular context. SRv6 Manager is responsible for allocating
+ * a SID from a given SID block and associating with the context.
+ *
+ * Example:
+ *    bgp asks to associate a SID to the context {behavior=End.DT46 vrf=Vrf10}.
+ *    SRv6 Manager allocate SID fc00:0:1:e000:: for that context.
+ */
+struct zebra_srv6_sid_ctx {
+       /* SRv6 SID context information. */
+       struct srv6_sid_ctx ctx;
+
+       /* SID associated with the context. */
+       struct zebra_srv6_sid *sid;
+};
+
 /* SRv6 instance structure. */
 struct zebra_srv6 {
        struct list *locators;
@@ -112,6 +202,9 @@ struct zebra_srv6 {
        /* SRv6 SID formats */
        struct list *sid_formats;
 
+       /* SRv6 SIDs */
+       struct list *sids;
+
        /* SRv6 SID blocks */
        struct list *sid_blocks;
 };
@@ -185,4 +278,16 @@ extern void delete_zebra_srv6_sid_block(void *val);
 extern struct zebra_srv6_sid_block *
 zebra_srv6_sid_block_lookup(struct prefix_ipv6 *prefix);
 
+extern struct zebra_srv6_sid *
+zebra_srv6_sid_alloc(struct zebra_srv6_sid_ctx *ctx, struct in6_addr *sid_value,
+                    struct srv6_locator *locator,
+                    struct zebra_srv6_sid_block *sid_block, uint32_t sid_func,
+                    enum srv6_sid_alloc_mode alloc_mode);
+extern void zebra_srv6_sid_free(struct zebra_srv6_sid *sid);
+extern void delete_zebra_srv6_sid(void *val);
+
+extern struct zebra_srv6_sid_ctx *zebra_srv6_sid_ctx_alloc(void);
+extern void zebra_srv6_sid_ctx_free(struct zebra_srv6_sid_ctx *ctx);
+extern void delete_zebra_srv6_sid_ctx(void *val);
+
 #endif /* _ZEBRA_SRV6_H */