diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | isisd/isis_lsp.c | 27 | ||||
-rw-r--r-- | isisd/isisd.c | 98 | ||||
-rw-r--r-- | isisd/isisd.h | 5 | ||||
-rw-r--r-- | tests/topotests/isis_topo1/test_isis_topo1.py | 74 |
5 files changed, 152 insertions, 53 deletions
diff --git a/configure.ac b/configure.ac index 8c1fab0ea..00251fa38 100644 --- a/configure.ac +++ b/configure.ac @@ -2631,6 +2631,7 @@ AC_DEFINE_UNQUOTED([ZEBRA_SERV_PATH], ["$frr_statedir%s%s/zserv.api"], [zebra ap AC_DEFINE_UNQUOTED([BFDD_CONTROL_SOCKET], ["$frr_statedir%s%s/bfdd.sock"], [bfdd control socket]) AC_DEFINE_UNQUOTED([OSPFD_GR_STATE], ["$frr_statedir%s/ospfd-gr.json"], [ospfd GR state information]) AC_DEFINE_UNQUOTED([OSPF6D_GR_STATE], ["$frr_statedir/ospf6d-gr.json"], [ospf6d GR state information]) +AC_DEFINE_UNQUOTED([ISISD_RESTART], ["$frr_statedir%s/isid-restart.json"], [isisd restart information]) AC_DEFINE_UNQUOTED([OSPF6_AUTH_SEQ_NUM_FILE], ["$frr_statedir/ospf6d-at-seq-no.dat"], [ospf6d AT Sequence number information]) AC_DEFINE_UNQUOTED([DAEMON_VTY_DIR], ["$frr_statedir%s%s"], [daemon vty directory]) AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory]) diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 2dc6f15c7..63b4edb1e 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -1372,6 +1372,7 @@ int lsp_generate(struct isis_area *area, int level) uint32_t seq_num = 0; uint8_t lspid[ISIS_SYS_ID_LEN + 2]; uint16_t rem_lifetime, refresh_time; + uint32_t overload_time; if ((area == NULL) || (area->is_type & level) != level) return ISIS_ERROR; @@ -1380,6 +1381,18 @@ int lsp_generate(struct isis_area *area, int level) memcpy(&lspid, area->isis->sysid, ISIS_SYS_ID_LEN); + /* Check if device should be overloaded on startup */ + if (device_startup) { + overload_time = isis_restart_read_overload_time(area); + if (overload_time > 0) { + isis_area_overload_bit_set(area, true); + thread_add_timer(master, set_overload_on_start_timer, + area, overload_time, + &area->t_overload_on_startup_timer); + } + device_startup = false; + } + /* only builds the lsp if the area shares the level */ oldlsp = lsp_search(&area->lspdb[level - 1], lspid); if (oldlsp) { @@ -1448,20 +1461,6 @@ static int lsp_regenerate(struct isis_area *area, int level) if ((area == NULL) || (area->is_type & level) != level) return ISIS_ERROR; - /* - * Check if the device is initializing and set overload bit on startup - * is configured. - */ - if (device_startup) { - if (area->overload_on_startup_time > 0) { - isis_area_overload_bit_set(area, true); - thread_add_timer(master, set_overload_on_start_timer, - area, area->overload_on_startup_time, - &area->t_overload_on_startup_timer); - } - device_startup = false; - } - head = &area->lspdb[level - 1]; memset(lspid, 0, ISIS_SYS_ID_LEN + 2); memcpy(lspid, area->isis->sysid, ISIS_SYS_ID_LEN); diff --git a/isisd/isisd.c b/isisd/isisd.c index d59a41184..7dd08cb13 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -3214,8 +3214,104 @@ void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit) void isis_area_overload_on_startup_set(struct isis_area *area, uint32_t startup_time) { - if (area->overload_on_startup_time != startup_time) + if (area->overload_on_startup_time != startup_time) { area->overload_on_startup_time = startup_time; + isis_restart_write_overload_time(area, startup_time); + } +} + +/* + * Returns the path of the file (non-volatile memory) that contains restart + * information. + */ +char *isis_restart_filepath() +{ + static char filepath[MAXPATHLEN]; + snprintf(filepath, sizeof(filepath), ISISD_RESTART, ""); + return filepath; +} + +/* + * Record in non-volatile memory the overload on startup time. + */ +void isis_restart_write_overload_time(struct isis_area *isis_area, + uint32_t overload_time) +{ + char *filepath; + const char *area_name; + json_object *json; + json_object *json_areas; + json_object *json_area; + + filepath = isis_restart_filepath(); + area_name = isis_area->area_tag; + + json = json_object_from_file(filepath); + if (json == NULL) + json = json_object_new_object(); + + json_object_object_get_ex(json, "areas", &json_areas); + if (!json_areas) { + json_areas = json_object_new_object(); + json_object_object_add(json, "areas", json_areas); + } + + json_object_object_get_ex(json_areas, area_name, &json_area); + if (!json_area) { + json_area = json_object_new_object(); + json_object_object_add(json_areas, area_name, json_area); + } + + json_object_int_add(json_area, "overload_time", + isis_area->overload_on_startup_time); + json_object_to_file_ext(filepath, json, JSON_C_TO_STRING_PRETTY); + json_object_free(json); +} + +/* + * Fetch from non-volatile memory the overload on startup time. + */ +uint32_t isis_restart_read_overload_time(struct isis_area *isis_area) +{ + char *filepath; + const char *area_name; + json_object *json; + json_object *json_areas; + json_object *json_area; + json_object *json_overload_time; + uint32_t overload_time = 0; + + filepath = isis_restart_filepath(); + area_name = isis_area->area_tag; + + json = json_object_from_file(filepath); + if (json == NULL) + json = json_object_new_object(); + + json_object_object_get_ex(json, "areas", &json_areas); + if (!json_areas) { + json_areas = json_object_new_object(); + json_object_object_add(json, "areas", json_areas); + } + + json_object_object_get_ex(json_areas, area_name, &json_area); + if (!json_area) { + json_area = json_object_new_object(); + json_object_object_add(json_areas, area_name, json_area); + } + + json_object_object_get_ex(json_area, "overload_time", + &json_overload_time); + if (json_overload_time) { + overload_time = json_object_get_int(json_overload_time); + } + + json_object_object_del(json_areas, area_name); + + json_object_to_file_ext(filepath, json, JSON_C_TO_STRING_PRETTY); + json_object_free(json); + + return overload_time; } void isis_area_attached_bit_send_set(struct isis_area *area, bool attached_bit) diff --git a/isisd/isisd.h b/isisd/isisd.h index 81877f745..bc1aa1295 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -319,7 +319,10 @@ void show_isis_database_lspdb_json(struct json_object *json, void show_isis_database_lspdb_vty(struct vty *vty, struct isis_area *area, int level, struct lspdb_head *lspdb, const char *argv, int ui_level); - +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); /* YANG paths */ #define ISIS_INSTANCE "/frr-isisd:isis/instance" #define ISIS_SR "/frr-isisd:isis/instance/segment-routing" diff --git a/tests/topotests/isis_topo1/test_isis_topo1.py b/tests/topotests/isis_topo1/test_isis_topo1.py index 519ebba0c..8b6c3772b 100644 --- a/tests/topotests/isis_topo1/test_isis_topo1.py +++ b/tests/topotests/isis_topo1/test_isis_topo1.py @@ -436,35 +436,6 @@ def test_isis_overload_on_startup(): assert result -@retry(retry_timeout=200) -def _check_lsp_overload_bit(router, overloaded_router_lsp, att_p_ol_expected): - "Verfiy overload bit in router's LSP" - - tgen = get_topogen() - router = tgen.gears[router] - logger.info(f"check_overload_bit {router}") - isis_database_output = router.vtysh_cmd( - "show isis database {} json".format(overloaded_router_lsp) - ) - - database_json = json.loads(isis_database_output) - att_p_ol = database_json["areas"][0]["levels"][1]["att-p-ol"] - if att_p_ol == att_p_ol_expected: - return True - return "{} peer with expected att_p_ol {} got {} ".format( - router.name, att_p_ol_expected, att_p_ol - ) - - -def check_lsp_overload_bit(router, overloaded_router_lsp, att_p_ol_expected): - "Verfiy overload bit in router's LSP" - - assertmsg = _check_lsp_overload_bit( - router, overloaded_router_lsp, att_p_ol_expected - ) - assert assertmsg is True, assertmsg - - def test_isis_overload_on_startup_cancel_timer(): "Check that overload on startup timer is cancelled when overload bit is set/unset" @@ -476,7 +447,9 @@ def test_isis_overload_on_startup_cancel_timer(): if tgen.routers_have_failure(): pytest.skip(tgen.errors) - logger.info("Testing overload on startup behavior with set overload bit: cancel timer") + logger.info( + "Testing overload on startup behavior with set overload bit: cancel timer" + ) # Configure set-overload-bit on-startup on r3 r3 = tgen.gears["r3"] @@ -527,7 +500,9 @@ def test_isis_overload_on_startup_override_timer(): if tgen.routers_have_failure(): pytest.skip(tgen.errors) - logger.info("Testing overload on startup behavior with set overload bit: override timer") + logger.info( + "Testing overload on startup behavior with set overload bit: override timer" + ) # Configure set-overload-bit on-startup on r3 r3 = tgen.gears["r3"] @@ -559,14 +534,41 @@ def test_isis_overload_on_startup_override_timer(): @retry(retry_timeout=200) -def _check_overload_timer(router, timer_expected): +def _check_lsp_overload_bit(router, overloaded_router_lsp, att_p_ol_expected): "Verfiy overload bit in router's LSP" tgen = get_topogen() router = tgen.gears[router] - thread_output = router.vtysh_cmd( - "show thread timers" + logger.info(f"check_overload_bit {router}") + isis_database_output = router.vtysh_cmd( + "show isis database {} json".format(overloaded_router_lsp) + ) + + database_json = json.loads(isis_database_output) + att_p_ol = database_json["areas"][0]["levels"][1]["att-p-ol"] + if att_p_ol == att_p_ol_expected: + return True + return "{} peer with expected att_p_ol {} got {} ".format( + router.name, att_p_ol_expected, att_p_ol + ) + + +def check_lsp_overload_bit(router, overloaded_router_lsp, att_p_ol_expected): + "Verfiy overload bit in router's LSP" + + assertmsg = _check_lsp_overload_bit( + router, overloaded_router_lsp, att_p_ol_expected ) + assert assertmsg is True, assertmsg + + +@retry(retry_timeout=200) +def _check_overload_timer(router, timer_expected): + "Verfiy overload bit in router's LSP" + + tgen = get_topogen() + router = tgen.gears[router] + thread_output = router.vtysh_cmd("show thread timers") timer_running = "set_overload_on_start_timer" in thread_output if timer_running == timer_expected: @@ -577,9 +579,7 @@ def _check_overload_timer(router, timer_expected): def check_overload_timer(router, timer_expected): "Verfiy overload bit in router's LSP" - assertmsg = _check_overload_timer( - router, timer_expected - ) + assertmsg = _check_overload_timer(router, timer_expected) assert assertmsg is True, assertmsg |