isisd: Add JSON object functions to save overload status between restarts.

Signed-off-by: Isabella de Leon <ideleon@microsoft.com>
This commit is contained in:
Isabella de Leon 2022-10-12 16:03:29 -07:00
parent 4afc783610
commit 450841fe05
5 changed files with 152 additions and 53 deletions

View File

@ -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])

View File

@ -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);

View File

@ -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)

View File

@ -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"

View File

@ -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"]
@ -558,15 +533,42 @@ def test_isis_overload_on_startup_override_timer():
check_lsp_overload_bit("r3", "r3.00-00", "0/0/1")
@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
@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"
)
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