mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:53:55 +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. */
|
struct list *adj_sids; /* Segment Routing Adj-SIDs. */
|
||||||
uint32_t snmp_idx;
|
uint32_t snmp_idx;
|
||||||
struct listnode *snmp_list_node;
|
struct listnode *snmp_list_node;
|
||||||
|
|
||||||
|
struct list *srv6_endx_sids; /* SRv6 End.X SIDs. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct isis_threeway_adj;
|
struct isis_threeway_adj;
|
||||||
|
@ -11,14 +11,18 @@
|
|||||||
|
|
||||||
#include "srv6.h"
|
#include "srv6.h"
|
||||||
#include "termtable.h"
|
#include "termtable.h"
|
||||||
|
#include "lib/lib_errors.h"
|
||||||
|
|
||||||
#include "isisd/isisd.h"
|
#include "isisd/isisd.h"
|
||||||
|
#include "isisd/isis_adjacency.h"
|
||||||
#include "isisd/isis_misc.h"
|
#include "isisd/isis_misc.h"
|
||||||
|
#include "isisd/isis_route.h"
|
||||||
#include "isisd/isis_srv6.h"
|
#include "isisd/isis_srv6.h"
|
||||||
#include "isisd/isis_zebra.h"
|
#include "isisd/isis_zebra.h"
|
||||||
|
|
||||||
/* Local variables and functions */
|
/* Local variables and functions */
|
||||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_SRV6_SID, "ISIS SRv6 Segment ID");
|
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.
|
* 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 listnode *node, *nnode;
|
||||||
struct srv6_locator_chunk *chunk;
|
struct srv6_locator_chunk *chunk;
|
||||||
struct isis_srv6_sid *sid;
|
struct isis_srv6_sid *sid;
|
||||||
|
struct srv6_adjacency *sra;
|
||||||
|
|
||||||
if (strncmp(area->srv6db.config.srv6_locator_name, "",
|
if (strncmp(area->srv6db.config.srv6_locator_name, "",
|
||||||
sizeof(area->srv6db.config.srv6_locator_name)) == 0) {
|
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);
|
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 */
|
/* Inform Zebra that we are releasing the SRv6 locator */
|
||||||
ret = isis_zebra_srv6_manager_release_locator_chunk(
|
ret = isis_zebra_srv6_manager_release_locator_chunk(
|
||||||
area->srv6db.config.srv6_locator_name);
|
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);
|
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.
|
* 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)
|
void isis_srv6_init(void)
|
||||||
{
|
{
|
||||||
install_element(VIEW_NODE, &show_srv6_node_cmd);
|
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)
|
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 */
|
/* List of SRv6 SIDs allocated by the IS-IS instance */
|
||||||
struct list *srv6_sids;
|
struct list *srv6_sids;
|
||||||
|
|
||||||
|
/* List of SRv6 End.X SIDs allocated by the IS-IS instance */
|
||||||
|
struct list *srv6_endx_sids;
|
||||||
|
|
||||||
/* Area SRv6 configuration. */
|
/* Area SRv6 configuration. */
|
||||||
struct {
|
struct {
|
||||||
/* Administrative status of SRv6 */
|
/* 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,
|
void isis_srv6_locator2tlv(const struct isis_srv6_locator *loc,
|
||||||
struct isis_srv6_locator_tlv *loc_tlv);
|
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 */
|
#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);
|
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,
|
void isis_tlvs_del_asla_flex_algo(struct isis_ext_subtlvs *ext,
|
||||||
struct isis_asla_subtlvs *asla)
|
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);
|
struct isis_srv6_sid *sid);
|
||||||
void isis_tlvs_add_srv6_locator(struct isis_tlvs *tlvs, uint16_t mtid,
|
void isis_tlvs_add_srv6_locator(struct isis_tlvs *tlvs, uint16_t mtid,
|
||||||
struct isis_srv6_locator *loc);
|
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
|
#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 *c;
|
||||||
struct srv6_locator_chunk *chunk = srv6_locator_chunk_alloc();
|
struct srv6_locator_chunk *chunk = srv6_locator_chunk_alloc();
|
||||||
struct isis_srv6_sid *sid;
|
struct isis_srv6_sid *sid;
|
||||||
|
struct isis_adjacency *adj;
|
||||||
enum srv6_endpoint_behavior_codepoint behavior;
|
enum srv6_endpoint_behavior_codepoint behavior;
|
||||||
bool allocated = false;
|
bool allocated = false;
|
||||||
|
|
||||||
@ -1181,6 +1182,12 @@ static int isis_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
|
|||||||
/* Store the SID */
|
/* Store the SID */
|
||||||
listnode_add(area->srv6db.srv6_sids, 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 */
|
/* Regenerate LSPs to advertise the new locator and the SID */
|
||||||
lsp_regenerate_schedule(area, area->is_type, 0);
|
lsp_regenerate_schedule(area, area->is_type, 0);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user