diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index dc598ea5bf..200d00821f 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -493,7 +493,15 @@ Known limitations: .. clicmd:: [no] segment-routing global-block (0-1048575) (0-1048575) Set the Segment Routing Global Block i.e. the label range used by MPLS - to store label in the MPLS FIB. + to store label in the MPLS FIB for Prefix SID. Note that the block size + may not exceed 65535. + +.. index:: [no] segment-routing local-block (0-1048575) (0-1048575) +.. clicmd:: [no] segment-routing local-block (0-1048575) (0-1048575) + + Set the Segment Routing Local Block i.e. the label range used by MPLS + to store label in the MPLS FIB for Adjacency SID. Note that the block size + may not exceed 65535. .. index:: [no] segment-routing node-msd (1-16) .. clicmd:: [no] segment-routing node-msd (1-16) diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index c421750a82..df69b1c7be 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -1400,8 +1400,8 @@ DEFPY (isis_sr_global_block_label_range, "segment-routing global-block (16-1048575)$lower_bound (16-1048575)$upper_bound", SR_STR "Segment Routing Global Block label range\n" - "The lower bound of SRGB (16-1048575)\n" - "The upper bound of SRGB (16-1048575)\n") + "The lower bound of the block\n" + "The upper bound of the block (block size may not exceed 65535)\n") { nb_cli_enqueue_change(vty, "./segment-routing/srgb/lower-bound", NB_OP_MODIFY, lower_bound_str); @@ -1413,12 +1413,12 @@ DEFPY (isis_sr_global_block_label_range, DEFPY (no_isis_sr_global_block_label_range, no_isis_sr_global_block_label_range_cmd, - "no segment-routing global-block [(0-1048575) (0-1048575)]", + "no segment-routing global-block [(16-1048575) (16-1048575)]", NO_STR SR_STR "Segment Routing Global Block label range\n" - "The lower bound of SRGB (16-1048575)\n" - "The upper bound of SRGB (block size may not exceed 65535)\n") + "The lower bound of the block\n" + "The upper bound of the block (block size may not exceed 65535)\n") { nb_cli_enqueue_change(vty, "./segment-routing/srgb/lower-bound", NB_OP_MODIFY, NULL); @@ -1436,6 +1436,50 @@ void cli_show_isis_srgb(struct vty *vty, struct lyd_node *dnode, yang_dnode_get_string(dnode, "./upper-bound")); } +/* + * XPath: /frr-isisd:isis/instance/segment-routing/srlb + */ +DEFPY (isis_sr_local_block_label_range, + isis_sr_local_block_label_range_cmd, + "segment-routing local-block (16-1048575)$lower_bound (16-1048575)$upper_bound", + SR_STR + "Segment Routing Local Block label range\n" + "The lower bound of the block\n" + "The upper bound of the block (block size may not exceed 65535)\n") +{ + nb_cli_enqueue_change(vty, "./segment-routing/srlb/lower-bound", + NB_OP_MODIFY, lower_bound_str); + nb_cli_enqueue_change(vty, "./segment-routing/srlb/upper-bound", + NB_OP_MODIFY, upper_bound_str); + + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY (no_isis_sr_local_block_label_range, + no_isis_sr_local_block_label_range_cmd, + "no segment-routing local-block [(16-1048575) (16-1048575)]", + NO_STR + SR_STR + "Segment Routing Local Block label range\n" + "The lower bound of the block\n" + "The upper bound of the block (block size may not exceed 65535)\n") +{ + nb_cli_enqueue_change(vty, "./segment-routing/srlb/lower-bound", + NB_OP_MODIFY, NULL); + nb_cli_enqueue_change(vty, "./segment-routing/srlb/upper-bound", + NB_OP_MODIFY, NULL); + + return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_srlb(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + vty_out(vty, " segment-routing local-block %s %s\n", + yang_dnode_get_string(dnode, "./lower-bound"), + yang_dnode_get_string(dnode, "./upper-bound")); +} + /* * XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd */ @@ -2308,6 +2352,8 @@ void isis_cli_init(void) install_element(ISIS_NODE, &no_isis_sr_enable_cmd); install_element(ISIS_NODE, &isis_sr_global_block_label_range_cmd); install_element(ISIS_NODE, &no_isis_sr_global_block_label_range_cmd); + install_element(ISIS_NODE, &isis_sr_local_block_label_range_cmd); + install_element(ISIS_NODE, &no_isis_sr_local_block_label_range_cmd); install_element(ISIS_NODE, &isis_sr_node_msd_cmd); install_element(ISIS_NODE, &no_isis_sr_node_msd_cmd); install_element(ISIS_NODE, &isis_sr_prefix_sid_cmd); diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index e578f616f4..9b04eef6a2 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -933,14 +933,23 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) struct isis_sr_db *srdb = &area->srdb; uint32_t range_size; + /* SRGB first */ range_size = srdb->config.srgb_upper_bound - srdb->config.srgb_lower_bound + 1; cap.srgb.flags = ISIS_SUBTLV_SRGB_FLAG_I | ISIS_SUBTLV_SRGB_FLAG_V; cap.srgb.range_size = range_size; cap.srgb.lower_bound = srdb->config.srgb_lower_bound; + /* Then Algorithm */ cap.algo[0] = SR_ALGORITHM_SPF; cap.algo[1] = SR_ALGORITHM_UNSET; + /* SRLB */ + cap.srlb.flags = 0; + range_size = srdb->config.srlb_upper_bound + - srdb->config.srlb_lower_bound + 1; + cap.srlb.range_size = range_size; + cap.srlb.lower_bound = srdb->config.srlb_lower_bound; + /* And finally MSD */ cap.msd = srdb->config.msd; } diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index f1f183cc59..1d842eb13b 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -465,6 +465,7 @@ const struct frr_yang_module_info frr_isisd_info = { .xpath = "/frr-isisd:isis/instance/segment-routing/srgb", .cbs = { .apply_finish = isis_instance_segment_routing_srgb_apply_finish, + .pre_validate = isis_instance_segment_routing_srgb_pre_validate, .cli_show = cli_show_isis_srgb, }, }, @@ -480,6 +481,26 @@ const struct frr_yang_module_info frr_isisd_info = { .modify = isis_instance_segment_routing_srgb_upper_bound_modify, }, }, + { + .xpath = "/frr-isisd:isis/instance/segment-routing/srlb", + .cbs = { + .apply_finish = isis_instance_segment_routing_srlb_apply_finish, + .pre_validate = isis_instance_segment_routing_srlb_pre_validate, + .cli_show = cli_show_isis_srlb, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/segment-routing/srlb/lower-bound", + .cbs = { + .modify = isis_instance_segment_routing_srlb_lower_bound_modify, + }, + }, + { + .xpath = "/frr-isisd:isis/instance/segment-routing/srlb/upper-bound", + .cbs = { + .modify = isis_instance_segment_routing_srlb_upper_bound_modify, + }, + }, { .xpath = "/frr-isisd:isis/instance/segment-routing/msd/node-msd", .cbs = { diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index 36dbc2d619..e887b1a388 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -180,6 +180,10 @@ int isis_instance_segment_routing_srgb_lower_bound_modify( struct nb_cb_modify_args *args); int isis_instance_segment_routing_srgb_upper_bound_modify( struct nb_cb_modify_args *args); +int isis_instance_segment_routing_srlb_lower_bound_modify( + struct nb_cb_modify_args *args); +int isis_instance_segment_routing_srlb_upper_bound_modify( + struct nb_cb_modify_args *args); int isis_instance_segment_routing_msd_node_msd_modify( struct nb_cb_modify_args *args); int isis_instance_segment_routing_msd_node_msd_destroy( @@ -289,6 +293,10 @@ lib_interface_state_isis_event_counters_authentication_fails_get_elem( /* Optional 'pre_validate' callbacks. */ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate( struct nb_cb_pre_validate_args *args); +int isis_instance_segment_routing_srgb_pre_validate( + struct nb_cb_pre_validate_args *args); +int isis_instance_segment_routing_srlb_pre_validate( + struct nb_cb_pre_validate_args *args); /* Optional 'apply_finish' callbacks. */ void ietf_backoff_delay_apply_finish(struct nb_cb_apply_finish_args *args); @@ -304,6 +312,8 @@ void redistribute_ipv4_apply_finish(struct nb_cb_apply_finish_args *args); void redistribute_ipv6_apply_finish(struct nb_cb_apply_finish_args *args); void isis_instance_segment_routing_srgb_apply_finish( struct nb_cb_apply_finish_args *args); +void isis_instance_segment_routing_srlb_apply_finish( + struct nb_cb_apply_finish_args *args); void isis_instance_segment_routing_prefix_sid_map_prefix_sid_apply_finish( struct nb_cb_apply_finish_args *args); @@ -370,6 +380,8 @@ void cli_show_isis_sr_enabled(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_isis_srgb(struct vty *vty, struct lyd_node *dnode, bool show_defaults); +void cli_show_isis_srlb(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); void cli_show_isis_node_msd(struct vty *vty, struct lyd_node *dnode, bool show_defaults); void cli_show_isis_prefix_sid(struct vty *vty, struct lyd_node *dnode, diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 9633e46415..fafa22b492 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -1449,6 +1449,38 @@ int isis_instance_segment_routing_enabled_modify( /* * XPath: /frr-isisd:isis/instance/segment-routing/srgb */ +int isis_instance_segment_routing_srgb_pre_validate( + struct nb_cb_pre_validate_args *args) +{ + uint32_t srgb_lbound; + uint32_t srgb_ubound; + uint32_t srlb_lbound; + uint32_t srlb_ubound; + + srgb_lbound = yang_dnode_get_uint32(args->dnode, "./lower-bound"); + srgb_ubound = yang_dnode_get_uint32(args->dnode, "./upper-bound"); + srlb_lbound = yang_dnode_get_uint32(args->dnode, "../srlb/lower-bound"); + srlb_ubound = yang_dnode_get_uint32(args->dnode, "../srlb/upper-bound"); + + /* Check that the block size does not exceed 65535 */ + if ((srgb_ubound - srgb_lbound + 1) > 65535) { + zlog_warn( + "New SR Global Block (%u/%u) exceed the limit of 65535", + srgb_lbound, srgb_ubound); + return NB_ERR_VALIDATION; + } + + /* Validate SRGB against SRLB */ + if (!((srgb_ubound < srlb_lbound) || (srgb_lbound > srlb_ubound))) { + zlog_warn( + "New SR Global Block (%u/%u) conflict with Local Block (%u/%u)", + srgb_lbound, srgb_ubound, srlb_lbound, srlb_ubound); + return NB_ERR_VALIDATION; + } + + return NB_OK; +} + void isis_instance_segment_routing_srgb_apply_finish( struct nb_cb_apply_finish_args *args) { @@ -1521,6 +1553,104 @@ int isis_instance_segment_routing_srgb_upper_bound_modify( return NB_OK; } +/* + * XPath: /frr-isisd:isis/instance/segment-routing/srlb + */ +int isis_instance_segment_routing_srlb_pre_validate( + struct nb_cb_pre_validate_args *args) +{ + uint32_t srgb_lbound; + uint32_t srgb_ubound; + uint32_t srlb_lbound; + uint32_t srlb_ubound; + + srgb_lbound = yang_dnode_get_uint32(args->dnode, "../srgb/lower-bound"); + srgb_ubound = yang_dnode_get_uint32(args->dnode, "../srgb/upper-bound"); + srlb_lbound = yang_dnode_get_uint32(args->dnode, "./lower-bound"); + srlb_ubound = yang_dnode_get_uint32(args->dnode, "./upper-bound"); + + /* Check that the block size does not exceed 65535 */ + if ((srlb_ubound - srlb_lbound + 1) > 65535) { + zlog_warn( + "New SR Local Block (%u/%u) exceed the limit of 65535", + srlb_lbound, srlb_ubound); + return NB_ERR_VALIDATION; + } + + /* Validate SRLB against SRGB */ + if (!((srlb_ubound < srgb_lbound) || (srlb_lbound > srgb_ubound))) { + zlog_warn( + "New SR Local Block (%u/%u) conflict with Global Block (%u/%u)", + srlb_lbound, srlb_ubound, srgb_lbound, srgb_ubound); + return NB_ERR_VALIDATION; + } + + return NB_OK; +} + +void isis_instance_segment_routing_srlb_apply_finish( + struct nb_cb_apply_finish_args *args) +{ + struct isis_area *area; + uint32_t lower_bound, upper_bound; + + area = nb_running_get_entry(args->dnode, NULL, true); + lower_bound = yang_dnode_get_uint32(args->dnode, "./lower-bound"); + upper_bound = yang_dnode_get_uint32(args->dnode, "./upper-bound"); + + isis_sr_cfg_srlb_update(area, lower_bound, upper_bound); +} + +/* + * XPath: /frr-isisd:isis/instance/segment-routing/srlb/lower-bound + */ +int isis_instance_segment_routing_srlb_lower_bound_modify( + struct nb_cb_modify_args *args) +{ + uint32_t lower_bound = yang_dnode_get_uint32(args->dnode, NULL); + + switch (args->event) { + case NB_EV_VALIDATE: + if (!IS_MPLS_UNRESERVED_LABEL(lower_bound)) { + zlog_warn("Invalid SRLB lower bound: %" PRIu32, + lower_bound); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-isisd:isis/instance/segment-routing/srlb/upper-bound + */ +int isis_instance_segment_routing_srlb_upper_bound_modify( + struct nb_cb_modify_args *args) +{ + uint32_t upper_bound = yang_dnode_get_uint32(args->dnode, NULL); + + switch (args->event) { + case NB_EV_VALIDATE: + if (!IS_MPLS_UNRESERVED_LABEL(upper_bound)) { + zlog_warn("Invalid SRLB upper bound: %" PRIu32, + upper_bound); + return NB_ERR_VALIDATION; + } + break; + case NB_EV_PREPARE: + case NB_EV_ABORT: + case NB_EV_APPLY: + break; + } + + return NB_OK; +} + /* * XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd */ diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c index c24c0608b2..32de71cca6 100644 --- a/isisd/isis_sr.c +++ b/isisd/isis_sr.c @@ -52,6 +52,10 @@ DEFINE_MTYPE_STATIC(ISISD, ISIS_SR_INFO, "ISIS segment routing information") static void sr_prefix_uninstall(struct sr_prefix *srp); static void sr_prefix_reinstall(struct sr_prefix *srp, bool make_before_break); +static void sr_local_block_delete(struct isis_area *area); +static int sr_local_block_init(struct isis_area *area); +static void sr_adj_sid_update(struct sr_adjacency *sra, + struct sr_local_block *srlb); /* --- RB-Tree Management functions ----------------------------------------- */ @@ -135,7 +139,8 @@ int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound, { struct isis_sr_db *srdb = &area->srdb; - sr_debug("ISIS-Sr (%s): Update SRGB", area->area_tag); + sr_debug("ISIS-Sr (%s): Update SRGB with new range [%u/%u]", + area->area_tag, lower_bound, upper_bound); /* First release the old SRGB. */ if (srdb->config.enabled) @@ -148,14 +153,14 @@ int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound, if (srdb->enabled) { struct sr_prefix *srp; - /* Request new SRGB if SR is enabled. */ + /* then request new SRGB if SR is enabled. */ if (isis_zebra_request_label_range( srdb->config.srgb_lower_bound, srdb->config.srgb_upper_bound - srdb->config.srgb_lower_bound + 1)) return -1; - sr_debug(" |- Got new SRGB %u/%u", + sr_debug(" |- Got new SRGB [%u/%u]", srdb->config.srgb_lower_bound, srdb->config.srgb_upper_bound); @@ -177,6 +182,54 @@ int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound, return 0; } +/** + * Update Segment Routing Local Block range which is reserved though the + * Label Manager. This function trigger the update of local Adjacency-SID + * installation. + * + * @param area IS-IS area + * @param lower_bound Lower bound of SRLB + * @param upper_bound Upper bound of SRLB + * + * @return 0 on success, -1 otherwise + */ +int isis_sr_cfg_srlb_update(struct isis_area *area, uint32_t lower_bound, + uint32_t upper_bound) +{ + struct isis_sr_db *srdb = &area->srdb; + struct listnode *node, *nnode; + struct sr_adjacency *sra; + int rc; + + sr_debug("ISIS-Sr (%s): Update SRLB with new range [%u/%u]", + area->area_tag, lower_bound, upper_bound); + + /* First Delete SRLB */ + sr_local_block_delete(area); + + srdb->config.srlb_lower_bound = lower_bound; + srdb->config.srlb_upper_bound = upper_bound; + + if (!srdb->enabled) + return 0; + + /* Initialize new SRLB */ + rc = sr_local_block_init(area); + if (rc !=0) + return rc; + + /* Reinstall local Adjacency-SIDs with new labels. */ + for (ALL_LIST_ELEMENTS(area->srdb.adj_sids, node, nnode, sra)) + sr_adj_sid_update(sra, &srdb->srlb); + + /* Update Router Capability */ + + /* Update and Flood LSP */ + lsp_regenerate_schedule(area, area->is_type, 0); + + return 0; +} + /** * Add new Prefix-SID configuration to the SRDB. * @@ -404,15 +457,13 @@ static struct sr_prefix *sr_prefix_find_by_node(struct sr_node *srn, * @return New Segment Routing Node structure */ static struct sr_node *sr_node_add(struct isis_area *area, int level, - const uint8_t *sysid, - const struct isis_router_cap *cap) + const uint8_t *sysid) { struct sr_node *srn; srn = XCALLOC(MTYPE_ISIS_SR_INFO, sizeof(*srn)); srn->level = level; memcpy(srn->sysid, sysid, ISIS_SYS_ID_LEN); - srn->cap = *cap; srn->area = area; srdb_node_prefix_init(&srn->prefix_sids); srdb_node_add(&area->srdb.sr_nodes[level - 1], srn); @@ -886,6 +937,26 @@ static inline void sr_prefix_reinstall(struct sr_prefix *srp, /* --- IS-IS LSP Parse functions -------------------------------------------- */ +/** + * Compare Router Capabilities. Only Flags, SRGB and Algorithm are used for the + * comparison. MSD and SRLB modification must not trigger and SR-Prefix update. + * + * @param r1 First Router Capabilities to compare + * @param r2 Second Router Capabilities to compare + * @return 0 if r1 and r2 are equal or -1 otherwise + */ +static int router_cap_cmp(const struct isis_router_cap *r1, + const struct isis_router_cap *r2) +{ + if (r1->flags == r2->flags + && r1->srgb.lower_bound == r2->srgb.lower_bound + && r1->srgb.range_size == r2->srgb.range_size + && r1->algo[0] == r2->algo[0]) + return 0; + else + return -1; +} + /** * Parse all SR-related information from the given Router Capabilities TLV. * @@ -909,8 +980,7 @@ parse_router_cap_tlv(struct isis_area *area, int level, const uint8_t *sysid, srn = sr_node_find(area, level, sysid); if (srn) { - if (memcmp(&srn->cap, router_cap, sizeof(srn->cap)) != 0) { - srn->cap = *router_cap; + if (router_cap_cmp(&srn->cap, router_cap) != 0) { srn->state = SRDB_STATE_MODIFIED; } else srn->state = SRDB_STATE_UNCHANGED; @@ -919,10 +989,16 @@ parse_router_cap_tlv(struct isis_area *area, int level, const uint8_t *sysid, : "Unchanged", sysid_print(srn->sysid)); } else { - srn = sr_node_add(area, level, sysid, router_cap); + srn = sr_node_add(area, level, sysid); srn->state = SRDB_STATE_NEW; } + /* + * Update Router Capabilities in any case as SRLB or MSD + * modification are not take into account for comparison. + */ + srn->cap = *router_cap; + return srn; } @@ -1242,6 +1318,150 @@ static int sr_route_update(struct isis_area *area, struct prefix *prefix, return 0; } +/* --- Segment Routing Local Block management functions --------------------- */ + +/** + * Initialize Segment Routing Local Block from SRDB configuration and reserve + * block of bits to manage label allocation. + * + * @param area IS-IS area + */ +static void sr_local_block_init(struct isis_area *area) +{ + struct isis_sr_db *srdb = &area->srdb; + struct sr_local_block *srlb = &srdb->srlb; + + /* + * Request SRLB to the label manager. If the allocation fails, return + * an error to disable SR until a new SRLB is successfully allocated. + */ + if (isis_zebra_request_label_range( + srdb->config.srlb_lower_bound, + srdb->config.srlb_upper_bound + - srdb->config.srlb_lower_bound + 1)) + return; + + sr_debug("ISIS-Sr (%s): Got new SRLB [%u/%u]", area->area_tag, + srdb->config.srlb_lower_bound, srdb->config.srlb_upper_bound); + + /* Initialize the SRLB */ + srlb->start = srdb->config.srlb_lower_bound; + srlb->end = srdb->config.srlb_upper_bound; + srlb->current = 0; + /* Compute the needed Used Mark number and allocate them */ + srlb->max_block = (srlb->end - srlb->start + 1) / SRLB_BLOCK_SIZE; + if (((srlb->end - srlb->start + 1) % SRLB_BLOCK_SIZE) != 0) + srlb->max_block++; + srlb->used_mark = XCALLOC(MTYPE_ISIS_SR_INFO, + srlb->max_block * SRLB_BLOCK_SIZE); +} + +/** + * Remove Segment Routing Local Block. + * + * @param area IS-IS area + */ +static void sr_local_block_delete(struct isis_area *area) +{ + struct isis_sr_db *srdb = &area->srdb; + struct sr_local_block *srlb = &srdb->srlb; + + sr_debug("ISIS-Sr (%s): Remove SRLB [%u/%u]", area->area_tag, + srlb->start, srlb->end); + + /* First release the label block */ + isis_zebra_release_label_range(srdb->config.srlb_lower_bound, + srdb->config.srlb_upper_bound); + + /* Then reset SRLB structure */ + if (srlb->used_mark != NULL) + XFREE(MTYPE_ISIS_SR_INFO, srlb->used_mark); + memset(srlb, 0, sizeof(struct sr_local_block)); +} + +/** + * Request a label from the Segment Routing Local Block. + * + * @param srlb Segment Routing Local Block + * + * @return First available label on success or MPLS_INVALID_LABEL if the + * block of labels is full + */ +static mpls_label_t sr_local_block_request_label(struct sr_local_block *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 srlb Segment Routing Local Block + * @param label Label to be release + * + * @return 0 on success or -1 if label falls outside SRLB + */ +static int sr_local_block_release_label(struct sr_local_block *srlb, + mpls_label_t label) +{ + uint32_t index; + uint32_t pos; + + /* Check that label falls inside the SRLB */ + if ((label < srlb->start) || (label > srlb->end)) { + flog_warn(EC_ISIS_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 Adjacency-SID management functions ------------------- */ /** @@ -1293,7 +1513,11 @@ static void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, if (backup) SET_FLAG(flags, EXT_SUBTLV_LINK_ADJ_SID_BFLG); - input_label = isis_zebra_request_dynamic_label(); + /* Get a label from the SRLB for this Adjacency */ + input_label = sr_local_block_request_label(&area->srdb.srlb); + if (input_label == MPLS_INVALID_LABEL) + return; + if (circuit->ext == NULL) circuit->ext = isis_alloc_ext_subtlvs(); @@ -1351,6 +1575,36 @@ static void sr_adj_sid_add(struct isis_adjacency *adj, int family) sr_adj_sid_add_single(adj, family, true); } +static void sr_adj_sid_update(struct sr_adjacency *sra, + struct sr_local_block *srlb) +{ + struct isis_circuit *circuit = sra->adj->circuit; + + /* First remove the old MPLS Label */ + isis_zebra_send_adjacency_sid(ZEBRA_MPLS_LABELS_DELETE, sra); + + /* Got new label in the new SRLB */ + sra->nexthop.label = sr_local_block_request_label(srlb); + if (sra->nexthop.label == MPLS_INVALID_LABEL) + return; + + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + sra->u.ladj_sid->sid = sra->nexthop.label; + break; + case CIRCUIT_T_P2P: + sra->u.adj_sid->sid = sra->nexthop.label; + break; + default: + flog_warn(EC_LIB_DEVELOPMENT, "%s: unexpected circuit type: %u", + __func__, circuit->circ_type); + break; + } + + /* Finally configure the new MPLS Label */ + isis_zebra_send_adjacency_sid(ZEBRA_MPLS_LABELS_ADD, sra); +} + /** * Delete local Adj-SID. * @@ -1368,11 +1622,13 @@ static void sr_adj_sid_del(struct sr_adjacency *sra) /* Release dynamic label and remove subTLVs */ switch (circuit->circ_type) { case CIRCUIT_T_BROADCAST: - isis_zebra_release_dynamic_label(sra->u.ladj_sid->sid); + sr_local_block_release_label(&area->srdb.srlb, + sra->u.ladj_sid->sid); isis_tlvs_del_lan_adj_sid(circuit->ext, sra->u.ladj_sid); break; case CIRCUIT_T_P2P: - isis_zebra_release_dynamic_label(sra->u.adj_sid->sid); + sr_local_block_release_label(&area->srdb.srlb, + sra->u.adj_sid->sid); isis_tlvs_del_adj_sid(circuit->ext, sra->u.adj_sid); break; default: @@ -1730,7 +1986,7 @@ static void show_node(struct vty *vty, struct isis_area *area, int level) /* Prepare table. */ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]); - ttable_add_row(tt, "System ID|SRGB|Algorithm|MSD"); + ttable_add_row(tt, "System ID|SRGB|SRLB|Algorithm|MSD"); tt->style.cell.rpad = 2; tt->style.corner = '+'; ttable_restyle(tt); @@ -1738,13 +1994,17 @@ static void show_node(struct vty *vty, struct isis_area *area, int level) /* Process all SR-Node from the SRDB */ frr_each (srdb_node, &area->srdb.sr_nodes[level - 1], srn) { - ttable_add_row(tt, "%s|%u - %u|%s|%u", sysid_print(srn->sysid), - srn->cap.srgb.lower_bound, - srn->cap.srgb.lower_bound - + srn->cap.srgb.range_size - 1, - srn->cap.algo[0] == SR_ALGORITHM_SPF ? "SPF" - : "S-SPF", - srn->cap.msd); + ttable_add_row( + tt, "%s|%u - %u|%u - %u|%s|%u", + sysid_print(srn->sysid), + srn->cap.srgb.lower_bound, + srn->cap.srgb.lower_bound + srn->cap.srgb.range_size + - 1, + srn->cap.srlb.lower_bound, + srn->cap.srlb.lower_bound + srn->cap.srlb.range_size + - 1, + srn->cap.algo[0] == SR_ALGORITHM_SPF ? "SPF" : "S-SPF", + srn->cap.msd); } /* Dump the generated table. */ @@ -1794,6 +2054,10 @@ int isis_sr_start(struct isis_area *area) struct isis_circuit *circuit; struct listnode *node; + /* Initialize the SRLB */ + if (sr_local_block_init(area) != 0) + return -1; + /* * Request SGRB to the label manager. If the allocation fails, return * an error to disable SR until a new SRGB is successfully allocated. @@ -1876,6 +2140,9 @@ void isis_sr_stop(struct isis_area *area) isis_zebra_release_label_range(srdb->config.srgb_lower_bound, srdb->config.srgb_upper_bound); + /* Delete SRLB */ + sr_local_block_delete(area); + /* Regenerate LSPs to advertise that the Node is no more SR enable. */ lsp_regenerate_schedule(area, area->is_type, 0); } @@ -1909,10 +2176,16 @@ void isis_sr_area_init(struct isis_area *area) yang_get_default_uint32("%s/srgb/lower-bound", ISIS_SR); srdb->config.srgb_upper_bound = yang_get_default_uint32("%s/srgb/upper-bound", ISIS_SR); + srdb->config.srlb_lower_bound = + yang_get_default_uint32("%s/srlb/lower-bound", ISIS_SR); + srdb->config.srlb_upper_bound = + yang_get_default_uint32("%s/srlb/upper-bound", ISIS_SR); #else srdb->config.enabled = false; srdb->config.srgb_lower_bound = SRGB_LOWER_BOUND; srdb->config.srgb_upper_bound = SRGB_UPPER_BOUND; + srdb->config.srlb_lower_bound = SRLB_LOWER_BOUND; + srdb->config.srlb_upper_bound = SRLB_UPPER_BOUND; #endif srdb->config.msd = 0; srdb_prefix_cfg_init(&srdb->config.prefix_sids); diff --git a/isisd/isis_sr.h b/isisd/isis_sr.h index dec329ab48..45728f1eb1 100644 --- a/isisd/isis_sr.h +++ b/isisd/isis_sr.h @@ -53,6 +53,8 @@ #define SRGB_LOWER_BOUND 16000 #define SRGB_UPPER_BOUND 23999 +#define SRLB_LOWER_BOUND 15000 +#define SRLB_UPPER_BOUND 15999 /* Segment Routing Data Base (SRDB) RB-Tree structure */ PREDECL_RBTREE_UNIQ(srdb_node) @@ -60,6 +62,16 @@ PREDECL_RBTREE_UNIQ(srdb_node_prefix) PREDECL_RBTREE_UNIQ(srdb_area_prefix) PREDECL_RBTREE_UNIQ(srdb_prefix_cfg) +/* Segment Routing Local Block allocation */ +struct sr_local_block { + uint32_t start; + uint32_t end; + uint32_t current; + uint32_t max_block; + uint64_t *used_mark; +}; +#define SRLB_BLOCK_SIZE 64 + /* Segment Routing Adjacency-SID type. */ enum sr_adj_type { ISIS_SR_ADJ_NORMAL = 0, @@ -220,6 +232,9 @@ struct isis_sr_db { /* Segment Routing Prefix-SIDs per IS-IS level. */ struct srdb_area_prefix_head prefix_sids[ISIS_LEVELS]; + /* Management of SRLB allocation */ + struct sr_local_block srlb; + /* Area Segment Routing configuration. */ struct { /* Administrative status of Segment Routing. */ @@ -229,6 +244,10 @@ struct isis_sr_db { uint32_t srgb_lower_bound; uint32_t srgb_upper_bound; + /* Segment Routing Local Block lower & upper bound. */ + uint32_t srlb_lower_bound; + uint32_t srlb_upper_bound; + /* Maximum SID Depth supported by the node. */ uint8_t msd; @@ -240,6 +259,8 @@ struct isis_sr_db { /* Prototypes. */ extern int isis_sr_cfg_srgb_update(struct isis_area *area, uint32_t lower_bound, uint32_t upper_bound); +extern int isis_sr_cfg_srlb_update(struct isis_area *area, uint32_t lower_bound, + uint32_t upper_bound); extern struct sr_prefix_cfg * isis_sr_cfg_prefix_add(struct isis_area *area, const struct prefix *prefix); extern void isis_sr_cfg_prefix_del(struct sr_prefix_cfg *pcfg); diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index 923956fa6d..a58038b327 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -2620,30 +2620,35 @@ static void format_tlv_router_cap(const struct isis_router_cap *router_cap, /* Segment Routing Global Block as per RFC8667 section #3.1 */ if (router_cap->srgb.range_size != 0) - sbuf_push(buf, indent, - " Segment Routing: I:%s V:%s, SRGB Base: %d Range: %d\n", + sbuf_push( + buf, indent, + " Segment Routing: I:%s V:%s, Global Block Base: %u Range: %u\n", IS_SR_IPV4(router_cap->srgb) ? "1" : "0", IS_SR_IPV6(router_cap->srgb) ? "1" : "0", router_cap->srgb.lower_bound, router_cap->srgb.range_size); + /* Segment Routing Local Block as per RFC8667 section #3.3 */ + if (router_cap->srlb.range_size != 0) + sbuf_push(buf, indent, " SR Local Block Base: %u Range: %u\n", + router_cap->srlb.lower_bound, + router_cap->srlb.range_size); + /* Segment Routing Algorithms as per RFC8667 section #3.2 */ if (router_cap->algo[0] != SR_ALGORITHM_UNSET) { - sbuf_push(buf, indent, " Algorithm: %s", - router_cap->algo[0] == 0 ? "0: SPF" - : "0: Strict SPF"); - for (int i = 1; i < SR_ALGORITHM_COUNT; i++) + sbuf_push(buf, indent, " SR Algorithm:\n"); + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) if (router_cap->algo[i] != SR_ALGORITHM_UNSET) - sbuf_push(buf, indent, " %s", - router_cap->algo[1] == 0 - ? "0: SPF" - : "0: Strict SPF"); - sbuf_push(buf, indent, "\n"); + sbuf_push(buf, indent, " %u: %s\n", i, + router_cap->algo[i] == 0 + ? "SPF" + : "Strict SPF"); } /* Segment Routing Node MSD as per RFC8491 section #2 */ if (router_cap->msd != 0) - sbuf_push(buf, indent, " Node MSD: %d\n", router_cap->msd); + sbuf_push(buf, indent, " Node Maximum SID Depth: %u\n", + router_cap->msd); } static void free_tlv_router_cap(struct isis_router_cap *router_cap) @@ -2699,6 +2704,20 @@ static int pack_tlv_router_cap(const struct isis_router_cap *router_cap, for (int i = 0; i < nb_algo; i++) stream_putc(s, router_cap->algo[i]); } + + /* Local Block if defined as per RFC8667 section #3.3 */ + if ((router_cap->srlb.range_size != 0) + && (router_cap->srlb.lower_bound != 0)) { + stream_putc(s, ISIS_SUBTLV_SRLB); + stream_putc(s, ISIS_SUBTLV_SID_LABEL_RANGE_SIZE); + /* No Flags are defined for SRLB */ + stream_putc(s, 0); + stream_put3(s, router_cap->srlb.range_size); + stream_putc(s, ISIS_SUBTLV_SID_LABEL); + stream_putc(s, ISIS_SUBTLV_SID_LABEL_SIZE); + stream_put3(s, router_cap->srlb.lower_bound); + } + /* And finish with MSD if set as per RFC8491 section #2 */ if (router_cap->msd != 0) { stream_putc(s, ISIS_SUBTLV_NODE_MSD); @@ -2721,6 +2740,7 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, void *dest, int indent) { struct isis_tlvs *tlvs = dest; + struct isis_router_cap *rcap; uint8_t type; uint8_t length; uint8_t subtlv_len; @@ -2741,47 +2761,51 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, } /* Allocate router cap structure and initialize SR Algorithms */ - tlvs->router_cap = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->router_cap)); + rcap = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct isis_router_cap)); for (int i = 0; i < SR_ALGORITHM_COUNT; i++) - tlvs->router_cap->algo[i] = SR_ALGORITHM_UNSET; + rcap->algo[i] = SR_ALGORITHM_UNSET; /* Get Router ID and Flags */ - tlvs->router_cap->router_id.s_addr = stream_get_ipv4(s); - tlvs->router_cap->flags = stream_getc(s); + rcap->router_id.s_addr = stream_get_ipv4(s); + rcap->flags = stream_getc(s); /* Parse remaining part of the TLV if present */ subtlv_len = tlv_len - ISIS_ROUTER_CAP_SIZE; while (subtlv_len > 2) { - struct isis_router_cap *rc = tlvs->router_cap; uint8_t msd_type; type = stream_getc(s); length = stream_getc(s); switch (type) { case ISIS_SUBTLV_SID_LABEL_RANGE: - rc->srgb.flags = stream_getc(s); - rc->srgb.range_size = stream_get3(s); + /* Only one SRGB is supported. Skip subsequent one */ + if (rcap->srgb.range_size != 0) { + stream_forward_getp(s, length); + continue; + } + rcap->srgb.flags = stream_getc(s); + rcap->srgb.range_size = stream_get3(s); /* Skip Type and get Length of SID Label */ stream_getc(s); sid_len = stream_getc(s); if (sid_len == ISIS_SUBTLV_SID_LABEL_SIZE) - rc->srgb.lower_bound = stream_get3(s); + rcap->srgb.lower_bound = stream_get3(s); else - rc->srgb.lower_bound = stream_getl(s); + rcap->srgb.lower_bound = stream_getl(s); /* SRGB sanity checks. */ - if (rc->srgb.range_size == 0 - || (rc->srgb.lower_bound <= MPLS_LABEL_RESERVED_MAX) - || ((rc->srgb.lower_bound + rc->srgb.range_size - 1) + if (rcap->srgb.range_size == 0 + || (rcap->srgb.lower_bound <= MPLS_LABEL_RESERVED_MAX) + || ((rcap->srgb.lower_bound + rcap->srgb.range_size - 1) > MPLS_LABEL_UNRESERVED_MAX)) { sbuf_push(log, indent, "Invalid label range. Reset SRGB\n"); - rc->srgb.lower_bound = 0; - rc->srgb.range_size = 0; + rcap->srgb.lower_bound = 0; + rcap->srgb.range_size = 0; } break; case ISIS_SUBTLV_ALGORITHM: /* Only 2 algorithms are supported: SPF & Strict SPF */ - stream_get(&rc->algo, s, + stream_get(&rcap->algo, s, length > SR_ALGORITHM_COUNT ? SR_ALGORITHM_COUNT : length); @@ -2789,12 +2813,39 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, stream_forward_getp( s, length - SR_ALGORITHM_COUNT); break; + case ISIS_SUBTLV_SRLB: + /* RFC 8667 section #3.3: Only one SRLB is authorized */ + if (rcap->srlb.range_size != 0) { + stream_forward_getp(s, length); + continue; + } + /* Ignore Flags which are not defined */ + stream_getc(s); + rcap->srlb.range_size = stream_get3(s); + /* Skip Type and get Length of SID Label */ + stream_getc(s); + sid_len = stream_getc(s); + if (sid_len == ISIS_SUBTLV_SID_LABEL_SIZE) + rcap->srlb.lower_bound = stream_get3(s); + else + rcap->srlb.lower_bound = stream_getl(s); + + /* SRLB sanity checks. */ + if (rcap->srlb.range_size == 0 + || (rcap->srlb.lower_bound <= MPLS_LABEL_RESERVED_MAX) + || ((rcap->srlb.lower_bound + rcap->srlb.range_size - 1) + > MPLS_LABEL_UNRESERVED_MAX)) { + sbuf_push(log, indent, "Invalid label range. Reset SRLB\n"); + rcap->srlb.lower_bound = 0; + rcap->srlb.range_size = 0; + } + break; case ISIS_SUBTLV_NODE_MSD: msd_type = stream_getc(s); - rc->msd = stream_getc(s); + rcap->msd = stream_getc(s); /* Only BMI-MSD type has been defined in RFC 8491 */ if (msd_type != MSD_TYPE_BASE_MPLS_IMPOSITION) - rc->msd = 0; + rcap->msd = 0; break; default: stream_forward_getp(s, length); @@ -2802,6 +2853,7 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, } subtlv_len = subtlv_len - length - 2; } + tlvs->router_cap = rcap; return 0; } diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h index f468d85bbd..0cf49b526f 100644 --- a/isisd/isis_tlvs.h +++ b/isisd/isis_tlvs.h @@ -141,8 +141,8 @@ struct isis_threeway_adj { #define IS_SR_IPV4(srgb) (srgb.flags & ISIS_SUBTLV_SRGB_FLAG_I) #define IS_SR_IPV6(srgb) (srgb.flags & ISIS_SUBTLV_SRGB_FLAG_V) -/* Structure aggregating SRGB info */ -struct isis_srgb { +/* Structure aggregating SR Global (SRGB) or Local (SRLB) Block info */ +struct isis_sr_block { uint8_t flags; uint32_t range_size; uint32_t lower_bound; @@ -214,7 +214,8 @@ struct isis_router_cap { uint8_t flags; /* RFC 8667 section #3 */ - struct isis_srgb srgb; + struct isis_sr_block srgb; + struct isis_sr_block srlb; uint8_t algo[SR_ALGORITHM_COUNT]; /* RFC 8491 */ #define MSD_TYPE_BASE_MPLS_IMPOSITION 0x01 @@ -398,10 +399,11 @@ enum isis_tlv_type { ISIS_SUBTLV_RAS = 24, ISIS_SUBTLV_RIP = 25, - /* RFC 8667 section #2 */ + /* RFC 8667 section #4 IANA allocation */ ISIS_SUBTLV_SID_LABEL = 1, ISIS_SUBTLV_SID_LABEL_RANGE = 2, ISIS_SUBTLV_ALGORITHM = 19, + ISIS_SUBTLV_SRLB = 22, ISIS_SUBTLV_PREFIX_SID = 3, ISIS_SUBTLV_ADJ_SID = 31, ISIS_SUBTLV_LAN_ADJ_SID = 32, @@ -431,7 +433,7 @@ enum ext_subtlv_size { /* RFC 8491 */ ISIS_SUBTLV_NODE_MSD_SIZE = 2, - /* RFC 8667 section #2 */ + /* RFC 8667 sections #2 & #3 */ ISIS_SUBTLV_SID_LABEL_SIZE = 3, ISIS_SUBTLV_SID_LABEL_RANGE_SIZE = 9, ISIS_SUBTLV_ALGORITHM_SIZE = 4, diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index e0bf0cee14..fa108c3637 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -56,10 +56,6 @@ struct zclient *zclient; static struct zclient *zclient_sync; -/* List of chunks of labels externally assigned by zebra. */ -static struct list *label_chunk_list; -static struct listnode *current_label_chunk; - static void isis_zebra_label_manager_connect(void); /* Router-id update message from zebra. */ @@ -511,160 +507,6 @@ void isis_zebra_release_label_range(uint32_t start, uint32_t end) zlog_warn("%s: error releasing label range!", __func__); } -/** - * Get a new Label Chunk from the Label Manager. The new Label Chunk is - * added to the Label Chunk list. - * - * @return 0 on success, -1 on failure - */ -static int isis_zebra_get_label_chunk(void) -{ - int ret; - uint32_t start, end; - struct label_chunk *new_label_chunk; - - if (zclient_sync->sock == -1) - isis_zebra_label_manager_connect(); - - ret = lm_get_label_chunk(zclient_sync, 0, MPLS_LABEL_BASE_ANY, - CHUNK_SIZE, &start, &end); - if (ret < 0) { - zlog_warn("%s: error getting label chunk!", __func__); - return -1; - } - - new_label_chunk = calloc(1, sizeof(struct label_chunk)); - if (!new_label_chunk) { - zlog_warn("%s: error trying to allocate label chunk %u - %u", - __func__, start, end); - return -1; - } - - new_label_chunk->start = start; - new_label_chunk->end = end; - new_label_chunk->used_mask = 0; - - listnode_add(label_chunk_list, (void *)new_label_chunk); - - /* let's update current if needed */ - if (!current_label_chunk) - current_label_chunk = listtail(label_chunk_list); - - return 0; -} - -/** - * Request a label from the Label Chunk list. - * - * @return valid label on success or MPLS_INVALID_LABEL on failure - */ -mpls_label_t isis_zebra_request_dynamic_label(void) -{ - struct label_chunk *label_chunk; - uint32_t i, size; - uint64_t pos; - uint32_t label = MPLS_INVALID_LABEL; - - while (current_label_chunk) { - label_chunk = listgetdata(current_label_chunk); - if (!label_chunk) - goto end; - - /* try to get next free label in currently used label chunk */ - size = label_chunk->end - label_chunk->start + 1; - for (i = 0, pos = 1; i < size; i++, pos <<= 1) { - if (!(pos & label_chunk->used_mask)) { - label_chunk->used_mask |= pos; - label = label_chunk->start + i; - goto end; - } - } - current_label_chunk = listnextnode(current_label_chunk); - } - -end: - /* - * we moved till the last chunk, or were not able to find a label, so - * let's ask for another one. - */ - if (!current_label_chunk - || current_label_chunk == listtail(label_chunk_list) - || label == MPLS_INVALID_LABEL) { - if (isis_zebra_get_label_chunk() != 0) - zlog_warn("%s: error getting label chunk!", __func__); - } - - return label; -} - -/** - * Delete a Label Chunk. - * - * @param val Pointer to the Label Chunk to free - */ -static void isis_zebra_del_label_chunk(void *val) -{ - free(val); -} - -/** - * Release a pre-allocated Label chunk to the Label Manager. - * - * @param start start of the label chunk to release - * @param end end of the label chunk to release - * - * @return 0 on success, -1 on failure - */ -static int isis_zebra_release_label_chunk(uint32_t start, uint32_t end) -{ - int ret; - - ret = lm_release_label_chunk(zclient_sync, start, end); - if (ret < 0) { - zlog_warn("%s: error releasing label chunk!", __func__); - return -1; - } - - return 0; -} - -/** - * Release a pre-attributes label to the Label Chunk list. - * - * @param label Label to be release - */ -void isis_zebra_release_dynamic_label(mpls_label_t label) -{ - struct listnode *node; - struct label_chunk *label_chunk; - uint64_t pos; - - for (ALL_LIST_ELEMENTS_RO(label_chunk_list, node, label_chunk)) { - if (!(label <= label_chunk->end && label >= label_chunk->start)) - continue; - - pos = 1ULL << (label - label_chunk->start); - label_chunk->used_mask &= ~pos; - - /* - * If nobody is using this chunk and it's not - * current_label_chunk, then free it. - */ - if (!label_chunk->used_mask && (current_label_chunk != node)) { - if (isis_zebra_release_label_chunk(label_chunk->start, - label_chunk->end) - != 0) - zlog_warn("%s: error releasing label chunk!", - __func__); - else { - listnode_delete(label_chunk_list, label_chunk); - isis_zebra_del_label_chunk(label_chunk); - } - } - break; - } -} - /** * Connect to the Label Manager. */ @@ -689,14 +531,8 @@ static void isis_zebra_label_manager_connect(void) /* Connect to label manager */ while (lm_label_manager_connect(zclient_sync, 0) != 0) { - zlog_warn("%s: re-attempt connecting to label manager!", __func__); - sleep(1); - } - - label_chunk_list = list_new(); - label_chunk_list->del = isis_zebra_del_label_chunk; - while (isis_zebra_get_label_chunk() != 0) { - zlog_warn("%s: re-attempt getting first label chunk!", __func__); + zlog_warn("%s: re-attempt connecting to label manager!", + __func__); sleep(1); } } diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h index b143d34626..e853ce34d9 100644 --- a/isisd/isis_zebra.h +++ b/isisd/isis_zebra.h @@ -51,7 +51,5 @@ void isis_zebra_redistribute_set(afi_t afi, int type); void isis_zebra_redistribute_unset(afi_t afi, int type); int isis_zebra_request_label_range(uint32_t base, uint32_t chunk_size); void isis_zebra_release_label_range(uint32_t start, uint32_t end); -mpls_label_t isis_zebra_request_dynamic_label(void); -void isis_zebra_release_dynamic_label(mpls_label_t label); #endif /* _ZEBRA_ISIS_ZEBRA_H */ diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 445a59bc8a..befdc3467d 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -1213,6 +1213,23 @@ module frr-isisd { "Upper value in the label range."; } } + container srlb { + description + "Local blocks to be advertised."; + must "./upper-bound > ./lower-bound"; + leaf lower-bound { + type uint32; + default "15000"; + description + "Lower value in the label range."; + } + leaf upper-bound { + type uint32; + default "15999"; + description + "Upper value in the label range."; + } + } container msd { description "MSD configuration.";