mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 21:10:28 +00:00
isisd: Add support for SRv6 Adjacency SIDs
An SRv6 adjacency SID is a SID that is associated with a particular adjacency. Adjacency SIDs are advertised using the SRv6 End.X SID Sub-TLV (RFC 9352 section #8.1) or SRv6 LAN End.X SID Sub-TLV (RFC 9352 section #8.2). This commit defines the following Adj SIDs management functions: * srv6_endx_sid_add_single: add a new SRv6 Adjacency SID * srv6_endx_sid_del: delete an SRv6 Adjacency SID * isis_srv6_endx_sid_find: lookup SRv6 End.X SID by type It also attaches some callbacks to the hooks isis_adj_state_change_hook, isis_adj_ip_enabled_hook, isis_adj_ip_disabled_hook, which are responsible for installing/removing an SRv6 Adjacency SID automatically when the state of an IS-IS adjacency changes. Signed-off-by: Carmine Scarpitta <carmine.scarpitta@uniroma2.it>
This commit is contained in:
parent
7db1a90475
commit
ecb2675f1e
@ -98,6 +98,8 @@ struct isis_adjacency {
|
||||
struct list *adj_sids; /* Segment Routing Adj-SIDs. */
|
||||
uint32_t snmp_idx;
|
||||
struct listnode *snmp_list_node;
|
||||
|
||||
struct list *srv6_endx_sids; /* SRv6 End.X SIDs. */
|
||||
};
|
||||
|
||||
struct isis_threeway_adj;
|
||||
|
@ -11,14 +11,18 @@
|
||||
|
||||
#include "srv6.h"
|
||||
#include "termtable.h"
|
||||
#include "lib/lib_errors.h"
|
||||
|
||||
#include "isisd/isisd.h"
|
||||
#include "isisd/isis_adjacency.h"
|
||||
#include "isisd/isis_misc.h"
|
||||
#include "isisd/isis_route.h"
|
||||
#include "isisd/isis_srv6.h"
|
||||
#include "isisd/isis_zebra.h"
|
||||
|
||||
/* Local variables and functions */
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_SRV6_SID, "ISIS SRv6 Segment ID");
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_SRV6_INFO, "ISIS SRv6 information");
|
||||
|
||||
/**
|
||||
* Fill in SRv6 SID Structure Sub-Sub-TLV with information from an SRv6 SID.
|
||||
@ -97,6 +101,7 @@ bool isis_srv6_locator_unset(struct isis_area *area)
|
||||
struct listnode *node, *nnode;
|
||||
struct srv6_locator_chunk *chunk;
|
||||
struct isis_srv6_sid *sid;
|
||||
struct srv6_adjacency *sra;
|
||||
|
||||
if (strncmp(area->srv6db.config.srv6_locator_name, "",
|
||||
sizeof(area->srv6db.config.srv6_locator_name)) == 0) {
|
||||
@ -119,6 +124,10 @@ bool isis_srv6_locator_unset(struct isis_area *area)
|
||||
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);
|
||||
|
||||
/* Inform Zebra that we are releasing the SRv6 locator */
|
||||
ret = isis_zebra_srv6_manager_release_locator_chunk(
|
||||
area->srv6db.config.srv6_locator_name);
|
||||
@ -298,6 +307,296 @@ void isis_srv6_sid_free(struct isis_srv6_sid *sid)
|
||||
XFREE(MTYPE_ISIS_SRV6_SID, sid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all backup SRv6 End.X SIDs.
|
||||
*
|
||||
* @param area IS-IS area
|
||||
* @param level IS-IS level
|
||||
*/
|
||||
void isis_area_delete_backup_srv6_endx_sids(struct isis_area *area, int level)
|
||||
{
|
||||
struct srv6_adjacency *sra;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(area->srv6db.srv6_endx_sids, node, nnode, sra))
|
||||
if (sra->type == ISIS_SRV6_LAN_BACKUP &&
|
||||
(sra->adj->level & level))
|
||||
srv6_endx_sid_del(sra);
|
||||
}
|
||||
|
||||
/* --- SRv6 End.X SID management functions ------------------- */
|
||||
|
||||
/**
|
||||
* Add new local End.X SID.
|
||||
*
|
||||
* @param adj IS-IS Adjacency
|
||||
* @param backup True to initialize backup Adjacency SID
|
||||
* @param nexthops List of backup nexthops (for backup End.X SIDs only)
|
||||
*/
|
||||
void srv6_endx_sid_add_single(struct isis_adjacency *adj, bool backup,
|
||||
struct list *nexthops)
|
||||
{
|
||||
struct isis_circuit *circuit = adj->circuit;
|
||||
struct isis_area *area = circuit->area;
|
||||
struct srv6_adjacency *sra;
|
||||
struct isis_srv6_endx_sid_subtlv *adj_sid;
|
||||
struct isis_srv6_lan_endx_sid_subtlv *ladj_sid;
|
||||
struct in6_addr nexthop;
|
||||
uint8_t flags = 0;
|
||||
struct srv6_locator_chunk *chunk;
|
||||
uint32_t behavior;
|
||||
|
||||
if (!area || !area->srv6db.srv6_locator_chunks ||
|
||||
list_isempty(area->srv6db.srv6_locator_chunks))
|
||||
return;
|
||||
|
||||
sr_debug("ISIS-SRv6 (%s): Add %s End.X SID", area->area_tag,
|
||||
backup ? "Backup" : "Primary");
|
||||
|
||||
/* Determine nexthop IP address */
|
||||
if (!circuit->ipv6_router || !adj->ll_ipv6_count)
|
||||
return;
|
||||
|
||||
chunk = (struct srv6_locator_chunk *)listgetdata(
|
||||
listhead(area->srv6db.srv6_locator_chunks));
|
||||
if (!chunk)
|
||||
return;
|
||||
|
||||
nexthop = adj->ll_ipv6_addrs[0];
|
||||
|
||||
/* Prepare SRv6 End.X as per RFC9352 section #8.1 */
|
||||
if (backup)
|
||||
SET_FLAG(flags, EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG);
|
||||
|
||||
if (circuit->ext == NULL)
|
||||
circuit->ext = isis_alloc_ext_subtlvs();
|
||||
|
||||
behavior = (CHECK_FLAG(chunk->flags, SRV6_LOCATOR_USID))
|
||||
? SRV6_ENDPOINT_BEHAVIOR_END_X_NEXT_CSID
|
||||
: SRV6_ENDPOINT_BEHAVIOR_END_X;
|
||||
|
||||
sra = XCALLOC(MTYPE_ISIS_SRV6_INFO, sizeof(*sra));
|
||||
sra->type = backup ? ISIS_SRV6_LAN_BACKUP : ISIS_SRV6_ADJ_NORMAL;
|
||||
sra->behavior = behavior;
|
||||
sra->locator = chunk;
|
||||
sra->structure.loc_block_len = chunk->block_bits_length;
|
||||
sra->structure.loc_node_len = chunk->node_bits_length;
|
||||
sra->structure.func_len = chunk->function_bits_length;
|
||||
sra->structure.arg_len = chunk->argument_bits_length;
|
||||
sra->nexthop = nexthop;
|
||||
|
||||
sra->sid = srv6_locator_request_sid(area, chunk, -1);
|
||||
if (IPV6_ADDR_SAME(&sra->sid, &in6addr_any)) {
|
||||
XFREE(MTYPE_ISIS_SRV6_INFO, sra);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (circuit->circ_type) {
|
||||
/* SRv6 LAN End.X SID for Broadcast interface section #8.2 */
|
||||
case CIRCUIT_T_BROADCAST:
|
||||
ladj_sid = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*ladj_sid));
|
||||
memcpy(ladj_sid->neighbor_id, adj->sysid,
|
||||
sizeof(ladj_sid->neighbor_id));
|
||||
ladj_sid->flags = flags;
|
||||
ladj_sid->algorithm = SR_ALGORITHM_SPF;
|
||||
ladj_sid->weight = 0;
|
||||
ladj_sid->behavior = sra->behavior;
|
||||
ladj_sid->sid = sra->sid;
|
||||
ladj_sid->subsubtlvs = isis_alloc_subsubtlvs(
|
||||
ISIS_CONTEXT_SUBSUBTLV_SRV6_ENDX_SID);
|
||||
ladj_sid->subsubtlvs->srv6_sid_structure = XCALLOC(
|
||||
MTYPE_ISIS_SUBSUBTLV,
|
||||
sizeof(*ladj_sid->subsubtlvs->srv6_sid_structure));
|
||||
ladj_sid->subsubtlvs->srv6_sid_structure->loc_block_len =
|
||||
sra->structure.loc_block_len;
|
||||
ladj_sid->subsubtlvs->srv6_sid_structure->loc_node_len =
|
||||
sra->structure.loc_node_len;
|
||||
ladj_sid->subsubtlvs->srv6_sid_structure->func_len =
|
||||
sra->structure.func_len;
|
||||
ladj_sid->subsubtlvs->srv6_sid_structure->arg_len =
|
||||
sra->structure.arg_len;
|
||||
isis_tlvs_add_srv6_lan_endx_sid(circuit->ext, ladj_sid);
|
||||
sra->u.lendx_sid = ladj_sid;
|
||||
break;
|
||||
/* SRv6 End.X SID for Point to Point interface section #8.1 */
|
||||
case CIRCUIT_T_P2P:
|
||||
adj_sid = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*adj_sid));
|
||||
adj_sid->flags = flags;
|
||||
adj_sid->algorithm = SR_ALGORITHM_SPF;
|
||||
adj_sid->weight = 0;
|
||||
adj_sid->behavior = sra->behavior;
|
||||
adj_sid->sid = sra->sid;
|
||||
adj_sid->subsubtlvs = isis_alloc_subsubtlvs(
|
||||
ISIS_CONTEXT_SUBSUBTLV_SRV6_ENDX_SID);
|
||||
adj_sid->subsubtlvs->srv6_sid_structure = XCALLOC(
|
||||
MTYPE_ISIS_SUBSUBTLV,
|
||||
sizeof(*adj_sid->subsubtlvs->srv6_sid_structure));
|
||||
adj_sid->subsubtlvs->srv6_sid_structure->loc_block_len =
|
||||
sra->structure.loc_block_len;
|
||||
adj_sid->subsubtlvs->srv6_sid_structure->loc_node_len =
|
||||
sra->structure.loc_node_len;
|
||||
adj_sid->subsubtlvs->srv6_sid_structure->func_len =
|
||||
sra->structure.func_len;
|
||||
adj_sid->subsubtlvs->srv6_sid_structure->arg_len =
|
||||
sra->structure.arg_len;
|
||||
isis_tlvs_add_srv6_endx_sid(circuit->ext, adj_sid);
|
||||
sra->u.endx_sid = adj_sid;
|
||||
break;
|
||||
default:
|
||||
flog_err(EC_LIB_DEVELOPMENT, "%s: unexpected circuit type: %u",
|
||||
__func__, circuit->circ_type);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Add Adjacency-SID in SRDB */
|
||||
sra->adj = adj;
|
||||
listnode_add(area->srv6db.srv6_endx_sids, sra);
|
||||
listnode_add(adj->srv6_endx_sids, sra);
|
||||
|
||||
isis_zebra_srv6_adj_sid_install(sra);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Primary and Backup local SRv6 End.X SID.
|
||||
*
|
||||
* @param adj IS-IS Adjacency
|
||||
*/
|
||||
void srv6_endx_sid_add(struct isis_adjacency *adj)
|
||||
{
|
||||
srv6_endx_sid_add_single(adj, false, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete local SRv6 End.X SID.
|
||||
*
|
||||
* @param sra SRv6 Adjacency
|
||||
*/
|
||||
void srv6_endx_sid_del(struct srv6_adjacency *sra)
|
||||
{
|
||||
struct isis_circuit *circuit = sra->adj->circuit;
|
||||
struct isis_area *area = circuit->area;
|
||||
|
||||
sr_debug("ISIS-SRv6 (%s): Delete SRv6 End.X SID", area->area_tag);
|
||||
|
||||
isis_zebra_srv6_adj_sid_uninstall(sra);
|
||||
|
||||
/* Release dynamic SRv6 SID and remove subTLVs */
|
||||
switch (circuit->circ_type) {
|
||||
case CIRCUIT_T_BROADCAST:
|
||||
isis_tlvs_del_srv6_lan_endx_sid(circuit->ext, sra->u.lendx_sid);
|
||||
break;
|
||||
case CIRCUIT_T_P2P:
|
||||
isis_tlvs_del_srv6_endx_sid(circuit->ext, sra->u.endx_sid);
|
||||
break;
|
||||
default:
|
||||
flog_err(EC_LIB_DEVELOPMENT, "%s: unexpected circuit type: %u",
|
||||
__func__, circuit->circ_type);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sra->type == ISIS_SRV6_LAN_BACKUP && sra->backup_nexthops) {
|
||||
sra->backup_nexthops->del =
|
||||
(void (*)(void *))isis_nexthop_delete;
|
||||
list_delete(&sra->backup_nexthops);
|
||||
}
|
||||
|
||||
/* Remove Adjacency-SID from the SRDB */
|
||||
listnode_delete(area->srv6db.srv6_endx_sids, sra);
|
||||
listnode_delete(sra->adj->srv6_endx_sids, sra);
|
||||
XFREE(MTYPE_ISIS_SRV6_INFO, sra);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup SRv6 End.X SID by type.
|
||||
*
|
||||
* @param adj IS-IS Adjacency
|
||||
* @param type SRv6 End.X SID type
|
||||
*/
|
||||
struct srv6_adjacency *isis_srv6_endx_sid_find(struct isis_adjacency *adj,
|
||||
enum srv6_adj_type type)
|
||||
{
|
||||
struct srv6_adjacency *sra;
|
||||
struct listnode *node;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(adj->srv6_endx_sids, node, sra))
|
||||
if (sra->type == type)
|
||||
return sra;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all SRv6 End.X SIDs associated to an adjacency that is going down.
|
||||
*
|
||||
* @param adj IS-IS Adjacency
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
static int srv6_adj_state_change(struct isis_adjacency *adj)
|
||||
{
|
||||
struct srv6_adjacency *sra;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
if (!adj->circuit->area->srv6db.config.enabled)
|
||||
return 0;
|
||||
|
||||
if (adj->adj_state == ISIS_ADJ_UP)
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(adj->srv6_endx_sids, node, nnode, sra))
|
||||
srv6_endx_sid_del(sra);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* When IS-IS Adjacency got one or more IPv6 addresses, add new
|
||||
* IPv6 address to corresponding SRv6 End.X SID accordingly.
|
||||
*
|
||||
* @param adj IS-IS Adjacency
|
||||
* @param family Inet Family (IPv4 or IPv6)
|
||||
* @param global Indicate if it concerns the Local or Global IPv6 addresses
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
static int srv6_adj_ip_enabled(struct isis_adjacency *adj, int family,
|
||||
bool global)
|
||||
{
|
||||
if (!adj->circuit->area->srv6db.config.enabled || global ||
|
||||
family != AF_INET6)
|
||||
return 0;
|
||||
|
||||
srv6_endx_sid_add(adj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* When IS-IS Adjacency doesn't have any IPv6 addresses anymore,
|
||||
* delete the corresponding SRv6 End.X SID(s) accordingly.
|
||||
*
|
||||
* @param adj IS-IS Adjacency
|
||||
* @param family Inet Family (IPv4 or IPv6)
|
||||
* @param global Indicate if it concerns the Local or Global IPv6 addresses
|
||||
*
|
||||
* @return 0
|
||||
*/
|
||||
static int srv6_adj_ip_disabled(struct isis_adjacency *adj, int family,
|
||||
bool global)
|
||||
{
|
||||
struct srv6_adjacency *sra;
|
||||
struct listnode *node, *nnode;
|
||||
|
||||
if (!adj->circuit->area->srv6db.config.enabled || global ||
|
||||
family != AF_INET6)
|
||||
return 0;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(adj->srv6_endx_sids, node, nnode, sra))
|
||||
srv6_endx_sid_del(sra);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Segment Routing over IPv6 (SRv6) Node.
|
||||
*
|
||||
@ -444,6 +743,11 @@ void isis_srv6_area_term(struct isis_area *area)
|
||||
void isis_srv6_init(void)
|
||||
{
|
||||
install_element(VIEW_NODE, &show_srv6_node_cmd);
|
||||
|
||||
/* Register hooks. */
|
||||
hook_register(isis_adj_state_change_hook, srv6_adj_state_change);
|
||||
hook_register(isis_adj_ip_enabled_hook, srv6_adj_ip_enabled);
|
||||
hook_register(isis_adj_ip_disabled_hook, srv6_adj_ip_disabled);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -451,4 +755,8 @@ void isis_srv6_init(void)
|
||||
*/
|
||||
void isis_srv6_term(void)
|
||||
{
|
||||
/* Unregister hooks. */
|
||||
hook_unregister(isis_adj_state_change_hook, srv6_adj_state_change);
|
||||
hook_unregister(isis_adj_ip_enabled_hook, srv6_adj_ip_enabled);
|
||||
hook_unregister(isis_adj_ip_disabled_hook, srv6_adj_ip_disabled);
|
||||
}
|
||||
|
@ -120,6 +120,9 @@ struct isis_srv6_db {
|
||||
/* List of SRv6 SIDs allocated by the IS-IS instance */
|
||||
struct list *srv6_sids;
|
||||
|
||||
/* List of SRv6 End.X SIDs allocated by the IS-IS instance */
|
||||
struct list *srv6_endx_sids;
|
||||
|
||||
/* Area SRv6 configuration. */
|
||||
struct {
|
||||
/* Administrative status of SRv6 */
|
||||
@ -164,4 +167,12 @@ void isis_srv6_end_sid2subtlv(const struct isis_srv6_sid *sid,
|
||||
void isis_srv6_locator2tlv(const struct isis_srv6_locator *loc,
|
||||
struct isis_srv6_locator_tlv *loc_tlv);
|
||||
|
||||
void srv6_endx_sid_add_single(struct isis_adjacency *adj, bool backup,
|
||||
struct list *nexthops);
|
||||
void srv6_endx_sid_add(struct isis_adjacency *adj);
|
||||
void srv6_endx_sid_del(struct srv6_adjacency *sra);
|
||||
struct srv6_adjacency *isis_srv6_endx_sid_find(struct isis_adjacency *adj,
|
||||
enum srv6_adj_type type);
|
||||
void isis_area_delete_backup_srv6_endx_sids(struct isis_area *area, int level);
|
||||
|
||||
#endif /* _FRR_ISIS_SRV6_H */
|
||||
|
@ -7913,6 +7913,44 @@ void isis_tlvs_del_lan_adj_sid(struct isis_ext_subtlvs *exts,
|
||||
UNSET_SUBTLV(exts, EXT_LAN_ADJ_SID);
|
||||
}
|
||||
|
||||
/* Add IS-IS SRv6 End.X SID subTLVs */
|
||||
void isis_tlvs_add_srv6_endx_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_srv6_endx_sid_subtlv *adj)
|
||||
{
|
||||
append_item(&exts->srv6_endx_sid, (struct isis_item *)adj);
|
||||
SET_SUBTLV(exts, EXT_SRV6_ENDX_SID);
|
||||
}
|
||||
|
||||
/* Delete IS-IS SRv6 End.X SID subTLVs */
|
||||
void isis_tlvs_del_srv6_endx_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_srv6_endx_sid_subtlv *adj)
|
||||
{
|
||||
isis_free_subsubtlvs(adj->subsubtlvs);
|
||||
delete_item(&exts->srv6_endx_sid, (struct isis_item *)adj);
|
||||
XFREE(MTYPE_ISIS_SUBTLV, adj);
|
||||
if (exts->srv6_endx_sid.count == 0)
|
||||
UNSET_SUBTLV(exts, EXT_SRV6_ENDX_SID);
|
||||
}
|
||||
|
||||
/* Add IS-IS SRv6 LAN End.X SID subTLVs */
|
||||
void isis_tlvs_add_srv6_lan_endx_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_srv6_lan_endx_sid_subtlv *lan)
|
||||
{
|
||||
append_item(&exts->srv6_lan_endx_sid, (struct isis_item *)lan);
|
||||
SET_SUBTLV(exts, EXT_SRV6_LAN_ENDX_SID);
|
||||
}
|
||||
|
||||
/* Delete IS-IS SRv6 LAN End.X SID subTLVs */
|
||||
void isis_tlvs_del_srv6_lan_endx_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_srv6_lan_endx_sid_subtlv *lan)
|
||||
{
|
||||
isis_free_subsubtlvs(lan->subsubtlvs);
|
||||
delete_item(&exts->srv6_lan_endx_sid, (struct isis_item *)lan);
|
||||
XFREE(MTYPE_ISIS_SUBTLV, lan);
|
||||
if (exts->srv6_lan_endx_sid.count == 0)
|
||||
UNSET_SUBTLV(exts, EXT_SRV6_LAN_ENDX_SID);
|
||||
}
|
||||
|
||||
void isis_tlvs_del_asla_flex_algo(struct isis_ext_subtlvs *ext,
|
||||
struct isis_asla_subtlvs *asla)
|
||||
{
|
||||
|
@ -891,4 +891,13 @@ void isis_subtlvs_add_srv6_end_sid(struct isis_subtlvs *subtlvs,
|
||||
struct isis_srv6_sid *sid);
|
||||
void isis_tlvs_add_srv6_locator(struct isis_tlvs *tlvs, uint16_t mtid,
|
||||
struct isis_srv6_locator *loc);
|
||||
|
||||
void isis_tlvs_add_srv6_endx_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_srv6_endx_sid_subtlv *adj);
|
||||
void isis_tlvs_del_srv6_endx_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_srv6_endx_sid_subtlv *adj);
|
||||
void isis_tlvs_add_srv6_lan_endx_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_srv6_lan_endx_sid_subtlv *lan);
|
||||
void isis_tlvs_del_srv6_lan_endx_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_srv6_lan_endx_sid_subtlv *lan);
|
||||
#endif
|
||||
|
@ -1126,6 +1126,7 @@ static int isis_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
|
||||
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;
|
||||
|
||||
@ -1181,6 +1182,12 @@ static int isis_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
|
||||
/* 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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user