summaryrefslogtreecommitdiff
path: root/isisd/isis_zebra.c
diff options
context:
space:
mode:
Diffstat (limited to 'isisd/isis_zebra.c')
-rw-r--r--isisd/isis_zebra.c585
1 files changed, 571 insertions, 14 deletions
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 59b80c1e20..2412ec5e84 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -98,6 +98,8 @@ static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS)
isis_circuit_add_addr(circuit, c);
}
+ sr_if_addr_update(c->ifp);
+
return 0;
}
@@ -125,6 +127,8 @@ static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS)
isis_circuit_del_addr(circuit, c);
}
+ sr_if_addr_update(c->ifp);
+
connected_free(&c);
return 0;
@@ -304,6 +308,9 @@ void isis_zebra_route_del_route(struct isis *isis,
if (zclient->sock < 0)
return;
+ if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
+ return;
+
memset(&api, 0, sizeof(api));
api.vrf_id = isis->vrf_id;
api.type = PROTO_TYPE;
@@ -447,7 +454,7 @@ void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra)
znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
/* Set backup nexthops. */
- if (sra->type == ISIS_SR_LAN_BACKUP) {
+ if (sra->type == ISIS_SR_ADJ_BACKUP) {
int count;
count = isis_zebra_add_nexthops(isis, sra->backup_nexthops,
@@ -498,10 +505,10 @@ static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix,
- api.distance, api.metric, api.tag);
+ api.distance, api.metric, api.tag, api.instance);
else
- isis_redist_delete(isis, api.type, &api.prefix,
- &api.src_prefix);
+ isis_redist_delete(isis, api.type, &api.prefix, &api.src_prefix,
+ api.instance);
return 0;
}
@@ -511,24 +518,26 @@ int isis_distribute_list_update(int routetype)
return 0;
}
-void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id)
+void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id,
+ uint16_t tableid)
{
if (type == DEFAULT_ROUTE)
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
zclient, afi, vrf_id);
else
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
- 0, vrf_id);
+ tableid, vrf_id);
}
-void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id)
+void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id,
+ uint16_t tableid)
{
if (type == DEFAULT_ROUTE)
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
zclient, afi, vrf_id);
else
zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
- type, 0, vrf_id);
+ type, tableid, vrf_id);
}
/**
@@ -772,9 +781,9 @@ static int isis_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
switch (info.type) {
case LINK_STATE_SYNC:
- STREAM_GETC(s, dst.proto);
- STREAM_GETW(s, dst.instance);
- STREAM_GETL(s, dst.session_id);
+ dst.proto = info.src_proto;
+ dst.instance = info.src_instance;
+ dst.session_id = info.src_session_id;
dst.type = LINK_STATE_SYNC;
ret = isis_te_sync_ted(dst);
break;
@@ -814,6 +823,551 @@ static int isis_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
return ret;
}
+/**
+ * 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 isis_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;
+ }
+
+ sr_debug(" |- %s SRv6 SID %pI6 behavior %s",
+ 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 = PROTO_TYPE;
+ 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 area IS-IS area
+ * @param sid SRv6 SID
+ */
+void isis_zebra_srv6_sid_install(struct isis_area *area,
+ struct isis_srv6_sid *sid)
+{
+ enum seg6local_action_t action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
+ uint16_t prefixlen = IPV6_MAX_BITLEN;
+ struct seg6local_context ctx = {};
+ struct interface *ifp;
+
+ if (!area || !sid)
+ return;
+
+ sr_debug("ISIS-SRv6 (%s): setting SRv6 SID %pI6", area->area_tag,
+ &sid->sid);
+
+ switch (sid->behavior) {
+ case SRV6_ENDPOINT_BEHAVIOR_END:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END;
+ prefixlen = IPV6_MAX_BITLEN;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END;
+ prefixlen = sid->locator->block_bits_length +
+ sid->locator->node_bits_length;
+ 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_X:
+ case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID:
+ case SRV6_ENDPOINT_BEHAVIOR_RESERVED:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_OPAQUE:
+ default:
+ zlog_err(
+ "ISIS-SRv6 (%s): unsupported SRv6 endpoint behavior %u",
+ area->area_tag, sid->behavior);
+ return;
+ }
+
+ /* Attach the SID to the SRv6 interface */
+ ifp = if_lookup_by_name(area->srv6db.config.srv6_ifname, VRF_DEFAULT);
+ if (!ifp) {
+ zlog_warn(
+ "Failed to install SRv6 SID %pI6: %s interface not found",
+ &sid->sid, area->srv6db.config.srv6_ifname);
+ return;
+ }
+
+ /* Send the SID to zebra */
+ isis_zebra_send_localsid(ZEBRA_ROUTE_ADD, &sid->sid, prefixlen,
+ ifp->ifindex, action, &ctx);
+}
+
+/**
+ * Uninstall SRv6 SID from the forwarding plane through Zebra.
+ *
+ * @param area IS-IS area
+ * @param sid SRv6 SID
+ */
+void isis_zebra_srv6_sid_uninstall(struct isis_area *area,
+ struct isis_srv6_sid *sid)
+{
+ enum seg6local_action_t action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
+ struct interface *ifp;
+ uint16_t prefixlen = IPV6_MAX_BITLEN;
+
+ if (!area || !sid)
+ return;
+
+ sr_debug("ISIS-SRv6 (%s): delete SID %pI6", area->area_tag, &sid->sid);
+
+ switch (sid->behavior) {
+ case SRV6_ENDPOINT_BEHAVIOR_END:
+ prefixlen = IPV6_MAX_BITLEN;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
+ prefixlen = sid->locator->block_bits_length +
+ sid->locator->node_bits_length;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_RESERVED:
+ case SRV6_ENDPOINT_BEHAVIOR_END_X:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46:
+ case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_OPAQUE:
+ default:
+ zlog_err(
+ "ISIS-SRv6 (%s): unsupported SRv6 endpoint behavior %u",
+ area->area_tag, sid->behavior);
+ return;
+ }
+
+ /* The SID is attached to the SRv6 interface */
+ ifp = if_lookup_by_name(area->srv6db.config.srv6_ifname, VRF_DEFAULT);
+ if (!ifp) {
+ zlog_warn("%s interface not found: nothing to uninstall",
+ area->srv6db.config.srv6_ifname);
+ return;
+ }
+
+ /* Send delete request to zebra */
+ isis_zebra_send_localsid(ZEBRA_ROUTE_DELETE, &sid->sid, prefixlen,
+ ifp->ifindex, action, NULL);
+}
+
+void isis_zebra_srv6_adj_sid_install(struct srv6_adjacency *sra)
+{
+ enum seg6local_action_t action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
+ struct seg6local_context ctx = {};
+ uint16_t prefixlen = IPV6_MAX_BITLEN;
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ struct isis_area *area;
+
+ if (!sra)
+ return;
+
+ circuit = sra->adj->circuit;
+ area = circuit->area;
+
+ sr_debug("ISIS-SRv6 (%s): setting adjacency SID %pI6", area->area_tag,
+ &sra->sid);
+
+ switch (sra->behavior) {
+ case SRV6_ENDPOINT_BEHAVIOR_END_X:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
+ prefixlen = IPV6_MAX_BITLEN;
+ ctx.nh6 = sra->nexthop;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID:
+ action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
+ prefixlen = sra->locator->block_bits_length +
+ sra->locator->node_bits_length +
+ sra->locator->function_bits_length;
+ ctx.nh6 = sra->nexthop;
+ SET_SRV6_FLV_OP(ctx.flv.flv_ops,
+ ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
+ ctx.flv.lcblock_len = sra->locator->block_bits_length;
+ ctx.flv.lcnode_func_len = sra->locator->node_bits_length;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_RESERVED:
+ case SRV6_ENDPOINT_BEHAVIOR_END:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46:
+ case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_OPAQUE:
+ default:
+ zlog_err(
+ "ISIS-SRv6 (%s): unsupported SRv6 endpoint behavior %u",
+ area->area_tag, sra->behavior);
+ return;
+ }
+
+ ifp = sra->adj->circuit->interface;
+
+ isis_zebra_send_localsid(ZEBRA_ROUTE_ADD, &sra->sid, prefixlen,
+ ifp->ifindex, action, &ctx);
+}
+
+void isis_zebra_srv6_adj_sid_uninstall(struct srv6_adjacency *sra)
+{
+ enum seg6local_action_t action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
+ struct interface *ifp;
+ uint16_t prefixlen = IPV6_MAX_BITLEN;
+ struct isis_circuit *circuit;
+ struct isis_area *area;
+
+ if (!sra)
+ return;
+
+ circuit = sra->adj->circuit;
+ area = circuit->area;
+
+ switch (sra->behavior) {
+ case SRV6_ENDPOINT_BEHAVIOR_END_X:
+ prefixlen = IPV6_MAX_BITLEN;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID:
+ prefixlen = sra->locator->block_bits_length +
+ sra->locator->node_bits_length +
+ sra->locator->function_bits_length;
+ break;
+ case SRV6_ENDPOINT_BEHAVIOR_RESERVED:
+ case SRV6_ENDPOINT_BEHAVIOR_END:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46:
+ case SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT6_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT4_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_END_DT46_USID:
+ case SRV6_ENDPOINT_BEHAVIOR_OPAQUE:
+ default:
+ zlog_err(
+ "ISIS-SRv6 (%s): unsupported SRv6 endpoint behavior %u",
+ area->area_tag, sra->behavior);
+ return;
+ }
+
+ ifp = sra->adj->circuit->interface;
+
+ sr_debug("ISIS-SRv6 (%s): delete End.X SID %pI6", area->area_tag,
+ &sra->sid);
+
+ isis_zebra_send_localsid(ZEBRA_ROUTE_DELETE, &sra->sid, prefixlen,
+ ifp->ifindex, action, NULL);
+}
+
+/**
+ * Callback to process an SRv6 locator chunk received from SRv6 Manager (zebra).
+ *
+ * @result 0 on success, -1 otherwise
+ */
+static int isis_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
+{
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+ struct stream *s = NULL;
+ struct listnode *node;
+ struct isis_area *area;
+ struct srv6_locator_chunk *c;
+ struct srv6_locator_chunk *chunk = srv6_locator_chunk_alloc();
+ struct isis_srv6_sid *sid;
+ struct isis_adjacency *adj;
+ enum srv6_endpoint_behavior_codepoint behavior;
+ bool allocated = false;
+
+ if (!isis) {
+ srv6_locator_chunk_free(&chunk);
+ return -1;
+ }
+
+ /* Decode the received zebra message */
+ s = zclient->ibuf;
+ if (zapi_srv6_locator_chunk_decode(s, chunk) < 0) {
+ srv6_locator_chunk_free(&chunk);
+ return -1;
+ }
+
+ sr_debug(
+ "Received SRv6 locator chunk from zebra: name %s, "
+ "prefix %pFX, block_len %u, node_len %u, func_len %u, arg_len %u",
+ chunk->locator_name, &chunk->prefix, chunk->block_bits_length,
+ chunk->node_bits_length, chunk->function_bits_length,
+ chunk->argument_bits_length);
+
+ /* Walk through all areas of the ISIS instance */
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
+ if (strncmp(area->srv6db.config.srv6_locator_name,
+ chunk->locator_name,
+ sizeof(area->srv6db.config.srv6_locator_name)) != 0)
+ continue;
+
+ for (ALL_LIST_ELEMENTS_RO(area->srv6db.srv6_locator_chunks,
+ node, c)) {
+ if (!prefix_cmp(&c->prefix, &chunk->prefix)) {
+ srv6_locator_chunk_free(&chunk);
+ return 0;
+ }
+ }
+
+ sr_debug(
+ "SRv6 locator chunk (locator %s, prefix %pFX) assigned to IS-IS area %s",
+ chunk->locator_name, &chunk->prefix, area->area_tag);
+
+ /* Add the SRv6 Locator chunk to the per-area chunks list */
+ listnode_add(area->srv6db.srv6_locator_chunks, chunk);
+
+ /* Decide which behavior to use,depending on the locator type
+ * (i.e. uSID vs classic locator) */
+ behavior = (CHECK_FLAG(chunk->flags, SRV6_LOCATOR_USID))
+ ? SRV6_ENDPOINT_BEHAVIOR_END_NEXT_CSID
+ : SRV6_ENDPOINT_BEHAVIOR_END;
+
+ /* Allocate new SRv6 End SID */
+ sid = isis_srv6_sid_alloc(area, chunk, behavior, 0);
+ if (!sid)
+ return -1;
+
+ /* Install the new SRv6 End SID in the forwarding plane through
+ * Zebra */
+ isis_zebra_srv6_sid_install(area, sid);
+
+ /* Store the SID */
+ listnode_add(area->srv6db.srv6_sids, sid);
+
+ /* Create SRv6 End.X SIDs from existing IS-IS Adjacencies */
+ for (ALL_LIST_ELEMENTS_RO(area->adjacency_list, node, adj)) {
+ if (adj->ll_ipv6_count > 0)
+ srv6_endx_sid_add(adj);
+ }
+
+ /* Regenerate LSPs to advertise the new locator and the SID */
+ lsp_regenerate_schedule(area, area->is_type, 0);
+
+ allocated = true;
+ break;
+ }
+
+ if (!allocated) {
+ sr_debug("No IS-IS area configured for the locator %s",
+ chunk->locator_name);
+ srv6_locator_chunk_free(&chunk);
+ }
+
+ return 0;
+}
+
+/**
+ * Callback to process an SRv6 locator received from SRv6 Manager (zebra).
+ *
+ * @result 0 on success, -1 otherwise
+ */
+static int isis_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
+{
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+ struct srv6_locator loc = {};
+ struct listnode *node;
+ struct isis_area *area;
+
+ if (!isis)
+ return -1;
+
+ /* Decode the SRv6 locator */
+ if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
+ return -1;
+
+ sr_debug(
+ "New SRv6 locator allocated in zebra: name %s, "
+ "prefix %pFX, block_len %u, node_len %u, func_len %u, arg_len %u",
+ loc.name, &loc.prefix, loc.block_bits_length,
+ loc.node_bits_length, loc.function_bits_length,
+ loc.argument_bits_length);
+
+ /* Lookup on the IS-IS areas */
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
+ /* If SRv6 is enabled on this area and the configured locator
+ * corresponds to the new locator, then request a chunk from the
+ * locator */
+ if (area->srv6db.config.enabled &&
+ strncmp(area->srv6db.config.srv6_locator_name, loc.name,
+ sizeof(area->srv6db.config.srv6_locator_name)) == 0) {
+ sr_debug(
+ "Sending a request to get a chunk from the SRv6 locator %s (%pFX) "
+ "for IS-IS area %s",
+ loc.name, &loc.prefix, area->area_tag);
+
+ if (isis_zebra_srv6_manager_get_locator_chunk(
+ loc.name) < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Callback to process a notification from SRv6 Manager (zebra) of an SRv6
+ * locator deleted.
+ *
+ * @result 0 on success, -1 otherwise
+ */
+static int isis_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
+{
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+ struct srv6_locator loc = {};
+ struct isis_area *area;
+ struct listnode *node, *nnode;
+ struct srv6_locator_chunk *chunk;
+ struct isis_srv6_sid *sid;
+ struct srv6_adjacency *sra;
+
+ if (!isis)
+ return -1;
+
+ /* Decode the received zebra message */
+ if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
+ return -1;
+
+ sr_debug(
+ "SRv6 locator deleted in zebra: name %s, "
+ "prefix %pFX, block_len %u, node_len %u, func_len %u, arg_len %u",
+ loc.name, &loc.prefix, loc.block_bits_length,
+ loc.node_bits_length, loc.function_bits_length,
+ loc.argument_bits_length);
+
+ /* Walk through all areas of the ISIS instance */
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
+ if (strncmp(area->srv6db.config.srv6_locator_name, loc.name,
+ sizeof(area->srv6db.config.srv6_locator_name)) != 0)
+ continue;
+
+ /* Delete SRv6 SIDs */
+ for (ALL_LIST_ELEMENTS(area->srv6db.srv6_sids, node, nnode,
+ sid)) {
+
+ sr_debug(
+ "Deleting SRv6 SID (locator %s, sid %pI6) from IS-IS area %s",
+ area->srv6db.config.srv6_locator_name,
+ &sid->sid, area->area_tag);
+
+ /* Uninstall the SRv6 SID from the forwarding plane
+ * through Zebra */
+ isis_zebra_srv6_sid_uninstall(area, sid);
+
+ listnode_delete(area->srv6db.srv6_sids, sid);
+ isis_srv6_sid_free(sid);
+ }
+
+ /* Uninstall all local Adjacency-SIDs. */
+ for (ALL_LIST_ELEMENTS(area->srv6db.srv6_endx_sids, node, nnode,
+ sra))
+ srv6_endx_sid_del(sra);
+
+ /* Free the SRv6 locator chunks */
+ for (ALL_LIST_ELEMENTS(area->srv6db.srv6_locator_chunks, node,
+ nnode, chunk)) {
+ if (prefix_match((struct prefix *)&loc.prefix,
+ (struct prefix *)&chunk->prefix)) {
+ listnode_delete(
+ area->srv6db.srv6_locator_chunks,
+ chunk);
+ srv6_locator_chunk_free(&chunk);
+ }
+ }
+
+ /* Regenerate LSPs to advertise that the locator no longer
+ * exists */
+ lsp_regenerate_schedule(area, area->is_type, 0);
+ }
+
+ return 0;
+}
+
+/**
+ * Request an SRv6 locator chunk to the SRv6 Manager (zebra) asynchronously.
+ *
+ * @param locator_name Name of SRv6 locator
+ *
+ * @result 0 on success, -1 otherwise
+ */
+int isis_zebra_srv6_manager_get_locator_chunk(const char *name)
+{
+ return srv6_manager_get_locator_chunk(zclient, name);
+}
+
+
+/**
+ * Release an SRv6 locator chunk.
+ *
+ * @param locator_name Name of SRv6 locator
+ *
+ * @result 0 on success, -1 otherwise
+ */
+int isis_zebra_srv6_manager_release_locator_chunk(const char *name)
+{
+ return srv6_manager_release_locator_chunk(zclient, name);
+}
+
static zclient_handler *const isis_handlers[] = {
[ZEBRA_ROUTER_ID_UPDATE] = isis_router_id_update_zebra,
[ZEBRA_INTERFACE_ADDRESS_ADD] = isis_zebra_if_address_add,
@@ -825,6 +1379,11 @@ static zclient_handler *const isis_handlers[] = {
[ZEBRA_OPAQUE_MESSAGE] = isis_opaque_msg_handler,
[ZEBRA_CLIENT_CLOSE_NOTIFY] = isis_zebra_client_close_notify,
+
+ [ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
+ isis_zebra_process_srv6_locator_chunk,
+ [ZEBRA_SRV6_LOCATOR_ADD] = isis_zebra_process_srv6_locator_add,
+ [ZEBRA_SRV6_LOCATOR_DELETE] = isis_zebra_process_srv6_locator_delete,
};
void isis_zebra_init(struct event_loop *master, int instance)
@@ -836,9 +1395,7 @@ void isis_zebra_init(struct event_loop *master, int instance)
zclient->zebra_connected = isis_zebra_connected;
/* Initialize special zclient for synchronous message exchanges. */
- struct zclient_options options = zclient_options_default;
- options.synchronous = true;
- zclient_sync = zclient_new(master, &options, NULL, 0);
+ zclient_sync = zclient_new(master, &zclient_options_sync, NULL, 0);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_ISIS;
zclient_sync->instance = instance;