diff options
Diffstat (limited to 'staticd/static_srv6.c')
| -rw-r--r-- | staticd/static_srv6.c | 174 |
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); +} |
