diff options
| -rw-r--r-- | doc/developer/ospf-sr.rst | 19 | ||||
| -rw-r--r-- | doc/user/ospfd.rst | 12 | ||||
| -rw-r--r-- | ospfd/ospf_errors.c | 6 | ||||
| -rw-r--r-- | ospfd/ospf_errors.h | 1 | ||||
| -rw-r--r-- | ospfd/ospf_ext.c | 165 | ||||
| -rw-r--r-- | ospfd/ospf_ext.h | 1 | ||||
| -rw-r--r-- | ospfd/ospf_ri.c | 86 | ||||
| -rw-r--r-- | ospfd/ospf_ri.h | 10 | ||||
| -rw-r--r-- | ospfd/ospf_sr.c | 516 | ||||
| -rw-r--r-- | ospfd/ospf_sr.h | 70 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json | 24 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r1/ospfd.conf | 1 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json | 4 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json | 30 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json | 6 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json | 16 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r3/ospfd.conf | 1 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json | 27 | ||||
| -rw-r--r-- | tests/topotests/ospf-sr-topo1/r4/ospfd.conf | 1 |
19 files changed, 792 insertions, 204 deletions
diff --git a/doc/developer/ospf-sr.rst b/doc/developer/ospf-sr.rst index 070465db5b..efe9b1b12f 100644 --- a/doc/developer/ospf-sr.rst +++ b/doc/developer/ospf-sr.rst @@ -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. diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst index 16eaf3be2a..ef3eb38510 100644 --- a/doc/user/ospfd.rst +++ b/doc/user/ospfd.rst @@ -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) diff --git a/ospfd/ospf_errors.c b/ospfd/ospf_errors.c index a985efc668..2de77a43f6 100644 --- a/ospfd/ospf_errors.c +++ b/ospfd/ospf_errors.c @@ -158,6 +158,12 @@ static struct log_ref ferr_ospf_err[] = { .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", .description = "OSPF Segment Routing invalid Algorithm", diff --git a/ospfd/ospf_errors.h b/ospfd/ospf_errors.h index 726f7d9c8b..df5bdaa491 100644 --- a/ospfd/ospf_errors.h +++ b/ospfd/ospf_errors.h @@ -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, diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c index 6dd5d78bd0..8e4548f74d 100644 --- a/ospfd/ospf_ext.c +++ b/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 */ diff --git a/ospfd/ospf_ext.h b/ospfd/ospf_ext.h index 0071584e26..b1e4feb6df 100644 --- a/ospfd/ospf_ext.h +++ b/ospfd/ospf_ext.h @@ -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, diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index ececed0643..8eeaf7be3c 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -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: diff --git a/ospfd/ospf_ri.h b/ospfd/ospf_ri.h index 84511ac5e7..4729677bca 100644 --- a/ospfd/ospf_ri.h +++ b/ospfd/ospf_ri.h @@ -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 */ diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index 5cc05e6727..ebc31a90f4 100644 --- a/ospfd/ospf_sr.c +++ b/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 @@ -219,6 +220,182 @@ static struct sr_node *get_sr_node_by_nexthop(struct ospf *ospf, } /* + * 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); diff --git a/ospfd/ospf_sr.h b/ospfd/ospf_sr.h index f30d7da395..c54d2dcc3c 100644 --- a/ospfd/ospf_sr.h +++ b/ospfd/ospf_sr.h @@ -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 + +/* Default min and size of SR Local Block label range */ +#define DEFAULT_SRLB_LABEL 15000 +#define DEFAULT_SRLB_SIZE 1000 -/* Structure aggregating SRGB info retrieved from an lsa */ -struct sr_srgb { +/* 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); diff --git a/tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json b/tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json index 0416bd6ce2..57bcbaeffc 100644 --- a/tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json +++ b/tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json @@ -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" diff --git a/tests/topotests/ospf-sr-topo1/r1/ospfd.conf b/tests/topotests/ospf-sr-topo1/r1/ospfd.conf index 292d4e6367..f8fac2428c 100644 --- a/tests/topotests/ospf-sr-topo1/r1/ospfd.conf +++ b/tests/topotests/ospf-sr-topo1/r1/ospfd.conf @@ -1,3 +1,4 @@ +debug ospf sr ! interface lo ip ospf area 0.0.0.0 diff --git a/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json index dd42e326ce..fdf0886bcd 100644 --- a/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json +++ b/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json @@ -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" diff --git a/tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json b/tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json index eb202b82cd..6ea0f0a0cf 100644 --- a/tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json +++ b/tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json @@ -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, diff --git a/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json index f3462e239e..d343315f07 100644 --- a/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json +++ b/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json @@ -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":[ { diff --git a/tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json b/tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json index b36fe674ad..e7371ff593 100644 --- a/tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json +++ b/tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json @@ -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" } diff --git a/tests/topotests/ospf-sr-topo1/r3/ospfd.conf b/tests/topotests/ospf-sr-topo1/r3/ospfd.conf index cf274bed2e..38d525f34f 100644 --- a/tests/topotests/ospf-sr-topo1/r3/ospfd.conf +++ b/tests/topotests/ospf-sr-topo1/r3/ospfd.conf @@ -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 diff --git a/tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json b/tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json index d92ec91c72..a241b32607 100644 --- a/tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json +++ b/tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json @@ -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" } diff --git a/tests/topotests/ospf-sr-topo1/r4/ospfd.conf b/tests/topotests/ospf-sr-topo1/r4/ospfd.conf index 65fdce69f7..9d0d148812 100644 --- a/tests/topotests/ospf-sr-topo1/r4/ospfd.conf +++ b/tests/topotests/ospf-sr-topo1/r4/ospfd.conf @@ -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 |
