mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-01-25 16:51:15 +00:00
ospfd: Add Segment Routing Local Block
RFC 8665 defines a Segment Routing Local Block for Adjacency SID. This patch provides the possibility to modify the SRLB as well as reserved the block range from the Label Manager. - Introduce new CLI 'segment-routing local-block' - Add local block to SRDB structure - Parse / Serialize SRLB in Router Information LSA - Update OSPF-SR topotest - Update documentation Signed-off-by: Olivier Dugeon <olivier.dugeon@orange.com>
This commit is contained in:
parent
d81b8e0e1a
commit
6f751f1493
@ -1,8 +1,7 @@
|
||||
OSPF Segment Routing
|
||||
====================
|
||||
|
||||
This is an EXPERIMENTAL support of draft
|
||||
`draft-ietf-ospf-segment-routing-extensions-24`.
|
||||
This is an EXPERIMENTAL support of `RFC 8665`.
|
||||
DON'T use it for production network.
|
||||
|
||||
Supported Features
|
||||
@ -10,12 +9,13 @@ Supported Features
|
||||
|
||||
* Automatic computation of Primary and Backup Adjacency SID with
|
||||
Cisco experimental remote IP address
|
||||
* SRGB configuration
|
||||
* SRGB & SRLB configuration
|
||||
* Prefix configuration for Node SID with optional NO-PHP flag (Linux
|
||||
kernel support both mode)
|
||||
* Node MSD configuration (with Linux Kernel >= 4.10 a maximum of 32 labels
|
||||
could be stack)
|
||||
* Automatic provisioning of MPLS table
|
||||
* Equal Cost Multi-Path (ECMP)
|
||||
* Static route configuration with label stack up to 32 labels
|
||||
|
||||
Interoperability
|
||||
@ -243,16 +243,16 @@ Routing.
|
||||
router ospf
|
||||
ospf router-id 192.168.1.11
|
||||
capability opaque
|
||||
mpls-te on
|
||||
mpls-te router-address 192.168.1.11
|
||||
router-info area 0.0.0.0
|
||||
segment-routing on
|
||||
segment-routing global-block 10000 19999
|
||||
segment-routing local-block 5000 5999
|
||||
segment-routing node-msd 8
|
||||
segment-routing prefix 192.168.1.11/32 index 1100
|
||||
|
||||
The first segment-routing statement enable it. The Second one set the SRGB,
|
||||
third line the MSD and finally, set the Prefix SID index for a given prefix.
|
||||
The first segment-routing statement enables it. The second and third one set
|
||||
the SRGB and SRLB respectively, fourth line the MSD and finally, set the
|
||||
Prefix SID index for a given prefix.
|
||||
|
||||
Note that only prefix of Loopback interface could be configured with a Prefix
|
||||
SID. It is possible to add `no-php-flag` at the end of the prefix command to
|
||||
disable Penultimate Hop Popping. This advertises to peers that they MUST NOT pop
|
||||
@ -265,9 +265,6 @@ Known limitations
|
||||
* Only single Area is supported. ABR is not yet supported
|
||||
* Only SPF algorithm is supported
|
||||
* Extended Prefix Range is not supported
|
||||
* MPLS table are not flush at startup. Thus, restarting zebra process is
|
||||
mandatory to remove old MPLS entries in the data plane after a crash of
|
||||
ospfd daemon
|
||||
* With NO Penultimate Hop Popping, it is not possible to express a Segment
|
||||
Path with an Adjacency SID due to the impossibility for the Linux Kernel to
|
||||
perform double POP instruction.
|
||||
|
||||
@ -1071,8 +1071,8 @@ Router Information
|
||||
Segment Routing
|
||||
===============
|
||||
|
||||
This is an EXPERIMENTAL support of Segment Routing as per draft
|
||||
`draft-ietf-ospf-segment-routing-extensions-24.txt` for MPLS dataplane.
|
||||
This is an EXPERIMENTAL support of Segment Routing as per `RFC 8665` for MPLS
|
||||
dataplane.
|
||||
|
||||
.. index:: [no] segment-routing on
|
||||
.. clicmd:: [no] segment-routing on
|
||||
@ -1085,7 +1085,13 @@ This is an EXPERIMENTAL support of Segment Routing as per draft
|
||||
.. clicmd:: [no] segment-routing global-block (0-1048575) (0-1048575)
|
||||
|
||||
Fix the Segment Routing Global Block i.e. the label range used by MPLS to
|
||||
store label in the MPLS FIB.
|
||||
store label in the MPLS FIB for Prefix SID.
|
||||
|
||||
.. index:: [no] segment-routing local-block (0-1048575) (0-1048575)
|
||||
.. clicmd:: [no] segment-routing local-block (0-1048575) (0-1048575)
|
||||
|
||||
Fix the Segment Routing Local Block i.e. the label range used by MPLS to
|
||||
store label in the MPLS FIB for Adjacency SID.
|
||||
|
||||
.. index:: [no] segment-routing node-msd (1-16)
|
||||
.. clicmd:: [no] segment-routing node-msd (1-16)
|
||||
|
||||
@ -157,6 +157,12 @@ static struct log_ref ferr_ospf_err[] = {
|
||||
.description = "OSPF Segment Routing invalid lsa id",
|
||||
.suggestion = "Restart OSPF instance, If the problem persists, report the problem for troubleshooting"
|
||||
},
|
||||
{
|
||||
.code = EC_OSPF_SR_SID_OVERFLOW,
|
||||
.title = "OSPF SR Segment-ID overflow",
|
||||
.description = "OSPF Segment Routing ID index or label exceed Global or Local Block Range",
|
||||
.suggestion = "Restart OSPF instance, If the problem persists, report the problem for troubleshooting"
|
||||
},
|
||||
{
|
||||
.code = EC_OSPF_INVALID_ALGORITHM,
|
||||
.title = "OSPF SR Invalid Algorithm",
|
||||
|
||||
@ -31,6 +31,7 @@ enum ospf_log_refs {
|
||||
EC_OSPF_SR_INVALID_DB,
|
||||
EC_OSPF_SR_NODE_CREATE,
|
||||
EC_OSPF_SR_INVALID_LSA_ID,
|
||||
EC_OSPF_SR_SID_OVERFLOW,
|
||||
EC_OSPF_INVALID_ALGORITHM,
|
||||
EC_OSPF_FSM_INVALID_STATE,
|
||||
EC_OSPF_SET_METRIC_PLUS,
|
||||
|
||||
165
ospfd/ospf_ext.c
165
ospfd/ospf_ext.c
@ -98,6 +98,7 @@ static void ospf_ext_link_lsa_schedule(struct ext_itf *exti,
|
||||
static void ospf_ext_lsa_schedule(struct ext_itf *exti, enum lsa_opcode op);
|
||||
static int ospf_ext_link_lsa_update(struct ospf_lsa *lsa);
|
||||
static int ospf_ext_pref_lsa_update(struct ospf_lsa *lsa);
|
||||
static void ospf_ext_link_delete_adj_sid(struct ext_itf *exti);
|
||||
static void del_ext_info(void *val);
|
||||
|
||||
/*
|
||||
@ -434,6 +435,20 @@ static void set_lan_adj_sid(struct ext_itf *exti, bool backup, uint32_t value,
|
||||
exti->lan_sid[index].neighbor_id = neighbor_id;
|
||||
}
|
||||
|
||||
static void unset_adjacency_sid(struct ext_itf *exti)
|
||||
{
|
||||
/* Reset Adjacency TLV */
|
||||
if (exti->type == ADJ_SID) {
|
||||
TLV_TYPE(exti->adj_sid[0]) = 0;
|
||||
TLV_TYPE(exti->adj_sid[1]) = 0;
|
||||
}
|
||||
/* or Lan-Adjacency TLV */
|
||||
if (exti->type == LAN_ADJ_SID) {
|
||||
TLV_TYPE(exti->lan_sid[0]) = 0;
|
||||
TLV_TYPE(exti->lan_sid[1]) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Experimental SubTLV from Cisco */
|
||||
static void set_rmt_itf_addr(struct ext_itf *exti, struct in_addr rmtif)
|
||||
{
|
||||
@ -452,7 +467,7 @@ static void ospf_extended_lsa_delete(struct ext_itf *exti)
|
||||
return;
|
||||
|
||||
osr_debug("EXT (%s): Disable %s%s%s-SID on interface %s", __func__,
|
||||
exti->stype == PREF_SID ? "Prefix" : "",
|
||||
exti->stype == LOCAL_SID ? "Prefix" : "",
|
||||
exti->stype == ADJ_SID ? "Adjacency" : "",
|
||||
exti->stype == LAN_ADJ_SID ? "LAN-Adjacency" : "",
|
||||
exti->ifp->name);
|
||||
@ -465,8 +480,10 @@ static void ospf_extended_lsa_delete(struct ext_itf *exti)
|
||||
|
||||
/* De-activate this Extended Prefix/Link and remove corresponding
|
||||
* Segment-Routing Prefix-SID or (LAN)-ADJ-SID */
|
||||
exti->flags = EXT_LPFLG_LSA_INACTIVE;
|
||||
ospf_sr_ext_itf_delete(exti);
|
||||
if (exti->stype == ADJ_SID || exti->stype == LAN_ADJ_SID)
|
||||
ospf_ext_link_delete_adj_sid(exti);
|
||||
else
|
||||
ospf_sr_ext_itf_delete(exti);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -521,6 +538,97 @@ uint32_t ospf_ext_schedule_prefix_index(struct interface *ifp, uint32_t index,
|
||||
return SET_OPAQUE_LSID(exti->type, exti->instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Adjacecny-SID for Extended Link LSA
|
||||
*
|
||||
* @param exti Extended Link information
|
||||
*/
|
||||
static void ospf_ext_link_update_adj_sid(struct ext_itf *exti)
|
||||
{
|
||||
mpls_label_t label;
|
||||
mpls_label_t bck_label;
|
||||
|
||||
/* Process only (LAN)Adjacency-SID Type */
|
||||
if (exti->stype != ADJ_SID && exti->stype != LAN_ADJ_SID)
|
||||
return;
|
||||
|
||||
/* Request Primary & Backup Labels from Label Manager */
|
||||
bck_label = ospf_sr_local_block_request_label();
|
||||
label = ospf_sr_local_block_request_label();
|
||||
if (bck_label == MPLS_INVALID_LABEL || label == MPLS_INVALID_LABEL) {
|
||||
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
|
||||
ospf_ext_lsa_schedule(exti, FLUSH_THIS_LSA);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set Adjacency-SID, backup first */
|
||||
if (exti->stype == ADJ_SID) {
|
||||
set_adj_sid(exti, true, bck_label, SID_LABEL);
|
||||
set_adj_sid(exti, false, label, SID_LABEL);
|
||||
} else {
|
||||
set_lan_adj_sid(exti, true, bck_label, SID_LABEL,
|
||||
exti->lan_sid[0].neighbor_id);
|
||||
set_lan_adj_sid(exti, false, label, SID_LABEL,
|
||||
exti->lan_sid[1].neighbor_id);
|
||||
}
|
||||
|
||||
/* Finally, add corresponding SR Link in SRDB & MPLS LFIB */
|
||||
SET_FLAG(exti->flags, EXT_LPFLG_FIB_ENTRY_SET);
|
||||
ospf_sr_ext_itf_add(exti);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Adjacecny-SID for Extended Link LSA
|
||||
*
|
||||
* @param exti Extended Link information
|
||||
*/
|
||||
static void ospf_ext_link_delete_adj_sid(struct ext_itf *exti)
|
||||
{
|
||||
/* Process only (LAN)Adjacency-SID Type */
|
||||
if (exti->stype != ADJ_SID && exti->stype != LAN_ADJ_SID)
|
||||
return;
|
||||
|
||||
/* Release Primary & Backup Labels from Label Manager */
|
||||
if (exti->stype == ADJ_SID) {
|
||||
ospf_sr_local_block_release_label(exti->adj_sid[0].value);
|
||||
ospf_sr_local_block_release_label(exti->adj_sid[1].value);
|
||||
} else {
|
||||
ospf_sr_local_block_release_label(exti->adj_sid[0].value);
|
||||
ospf_sr_local_block_release_label(exti->adj_sid[1].value);
|
||||
}
|
||||
/* And reset corresponding TLV */
|
||||
unset_adjacency_sid(exti);
|
||||
|
||||
/* Finally, remove corresponding SR Link in SRDB & MPLS LFIB */
|
||||
UNSET_FLAG(exti->flags, EXT_LPFLG_FIB_ENTRY_SET);
|
||||
ospf_sr_ext_itf_delete(exti);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Extended Link LSA once Segment Routing Label Block has been changed.
|
||||
*/
|
||||
void ospf_ext_link_srlb_update(void)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct ext_itf *exti;
|
||||
|
||||
|
||||
osr_debug("EXT (%s): Update Extended Links with new SRLB", __func__);
|
||||
|
||||
/* Update all Extended Link Adjaceny-SID */
|
||||
for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
|
||||
/* Skip Extended Prefix */
|
||||
if (exti->stype == PREF_SID || exti->stype == LOCAL_SID)
|
||||
continue;
|
||||
|
||||
/* Skip inactive Extended Link */
|
||||
if (!CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE))
|
||||
continue;
|
||||
|
||||
ospf_ext_link_update_adj_sid(exti);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by Segment Routing to activate/deactivate Extended Link/Prefix flooding
|
||||
*
|
||||
@ -541,10 +649,15 @@ void ospf_ext_update_sr(bool enable)
|
||||
|
||||
/* Refresh LSAs if already engaged or originate */
|
||||
for (ALL_LIST_ELEMENTS_RO(OspfEXT.iflist, node, exti)) {
|
||||
/* Skip inactive Extended Link */
|
||||
/* Skip Inactive Extended Link */
|
||||
if (!CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE))
|
||||
continue;
|
||||
|
||||
/* Update Extended Link (LAN)Adj-SID if not set */
|
||||
if (!CHECK_FLAG(exti->flags, EXT_LPFLG_FIB_ENTRY_SET))
|
||||
ospf_ext_link_update_adj_sid(exti);
|
||||
|
||||
/* Finally, flood the extended Link */
|
||||
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
|
||||
ospf_ext_lsa_schedule(exti, REFRESH_THIS_LSA);
|
||||
else
|
||||
@ -684,7 +797,6 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status)
|
||||
{
|
||||
struct ospf_interface *oi = nbr->oi;
|
||||
struct ext_itf *exti;
|
||||
uint32_t label;
|
||||
|
||||
/* Process Link only when neighbor old or new state is NSM Full */
|
||||
if (nbr->state != NSM_Full && old_status != NSM_Full)
|
||||
@ -709,7 +821,10 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status)
|
||||
|
||||
/* Remove Extended Link if Neighbor State goes Down or Deleted */
|
||||
if (nbr->state == NSM_Down || nbr->state == NSM_Deleted) {
|
||||
ospf_extended_lsa_delete(exti);
|
||||
ospf_ext_link_delete_adj_sid(exti);
|
||||
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
|
||||
ospf_ext_link_lsa_schedule(exti, FLUSH_THIS_LSA);
|
||||
exti->flags = EXT_LPFLG_LSA_INACTIVE;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -729,11 +844,6 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status)
|
||||
set_ext_link(exti, OSPF_IFTYPE_POINTOPOINT, nbr->router_id,
|
||||
oi->address->u.prefix4);
|
||||
|
||||
/* Set Extended Link Adjacency SubTLVs, backup first */
|
||||
label = get_ext_link_label_value();
|
||||
set_adj_sid(exti, true, label, SID_LABEL);
|
||||
label = get_ext_link_label_value();
|
||||
set_adj_sid(exti, false, label, SID_LABEL);
|
||||
/* And Remote Interface address */
|
||||
set_rmt_itf_addr(exti, nbr->address.u.prefix4);
|
||||
|
||||
@ -747,11 +857,9 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status)
|
||||
set_ext_link(exti, OSPF_IFTYPE_BROADCAST, DR(oi),
|
||||
oi->address->u.prefix4);
|
||||
|
||||
/* Set Extended Link Adjacency SubTLVs, backup first */
|
||||
label = get_ext_link_label_value();
|
||||
set_lan_adj_sid(exti, true, label, SID_LABEL, nbr->router_id);
|
||||
label = get_ext_link_label_value();
|
||||
set_lan_adj_sid(exti, false, label, SID_LABEL, nbr->router_id);
|
||||
/* Set Neighbor ID */
|
||||
exti->lan_sid[0].neighbor_id = nbr->router_id;
|
||||
exti->lan_sid[1].neighbor_id = nbr->router_id;
|
||||
|
||||
break;
|
||||
|
||||
@ -764,36 +872,33 @@ static void ospf_ext_link_nsm_change(struct ospf_neighbor *nbr, int old_status)
|
||||
set_ext_link(exti, OSPF_IFTYPE_BROADCAST, DR(oi),
|
||||
oi->address->u.prefix4);
|
||||
|
||||
/* Set Extended Link Adjacency SubTLVs, backup first */
|
||||
label = get_ext_link_label_value();
|
||||
set_adj_sid(exti, true, label, SID_LABEL);
|
||||
label = get_ext_link_label_value();
|
||||
set_adj_sid(exti, false, label, SID_LABEL);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (CHECK_FLAG(exti->flags, EXT_LPFLG_FIB_ENTRY_SET))
|
||||
ospf_ext_link_delete_adj_sid(exti);
|
||||
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
|
||||
ospf_ext_link_lsa_schedule(exti, FLUSH_THIS_LSA);
|
||||
exti->flags = EXT_LPFLG_LSA_INACTIVE;
|
||||
return;
|
||||
}
|
||||
|
||||
osr_debug("EXT (%s): Complete %sAdjacency SID for interface %s ",
|
||||
__func__, exti->stype == ADJ_SID ? "" : "LAN-",
|
||||
oi->ifp->name);
|
||||
|
||||
/* flood this links params if everything is ok */
|
||||
SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
|
||||
|
||||
if (OspfEXT.enabled) {
|
||||
osr_debug("EXT (%s): Set %sAdjacency SID for interface %s ",
|
||||
__func__, exti->stype == ADJ_SID ? "" : "LAN-",
|
||||
oi->ifp->name);
|
||||
|
||||
/* Update (LAN)Adjacency SID */
|
||||
ospf_ext_link_update_adj_sid(exti);
|
||||
|
||||
/* flood this links params if everything is ok */
|
||||
if (CHECK_FLAG(exti->flags, EXT_LPFLG_LSA_ENGAGED))
|
||||
ospf_ext_link_lsa_schedule(exti, REFRESH_THIS_LSA);
|
||||
else
|
||||
ospf_ext_link_lsa_schedule(exti, REORIGINATE_THIS_LSA);
|
||||
}
|
||||
|
||||
/* Finally install (LAN)Adjacency-SID in the SRDB */
|
||||
ospf_sr_ext_itf_add(exti);
|
||||
}
|
||||
|
||||
/* Callbacks to handle Extended Link Segment Routing LSA information */
|
||||
|
||||
@ -189,6 +189,7 @@ extern int ospf_ext_init(void);
|
||||
extern void ospf_ext_term(void);
|
||||
extern void ospf_ext_finish(void);
|
||||
extern void ospf_ext_update_sr(bool enable);
|
||||
extern void ospf_ext_link_srlb_update(void);
|
||||
extern uint32_t ospf_ext_schedule_prefix_index(struct interface *ifp,
|
||||
uint32_t index,
|
||||
struct prefix_ipv4 *p,
|
||||
|
||||
@ -442,29 +442,52 @@ static void unset_sr_algorithm(uint8_t algo)
|
||||
TLV_LEN(OspfRI.sr_info.algo) = htons(0);
|
||||
}
|
||||
|
||||
/* Segment Routing Global Block SubTLV - section 3.2 */
|
||||
static void set_sr_sid_label_range(struct sr_srgb srgb)
|
||||
/* Set Segment Routing Global Block SubTLV - section 3.2 */
|
||||
static void set_sr_global_label_range(struct sr_block srgb)
|
||||
{
|
||||
/* Set Header */
|
||||
TLV_TYPE(OspfRI.sr_info.range) = htons(RI_SR_TLV_SID_LABEL_RANGE);
|
||||
TLV_LEN(OspfRI.sr_info.range) =
|
||||
TLV_TYPE(OspfRI.sr_info.srgb) = htons(RI_SR_TLV_SRGB_LABEL_RANGE);
|
||||
TLV_LEN(OspfRI.sr_info.srgb) =
|
||||
htons(SUBTLV_SID_LABEL_SIZE + sizeof(uint32_t));
|
||||
/* Set Range Size */
|
||||
OspfRI.sr_info.range.size = htonl(SET_RANGE_SIZE(srgb.range_size));
|
||||
OspfRI.sr_info.srgb.size = htonl(SET_RANGE_SIZE(srgb.range_size));
|
||||
/* Set Lower bound label SubTLV */
|
||||
TLV_TYPE(OspfRI.sr_info.range.lower) = htons(SUBTLV_SID_LABEL);
|
||||
TLV_LEN(OspfRI.sr_info.range.lower) = htons(SID_RANGE_LABEL_LENGTH);
|
||||
OspfRI.sr_info.range.lower.value = htonl(SET_LABEL(srgb.lower_bound));
|
||||
TLV_TYPE(OspfRI.sr_info.srgb.lower) = htons(SUBTLV_SID_LABEL);
|
||||
TLV_LEN(OspfRI.sr_info.srgb.lower) = htons(SID_RANGE_LABEL_LENGTH);
|
||||
OspfRI.sr_info.srgb.lower.value = htonl(SET_LABEL(srgb.lower_bound));
|
||||
}
|
||||
|
||||
/* Unset this SRGB SubTLV */
|
||||
static void unset_sr_sid_label_range(void)
|
||||
/* Unset Segment Routing Global Block SubTLV */
|
||||
static void unset_sr_global_label_range(void)
|
||||
{
|
||||
TLV_TYPE(OspfRI.sr_info.srgb) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.srgb) = htons(0);
|
||||
TLV_TYPE(OspfRI.sr_info.srgb.lower) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.srgb.lower) = htons(0);
|
||||
}
|
||||
|
||||
TLV_TYPE(OspfRI.sr_info.range) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.range) = htons(0);
|
||||
TLV_TYPE(OspfRI.sr_info.range.lower) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.range.lower) = htons(0);
|
||||
/* Set Segment Routing Local Block SubTLV - section 3.2 */
|
||||
static void set_sr_local_label_range(struct sr_block srlb)
|
||||
{
|
||||
/* Set Header */
|
||||
TLV_TYPE(OspfRI.sr_info.srlb) = htons(RI_SR_TLV_SRLB_LABEL_RANGE);
|
||||
TLV_LEN(OspfRI.sr_info.srlb) =
|
||||
htons(SUBTLV_SID_LABEL_SIZE + sizeof(uint32_t));
|
||||
/* Set Range Size */
|
||||
OspfRI.sr_info.srlb.size = htonl(SET_RANGE_SIZE(srlb.range_size));
|
||||
/* Set Lower bound label SubTLV */
|
||||
TLV_TYPE(OspfRI.sr_info.srlb.lower) = htons(SUBTLV_SID_LABEL);
|
||||
TLV_LEN(OspfRI.sr_info.srlb.lower) = htons(SID_RANGE_LABEL_LENGTH);
|
||||
OspfRI.sr_info.srlb.lower.value = htonl(SET_LABEL(srlb.lower_bound));
|
||||
}
|
||||
|
||||
/* Unset Segment Routing Local Block SubTLV */
|
||||
static void unset_sr_local_label_range(void)
|
||||
{
|
||||
TLV_TYPE(OspfRI.sr_info.srlb) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.srlb) = htons(0);
|
||||
TLV_TYPE(OspfRI.sr_info.srlb.lower) = htons(0);
|
||||
TLV_LEN(OspfRI.sr_info.srlb.lower) = htons(0);
|
||||
}
|
||||
|
||||
/* Set Maximum Stack Depth for this router */
|
||||
@ -563,7 +586,7 @@ static int is_mandated_params_set(struct ospf_router_info ori)
|
||||
return rc;
|
||||
|
||||
if ((ori.sr_info.enabled) && (ntohs(TLV_TYPE(ori.sr_info.algo)) == 0)
|
||||
&& (ntohs(TLV_TYPE(ori.sr_info.range)) == 0))
|
||||
&& (ntohs(TLV_TYPE(ori.sr_info.srgb)) == 0))
|
||||
return rc;
|
||||
|
||||
rc = 1;
|
||||
@ -575,13 +598,11 @@ static int is_mandated_params_set(struct ospf_router_info ori)
|
||||
* Used by Segment Routing to set new TLVs and Sub-TLVs values
|
||||
*
|
||||
* @param enable To activate or not Segment Routing router Information flooding
|
||||
* @param size Size of Label Range i.e. SRGB size
|
||||
* @param lower Lower bound of the Label Range i.e. SRGB first label
|
||||
* @param msd Maximum label Stack Depth supported by the router
|
||||
* @param srn Self Segment Routing node
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
|
||||
void ospf_router_info_update_sr(bool enable, struct sr_node *srn)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct ospf_ri_area_info *ai;
|
||||
@ -612,15 +633,17 @@ void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb, uint8_t msd)
|
||||
/* Unset or Set SR parameters */
|
||||
if (!enable) {
|
||||
unset_sr_algorithm(SR_ALGORITHM_SPF);
|
||||
unset_sr_sid_label_range();
|
||||
unset_sr_global_label_range();
|
||||
unset_sr_local_label_range();
|
||||
unset_sr_node_msd();
|
||||
OspfRI.sr_info.enabled = false;
|
||||
} else {
|
||||
// Only SR_ALGORITHM_SPF is supported
|
||||
set_sr_algorithm(SR_ALGORITHM_SPF);
|
||||
set_sr_sid_label_range(srgb);
|
||||
if (msd != 0)
|
||||
set_sr_node_msd(msd);
|
||||
set_sr_global_label_range(srn->srgb);
|
||||
set_sr_local_label_range(srn->srlb);
|
||||
if (srn->msd != 0)
|
||||
set_sr_node_msd(srn->msd);
|
||||
else
|
||||
unset_sr_node_msd();
|
||||
OspfRI.sr_info.enabled = true;
|
||||
@ -698,7 +721,9 @@ static void ospf_router_info_lsa_body_set(struct stream *s)
|
||||
/* Build Algorithm TLV */
|
||||
build_tlv(s, &TLV_HDR(OspfRI.sr_info.algo));
|
||||
/* Build SRGB TLV */
|
||||
build_tlv(s, &TLV_HDR(OspfRI.sr_info.range));
|
||||
build_tlv(s, &TLV_HDR(OspfRI.sr_info.srgb));
|
||||
/* Build SRLB TLV */
|
||||
build_tlv(s, &TLV_HDR(OspfRI.sr_info.srlb));
|
||||
/* Build MSD TLV */
|
||||
build_tlv(s, &TLV_HDR(OspfRI.sr_info.msd));
|
||||
}
|
||||
@ -1409,16 +1434,22 @@ static uint16_t show_vty_sr_range(struct vty *vty, struct tlv_header *tlvh)
|
||||
|
||||
if (vty != NULL) {
|
||||
vty_out(vty,
|
||||
" Segment Routing Range TLV:\n"
|
||||
" Segment Routing %s Range TLV:\n"
|
||||
" Range Size = %d\n"
|
||||
" SID Label = %d\n\n",
|
||||
ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
|
||||
? "Global"
|
||||
: "Local",
|
||||
GET_RANGE_SIZE(ntohl(range->size)),
|
||||
GET_LABEL(ntohl(range->lower.value)));
|
||||
} else {
|
||||
zlog_debug(
|
||||
" Segment Routing Range TLV:\n"
|
||||
" Segment Routing %s Range TLV:\n"
|
||||
" Range Size = %d\n"
|
||||
" SID Label = %d\n\n",
|
||||
ntohs(range->header.type) == RI_SR_TLV_SRGB_LABEL_RANGE
|
||||
? "Global"
|
||||
: "Local",
|
||||
GET_RANGE_SIZE(ntohl(range->size)),
|
||||
GET_LABEL(ntohl(range->lower.value)));
|
||||
}
|
||||
@ -1469,7 +1500,8 @@ static void ospf_router_info_show_info(struct vty *vty, struct ospf_lsa *lsa)
|
||||
case RI_SR_TLV_SR_ALGORITHM:
|
||||
sum += show_vty_sr_algorithm(vty, tlvh);
|
||||
break;
|
||||
case RI_SR_TLV_SID_LABEL_RANGE:
|
||||
case RI_SR_TLV_SRGB_LABEL_RANGE:
|
||||
case RI_SR_TLV_SRLB_LABEL_RANGE:
|
||||
sum += show_vty_sr_range(vty, tlvh);
|
||||
break;
|
||||
case RI_SR_TLV_NODE_MSD:
|
||||
|
||||
@ -201,7 +201,12 @@ struct ospf_ri_sr_info {
|
||||
* Segment Routing Global Block i.e. label range
|
||||
* Only one range supported in this code
|
||||
*/
|
||||
struct ri_sr_tlv_sid_label_range range;
|
||||
struct ri_sr_tlv_sid_label_range srgb;
|
||||
/*
|
||||
* Segment Routing Local Block.
|
||||
* Only one block is authorized - see section 3.3
|
||||
*/
|
||||
struct ri_sr_tlv_sid_label_range srlb;
|
||||
/* Maximum SID Depth supported by the node */
|
||||
struct ri_sr_tlv_node_msd msd;
|
||||
};
|
||||
@ -242,7 +247,6 @@ extern int ospf_router_info_init(void);
|
||||
extern void ospf_router_info_term(void);
|
||||
extern void ospf_router_info_finish(void);
|
||||
extern int ospf_router_info_enable(void);
|
||||
extern void ospf_router_info_update_sr(bool enable, struct sr_srgb srgb,
|
||||
uint8_t msd);
|
||||
extern void ospf_router_info_update_sr(bool enable, struct sr_node *self);
|
||||
extern struct scope_info ospf_router_info_get_flooding_scope(void);
|
||||
#endif /* _ZEBRA_OSPF_ROUTER_INFO_H */
|
||||
|
||||
516
ospfd/ospf_sr.c
516
ospfd/ospf_sr.c
@ -1,13 +1,14 @@
|
||||
/*
|
||||
* This is an implementation of Segment Routing
|
||||
* as per draft draft-ietf-ospf-segment-routing-extensions-24
|
||||
* as per RFC 8665 - OSPF Extensions for Segment Routing
|
||||
* and RFC 8476 - Signaling Maximum SID Depth (MSD) Using OSPF
|
||||
*
|
||||
* Module name: Segment Routing
|
||||
*
|
||||
* Author: Olivier Dugeon <olivier.dugeon@orange.com>
|
||||
* Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
|
||||
*
|
||||
* Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
|
||||
* Copyright (C) 2016 - 2020 Orange Labs http://www.orange.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
@ -218,6 +219,182 @@ static struct sr_node *get_sr_node_by_nexthop(struct ospf *ospf,
|
||||
return srn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Segment Routing Local Block management functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* It is necessary to known which label is already allocated to manage the range
|
||||
* of SRLB. This is particular useful when an interface flap (goes up / down
|
||||
* frequently). Here, SR will release and then allocate label for the Adjacency
|
||||
* for each concerned interface. If we don't care, there is a risk to run out of
|
||||
* label.
|
||||
*
|
||||
* For that purpose, a similar principle as already provided to manage chunk of
|
||||
* label is proposed. But, here, the label chunk has not a fix range of 64
|
||||
* labels that could be easily manage with a single variable of 64 bits size.
|
||||
* So, used_mark is used as a bit wise to mark label reserved (bit set) or not
|
||||
* (bit unset). Its size is equal to the number of label of the SRLB range round
|
||||
* up to 64 bits.
|
||||
*
|
||||
* - sr__local_block_init() computes the number of 64 bits variables that are
|
||||
* needed to manage the SRLB range and allocates this number.
|
||||
* - ospf_sr_local_block_request_label() pick up the first available label and
|
||||
* set corresponding bit
|
||||
* - ospf_sr_local_block_release_label() release label by reseting the
|
||||
* corresponding bit and set the next label to the first free position
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize Segment Routing Local Block from SRDB configuration and reserve
|
||||
* block of bits to manage label allocation.
|
||||
*
|
||||
* @param lower_bound The lower bound of the SRLB range
|
||||
* @param upper_bound The upper bound of the SRLB range
|
||||
*
|
||||
* @return 0 on success, -1 otherwise
|
||||
*/
|
||||
static int sr_local_block_init(uint32_t lower_bound, uint32_t upper_bound)
|
||||
{
|
||||
struct sr_local_block *srlb = &OspfSR.srlb;
|
||||
uint32_t size;
|
||||
|
||||
/* Check if SRLB is not already configured */
|
||||
if (srlb->reserved)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Request SRLB to the label manager. If the allocation fails, return
|
||||
* an error to disable SR until a new SRLB is successfully allocated.
|
||||
*/
|
||||
size = upper_bound - lower_bound + 1;
|
||||
if (ospf_zebra_request_label_range(lower_bound, size)) {
|
||||
srlb->reserved = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
osr_debug("SR (%s): Got new SRLB [%u/%u]", __func__, lower_bound,
|
||||
upper_bound);
|
||||
|
||||
/* Initialize the SRLB */
|
||||
srlb->start = lower_bound;
|
||||
srlb->end = upper_bound;
|
||||
srlb->current = 0;
|
||||
/* Compute the needed Used Mark number and allocate them */
|
||||
srlb->max_block = size / SRLB_BLOCK_SIZE;
|
||||
if ((size % SRLB_BLOCK_SIZE) != 0)
|
||||
srlb->max_block++;
|
||||
srlb->used_mark = XCALLOC(MTYPE_OSPF_SR_PARAMS,
|
||||
srlb->max_block * SRLB_BLOCK_SIZE);
|
||||
srlb->reserved = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Segment Routing Local Block.
|
||||
*
|
||||
*/
|
||||
static void sr_local_block_delete()
|
||||
{
|
||||
struct sr_local_block *srlb = &OspfSR.srlb;
|
||||
|
||||
/* Check if SRLB is not already delete */
|
||||
if (!srlb->reserved)
|
||||
return;
|
||||
|
||||
osr_debug("SR (%s): Remove SRLB [%u/%u]", __func__, srlb->start,
|
||||
srlb->end);
|
||||
|
||||
/* First release the label block */
|
||||
ospf_zebra_release_label_range(srlb->start, srlb->end);
|
||||
|
||||
/* Then reset SRLB structure */
|
||||
if (srlb->used_mark != NULL)
|
||||
XFREE(MTYPE_OSPF_SR_PARAMS, srlb->used_mark);
|
||||
srlb->reserved = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a label from the Segment Routing Local Block.
|
||||
*
|
||||
* @return First available label on success or MPLS_INVALID_LABEL if the
|
||||
* block of labels is full
|
||||
*/
|
||||
mpls_label_t ospf_sr_local_block_request_label(void)
|
||||
{
|
||||
struct sr_local_block *srlb = &OspfSR.srlb;
|
||||
mpls_label_t label;
|
||||
uint32_t index;
|
||||
uint32_t pos;
|
||||
|
||||
/* Check if we ran out of available labels */
|
||||
if (srlb->current >= srlb->end)
|
||||
return MPLS_INVALID_LABEL;
|
||||
|
||||
/* Get first available label and mark it used */
|
||||
label = srlb->current + srlb->start;
|
||||
index = srlb->current / SRLB_BLOCK_SIZE;
|
||||
pos = 1ULL << (srlb->current % SRLB_BLOCK_SIZE);
|
||||
srlb->used_mark[index] |= pos;
|
||||
|
||||
/* Jump to the next free position */
|
||||
srlb->current++;
|
||||
pos = srlb->current % SRLB_BLOCK_SIZE;
|
||||
while (srlb->current < srlb->end) {
|
||||
if (pos == 0)
|
||||
index++;
|
||||
if (!((1ULL << pos) & srlb->used_mark[index]))
|
||||
break;
|
||||
else {
|
||||
srlb->current++;
|
||||
pos = srlb->current % SRLB_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release label in the Segment Routing Local Block.
|
||||
*
|
||||
* @param label Label to be release
|
||||
*
|
||||
* @return 0 on success or -1 if label falls outside SRLB
|
||||
*/
|
||||
int ospf_sr_local_block_release_label(mpls_label_t label)
|
||||
{
|
||||
struct sr_local_block *srlb = &OspfSR.srlb;
|
||||
uint32_t index;
|
||||
uint32_t pos;
|
||||
|
||||
/* Check that label falls inside the SRLB */
|
||||
if ((label < srlb->start) || (label > srlb->end)) {
|
||||
flog_warn(EC_OSPF_SR_SID_OVERFLOW,
|
||||
"%s: Returning label %u is outside SRLB [%u/%u]",
|
||||
__func__, label, srlb->start, srlb->end);
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = (label - srlb->start) / SRLB_BLOCK_SIZE;
|
||||
pos = 1ULL << ((label - srlb->start) % SRLB_BLOCK_SIZE);
|
||||
srlb->used_mark[index] &= ~pos;
|
||||
/* Reset current to the first available position */
|
||||
for (index = 0; index < srlb->max_block; index++) {
|
||||
if (srlb->used_mark[index] != 0xFFFFFFFFFFFFFFFF) {
|
||||
for (pos = 0; pos < SRLB_BLOCK_SIZE; pos++)
|
||||
if (!((1ULL << pos) & srlb->used_mark[index])) {
|
||||
srlb->current =
|
||||
index * SRLB_BLOCK_SIZE + pos;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Segment Routing Initialization functions
|
||||
*/
|
||||
@ -258,8 +435,10 @@ static int ospf_sr_start(struct ospf *ospf)
|
||||
(void *)sr_node_new);
|
||||
|
||||
/* Complete & Store self SR Node */
|
||||
srn->srgb.range_size = OspfSR.srgb.range_size;
|
||||
srn->srgb.lower_bound = OspfSR.srgb.lower_bound;
|
||||
srn->srgb.range_size = OspfSR.srgb.size;
|
||||
srn->srgb.lower_bound = OspfSR.srgb.start;
|
||||
srn->srlb.lower_bound = OspfSR.srlb.start;
|
||||
srn->srlb.range_size = OspfSR.srlb.end - OspfSR.srlb.start + 1;
|
||||
srn->algo[0] = OspfSR.algo[0];
|
||||
srn->msd = OspfSR.msd;
|
||||
OspfSR.self = srn;
|
||||
@ -276,18 +455,19 @@ static int ospf_sr_start(struct ospf *ospf)
|
||||
}
|
||||
|
||||
/*
|
||||
* Request SGRB to the label manager if not already active. If the
|
||||
* allocation fails, return an error to disable SR until a new SRGB
|
||||
* is successfully allocated.
|
||||
* Request SRLB & SGRB to the label manager if not already reserved.
|
||||
* If the allocation fails, return an error to disable SR until a new
|
||||
* SRLB and/or SRGB are successfully allocated.
|
||||
*/
|
||||
if (!OspfSR.srgb_reserved) {
|
||||
if (ospf_zebra_request_label_range(OspfSR.srgb.lower_bound,
|
||||
OspfSR.srgb.range_size)
|
||||
sr_local_block_init(OspfSR.srlb.start, OspfSR.srlb.end);
|
||||
if (!OspfSR.srgb.reserved) {
|
||||
if (ospf_zebra_request_label_range(OspfSR.srgb.start,
|
||||
OspfSR.srgb.size)
|
||||
< 0) {
|
||||
OspfSR.srgb_reserved = false;
|
||||
OspfSR.srgb.reserved = false;
|
||||
return -1;
|
||||
} else
|
||||
OspfSR.srgb_reserved = true;
|
||||
OspfSR.srgb.reserved = true;
|
||||
}
|
||||
|
||||
/* SR is UP and ready to flood LSA */
|
||||
@ -296,7 +476,7 @@ static int ospf_sr_start(struct ospf *ospf)
|
||||
/* Set Router Information SR parameters */
|
||||
osr_debug("SR: Activate SR for Router Information LSA");
|
||||
|
||||
ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
|
||||
ospf_router_info_update_sr(true, OspfSR.self);
|
||||
|
||||
/* Update Ext LSA */
|
||||
osr_debug("SR: Activate SR for Extended Link/Prefix LSA");
|
||||
@ -341,13 +521,22 @@ static void ospf_sr_stop(void)
|
||||
/* Disable any re-attempt to connect to Label Manager */
|
||||
THREAD_TIMER_OFF(OspfSR.t_start_lm);
|
||||
|
||||
/* Release SRGB if active. */
|
||||
if (OspfSR.srgb_reserved) {
|
||||
/* Release SRGB & SRLB if active. */
|
||||
if (OspfSR.srgb.reserved)
|
||||
ospf_zebra_release_label_range(
|
||||
OspfSR.srgb.lower_bound,
|
||||
OspfSR.srgb.lower_bound + OspfSR.srgb.range_size - 1);
|
||||
OspfSR.srgb_reserved = false;
|
||||
}
|
||||
OspfSR.srgb.start,
|
||||
OspfSR.srgb.start + OspfSR.srgb.size - 1);
|
||||
sr_local_block_delete();
|
||||
|
||||
/* Revert SRGB, SRLB and MSD to default values */
|
||||
OspfSR.srgb.size = DEFAULT_SRGB_SIZE;
|
||||
OspfSR.srgb.start = DEFAULT_SRGB_LABEL;
|
||||
OspfSR.srgb.reserved = false;
|
||||
|
||||
OspfSR.srlb.start = DEFAULT_SRLB_LABEL;
|
||||
OspfSR.srlb.end = DEFAULT_SRLB_LABEL + DEFAULT_SRLB_SIZE - 1;
|
||||
OspfSR.srlb.reserved = false;
|
||||
OspfSR.msd = 0;
|
||||
|
||||
/*
|
||||
* Remove all SR Nodes from the Hash table. Prefix and Link SID will
|
||||
@ -376,15 +565,19 @@ int ospf_sr_init(void)
|
||||
/* Only AREA flooding is supported in this release */
|
||||
OspfSR.scope = OSPF_OPAQUE_AREA_LSA;
|
||||
|
||||
/* Initialize SRGB, Algorithms and MSD TLVs */
|
||||
/* Initialize Algorithms, SRGB, SRLB and MSD TLVs */
|
||||
/* Only Algorithm SPF is supported */
|
||||
OspfSR.algo[0] = SR_ALGORITHM_SPF;
|
||||
for (int i = 1; i < ALGORITHM_COUNT; i++)
|
||||
OspfSR.algo[i] = SR_ALGORITHM_UNSET;
|
||||
|
||||
OspfSR.srgb.range_size = MPLS_DEFAULT_MAX_SRGB_SIZE;
|
||||
OspfSR.srgb.lower_bound = MPLS_DEFAULT_MIN_SRGB_LABEL;
|
||||
OspfSR.srgb_reserved = false;
|
||||
OspfSR.srgb.size = DEFAULT_SRGB_SIZE;
|
||||
OspfSR.srgb.start = DEFAULT_SRGB_LABEL;
|
||||
OspfSR.srgb.reserved = false;
|
||||
|
||||
OspfSR.srlb.start = DEFAULT_SRLB_LABEL;
|
||||
OspfSR.srlb.end = DEFAULT_SRLB_LABEL + DEFAULT_SRLB_SIZE - 1;
|
||||
OspfSR.srlb.reserved = false;
|
||||
OspfSR.msd = 0;
|
||||
|
||||
/* Initialize Hash table for neighbor SR nodes */
|
||||
@ -443,7 +636,7 @@ void ospf_sr_finish(void)
|
||||
*/
|
||||
|
||||
/* Compute label from index */
|
||||
static mpls_label_t index2label(uint32_t index, struct sr_srgb srgb)
|
||||
static mpls_label_t index2label(uint32_t index, struct sr_block srgb)
|
||||
{
|
||||
mpls_label_t label;
|
||||
|
||||
@ -588,7 +781,7 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp)
|
||||
return rc;
|
||||
|
||||
/* Compute Input Label with self SRGB */
|
||||
srp->label_in = index2label(srp->sid, OspfSR.srgb);
|
||||
srp->label_in = index2label(srp->sid, OspfSR.self->srgb);
|
||||
|
||||
rc = 0;
|
||||
for (ALL_LIST_ELEMENTS_RO(srp->route->paths, node, path)) {
|
||||
@ -973,9 +1166,11 @@ static void update_in_nhlfe(struct hash_bucket *bucket, void *args)
|
||||
if (CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_VFLG))
|
||||
continue;
|
||||
|
||||
/* OK. Compute new input label ... */
|
||||
srp->label_in = index2label(srp->sid, OspfSR.srgb);
|
||||
/* ... and update MPLS LFIB */
|
||||
/* First, remove old MPLS table entries ... */
|
||||
ospf_zebra_delete_prefix_sid(srp);
|
||||
/* ... then compute new input label ... */
|
||||
srp->label_in = index2label(srp->sid, OspfSR.self->srgb);
|
||||
/* ... and install new MPLS LFIB */
|
||||
ospf_zebra_update_prefix_sid(srp);
|
||||
}
|
||||
}
|
||||
@ -1024,8 +1219,9 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
|
||||
struct tlv_header *tlvh;
|
||||
struct lsa_header *lsah = lsa->data;
|
||||
struct ri_sr_tlv_sid_label_range *ri_srgb = NULL;
|
||||
struct ri_sr_tlv_sid_label_range *ri_srlb = NULL;
|
||||
struct ri_sr_tlv_sr_algorithm *algo = NULL;
|
||||
struct sr_srgb srgb;
|
||||
struct sr_block srgb;
|
||||
uint16_t length = 0, sum = 0;
|
||||
uint8_t msd = 0;
|
||||
|
||||
@ -1061,10 +1257,14 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
|
||||
algo = (struct ri_sr_tlv_sr_algorithm *)tlvh;
|
||||
sum += TLV_SIZE(tlvh);
|
||||
break;
|
||||
case RI_SR_TLV_SID_LABEL_RANGE:
|
||||
case RI_SR_TLV_SRGB_LABEL_RANGE:
|
||||
ri_srgb = (struct ri_sr_tlv_sid_label_range *)tlvh;
|
||||
sum += TLV_SIZE(tlvh);
|
||||
break;
|
||||
case RI_SR_TLV_SRLB_LABEL_RANGE:
|
||||
ri_srlb = (struct ri_sr_tlv_sid_label_range *)tlvh;
|
||||
sum += TLV_SIZE(tlvh);
|
||||
break;
|
||||
case RI_SR_TLV_NODE_MSD:
|
||||
msd = ((struct ri_sr_tlv_node_msd *)(tlvh))->value;
|
||||
sum += TLV_SIZE(tlvh);
|
||||
@ -1121,9 +1321,12 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
|
||||
}
|
||||
/* update LSA ID */
|
||||
srn->instance = ntohl(lsah->id.s_addr);
|
||||
/* Copy SRGB */
|
||||
srn->srgb.range_size = srgb.range_size;
|
||||
srn->srgb.lower_bound = srgb.lower_bound;
|
||||
}
|
||||
|
||||
/* Set Algorithm */
|
||||
/* Update Algorithm, SRLB and MSD if present */
|
||||
if (algo != NULL) {
|
||||
int i;
|
||||
for (i = 0; i < ntohs(algo->header.length); i++)
|
||||
@ -1133,8 +1336,21 @@ void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa)
|
||||
} else {
|
||||
srn->algo[0] = SR_ALGORITHM_SPF;
|
||||
}
|
||||
|
||||
srn->msd = msd;
|
||||
if (ri_srlb != NULL) {
|
||||
srn->srlb.range_size = GET_RANGE_SIZE(ntohl(ri_srlb->size));
|
||||
srn->srlb.lower_bound = GET_LABEL(ntohl(ri_srlb->lower.value));
|
||||
}
|
||||
|
||||
osr_debug(" |- Update SR-Node[%pI4], SRGB[%u/%u], SRLB[%u/%u], Algo[%u], MSD[%u]",
|
||||
&srn->adv_router, srn->srgb.lower_bound, srn->srgb.range_size,
|
||||
srn->srlb.lower_bound, srn->srlb.range_size, srn->algo[0],
|
||||
srn->msd);
|
||||
|
||||
/* Check if SRGB has changed */
|
||||
if ((srn->srgb.range_size == srgb.range_size)
|
||||
&& (srn->srgb.lower_bound == srgb.lower_bound))
|
||||
return;
|
||||
|
||||
/* Copy SRGB */
|
||||
srn->srgb.range_size = srgb.range_size;
|
||||
@ -1526,18 +1742,6 @@ void ospf_sr_ext_prefix_lsa_delete(struct ospf_lsa *lsa)
|
||||
}
|
||||
}
|
||||
|
||||
/* Get Label for Extended Link SID */
|
||||
/* TODO: To be replace by Zebra Label Manager */
|
||||
uint32_t get_ext_link_label_value(void)
|
||||
{
|
||||
static uint32_t label = ADJ_SID_MIN - 1;
|
||||
|
||||
if (label < ADJ_SID_MAX)
|
||||
label += 1;
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update Prefix SID. Call by ospf_ext_pref_ism_change to
|
||||
* complete initial CLI command at startup.
|
||||
@ -1684,17 +1888,23 @@ void ospf_sr_config_write_router(struct vty *vty)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct sr_prefix *srp;
|
||||
uint32_t upper;
|
||||
|
||||
if (OspfSR.status != SR_OFF) {
|
||||
if (OspfSR.status == SR_UP) {
|
||||
vty_out(vty, " segment-routing on\n");
|
||||
|
||||
if ((OspfSR.srgb.lower_bound != MPLS_DEFAULT_MIN_SRGB_LABEL)
|
||||
|| (OspfSR.srgb.range_size != MPLS_DEFAULT_MAX_SRGB_SIZE)) {
|
||||
upper = OspfSR.srgb.start + OspfSR.srgb.size - 1;
|
||||
if ((OspfSR.srgb.start != DEFAULT_SRGB_LABEL)
|
||||
|| (OspfSR.srgb.size != DEFAULT_SRGB_SIZE))
|
||||
vty_out(vty, " segment-routing global-block %u %u\n",
|
||||
OspfSR.srgb.lower_bound,
|
||||
OspfSR.srgb.lower_bound + OspfSR.srgb.range_size
|
||||
- 1);
|
||||
}
|
||||
OspfSR.srgb.start, upper);
|
||||
|
||||
upper = DEFAULT_SRLB_LABEL + DEFAULT_SRLB_SIZE - 1;
|
||||
if ((OspfSR.srlb.start != DEFAULT_SRLB_LABEL)
|
||||
|| (OspfSR.srlb.end != upper))
|
||||
vty_out(vty, " segment-routing local-block %u %u\n",
|
||||
OspfSR.srlb.start, OspfSR.srlb.end);
|
||||
|
||||
if (OspfSR.msd != 0)
|
||||
vty_out(vty, " segment-routing node-msd %u\n",
|
||||
OspfSR.msd);
|
||||
@ -1759,7 +1969,7 @@ DEFUN (no_ospf_sr_enable,
|
||||
ospf_ext_update_sr(false);
|
||||
|
||||
/* then, disable Router Information SR parameters */
|
||||
ospf_router_info_update_sr(false, OspfSR.srgb, OspfSR.msd);
|
||||
ospf_router_info_update_sr(false, OspfSR.self);
|
||||
|
||||
/* Finally, stop Segment Routing */
|
||||
ospf_sr_stop();
|
||||
@ -1790,21 +2000,20 @@ static int update_srgb(uint32_t lower, uint32_t size)
|
||||
{
|
||||
|
||||
/* Check if values have changed */
|
||||
if ((OspfSR.srgb.range_size == size)
|
||||
&& (OspfSR.srgb.lower_bound == lower))
|
||||
if ((OspfSR.srgb.size == size) && (OspfSR.srgb.start == lower))
|
||||
return 0;
|
||||
|
||||
/* Release old SRGB if active. */
|
||||
if (OspfSR.srgb_reserved) {
|
||||
if (OspfSR.srgb.reserved) {
|
||||
ospf_zebra_release_label_range(
|
||||
OspfSR.srgb.lower_bound,
|
||||
OspfSR.srgb.lower_bound + OspfSR.srgb.range_size - 1);
|
||||
OspfSR.srgb_reserved = false;
|
||||
OspfSR.srgb.start,
|
||||
OspfSR.srgb.start + OspfSR.srgb.size - 1);
|
||||
OspfSR.srgb.reserved = false;
|
||||
}
|
||||
|
||||
/* Set new SRGB values */
|
||||
OspfSR.srgb.range_size = size;
|
||||
OspfSR.srgb.lower_bound = lower;
|
||||
OspfSR.srgb.size = size;
|
||||
OspfSR.srgb.start = lower;
|
||||
if (OspfSR.self != NULL) {
|
||||
OspfSR.self->srgb.range_size = size;
|
||||
OspfSR.self->srgb.lower_bound = lower;
|
||||
@ -1818,15 +2027,19 @@ static int update_srgb(uint32_t lower, uint32_t size)
|
||||
* Try to reserve the new block from the Label Manger. If the allocation
|
||||
* fails, disable SR until a new SRGB is successfully allocated.
|
||||
*/
|
||||
if (ospf_zebra_request_label_range(OspfSR.srgb.lower_bound,
|
||||
OspfSR.srgb.range_size) < 0) {
|
||||
OspfSR.srgb_reserved = false;
|
||||
if (ospf_zebra_request_label_range(OspfSR.srgb.start,
|
||||
OspfSR.srgb.size) < 0) {
|
||||
OspfSR.srgb.reserved = false;
|
||||
ospf_sr_stop();
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
OspfSR.srgb.reserved = true;
|
||||
|
||||
osr_debug("SR(%s): Got new SRGB [%u/%u]", __func__, OspfSR.srgb.start,
|
||||
OspfSR.srgb.start + OspfSR.srgb.size - 1);
|
||||
|
||||
/* SRGB is reserved, set Router Information parameters */
|
||||
ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
|
||||
ospf_router_info_update_sr(true, OspfSR.self);
|
||||
|
||||
/* and update NHLFE entries */
|
||||
hash_iterate(OspfSR.neighbors,
|
||||
@ -1836,8 +2049,8 @@ static int update_srgb(uint32_t lower, uint32_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFUN (sr_sid_label_range,
|
||||
sr_sid_label_range_cmd,
|
||||
DEFUN (sr_global_label_range,
|
||||
sr_global_label_range_cmd,
|
||||
"segment-routing global-block (16-1048575) (16-1048575)",
|
||||
SR_STR
|
||||
"Segment Routing Global Block label range\n"
|
||||
@ -1858,32 +2071,158 @@ DEFUN (sr_sid_label_range,
|
||||
upper = strtoul(argv[idx_up]->arg, NULL, 10);
|
||||
size = upper - lower + 1;
|
||||
|
||||
/* Validate SRGB against SRLB */
|
||||
if (!((upper < OspfSR.srlb.start) || (lower > OspfSR.srlb.end))) {
|
||||
vty_out(vty,
|
||||
"New SR Global Block (%u/%u) conflict with Local Block (%u/%u)\n",
|
||||
lower, upper, OspfSR.srlb.end, OspfSR.srlb.start);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (update_srgb(lower, size) < 0)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
else
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_sr_sid_label_range,
|
||||
no_sr_sid_label_range_cmd,
|
||||
"no segment-routing global-block [(0-1048575) (0-1048575)]",
|
||||
DEFUN (no_sr_global_label_range,
|
||||
no_sr_global_label_range_cmd,
|
||||
"no segment-routing global-block [(16-1048575) (16-1048575)]",
|
||||
NO_STR
|
||||
SR_STR
|
||||
"Segment Routing Global Block label range\n"
|
||||
"Lower-bound range in decimal (0-1048575)\n"
|
||||
"Upper-bound range in decimal (0-1048575)\n")
|
||||
"Lower-bound range in decimal (16-1048575)\n"
|
||||
"Upper-bound range in decimal (16-1048575)\n")
|
||||
{
|
||||
|
||||
if (!ospf_sr_enabled(vty))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
if (update_srgb(MPLS_DEFAULT_MIN_SRGB_SIZE,
|
||||
MPLS_DEFAULT_MIN_SRGB_LABEL) < 0)
|
||||
/* Validate SRGB against SRLB */
|
||||
uint32_t upper = DEFAULT_SRGB_LABEL + DEFAULT_SRGB_SIZE - 1;
|
||||
if (!((upper < OspfSR.srlb.start)
|
||||
|| (DEFAULT_SRGB_LABEL > OspfSR.srlb.end))) {
|
||||
vty_out(vty,
|
||||
"New SR Global Block (%u/%u) conflict with Local Block (%u/%u)\n",
|
||||
DEFAULT_SRGB_LABEL, upper, OspfSR.srlb.end,
|
||||
OspfSR.srlb.start);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
if (update_srgb(DEFAULT_SRGB_LABEL, DEFAULT_SRGB_SIZE) < 0)
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
else
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (sr_local_label_range,
|
||||
sr_local_label_range_cmd,
|
||||
"segment-routing local-block (16-1048575) (16-1048575)",
|
||||
SR_STR
|
||||
"Segment Routing Local Block label range\n"
|
||||
"Lower-bound range in decimal (16-1048575)\n"
|
||||
"Upper-bound range in decimal (16-1048575)\n")
|
||||
{
|
||||
uint32_t upper;
|
||||
uint32_t lower;
|
||||
uint32_t srgb_upper;
|
||||
int idx_low = 2;
|
||||
int idx_up = 3;
|
||||
|
||||
if (!ospf_sr_enabled(vty))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
/* Get lower and upper bound */
|
||||
lower = strtoul(argv[idx_low]->arg, NULL, 10);
|
||||
upper = strtoul(argv[idx_up]->arg, NULL, 10);
|
||||
|
||||
/* Check if values have changed */
|
||||
if ((OspfSR.srlb.start == lower)
|
||||
&& (OspfSR.srlb.end == upper))
|
||||
return CMD_SUCCESS;
|
||||
|
||||
/* Validate SRLB against SRGB */
|
||||
srgb_upper = OspfSR.srgb.start + OspfSR.srgb.size - 1;
|
||||
if (!((upper < OspfSR.srgb.start) || (lower > srgb_upper))) {
|
||||
vty_out(vty,
|
||||
"New SR Local Block (%u/%u) conflict with Global Block (%u/%u)\n",
|
||||
lower, upper, OspfSR.srgb.start, srgb_upper);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Remove old SRLB */
|
||||
sr_local_block_delete();
|
||||
|
||||
/* Try to reserve the new block from the Label Manger. If the allocation
|
||||
* fails, disable SR until a new SRLB is successfully allocated.
|
||||
*/
|
||||
if (sr_local_block_init(lower, upper) != 0) {
|
||||
ospf_sr_stop();
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* SRLB is reserved, Update Self SR-Node and Router Information LSA */
|
||||
OspfSR.self->srlb.lower_bound = lower;
|
||||
OspfSR.self->srlb.range_size = upper - lower + 1;
|
||||
ospf_router_info_update_sr(true, OspfSR.self);
|
||||
|
||||
/* and update (LAN)-Adjacency SID */
|
||||
ospf_ext_link_srlb_update();
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_sr_local_label_range,
|
||||
no_sr_local_label_range_cmd,
|
||||
"no segment-routing local-block [(16-1048575) (16-1048575)]",
|
||||
NO_STR
|
||||
SR_STR
|
||||
"Segment Routing Local Block label range\n"
|
||||
"Lower-bound range in decimal (16-1048575)\n"
|
||||
"Upper-bound range in decimal (16-1048575)\n")
|
||||
{
|
||||
|
||||
uint32_t upper;
|
||||
uint32_t srgb_end;
|
||||
|
||||
if (!ospf_sr_enabled(vty))
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
|
||||
/* First, remove old SRLB */
|
||||
sr_local_block_delete();
|
||||
|
||||
/* Validate SRLB against SRGB */
|
||||
srgb_end = OspfSR.srgb.start + OspfSR.srgb.size - 1;
|
||||
upper = DEFAULT_SRLB_LABEL + DEFAULT_SRLB_SIZE - 1;
|
||||
if (!((upper < OspfSR.srgb.start) || (DEFAULT_SRLB_LABEL > srgb_end))) {
|
||||
vty_out(vty,
|
||||
"New SR Local Block (%u/%u) conflict with Global Block (%u/%u)\n",
|
||||
DEFAULT_SRLB_LABEL, upper, OspfSR.srgb.start, srgb_end);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* Then, initialize SRLB with default value and try to reserve the new
|
||||
* block from the Label Manger. If the allocation fails, disable SR
|
||||
* until a new SRLB is successfully allocated.
|
||||
*/
|
||||
if (sr_local_block_init(DEFAULT_SRLB_LABEL, upper) != 0) {
|
||||
ospf_sr_stop();
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
/* SRLB is reserved, Update Self SR-Node and Router Information LSA */
|
||||
if (OspfSR.self != NULL) {
|
||||
OspfSR.self->srlb.lower_bound = DEFAULT_SRLB_LABEL;
|
||||
OspfSR.self->srlb.range_size = DEFAULT_SRLB_SIZE;
|
||||
}
|
||||
ospf_router_info_update_sr(true, OspfSR.self);
|
||||
|
||||
/* and update (LAN)-Adjacency SID */
|
||||
ospf_ext_link_srlb_update();
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (sr_node_msd,
|
||||
sr_node_msd_cmd,
|
||||
"segment-routing node-msd (1-16)",
|
||||
@ -1917,7 +2256,7 @@ DEFUN (sr_node_msd,
|
||||
|
||||
/* Set Router Information parameters if SR is UP */
|
||||
if (OspfSR.status == SR_UP)
|
||||
ospf_router_info_update_sr(true, OspfSR.srgb, OspfSR.msd);
|
||||
ospf_router_info_update_sr(true, OspfSR.self);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -1941,7 +2280,7 @@ DEFUN (no_sr_node_msd,
|
||||
|
||||
/* Set Router Information parameters if SR is UP */
|
||||
if (OspfSR.status == SR_UP)
|
||||
ospf_router_info_update_sr(true, OspfSR.srgb, 0);
|
||||
ospf_router_info_update_sr(true, OspfSR.self);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -1976,9 +2315,9 @@ DEFUN (sr_prefix_sid,
|
||||
/* Get & verify index value */
|
||||
argv_find(argv, argc, "(0-65535)", &idx);
|
||||
index = strtoul(argv[idx]->arg, NULL, 10);
|
||||
if (index > OspfSR.srgb.range_size - 1) {
|
||||
if (index > OspfSR.srgb.size - 1) {
|
||||
vty_out(vty, "Index %u must be lower than range size %u\n",
|
||||
index, OspfSR.srgb.range_size);
|
||||
index, OspfSR.srgb.size);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
@ -2263,6 +2602,7 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
|
||||
char pref[19];
|
||||
char sid[22];
|
||||
char op[32];
|
||||
uint32_t upper;
|
||||
json_object *json_node = NULL, *json_algo, *json_obj;
|
||||
json_object *json_prefix = NULL, *json_link = NULL;
|
||||
|
||||
@ -2280,6 +2620,10 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
|
||||
srn->srgb.range_size);
|
||||
json_object_int_add(json_node, "srgbLabel",
|
||||
srn->srgb.lower_bound);
|
||||
json_object_int_add(json_node, "srlbSize",
|
||||
srn->srlb.range_size);
|
||||
json_object_int_add(json_node, "srlbLabel",
|
||||
srn->srlb.lower_bound);
|
||||
json_algo = json_object_new_array();
|
||||
json_object_object_add(json_node, "algorithms", json_algo);
|
||||
for (int i = 0; i < ALGORITHM_COUNT; i++) {
|
||||
@ -2299,9 +2643,13 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
|
||||
json_object_int_add(json_node, "nodeMsd", srn->msd);
|
||||
} else {
|
||||
sbuf_push(&sbuf, 0, "SR-Node: %s", inet_ntoa(srn->adv_router));
|
||||
sbuf_push(&sbuf, 0, "\tSRGB (Size/Label): %u/%u",
|
||||
srn->srgb.range_size, srn->srgb.lower_bound);
|
||||
sbuf_push(&sbuf, 0, "\tAlgorithm(s): %s",
|
||||
upper = srn->srgb.lower_bound + srn->srgb.range_size - 1;
|
||||
sbuf_push(&sbuf, 0, "\tSRGB: [%u/%u]",
|
||||
srn->srgb.lower_bound, upper);
|
||||
upper = srn->srlb.lower_bound + srn->srlb.range_size - 1;
|
||||
sbuf_push(&sbuf, 0, "\tSRLB: [%u/%u]",
|
||||
srn->srlb.lower_bound, upper);
|
||||
sbuf_push(&sbuf, 0, "\tAlgo.(s): %s",
|
||||
srn->algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF");
|
||||
for (int i = 1; i < ALGORITHM_COUNT; i++) {
|
||||
if (srn->algo[i] == SR_ALGORITHM_UNSET)
|
||||
@ -2505,8 +2853,10 @@ void ospf_sr_register_vty(void)
|
||||
|
||||
install_element(OSPF_NODE, &ospf_sr_enable_cmd);
|
||||
install_element(OSPF_NODE, &no_ospf_sr_enable_cmd);
|
||||
install_element(OSPF_NODE, &sr_sid_label_range_cmd);
|
||||
install_element(OSPF_NODE, &no_sr_sid_label_range_cmd);
|
||||
install_element(OSPF_NODE, &sr_global_label_range_cmd);
|
||||
install_element(OSPF_NODE, &no_sr_global_label_range_cmd);
|
||||
install_element(OSPF_NODE, &sr_local_label_range_cmd);
|
||||
install_element(OSPF_NODE, &no_sr_local_label_range_cmd);
|
||||
install_element(OSPF_NODE, &sr_node_msd_cmd);
|
||||
install_element(OSPF_NODE, &no_sr_node_msd_cmd);
|
||||
install_element(OSPF_NODE, &sr_prefix_sid_cmd);
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
/*
|
||||
* This is an implementation of Segment Routing
|
||||
* as per draft draft-ietf-ospf-segment-routing-extensions-24
|
||||
* as per RFC 8665 - OSPF Extensions for Segment Routing
|
||||
* and RFC 8476 - Signaling Maximum SID Depth (MSD) Using OSPF
|
||||
*
|
||||
* Module name: Segment Routing header definitions
|
||||
*
|
||||
* Author: Olivier Dugeon <olivier.dugeon@orange.com>
|
||||
* Author: Anselme Sawadogo <anselmesawadogo@gmail.com>
|
||||
*
|
||||
* Copyright (C) 2016 - 2018 Orange Labs http://www.orange.com
|
||||
* Copyright (C) 2016 - 2020 Orange Labs http://www.orange.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
@ -37,13 +38,9 @@
|
||||
#define SET_LABEL(label) ((label << 8) & SET_LABEL_MASK)
|
||||
#define GET_LABEL(label) ((label >> 8) & GET_LABEL_MASK)
|
||||
|
||||
/* Label range for Adj-SID attribution purpose. Start just right after SRGB */
|
||||
#define ADJ_SID_MIN MPLS_DEFAULT_MAX_SRGB_LABEL
|
||||
#define ADJ_SID_MAX (MPLS_DEFAULT_MAX_SRGB_LABEL + 1000)
|
||||
|
||||
#define OSPF_SR_DEFAULT_METRIC 1
|
||||
|
||||
/* Segment Routing TLVs as per draft-ietf-ospf-segment-routing-extensions-19 */
|
||||
/* Segment Routing TLVs as per RFC 8665 */
|
||||
|
||||
/* Segment ID could be a Label (3 bytes) or an Index (4 bytes) */
|
||||
#define SID_LABEL 3
|
||||
@ -88,8 +85,9 @@ struct ri_sr_tlv_sr_algorithm {
|
||||
uint8_t value[ALGORITHM_COUNT];
|
||||
};
|
||||
|
||||
/* RI SID/Label Range TLV - section 3.2 */
|
||||
#define RI_SR_TLV_SID_LABEL_RANGE 9
|
||||
/* RI SID/Label Range TLV used for SRGB & SRLB - section 3.2 & 3.3 */
|
||||
#define RI_SR_TLV_SRGB_LABEL_RANGE 9
|
||||
#define RI_SR_TLV_SRLB_LABEL_RANGE 14
|
||||
struct ri_sr_tlv_sid_label_range {
|
||||
struct tlv_header header;
|
||||
/* Only 24 upper most bits are significant */
|
||||
@ -99,7 +97,7 @@ struct ri_sr_tlv_sid_label_range {
|
||||
struct subtlv_sid_label lower;
|
||||
};
|
||||
|
||||
/* RI Node/MSD TLV as per draft-ietf-ospf-segment-routing-msd-05 */
|
||||
/* RI Node/MSD TLV as per RFC 8476 */
|
||||
#define RI_SR_TLV_NODE_MSD 12
|
||||
struct ri_sr_tlv_node_msd {
|
||||
struct tlv_header header;
|
||||
@ -183,13 +181,38 @@ struct ext_subtlv_lan_adj_sid {
|
||||
* Following section define structure used to manage Segment Routing
|
||||
* information and TLVs / SubTLVs
|
||||
*/
|
||||
/* Default min and size of SR Global Block label range */
|
||||
#define DEFAULT_SRGB_LABEL 16000
|
||||
#define DEFAULT_SRGB_SIZE 8000
|
||||
|
||||
/* Structure aggregating SRGB info retrieved from an lsa */
|
||||
struct sr_srgb {
|
||||
/* Default min and size of SR Local Block label range */
|
||||
#define DEFAULT_SRLB_LABEL 15000
|
||||
#define DEFAULT_SRLB_SIZE 1000
|
||||
|
||||
/* Structure aggregating SR Range Block info retrieved from an lsa */
|
||||
struct sr_block {
|
||||
uint32_t range_size;
|
||||
uint32_t lower_bound;
|
||||
};
|
||||
|
||||
/* Segment Routing Global Block allocation */
|
||||
struct sr_global_block {
|
||||
bool reserved;
|
||||
uint32_t start;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
/* Segment Routing Local Block allocation */
|
||||
struct sr_local_block {
|
||||
bool reserved;
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
uint32_t current;
|
||||
uint32_t max_block;
|
||||
uint64_t *used_mark;
|
||||
};
|
||||
#define SRLB_BLOCK_SIZE 64
|
||||
|
||||
/* SID type to make difference between loopback interfaces and others */
|
||||
enum sid_type { PREF_SID, LOCAL_SID, ADJ_SID, LAN_ADJ_SID };
|
||||
|
||||
@ -221,16 +244,16 @@ struct ospf_sr_db {
|
||||
* Segment Routing Global Block i.e. label range
|
||||
* Only one range supported in this code
|
||||
*/
|
||||
struct sr_srgb srgb;
|
||||
struct sr_global_block srgb;
|
||||
|
||||
/* Thread timer to start Label Manager */
|
||||
struct thread *t_start_lm;
|
||||
|
||||
/* Status of SRGB: reserved within Label Manager or not */
|
||||
bool srgb_reserved;
|
||||
/* Segment Routing Local Block */
|
||||
struct sr_local_block srlb;
|
||||
|
||||
/* Maximum SID Depth supported by the node */
|
||||
uint8_t msd;
|
||||
|
||||
/* Thread timer to start Label Manager */
|
||||
struct thread *t_start_lm;
|
||||
};
|
||||
|
||||
/* Structure aggregating all received SR info from LSAs by node */
|
||||
@ -240,9 +263,9 @@ struct sr_node {
|
||||
uint32_t instance;
|
||||
|
||||
uint8_t algo[ALGORITHM_COUNT]; /* Algorithms supported by the node */
|
||||
/* Segment Routing Global Block i.e. label range */
|
||||
struct sr_srgb srgb;
|
||||
uint8_t msd; /* Maximum SID Depth */
|
||||
struct sr_block srgb; /* Segment Routing Global Block */
|
||||
struct sr_block srlb; /* Segment Routing Local Block */
|
||||
uint8_t msd; /* Maximum SID Depth */
|
||||
|
||||
/* List of Prefix & Link advertise by this node */
|
||||
struct list *ext_prefix; /* For Node SID */
|
||||
@ -252,7 +275,6 @@ struct sr_node {
|
||||
struct sr_node *neighbor;
|
||||
};
|
||||
|
||||
|
||||
/* Segment Routing - NHLFE info: support IPv4 Only */
|
||||
struct sr_nhlfe {
|
||||
struct in_addr nexthop;
|
||||
@ -319,6 +341,9 @@ struct sr_prefix {
|
||||
extern int ospf_sr_init(void);
|
||||
extern void ospf_sr_term(void);
|
||||
extern void ospf_sr_finish(void);
|
||||
/* Segment Routing label allocation functions */
|
||||
extern mpls_label_t ospf_sr_local_block_request_label(void);
|
||||
extern int ospf_sr_local_block_release_label(mpls_label_t label);
|
||||
/* Segment Routing LSA update & delete functions */
|
||||
extern void ospf_sr_ri_lsa_update(struct ospf_lsa *lsa);
|
||||
extern void ospf_sr_ri_lsa_delete(struct ospf_lsa *lsa);
|
||||
@ -331,7 +356,6 @@ struct ext_itf;
|
||||
extern void ospf_sr_ext_itf_add(struct ext_itf *exti);
|
||||
extern void ospf_sr_ext_itf_delete(struct ext_itf *exti);
|
||||
/* Segment Routing configuration functions */
|
||||
extern uint32_t get_ext_link_label_value(void);
|
||||
extern void ospf_sr_config_write_router(struct vty *vty);
|
||||
extern void ospf_sr_update_local_prefix(struct interface *ifp,
|
||||
struct prefix *p);
|
||||
|
||||
@ -3,8 +3,10 @@
|
||||
"srNodes":[
|
||||
{
|
||||
"routerID":"10.0.255.2",
|
||||
"srgbSize":20000,
|
||||
"srgbLabel":8000,
|
||||
"srgbSize":8000,
|
||||
"srgbLabel":16000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":15000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
@ -34,6 +36,8 @@
|
||||
"routerID":"10.0.255.4",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":10000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":5000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
@ -47,12 +51,12 @@
|
||||
"inputLabel":20400,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":8400,
|
||||
"outputLabel":16400,
|
||||
"interface":"r1-eth0",
|
||||
"nexthop":"10.0.0.2"
|
||||
},
|
||||
{
|
||||
"outputLabel":8400,
|
||||
"outputLabel":16400,
|
||||
"interface":"r1-eth1",
|
||||
"nexthop":"10.0.1.2"
|
||||
}
|
||||
@ -64,8 +68,14 @@
|
||||
"routerID":"10.0.255.3",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":10000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":5000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
}
|
||||
],
|
||||
"nodeMsd":8,
|
||||
"extendedPrefix":[
|
||||
{
|
||||
"prefix":"10.0.255.3\/32",
|
||||
@ -73,12 +83,12 @@
|
||||
"inputLabel":20300,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":8300,
|
||||
"outputLabel":16300,
|
||||
"interface":"r1-eth0",
|
||||
"nexthop":"10.0.0.2"
|
||||
},
|
||||
{
|
||||
"outputLabel":8300,
|
||||
"outputLabel":16300,
|
||||
"interface":"r1-eth1",
|
||||
"nexthop":"10.0.1.2"
|
||||
}
|
||||
@ -90,6 +100,8 @@
|
||||
"routerID":"10.0.255.1",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":20000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":15000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
debug ospf sr
|
||||
!
|
||||
interface lo
|
||||
ip ospf area 0.0.0.0
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
},
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8300,
|
||||
"outLabel":16300,
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.0.2"
|
||||
@ -76,7 +76,7 @@
|
||||
},
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8400,
|
||||
"outLabel":16400,
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.0.2"
|
||||
|
||||
@ -3,8 +3,10 @@
|
||||
"srNodes":[
|
||||
{
|
||||
"routerID":"10.0.255.2",
|
||||
"srgbSize":20000,
|
||||
"srgbLabel":8000,
|
||||
"srgbSize":8000,
|
||||
"srgbLabel":16000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":15000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
@ -95,13 +97,19 @@
|
||||
"routerID":"10.0.255.4",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":10000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":5000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
}
|
||||
],
|
||||
"nodeMsd":12,
|
||||
"extendedPrefix":[
|
||||
{
|
||||
"prefix":"10.0.255.4\/32",
|
||||
"sid":400,
|
||||
"inputLabel":8400,
|
||||
"inputLabel":16400,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":10400,
|
||||
@ -116,13 +124,19 @@
|
||||
"routerID":"10.0.255.3",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":10000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":5000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
}
|
||||
],
|
||||
"nodeMsd":8,
|
||||
"extendedPrefix":[
|
||||
{
|
||||
"prefix":"10.0.255.3\/32",
|
||||
"sid":300,
|
||||
"inputLabel":8300,
|
||||
"inputLabel":16300,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":3,
|
||||
@ -137,13 +151,19 @@
|
||||
"routerID":"10.0.255.1",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":20000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":15000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
}
|
||||
],
|
||||
"nodeMsd":16,
|
||||
"extendedPrefix":[
|
||||
{
|
||||
"prefix":"10.0.255.1\/32",
|
||||
"sid":100,
|
||||
"inputLabel":8100,
|
||||
"inputLabel":16100,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":20100,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[
|
||||
{
|
||||
"inLabel":8100,
|
||||
"inLabel":16100,
|
||||
"installed":true,
|
||||
"nexthops":[
|
||||
{
|
||||
@ -23,7 +23,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"inLabel":8300,
|
||||
"inLabel":16300,
|
||||
"installed":true,
|
||||
"nexthops":[
|
||||
{
|
||||
@ -39,7 +39,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"inLabel":8400,
|
||||
"inLabel":16400,
|
||||
"installed":true,
|
||||
"nexthops":[
|
||||
{
|
||||
|
||||
@ -3,8 +3,10 @@
|
||||
"srNodes":[
|
||||
{
|
||||
"routerID":"10.0.255.2",
|
||||
"srgbSize":20000,
|
||||
"srgbLabel":8000,
|
||||
"srgbSize":8000,
|
||||
"srgbLabel":16000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":15000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
@ -29,6 +31,8 @@
|
||||
"routerID":"10.0.255.4",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":10000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":5000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
@ -42,7 +46,7 @@
|
||||
"inputLabel":10400,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":8400,
|
||||
"outputLabel":16400,
|
||||
"interface":"r3-eth0",
|
||||
"nexthop":"10.0.3.2"
|
||||
}
|
||||
@ -54,6 +58,8 @@
|
||||
"routerID":"10.0.255.3",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":10000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":5000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
@ -97,6 +103,8 @@
|
||||
"routerID":"10.0.255.1",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":20000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":15000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
@ -110,7 +118,7 @@
|
||||
"inputLabel":10100,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":8100,
|
||||
"outputLabel":16100,
|
||||
"interface":"r3-eth0",
|
||||
"nexthop":"10.0.3.2"
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ router ospf
|
||||
capability opaque
|
||||
router-info area 0.0.0.0
|
||||
segment-routing on
|
||||
segment-routing local-block 5000 5999
|
||||
segment-routing global-block 10000 19999
|
||||
segment-routing node-msd 8
|
||||
segment-routing prefix 10.0.255.3/32 index 300
|
||||
|
||||
@ -3,9 +3,14 @@
|
||||
"srNodes":[
|
||||
{
|
||||
"routerID":"10.0.255.2",
|
||||
"srgbSize":20000,
|
||||
"srgbLabel":8000,
|
||||
"srgbSize":8000,
|
||||
"srgbLabel":16000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":15000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
}
|
||||
],
|
||||
"extendedPrefix":[
|
||||
{
|
||||
@ -26,6 +31,8 @@
|
||||
"routerID":"10.0.255.4",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":10000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":5000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
@ -69,8 +76,14 @@
|
||||
"routerID":"10.0.255.3",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":10000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":5000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
}
|
||||
],
|
||||
"nodeMsd":8,
|
||||
"extendedPrefix":[
|
||||
{
|
||||
"prefix":"10.0.255.3\/32",
|
||||
@ -78,7 +91,7 @@
|
||||
"inputLabel":10300,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":8300,
|
||||
"outputLabel":16300,
|
||||
"interface":"r4-eth0",
|
||||
"nexthop":"10.0.4.2"
|
||||
}
|
||||
@ -90,8 +103,14 @@
|
||||
"routerID":"10.0.255.1",
|
||||
"srgbSize":10000,
|
||||
"srgbLabel":20000,
|
||||
"srlbSize":1000,
|
||||
"srlbLabel":15000,
|
||||
"algorithms":[
|
||||
{
|
||||
"0":"SPF"
|
||||
}
|
||||
],
|
||||
"nodeMsd":16,
|
||||
"extendedPrefix":[
|
||||
{
|
||||
"prefix":"10.0.255.1\/32",
|
||||
@ -99,7 +118,7 @@
|
||||
"inputLabel":10100,
|
||||
"prefixRoute":[
|
||||
{
|
||||
"outputLabel":8100,
|
||||
"outputLabel":16100,
|
||||
"interface":"r4-eth0",
|
||||
"nexthop":"10.0.4.2"
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ router ospf
|
||||
capability opaque
|
||||
router-info area 0.0.0.0
|
||||
segment-routing on
|
||||
segment-routing local-block 5000 5999
|
||||
segment-routing global-block 10000 19999
|
||||
segment-routing node-msd 12
|
||||
segment-routing prefix 10.0.255.4/32 index 400 no-php-flag
|
||||
|
||||
Loading…
Reference in New Issue
Block a user