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)
- isis_zebra_release_label_range(srdb->config.srgb_lower_bound,
+ /* Just store new SRGB values if Label Manager is not available.
+ * SRGB will be configured later when SR start */
+ if (!isis_zebra_label_manager_ready()) {
+ srdb->config.srgb_lower_bound = lower_bound;
+ srdb->config.srgb_upper_bound = upper_bound;
+ return 0;
+ }
+
+ /* Label Manager is ready, start by releasing the old SRGB. */
+ if (srdb->srgb_active) {
+ isis_zebra_release_label_range(srdb->config.srgb_lower_bound,
srdb->config.srgb_upper_bound);
+ srdb->srgb_active = false;
+ }
srdb->config.srgb_lower_bound = lower_bound;
srdb->config.srgb_upper_bound = upper_bound;
if (isis_zebra_request_label_range(
srdb->config.srgb_lower_bound,
srdb->config.srgb_upper_bound
- - srdb->config.srgb_lower_bound + 1))
+ - srdb->config.srgb_lower_bound + 1) < 0) {
+ srdb->srgb_active = false;
return -1;
+ } else
+ srdb->srgb_active = true;
+
sr_debug(" |- Got new SRGB [%u/%u]",
srdb->config.srgb_lower_bound,
lsp_regenerate_schedule(area, area->is_type, 0);
} else if (srdb->config.enabled) {
/* Try to enable SR again using the new SRGB. */
- if (isis_sr_start(area) == 0)
- area->srdb.enabled = true;
+ isis_sr_start(area);
}
return 0;
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 */
+ /* Just store new SRLB values if Label Manager is not available.
+ * SRLB will be configured later when SR start */
+ if (!isis_zebra_label_manager_ready()) {
+ srdb->config.srlb_lower_bound = lower_bound;
+ srdb->config.srlb_upper_bound = upper_bound;
+ return 0;
+ }
+
+ /* LM is ready, start by deleting the old 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);
+ if (srdb->enabled) {
+ /* Initialize new SRLB */
+ if (sr_local_block_init(area) != 0)
+ return -1;
- /* Update Router Capability */
+ /* 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 and Flood LSP */
- lsp_regenerate_schedule(area, area->is_type, 0);
+ /* Update and Flood LSP */
+ lsp_regenerate_schedule(area, area->is_type, 0);
+ } else if (srdb->config.enabled) {
+ /* Try to enable SR again using the new SRLB. */
+ isis_sr_start(area);
+ }
return 0;
}
*
* @param area IS-IS area
*/
-static void sr_local_block_init(struct isis_area *area)
+static int sr_local_block_init(struct isis_area *area)
{
struct isis_sr_db *srdb = &area->srdb;
struct sr_local_block *srlb = &srdb->srlb;
+ /* Check if SRLB is not already configured */
+ if (srlb->active)
+ 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.
if (isis_zebra_request_label_range(
srdb->config.srlb_lower_bound,
srdb->config.srlb_upper_bound
- - srdb->config.srlb_lower_bound + 1))
- return;
+ - srdb->config.srlb_lower_bound + 1)) {
+ srlb->active = false;
+ return -1;
+ }
sr_debug("ISIS-Sr (%s): Got new SRLB [%u/%u]", area->area_tag,
srdb->config.srlb_lower_bound, srdb->config.srlb_upper_bound);
srlb->max_block++;
srlb->used_mark = XCALLOC(MTYPE_ISIS_SR_INFO,
srlb->max_block * SRLB_BLOCK_SIZE);
+ srlb->active = true;
+
+ return 0;
}
/**
struct isis_sr_db *srdb = &area->srdb;
struct sr_local_block *srlb = &srdb->srlb;
+ /* Check if SRLB is not already delete */
+ if (!srlb->active)
+ return;
+
sr_debug("ISIS-Sr (%s): Remove SRLB [%u/%u]", area->area_tag,
srlb->start, srlb->end);
/* 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));
+ srlb->active = false;
}
/**
/* --- IS-IS Segment Routing Management function ---------------------------- */
+/**
+ * Thread function to re-attempt connection to the Label Manager and thus be
+ * able to start Segment Routing.
+ *
+ * @param start Thread structure that contains area as argument
+ *
+ * @return 1 on success
+ */
+static int sr_start_label_manager(struct thread *start)
+{
+ struct isis_area *area;
+
+ area = THREAD_ARG(start);
+
+ /* re-attempt to start SR & Label Manager connection */
+ isis_sr_start(area);
+
+ return 1;
+}
+
/**
* Enable SR on the given IS-IS area.
*
struct isis_circuit *circuit;
struct listnode *node;
- /* Initialize the SRLB */
- if (sr_local_block_init(area) != 0)
+ /* First start Label Manager if not ready */
+ if (!isis_zebra_label_manager_ready())
+ if (isis_zebra_label_manager_connect() < 0) {
+ /* Re-attempt to connect to Label Manager in 1 sec. */
+ thread_add_timer(master, sr_start_label_manager, area,
+ 1, &srdb->t_start_lm);
+ return -1;
+ }
+
+ /* Label Manager is ready, 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.
+ * 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.
*/
- if (isis_zebra_request_label_range(
- srdb->config.srgb_lower_bound,
- srdb->config.srgb_upper_bound
- - srdb->config.srgb_lower_bound + 1))
- return -1;
+ if (!srdb->srgb_active) {
+ if (isis_zebra_request_label_range(
+ srdb->config.srgb_lower_bound,
+ srdb->config.srgb_upper_bound
+ - srdb->config.srgb_lower_bound + 1)
+ < 0) {
+ srdb->srgb_active = false;
+ return -1;
+ } else
+ srdb->srgb_active = true;
+ }
sr_debug("ISIS-Sr: Starting Segment Routing for area %s",
area->area_tag);
}
}
+ area->srdb.enabled = true;
+
/* Regenerate LSPs to advertise Segment Routing capabilities. */
lsp_regenerate_schedule(area, area->is_type, 0);
sr_debug("ISIS-Sr: Stopping Segment Routing for area %s",
area->area_tag);
+ /* Disable any re-attempt to connect to Label Manager */
+ THREAD_TIMER_OFF(srdb->t_start_lm);
+
/* Uninstall all local Adjacency-SIDs. */
for (ALL_LIST_ELEMENTS(area->srdb.adj_sids, node, nnode, sra))
sr_adj_sid_del(sra);
}
}
- /* Release SRGB. */
- isis_zebra_release_label_range(srdb->config.srgb_lower_bound,
- srdb->config.srgb_upper_bound);
+ /* Release SRGB if active. */
+ if (srdb->srgb_active) {
+ isis_zebra_release_label_range(srdb->config.srgb_lower_bound,
+ srdb->config.srgb_upper_bound);
+ srdb->srgb_active = false;
+ }
/* Delete SRLB */
sr_local_block_delete(area);
+ area->srdb.enabled = false;
+
/* Regenerate LSPs to advertise that the Node is no more SR enable. */
lsp_regenerate_schedule(area, area->is_type, 0);
}
/* Initialize Segment Routing Data Base */
memset(srdb, 0, sizeof(*srdb));
- srdb->enabled = false;
srdb->adj_sids = list_new();
for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
struct zclient *zclient;
static struct zclient *zclient_sync;
-static void isis_zebra_label_manager_connect(void);
-
/* Router-id update message from zebra. */
static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
{
/* Label Manager Functions */
+/**
+ * Check if Label Manager is Ready or not.
+ *
+ * @return True if Label Manager is ready, False otherwise
+ */
+bool isis_zebra_label_manager_ready(void)
+{
+ return (zclient_sync->sock > 0);
+}
+
/**
* Request Label Range to the Label Manager.
*
int ret;
uint32_t start, end;
- if (zclient_sync->sock == -1)
- isis_zebra_label_manager_connect();
+ if (zclient_sync->sock < 0)
+ return -1;
ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start,
&end);
*
* @param start start of label range to release
* @param end end of label range to release
+ *
+ * @return 0 on success, -1 otherwise
*/
-void isis_zebra_release_label_range(uint32_t start, uint32_t end)
+int isis_zebra_release_label_range(uint32_t start, uint32_t end)
{
int ret;
- if (zclient_sync->sock == -1)
- isis_zebra_label_manager_connect();
+ if (zclient_sync->sock < 0)
+ return -1;
ret = lm_release_label_chunk(zclient_sync, start, end);
- if (ret < 0)
+ if (ret < 0) {
zlog_warn("%s: error releasing label range!", __func__);
+ return -1;
+ }
+
+ return 0;
}
/**
* Connect to the Label Manager.
+ *
+ * @return 0 on success, -1 otherwise
*/
-static void isis_zebra_label_manager_connect(void)
+int isis_zebra_label_manager_connect(void)
{
/* Connect to label manager. */
- while (zclient_socket_connect(zclient_sync) < 0) {
- zlog_warn("%s: re-attempt connecting synchronous zclient!",
+ if (zclient_socket_connect(zclient_sync) < 0) {
+ zlog_warn("%s: failed connecting synchronous zclient!",
__func__);
- sleep(1);
+ return -1;
}
/* make socket non-blocking */
set_nonblocking(zclient_sync->sock);
/* Send hello to notify zebra this is a synchronous client */
- while (zclient_send_hello(zclient_sync) < 0) {
- zlog_warn(
- "%s: re-attempt sending hello for synchronous zclient!",
- __func__);
- sleep(1);
+ if (zclient_send_hello(zclient_sync) < 0) {
+ zlog_warn("%s: failed sending hello for synchronous zclient!",
+ __func__);
+ close(zclient_sync->sock);
+ zclient_sync->sock = -1;
+ return -1;
}
/* 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);
+ if (lm_label_manager_connect(zclient_sync, 0) != 0) {
+ zlog_warn("%s: failed connecting to label manager!", __func__);
+ if (zclient_sync->sock > 0) {
+ close(zclient_sync->sock);
+ zclient_sync->sock = -1;
+ }
+ return -1;
}
+
+ sr_debug("ISIS-Sr: Successfully connected to the Label Manager");
+
+ return 0;
}
static void isis_zebra_connected(struct zclient *zclient)
void isis_zebra_stop(void)
{
+ zclient_stop(zclient_sync);
+ zclient_free(zclient_sync);
zclient_stop(zclient);
zclient_free(zclient);
frr_fini();