summaryrefslogtreecommitdiff
path: root/staticd/static_srv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'staticd/static_srv6.c')
-rw-r--r--staticd/static_srv6.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/staticd/static_srv6.c b/staticd/static_srv6.c
new file mode 100644
index 0000000000..032bb9de9f
--- /dev/null
+++ b/staticd/static_srv6.c
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * STATICd - Segment Routing over IPv6 (SRv6) code
+ * Copyright (C) 2025 Alibaba Inc.
+ * Yuqing Zhao
+ * Lingyu Zhang
+ */
+#include <zebra.h>
+
+#include "vrf.h"
+#include "nexthop.h"
+
+#include "static_routes.h"
+#include "static_srv6.h"
+#include "static_vrf.h"
+#include "static_zebra.h"
+#include "static_debug.h"
+
+/*
+ * List of SRv6 SIDs.
+ */
+struct list *srv6_locators;
+struct list *srv6_sids;
+
+DEFINE_MTYPE_STATIC(STATIC, STATIC_SRV6_LOCATOR, "Static SRv6 locator");
+DEFINE_MTYPE_STATIC(STATIC, STATIC_SRV6_SID, "Static SRv6 SID");
+
+/*
+ * When an interface is enabled in the kernel, go through all the static SRv6 SIDs in
+ * the system that use this interface and install/remove them in the zebra RIB.
+ *
+ * ifp - The interface being enabled
+ * is_up - Whether the interface is up or down
+ */
+void static_ifp_srv6_sids_update(struct interface *ifp, bool is_up)
+{
+ struct static_srv6_sid *sid;
+ struct listnode *node;
+
+ if (!srv6_sids || !ifp)
+ return;
+
+ DEBUGD(&static_dbg_srv6, "%s: Interface %s %s. %s SIDs that depend on the interface",
+ __func__, (is_up) ? "enabled" : "disabled", (is_up) ? "Removing" : "disabled",
+ ifp->name);
+
+ /*
+ * iterate over the list of SRv6 SIDs and remove the SIDs that use this
+ * VRF from the zebra RIB
+ */
+ for (ALL_LIST_ELEMENTS_RO(srv6_sids, node, sid)) {
+ if ((strcmp(sid->attributes.vrf_name, ifp->name) == 0) ||
+ (strncmp(ifp->name, DEFAULT_SRV6_IFNAME, sizeof(ifp->name)) == 0 &&
+ (sid->behavior == SRV6_ENDPOINT_BEHAVIOR_END ||
+ sid->behavior == SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID))) {
+ if (is_up) {
+ static_zebra_srv6_sid_install(sid);
+ SET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
+ } else {
+ static_zebra_srv6_sid_uninstall(sid);
+ UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
+ }
+ }
+ }
+}
+
+/*
+ * Allocate an SRv6 SID object and initialize the fields common to all the
+ * behaviors (i.e., SID address and behavor).
+ */
+struct static_srv6_sid *static_srv6_sid_alloc(struct prefix_ipv6 *addr)
+{
+ struct static_srv6_sid *sid = NULL;
+
+ sid = XCALLOC(MTYPE_STATIC_SRV6_SID, sizeof(struct static_srv6_sid));
+ sid->addr = *addr;
+
+ return sid;
+}
+
+void static_srv6_sid_free(struct static_srv6_sid *sid)
+{
+ XFREE(MTYPE_STATIC_SRV6_SID, sid);
+}
+
+struct static_srv6_locator *static_srv6_locator_lookup(const char *name)
+{
+ struct static_srv6_locator *locator;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(srv6_locators, node, locator))
+ if (!strncmp(name, locator->name, SRV6_LOCNAME_SIZE))
+ return locator;
+ return NULL;
+}
+
+/*
+ * Look-up an SRv6 SID in the list of SRv6 SIDs.
+ */
+struct static_srv6_sid *static_srv6_sid_lookup(struct prefix_ipv6 *sid_addr)
+{
+ struct static_srv6_sid *sid;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(srv6_sids, node, sid))
+ if (memcmp(&sid->addr, sid_addr, sizeof(struct prefix_ipv6)) == 0)
+ return sid;
+
+ return NULL;
+}
+
+struct static_srv6_locator *static_srv6_locator_alloc(const char *name)
+{
+ struct static_srv6_locator *locator = NULL;
+
+ locator = XCALLOC(MTYPE_STATIC_SRV6_LOCATOR, sizeof(struct static_srv6_locator));
+ strlcpy(locator->name, name, sizeof(locator->name));
+
+ return locator;
+}
+
+void static_srv6_locator_free(struct static_srv6_locator *locator)
+{
+ XFREE(MTYPE_STATIC_SRV6_LOCATOR, locator);
+}
+
+void delete_static_srv6_locator(void *val)
+{
+ static_srv6_locator_free((struct static_srv6_locator *)val);
+}
+
+/*
+ * Remove an SRv6 SID from the zebra RIB (if it was previously installed) and
+ * release the memory previously allocated for the SID.
+ */
+void static_srv6_sid_del(struct static_srv6_sid *sid)
+{
+ if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID)) {
+ static_zebra_release_srv6_sid(sid);
+ UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID);
+ }
+
+ if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA)) {
+ static_zebra_srv6_sid_uninstall(sid);
+ UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
+ }
+
+ XFREE(MTYPE_STATIC_SRV6_SID, sid);
+}
+
+void delete_static_srv6_sid(void *val)
+{
+ static_srv6_sid_free((struct static_srv6_sid *)val);
+}
+
+/*
+ * Initialize SRv6 data structures.
+ */
+void static_srv6_init(void)
+{
+ srv6_locators = list_new();
+ srv6_locators->del = delete_static_srv6_locator;
+ srv6_sids = list_new();
+ srv6_sids->del = delete_static_srv6_sid;
+}
+
+/*
+ * Clean up all the SRv6 data structures.
+ */
+void static_srv6_cleanup(void)
+{
+ list_delete(&srv6_locators);
+ list_delete(&srv6_sids);
+}