mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-29 14:33:09 +00:00
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:
parent
4afc783610
commit
450841fe05
@ -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([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([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([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([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_VTY_DIR], ["$frr_statedir%s%s"], [daemon vty directory])
|
||||||
AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory])
|
AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory])
|
||||||
|
@ -1372,6 +1372,7 @@ int lsp_generate(struct isis_area *area, int level)
|
|||||||
uint32_t seq_num = 0;
|
uint32_t seq_num = 0;
|
||||||
uint8_t lspid[ISIS_SYS_ID_LEN + 2];
|
uint8_t lspid[ISIS_SYS_ID_LEN + 2];
|
||||||
uint16_t rem_lifetime, refresh_time;
|
uint16_t rem_lifetime, refresh_time;
|
||||||
|
uint32_t overload_time;
|
||||||
|
|
||||||
if ((area == NULL) || (area->is_type & level) != level)
|
if ((area == NULL) || (area->is_type & level) != level)
|
||||||
return ISIS_ERROR;
|
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);
|
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 */
|
/* only builds the lsp if the area shares the level */
|
||||||
oldlsp = lsp_search(&area->lspdb[level - 1], lspid);
|
oldlsp = lsp_search(&area->lspdb[level - 1], lspid);
|
||||||
if (oldlsp) {
|
if (oldlsp) {
|
||||||
@ -1448,20 +1461,6 @@ static int lsp_regenerate(struct isis_area *area, int level)
|
|||||||
if ((area == NULL) || (area->is_type & level) != level)
|
if ((area == NULL) || (area->is_type & level) != level)
|
||||||
return ISIS_ERROR;
|
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];
|
head = &area->lspdb[level - 1];
|
||||||
memset(lspid, 0, ISIS_SYS_ID_LEN + 2);
|
memset(lspid, 0, ISIS_SYS_ID_LEN + 2);
|
||||||
memcpy(lspid, area->isis->sysid, ISIS_SYS_ID_LEN);
|
memcpy(lspid, area->isis->sysid, ISIS_SYS_ID_LEN);
|
||||||
|
@ -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,
|
void isis_area_overload_on_startup_set(struct isis_area *area,
|
||||||
uint32_t startup_time)
|
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;
|
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)
|
void isis_area_attached_bit_send_set(struct isis_area *area, bool attached_bit)
|
||||||
|
@ -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,
|
void show_isis_database_lspdb_vty(struct vty *vty, struct isis_area *area,
|
||||||
int level, struct lspdb_head *lspdb,
|
int level, struct lspdb_head *lspdb,
|
||||||
const char *argv, int ui_level);
|
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 */
|
/* YANG paths */
|
||||||
#define ISIS_INSTANCE "/frr-isisd:isis/instance"
|
#define ISIS_INSTANCE "/frr-isisd:isis/instance"
|
||||||
#define ISIS_SR "/frr-isisd:isis/instance/segment-routing"
|
#define ISIS_SR "/frr-isisd:isis/instance/segment-routing"
|
||||||
|
@ -436,35 +436,6 @@ def test_isis_overload_on_startup():
|
|||||||
assert result
|
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():
|
def test_isis_overload_on_startup_cancel_timer():
|
||||||
"Check that overload on startup timer is cancelled when overload bit is set/unset"
|
"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():
|
if tgen.routers_have_failure():
|
||||||
pytest.skip(tgen.errors)
|
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
|
# Configure set-overload-bit on-startup on r3
|
||||||
r3 = tgen.gears["r3"]
|
r3 = tgen.gears["r3"]
|
||||||
@ -527,7 +500,9 @@ def test_isis_overload_on_startup_override_timer():
|
|||||||
if tgen.routers_have_failure():
|
if tgen.routers_have_failure():
|
||||||
pytest.skip(tgen.errors)
|
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
|
# Configure set-overload-bit on-startup on r3
|
||||||
r3 = tgen.gears["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")
|
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)
|
@retry(retry_timeout=200)
|
||||||
def _check_overload_timer(router, timer_expected):
|
def _check_overload_timer(router, timer_expected):
|
||||||
"Verfiy overload bit in router's LSP"
|
"Verfiy overload bit in router's LSP"
|
||||||
|
|
||||||
tgen = get_topogen()
|
tgen = get_topogen()
|
||||||
router = tgen.gears[router]
|
router = tgen.gears[router]
|
||||||
thread_output = router.vtysh_cmd(
|
thread_output = router.vtysh_cmd("show thread timers")
|
||||||
"show thread timers"
|
|
||||||
)
|
|
||||||
|
|
||||||
timer_running = "set_overload_on_start_timer" in thread_output
|
timer_running = "set_overload_on_start_timer" in thread_output
|
||||||
if timer_running == timer_expected:
|
if timer_running == timer_expected:
|
||||||
@ -577,9 +579,7 @@ def _check_overload_timer(router, timer_expected):
|
|||||||
def check_overload_timer(router, timer_expected):
|
def check_overload_timer(router, timer_expected):
|
||||||
"Verfiy overload bit in router's LSP"
|
"Verfiy overload bit in router's LSP"
|
||||||
|
|
||||||
assertmsg = _check_overload_timer(
|
assertmsg = _check_overload_timer(router, timer_expected)
|
||||||
router, timer_expected
|
|
||||||
)
|
|
||||||
assert assertmsg is True, assertmsg
|
assert assertmsg is True, assertmsg
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user