mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
175 lines
4.4 KiB
C
175 lines
4.4 KiB
C
// 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);
|
|
}
|