summaryrefslogtreecommitdiffstats
path: root/staticd
diff options
context:
space:
mode:
authorYuqing Zhao <galadriel.zyq@alibaba-inc.com>2025-01-13 11:03:48 +0100
committerYuqing Zhao <galadriel.zyq@alibaba-inc.com>2025-01-18 11:28:49 +0100
commite80f24df7e4c47924f274749b14143b894df7d3b (patch)
tree9384314979fba757f28ef24bde6abdae50fb908f /staticd
parentlib, isisd: Move DEFAULT_SRV6_IFNAME to global srv6.h header (diff)
downloadfrr-e80f24df7e4c47924f274749b14143b894df7d3b.tar.xz
frr-e80f24df7e4c47924f274749b14143b894df7d3b.zip
staticd: Request/Release SIDs to SID Manager
Signed-off-by: Yuqing Zhao <galadriel.zyq@alibaba-inc.com>
Diffstat (limited to 'staticd')
-rw-r--r--staticd/static_zebra.c653
-rw-r--r--staticd/static_zebra.h10
2 files changed, 663 insertions, 0 deletions
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index d76befc13..6e8d275d6 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -30,6 +30,9 @@
#include "static_nht.h"
#include "static_vty.h"
#include "static_debug.h"
+#include "zclient.h"
+#include "static_srv6.h"
+#include "lib_errors.h"
DEFINE_MTYPE_STATIC(STATIC, STATIC_NHT_DATA, "Static Nexthop tracking data");
PREDECL_HASH(static_nht_hash);
@@ -530,10 +533,660 @@ extern void static_zebra_route_add(struct static_path *pn, bool install)
zclient, &api);
}
+/**
+ * Send SRv6 SID to ZEBRA for installation or deletion.
+ *
+ * @param cmd ZEBRA_ROUTE_ADD or ZEBRA_ROUTE_DELETE
+ * @param sid SRv6 SID to install or delete
+ * @param prefixlen Prefix length
+ * @param oif Outgoing interface
+ * @param action SID action
+ * @param context SID context
+ */
+static void static_zebra_send_localsid(int cmd, const struct in6_addr *sid, uint16_t prefixlen,
+ ifindex_t oif, enum seg6local_action_t action,
+ const struct seg6local_context *context)
+{
+ struct prefix_ipv6 p = {};
+ struct zapi_route api = {};
+ struct zapi_nexthop *znh;
+
+ if (cmd != ZEBRA_ROUTE_ADD && cmd != ZEBRA_ROUTE_DELETE) {
+ flog_warn(EC_LIB_DEVELOPMENT, "%s: wrong ZEBRA command", __func__);
+ return;
+ }
+
+ if (prefixlen > IPV6_MAX_BITLEN) {
+ flog_warn(EC_LIB_DEVELOPMENT, "%s: wrong prefixlen %u", __func__, prefixlen);
+ return;
+ }
+
+ DEBUGD(&static_dbg_srv6, "%s: |- %s SRv6 SID %pI6 behavior %s", __func__,
+ cmd == ZEBRA_ROUTE_ADD ? "Add" : "Delete", sid, seg6local_action2str(action));
+
+ p.family = AF_INET6;
+ p.prefixlen = prefixlen;
+ p.prefix = *sid;
+
+ api.vrf_id = VRF_DEFAULT;
+ api.type = ZEBRA_ROUTE_STATIC;
+ api.instance = 0;
+ api.safi = SAFI_UNICAST;
+ memcpy(&api.prefix, &p, sizeof(p));
+
+ if (cmd == ZEBRA_ROUTE_DELETE)
+ return (void)zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+
+ SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
+ SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+
+ znh = &api.nexthops[0];
+
+ memset(znh, 0, sizeof(*znh));
+
+ znh->type = NEXTHOP_TYPE_IFINDEX;
+ znh->ifindex = oif;
+ SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
+ znh->seg6local_action = action;
+ memcpy(&znh->seg6local_ctx, context, sizeof(struct seg6local_context));
+
+ api.nexthop_num = 1;
+
+ zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
+}
+
+/**
+ * Install SRv6 SID in the forwarding plane through Zebra.
+ *
+ * @param sid SRv6 SID
+ */
+void static_zebra_srv6_sid_install(struct static_srv6_sid *sid)
+{
+ enum seg6local_action_t action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
+ struct seg6local_context ctx = {};
+ struct interface *ifp = NULL;
+ struct vrf *vrf;
+
+ if (!sid)
+ return;
+
+ if (CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA))
+ return;
+
+ if (!sid->locator) {
+ zlog_err("Failed to install SID %pFX: missing locator information", &sid->addr);
+ return;
+ }
+
+ switch (sid->behavior) {
+ case SRV6_ENDPOINT_BEHAVIOR_END:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END;
+ SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
+ ctx.flv.lcblock_len = sid->locator->block_bits_length;
+ ctx.flv.lcnode_func_len = sid->locator->node_bits_length;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf)) {
+ zlog_warn("Failed to install SID %pFX: VRF %s is inactive", &sid->addr,
+ sid->attributes.vrf_name);
+ return;
+ }
+ ctx.table = vrf->data.l.table_id;
+ ifp = if_get_vrf_loopback(vrf->vrf_id);
+ if (!ifp) {
+ zlog_warn("Failed to install SID %pFX: failed to get loopback for vrf %s",
+ &sid->addr, sid->attributes.vrf_name);
+ return;
+ }
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf)) {
+ zlog_warn("Failed to install SID %pFX: VRF %s is inactive", &sid->addr,
+ sid->attributes.vrf_name);
+ return;
+ }
+ ctx.table = vrf->data.l.table_id;
+ ifp = if_get_vrf_loopback(vrf->vrf_id);
+ if (!ifp) {
+ zlog_warn("Failed to install SID %pFX: failed to get loopback for vrf %s",
+ &sid->addr, sid->attributes.vrf_name);
+ return;
+ }
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf)) {
+ zlog_warn("Failed to install SID %pFX: VRF %s is inactive", &sid->addr,
+ sid->attributes.vrf_name);
+ return;
+ }
+ ctx.table = vrf->data.l.table_id;
+ ifp = if_get_vrf_loopback(vrf->vrf_id);
+ if (!ifp) {
+ zlog_warn("Failed to install SID %pFX: failed to get loopback for vrf %s",
+ &sid->addr, sid->attributes.vrf_name);
+ return;
+ }
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_X:
+ case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID:
+ case SRV6_ENDPOINT_BEHAVIOR_OPAQUE:
+ case SRV6_ENDPOINT_BEHAVIOR_RESERVED:
+ zlog_warn("unsupported behavior: %u", sid->behavior);
+ break;
+ }
+
+ ctx.block_len = sid->locator->block_bits_length;
+ ctx.node_len = sid->locator->node_bits_length;
+ ctx.function_len = sid->locator->function_bits_length;
+ ctx.argument_len = sid->locator->argument_bits_length;
+
+ /* Attach the SID to the SRv6 interface */
+ if (!ifp) {
+ ifp = if_lookup_by_name(DEFAULT_SRV6_IFNAME, VRF_DEFAULT);
+ if (!ifp) {
+ zlog_warn("Failed to install SRv6 SID %pFX: %s interface not found",
+ &sid->addr, DEFAULT_SRV6_IFNAME);
+ return;
+ }
+ }
+
+ /* Send the SID to zebra */
+ static_zebra_send_localsid(ZEBRA_ROUTE_ADD, &sid->addr.prefix, sid->addr.prefixlen,
+ ifp->ifindex, action, &ctx);
+
+ SET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
+}
+
+void static_zebra_srv6_sid_uninstall(struct static_srv6_sid *sid)
+{
+ enum seg6local_action_t action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
+ struct interface *ifp = NULL;
+ struct seg6local_context ctx = {};
+ struct vrf *vrf;
+
+ if (!sid)
+ return;
+
+ if (!CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA))
+ return;
+
+ if (!sid->locator) {
+ zlog_err("Failed to uninstall SID %pFX: missing locator information", &sid->addr);
+ return;
+ }
+
+ switch (sid->behavior) {
+ case SRV6_ENDPOINT_BEHAVIOR_END:
+ case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID:
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf)) {
+ zlog_warn("Failed to install SID %pFX: VRF %s is inactive", &sid->addr,
+ sid->attributes.vrf_name);
+ return;
+ }
+ ifp = if_get_vrf_loopback(vrf->vrf_id);
+ if (!ifp) {
+ zlog_warn("Failed to install SID %pFX: failed to get loopback for vrf %s",
+ &sid->addr, sid->attributes.vrf_name);
+ return;
+ }
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID:
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf)) {
+ zlog_warn("Failed to install SID %pFX: VRF %s is inactive", &sid->addr,
+ sid->attributes.vrf_name);
+ return;
+ }
+ ifp = if_get_vrf_loopback(vrf->vrf_id);
+ if (!ifp) {
+ zlog_warn("Failed to install SID %pFX: failed to get loopback for vrf %s",
+ &sid->addr, sid->attributes.vrf_name);
+ return;
+ }
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID:
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf)) {
+ zlog_warn("Failed to install SID %pFX: VRF %s is inactive", &sid->addr,
+ sid->attributes.vrf_name);
+ return;
+ }
+ ifp = if_get_vrf_loopback(vrf->vrf_id);
+ if (!ifp) {
+ zlog_warn("Failed to install SID %pFX: failed to get loopback for vrf %s",
+ &sid->addr, sid->attributes.vrf_name);
+ return;
+ }
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_X:
+ case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID:
+ case SRV6_ENDPOINT_BEHAVIOR_OPAQUE:
+ case SRV6_ENDPOINT_BEHAVIOR_RESERVED:
+ zlog_warn("unsupported behavior: %u", sid->behavior);
+ break;
+ }
+
+ /* The SID is attached to the SRv6 interface */
+ if (!ifp) {
+ ifp = if_lookup_by_name(DEFAULT_SRV6_IFNAME, VRF_DEFAULT);
+ if (!ifp) {
+ zlog_warn("%s interface not found: nothing to uninstall",
+ DEFAULT_SRV6_IFNAME);
+ return;
+ }
+ }
+
+ ctx.block_len = sid->locator->block_bits_length;
+ ctx.node_len = sid->locator->node_bits_length;
+ ctx.function_len = sid->locator->function_bits_length;
+ ctx.argument_len = sid->locator->argument_bits_length;
+
+ static_zebra_send_localsid(ZEBRA_ROUTE_DELETE, &sid->addr.prefix, sid->addr.prefixlen,
+ ifp->ifindex, action, &ctx);
+
+ UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
+}
+
+extern void static_zebra_request_srv6_sid(struct static_srv6_sid *sid)
+{
+ struct srv6_sid_ctx ctx = {};
+ int ret = 0;
+ struct vrf *vrf;
+
+ if (!sid)
+ return;
+
+ /* convert `srv6_endpoint_behavior_codepoint` to `seg6local_action_t` */
+ switch (sid->behavior) {
+ case SRV6_ENDPOINT_BEHAVIOR_END:
+ case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID:
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ /* process SRv6 SID attributes */
+ /* generate table ID from the VRF name, if configured */
+ if (sid->attributes.vrf_name[0] != '\0') {
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf))
+ return;
+ ctx.vrf_id = vrf->vrf_id;
+ }
+
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID:
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
+ /* process SRv6 SID attributes */
+ /* generate table ID from the VRF name, if configured */
+ if (sid->attributes.vrf_name[0] != '\0') {
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf))
+ return;
+ ctx.vrf_id = vrf->vrf_id;
+ }
+
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID:
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ /* process SRv6 SID attributes */
+ /* generate table ID from the VRF name, if configured */
+ if (sid->attributes.vrf_name[0] != '\0') {
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf))
+ return;
+ ctx.vrf_id = vrf->vrf_id;
+ }
+
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_X:
+ case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID:
+ case SRV6_ENDPOINT_BEHAVIOR_OPAQUE:
+ case SRV6_ENDPOINT_BEHAVIOR_RESERVED:
+ zlog_warn("unsupported behavior: %u", sid->behavior);
+ return;
+ }
+
+ /* Request SRv6 SID from SID Manager */
+ ret = srv6_manager_get_sid(zclient, &ctx, &sid->addr.prefix, sid->locator->name, NULL);
+ if (ret < 0)
+ zlog_warn("%s: error getting SRv6 SID!", __func__);
+}
+
+extern void static_zebra_release_srv6_sid(struct static_srv6_sid *sid)
+{
+ struct srv6_sid_ctx ctx = {};
+ struct vrf *vrf;
+ int ret = 0;
+
+ if (!sid || !CHECK_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID))
+ return;
+
+ /* convert `srv6_endpoint_behavior_codepoint` to `seg6local_action_t` */
+ switch (sid->behavior) {
+ case SRV6_ENDPOINT_BEHAVIOR_END:
+ case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID:
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ /* process SRv6 SID attributes */
+ /* generate table ID from the VRF name, if configured */
+ if (sid->attributes.vrf_name[0] != '\0') {
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf))
+ return;
+ ctx.vrf_id = vrf->vrf_id;
+ }
+
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID:
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
+ /* process SRv6 SID attributes */
+ /* generate table ID from the VRF name, if configured */
+ if (sid->attributes.vrf_name[0] != '\0') {
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf))
+ return;
+ ctx.vrf_id = vrf->vrf_id;
+ }
+
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID:
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ /* process SRv6 SID attributes */
+ /* generate table ID from the VRF name, if configured */
+ if (sid->attributes.vrf_name[0] != '\0') {
+ vrf = vrf_lookup_by_name(sid->attributes.vrf_name);
+ if (!vrf_is_enabled(vrf))
+ return;
+ ctx.vrf_id = vrf->vrf_id;
+ }
+
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_X:
+ case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID:
+ case SRV6_ENDPOINT_BEHAVIOR_OPAQUE:
+ case SRV6_ENDPOINT_BEHAVIOR_RESERVED:
+ zlog_warn("unsupported behavior: %u", sid->behavior);
+ return;
+ }
+
+ /* remove the SRv6 SID from the zebra RIB */
+ ret = srv6_manager_release_sid(zclient, &ctx);
+ if (ret == ZCLIENT_SEND_FAILURE)
+ flog_err(EC_LIB_ZAPI_SOCKET, "zclient_send_get_srv6_sid() delete failed: %s",
+ safe_strerror(errno));
+}
+
+/**
+ * Ask the SRv6 Manager (zebra) about a specific locator
+ *
+ * @param name Locator name
+ * @return 0 on success, -1 otherwise
+ */
+int static_zebra_srv6_manager_get_locator(const char *name)
+{
+ if (!name)
+ return -1;
+
+ /*
+ * Send the Get Locator request to the SRv6 Manager and return the
+ * result
+ */
+ return srv6_manager_get_locator(zclient, name);
+}
+
+static void request_srv6_sids(struct static_srv6_locator *locator)
+{
+ struct static_srv6_sid *sid;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(srv6_sids, node, sid)) {
+ if (sid->locator == locator)
+ static_zebra_request_srv6_sid(sid);
+ }
+}
+
+/**
+ * Internal function to process an SRv6 locator
+ *
+ * @param locator The locator to be processed
+ */
+static int static_zebra_process_srv6_locator_internal(struct srv6_locator *locator)
+{
+ struct static_srv6_locator *loc;
+ struct listnode *node;
+ struct static_srv6_sid *sid;
+
+ if (!locator)
+ return -1;
+
+ DEBUGD(&static_dbg_srv6,
+ "%s: Received SRv6 locator %s %pFX, loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u",
+ __func__, locator->name, &locator->prefix, locator->block_bits_length,
+ locator->node_bits_length, locator->function_bits_length,
+ locator->argument_bits_length);
+
+ /* If we are already aware about the locator, nothing to do */
+ loc = static_srv6_locator_lookup(locator->name);
+ if (loc)
+ return 0;
+
+ loc = static_srv6_locator_alloc(locator->name);
+
+ DEBUGD(&static_dbg_srv6, "%s: SRv6 locator (locator %s, prefix %pFX) set", __func__,
+ locator->name, &locator->prefix);
+
+ /* Store the locator prefix */
+ loc->prefix = locator->prefix;
+ loc->block_bits_length = locator->block_bits_length;
+ loc->node_bits_length = locator->node_bits_length;
+ loc->function_bits_length = locator->function_bits_length;
+ loc->argument_bits_length = locator->argument_bits_length;
+ loc->flags = locator->flags;
+
+ listnode_add(srv6_locators, loc);
+
+ for (ALL_LIST_ELEMENTS_RO(srv6_sids, node, sid)) {
+ if (strncmp(sid->locator_name, loc->name, sizeof(loc->name)) == 0)
+ sid->locator = loc;
+ }
+
+ /* Request SIDs from the locator */
+ request_srv6_sids(loc);
+
+ return 0;
+}
+
+/**
+ * Callback to process an SRv6 locator received from SRv6 Manager (zebra).
+ *
+ * @result 0 on success, -1 otherwise
+ */
+static int static_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
+{
+ struct srv6_locator loc = {};
+
+ if (!srv6_locators)
+ return -1;
+
+ /* Decode the SRv6 locator */
+ if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
+ return -1;
+
+ return static_zebra_process_srv6_locator_internal(&loc);
+}
+
+/**
+ * Callback to process a notification from SRv6 Manager (zebra) of an SRv6
+ * locator deleted.
+ *
+ * @result 0 on success, -1 otherwise
+ */
+static int static_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
+{
+ struct srv6_locator loc = {};
+ struct listnode *node2, *nnode2;
+ struct static_srv6_sid *sid;
+ struct static_srv6_locator *locator;
+
+ if (!srv6_locators)
+ return -1;
+
+ /* Decode the received zebra message */
+ if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
+ return -1;
+
+ DEBUGD(&static_dbg_srv6,
+ "%s: SRv6 locator deleted in zebra: name %s, prefix %pFX, block_len %u, node_len %u, func_len %u, arg_len %u",
+ __func__, loc.name, &loc.prefix, loc.block_bits_length, loc.node_bits_length,
+ loc.function_bits_length, loc.argument_bits_length);
+
+ locator = static_srv6_locator_lookup(loc.name);
+ if (!locator)
+ return 0;
+
+ DEBUGD(&static_dbg_srv6, "%s: Deleting srv6 sids from locator %s", __func__, locator->name);
+
+ /* Delete SRv6 SIDs */
+ for (ALL_LIST_ELEMENTS(srv6_sids, node2, nnode2, sid)) {
+ if (sid->locator != locator)
+ continue;
+
+
+ DEBUGD(&static_dbg_srv6, "%s: Deleting SRv6 SID (locator %s, sid %pFX)", __func__,
+ locator->name, &sid->addr);
+
+ /*
+ * Uninstall the SRv6 SID from the forwarding plane
+ * through Zebra
+ */
+ 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);
+ }
+ }
+
+ listnode_delete(srv6_locators, locator);
+ static_srv6_locator_free(locator);
+
+ return 0;
+}
+
+static int static_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
+{
+ struct srv6_sid_ctx ctx;
+ struct in6_addr sid_addr;
+ enum zapi_srv6_sid_notify note;
+ uint32_t sid_func;
+ struct listnode *node;
+ char buf[256];
+ struct static_srv6_sid *sid = NULL;
+ char *loc_name;
+ bool found = false;
+
+ if (!srv6_locators)
+ return -1;
+
+ /* Decode the received notification message */
+ if (!zapi_srv6_sid_notify_decode(zclient->ibuf, &ctx, &sid_addr, &sid_func, NULL, &note,
+ &loc_name)) {
+ zlog_err("%s : error in msg decode", __func__);
+ return -1;
+ }
+
+ DEBUGD(&static_dbg_srv6,
+ "%s: received SRv6 SID notify: ctx %s sid_value %pI6 sid_func %u note %s", __func__,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx), &sid_addr, sid_func,
+ zapi_srv6_sid_notify2str(note));
+
+ /* Handle notification */
+ switch (note) {
+ case ZAPI_SRV6_SID_ALLOCATED:
+
+ DEBUGD(&static_dbg_srv6, "%s: SRv6 SID %pI6 %s ALLOCATED", __func__, &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ for (ALL_LIST_ELEMENTS_RO(srv6_sids, node, sid)) {
+ if (IPV6_ADDR_SAME(&sid->addr.prefix, &sid_addr)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found || !sid) {
+ zlog_err("SRv6 SID %pI6 %s: not found", &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+ return 0;
+ }
+
+ SET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID);
+
+ /*
+ * Install the new SRv6 End SID in the forwarding plane through
+ * Zebra
+ */
+ static_zebra_srv6_sid_install(sid);
+
+ SET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_SENT_TO_ZEBRA);
+
+ break;
+ case ZAPI_SRV6_SID_RELEASED:
+
+ DEBUGD(&static_dbg_srv6, "%s: SRv6 SID %pI6 %s: RELEASED", __func__, &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ UNSET_FLAG(sid->flags, STATIC_FLAG_SRV6_SID_VALID);
+
+ break;
+ case ZAPI_SRV6_SID_FAIL_ALLOC:
+ zlog_err("SRv6 SID %pI6 %s: Failed to allocate", &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Error will be logged by zebra module */
+ break;
+ case ZAPI_SRV6_SID_FAIL_RELEASE:
+ zlog_err("%s: SRv6 SID %pI6 %s failure to release", __func__, &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Error will be logged by zebra module */
+ break;
+ }
+
+ return 0;
+}
+
static zclient_handler *const static_handlers[] = {
[ZEBRA_INTERFACE_ADDRESS_ADD] = interface_address_add,
[ZEBRA_INTERFACE_ADDRESS_DELETE] = interface_address_delete,
[ZEBRA_ROUTE_NOTIFY_OWNER] = route_notify_owner,
+ [ZEBRA_SRV6_LOCATOR_ADD] = static_zebra_process_srv6_locator_add,
+ [ZEBRA_SRV6_LOCATOR_DELETE] = static_zebra_process_srv6_locator_delete,
+ [ZEBRA_SRV6_SID_NOTIFY] = static_zebra_srv6_sid_notify,
};
void static_zebra_init(void)
diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h
index c4f4ebdcb..2a94c6dad 100644
--- a/staticd/static_zebra.h
+++ b/staticd/static_zebra.h
@@ -7,6 +7,8 @@
#ifndef __STATIC_ZEBRA_H__
#define __STATIC_ZEBRA_H__
+#include "static_srv6.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -22,6 +24,14 @@ extern void static_zebra_stop(void);
extern void static_zebra_vrf_register(struct vrf *vrf);
extern void static_zebra_vrf_unregister(struct vrf *vrf);
+extern int static_zebra_srv6_manager_get_locator(const char *name);
+
+extern void static_zebra_request_srv6_sid(struct static_srv6_sid *sid);
+extern void static_zebra_release_srv6_sid(struct static_srv6_sid *sid);
+
+extern void static_zebra_srv6_sid_install(struct static_srv6_sid *sid);
+extern void static_zebra_srv6_sid_uninstall(struct static_srv6_sid *sid);
+
#ifdef __cplusplus
}
#endif