summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--isisd/isis_lsp.c4
-rw-r--r--isisd/isis_main.c35
-rw-r--r--isisd/isisd.c13
-rw-r--r--isisd/isisd.h4
4 files changed, 56 insertions, 0 deletions
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 63b4edb1e1..595144147a 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -1377,6 +1377,10 @@ int lsp_generate(struct isis_area *area, int level)
if ((area == NULL) || (area->is_type & level) != level)
return ISIS_ERROR;
+ /* Check if config is still being processed */
+ if (thread_is_scheduled(t_isis_cfg))
+ return ISIS_OK;
+
memset(&lspid, 0, ISIS_SYS_ID_LEN + 2);
memcpy(&lspid, area->isis->sysid, ISIS_SYS_ID_LEN);
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 607661b540..ebd8eb28ef 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -181,6 +181,40 @@ static const struct frr_yang_module_info *const isisd_yang_modules[] = {
};
/* clang-format on */
+
+static void isis_config_finish(struct thread *t)
+{
+ struct listnode *node, *inode;
+ struct isis *isis;
+ struct isis_area *area;
+
+ for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
+ config_end_lsp_generate(area);
+ }
+}
+
+static void isis_config_start(void)
+{
+ /* Max wait time for config to load before generating lsp */
+#define ISIS_PRE_CONFIG_MAX_WAIT_SECONDS 600
+ THREAD_OFF(t_isis_cfg);
+ thread_add_timer(im->master, isis_config_finish, NULL,
+ ISIS_PRE_CONFIG_MAX_WAIT_SECONDS, &t_isis_cfg);
+}
+
+static void isis_config_end(void)
+{
+ /* If ISIS config processing thread isn't running, then
+ * we can return and rely it's properly handled.
+ */
+ if (!thread_is_scheduled(t_isis_cfg))
+ return;
+
+ THREAD_OFF(t_isis_cfg);
+ isis_config_finish(t_isis_cfg);
+}
+
#ifdef FABRICD
FRR_DAEMON_INFO(fabricd, OPEN_FABRIC, .vty_port = FABRICD_VTY_PORT,
@@ -244,6 +278,7 @@ int main(int argc, char **argv, char **envp)
/*
* initializations
*/
+ cmd_init_config_callbacks(isis_config_start, isis_config_end);
isis_error_init();
access_list_init();
access_list_add_hook(isis_filter_update);
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 7e40c21a0d..9c62c6b4f0 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -100,6 +100,9 @@ static struct isis_master isis_master;
/* ISIS process wide configuration pointer to export. */
struct isis_master *im;
+/* ISIS config processing thread */
+struct thread *t_isis_cfg;
+
#ifndef FABRICD
DEFINE_HOOK(isis_hook_db_overload, (const struct isis_area *area), (area));
#endif /* ifndef FABRICD */
@@ -3247,6 +3250,16 @@ void isis_area_overload_on_startup_set(struct isis_area *area,
}
}
+void config_end_lsp_generate(struct isis_area *area)
+{
+ if (listcount(area->area_addrs) > 0) {
+ if (CHECK_FLAG(area->is_type, IS_LEVEL_1))
+ lsp_generate(area, IS_LEVEL_1);
+ if (CHECK_FLAG(area->is_type, IS_LEVEL_2))
+ lsp_generate(area, IS_LEVEL_2);
+ }
+}
+
/*
* Returns the path of the file (non-volatile memory) that contains restart
* information.
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 38f20b2113..dae512c159 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -112,6 +112,8 @@ struct isis {
extern struct isis_master *im;
+extern struct thread *t_isis_cfg;
+
enum spf_tree_id {
SPFTREE_IPV4 = 0,
SPFTREE_IPV6,
@@ -327,6 +329,8 @@ char *isis_restart_filepath(void);
void isis_restart_write_overload_time(struct isis_area *isis_area,
uint32_t overload_time);
uint32_t isis_restart_read_overload_time(struct isis_area *isis_area);
+void config_end_lsp_generate(struct isis_area *area);
+
/* YANG paths */
#define ISIS_INSTANCE "/frr-isisd:isis/instance"
#define ISIS_SR "/frr-isisd:isis/instance/segment-routing"