diff options
author | Yuqing Zhao <galadriel.zyq@alibaba-inc.com> | 2025-01-13 11:03:48 +0100 |
---|---|---|
committer | Yuqing Zhao <galadriel.zyq@alibaba-inc.com> | 2025-01-18 11:28:49 +0100 |
commit | e80f24df7e4c47924f274749b14143b894df7d3b (patch) | |
tree | 9384314979fba757f28ef24bde6abdae50fb908f /staticd | |
parent | lib, isisd: Move DEFAULT_SRV6_IFNAME to global srv6.h header (diff) | |
download | frr-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.c | 653 | ||||
-rw-r--r-- | staticd/static_zebra.h | 10 |
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, ¬e, + &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 |