mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-06-13 17:49:56 +00:00
Merge pull request #11980 from isabelladeleon12/set_overload_startup
isisd: Add support for set-overload on-startup
This commit is contained in:
commit
07735ca345
@ -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])
|
||||
|
@ -83,6 +83,10 @@ writing, *isisd* does not support multiple ISIS processes.
|
||||
|
||||
Set overload bit to avoid any transit traffic.
|
||||
|
||||
.. clicmd:: set-overload-bit on-startup (0-86400)
|
||||
|
||||
Set overload bit on startup for the specified duration, in seconds. Reference: :rfc:`3277`
|
||||
|
||||
.. clicmd:: purge-originator
|
||||
|
||||
Enable or disable :rfc:`6232` purge originator identification.
|
||||
|
@ -404,7 +404,7 @@ DEFPY_YANG(set_overload_bit, set_overload_bit_cmd, "[no] set-overload-bit",
|
||||
"Reset overload bit to accept transit traffic\n"
|
||||
"Set overload bit to avoid any transit traffic\n")
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./overload", NB_OP_MODIFY,
|
||||
nb_cli_enqueue_change(vty, "./overload/enabled", NB_OP_MODIFY,
|
||||
no ? "false" : "true");
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
@ -418,6 +418,42 @@ void cli_show_isis_overload(struct vty *vty, const struct lyd_node *dnode,
|
||||
vty_out(vty, " set-overload-bit\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/overload/on-startup
|
||||
*/
|
||||
DEFPY_YANG(set_overload_bit_on_startup, set_overload_bit_on_startup_cmd,
|
||||
"set-overload-bit on-startup (0-86400)$val",
|
||||
"Set overload bit to avoid any transit traffic\n"
|
||||
"Set overload bit on startup\n"
|
||||
"Set overload time in seconds\n")
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./overload/on-startup", NB_OP_MODIFY,
|
||||
val_str);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
DEFPY_YANG(no_set_overload_bit_on_startup, no_set_overload_bit_on_startup_cmd,
|
||||
"no set-overload-bit on-startup [(0-86400)$val]",
|
||||
NO_STR
|
||||
"Reset overload bit to accept transit traffic\n"
|
||||
"Set overload bit on startup\n"
|
||||
"Set overload time in seconds\n")
|
||||
{
|
||||
nb_cli_enqueue_change(vty, "./overload/on-startup", NB_OP_DESTROY,
|
||||
NULL);
|
||||
|
||||
return nb_cli_apply_changes(vty, NULL);
|
||||
}
|
||||
|
||||
void cli_show_isis_overload_on_startup(struct vty *vty,
|
||||
const struct lyd_node *dnode,
|
||||
bool show_defaults)
|
||||
{
|
||||
vty_out(vty, " set-overload-bit on-startup %s\n",
|
||||
yang_dnode_get_string(dnode, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/attach-send
|
||||
*/
|
||||
@ -3107,6 +3143,9 @@ void isis_cli_init(void)
|
||||
install_element(ISIS_NODE, &dynamic_hostname_cmd);
|
||||
|
||||
install_element(ISIS_NODE, &set_overload_bit_cmd);
|
||||
install_element(ISIS_NODE, &set_overload_bit_on_startup_cmd);
|
||||
install_element(ISIS_NODE, &no_set_overload_bit_on_startup_cmd);
|
||||
|
||||
install_element(ISIS_NODE, &attached_bit_send_cmd);
|
||||
install_element(ISIS_NODE, &attached_bit_receive_ignore_cmd);
|
||||
|
||||
|
@ -68,6 +68,8 @@ static void lsp_l2_refresh_pseudo(struct thread *thread);
|
||||
|
||||
static void lsp_destroy(struct isis_lsp *lsp);
|
||||
|
||||
static bool device_startup;
|
||||
|
||||
int lsp_id_cmp(uint8_t *id1, uint8_t *id2)
|
||||
{
|
||||
return memcmp(id1, id2, ISIS_SYS_ID_LEN + 2);
|
||||
@ -437,6 +439,21 @@ bool isis_level2_adj_up(struct isis_area *area)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unset the overload bit after the timer expires
|
||||
*/
|
||||
void set_overload_on_start_timer(struct thread *thread)
|
||||
{
|
||||
struct isis_area *area = THREAD_ARG(thread);
|
||||
assert(area);
|
||||
|
||||
area->t_overload_on_startup_timer = NULL;
|
||||
|
||||
/* Check if set-overload-bit is not currently configured */
|
||||
if (!area->overload_configured)
|
||||
isis_area_overload_bit_set(area, false);
|
||||
}
|
||||
|
||||
static void isis_reset_attach_bit(struct isis_adjacency *adj)
|
||||
{
|
||||
struct isis_area *area = adj->circuit->area;
|
||||
@ -1355,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;
|
||||
@ -1363,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) {
|
||||
@ -2373,6 +2403,7 @@ int isis_lsp_iterate_is_reach(struct isis_lsp *lsp, uint16_t mtid,
|
||||
|
||||
void lsp_init(void)
|
||||
{
|
||||
device_startup = true;
|
||||
hook_register(isis_adj_state_change_hook,
|
||||
lsp_handle_adj_state_change);
|
||||
}
|
||||
|
@ -66,6 +66,7 @@ DECLARE_RBTREE_UNIQ(lspdb, struct isis_lsp, dbe, lspdb_compare);
|
||||
void lsp_db_init(struct lspdb_head *head);
|
||||
void lsp_db_fini(struct lspdb_head *head);
|
||||
void lsp_tick(struct thread *thread);
|
||||
void set_overload_on_start_timer(struct thread *thread);
|
||||
|
||||
int lsp_generate(struct isis_area *area, int level);
|
||||
#define lsp_regenerate_schedule(area, level, all_pseudo) \
|
||||
|
@ -81,11 +81,18 @@ const struct frr_yang_module_info frr_isisd_info = {
|
||||
},
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-isisd:isis/instance/overload",
|
||||
.xpath = "/frr-isisd:isis/instance/overload/enabled",
|
||||
.cbs = {
|
||||
.cli_show = cli_show_isis_overload,
|
||||
.modify = isis_instance_overload_modify,
|
||||
},
|
||||
.modify = isis_instance_overload_enabled_modify,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-isisd:isis/instance/overload/on-startup",
|
||||
.cbs = {
|
||||
.cli_show = cli_show_isis_overload_on_startup,
|
||||
.modify = isis_instance_overload_on_startup_modify,
|
||||
}
|
||||
},
|
||||
{
|
||||
.xpath = "/frr-isisd:isis/instance/metric-style",
|
||||
|
@ -37,7 +37,8 @@ int isis_instance_dynamic_hostname_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_attached_send_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_attached_receive_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_attached_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_overload_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_overload_enabled_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_overload_on_startup_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_metric_style_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_purge_originator_modify(struct nb_cb_modify_args *args);
|
||||
int isis_instance_lsp_mtu_modify(struct nb_cb_modify_args *args);
|
||||
@ -442,6 +443,9 @@ void cli_show_isis_attached_receive(struct vty *vty,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_overload(struct vty *vty, const struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_overload_on_startup(struct vty *vty,
|
||||
const struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_metric_style(struct vty *vty, const struct lyd_node *dnode,
|
||||
bool show_defaults);
|
||||
void cli_show_isis_area_pwd(struct vty *vty, const struct lyd_node *dnode,
|
||||
|
@ -336,9 +336,9 @@ int isis_instance_attached_modify(struct nb_cb_modify_args *args)
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/overload
|
||||
* XPath: /frr-isisd:isis/instance/overload/enabled
|
||||
*/
|
||||
int isis_instance_overload_modify(struct nb_cb_modify_args *args)
|
||||
int isis_instance_overload_enabled_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct isis_area *area;
|
||||
bool overload;
|
||||
@ -348,11 +348,31 @@ int isis_instance_overload_modify(struct nb_cb_modify_args *args)
|
||||
|
||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||
overload = yang_dnode_get_bool(args->dnode, NULL);
|
||||
area->overload_configured = overload;
|
||||
|
||||
isis_area_overload_bit_set(area, overload);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/overload/on-startup
|
||||
*/
|
||||
int isis_instance_overload_on_startup_modify(struct nb_cb_modify_args *args)
|
||||
{
|
||||
struct isis_area *area;
|
||||
uint32_t overload_time;
|
||||
|
||||
if (args->event != NB_EV_APPLY)
|
||||
return NB_OK;
|
||||
|
||||
overload_time = yang_dnode_get_uint32(args->dnode, NULL);
|
||||
area = nb_running_get_entry(args->dnode, NULL, true);
|
||||
isis_area_overload_on_startup_set(area, overload_time);
|
||||
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* XPath: /frr-isisd:isis/instance/metric-style
|
||||
*/
|
||||
|
113
isisd/isisd.c
113
isisd/isisd.c
@ -3198,9 +3198,15 @@ void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit)
|
||||
|
||||
if (new_overload_bit != area->overload_bit) {
|
||||
area->overload_bit = new_overload_bit;
|
||||
|
||||
if (new_overload_bit)
|
||||
if (new_overload_bit) {
|
||||
area->overload_counter++;
|
||||
} else {
|
||||
/* Cancel overload on startup timer if it's running */
|
||||
if (area->t_overload_on_startup_timer) {
|
||||
THREAD_OFF(area->t_overload_on_startup_timer);
|
||||
area->t_overload_on_startup_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef FABRICD
|
||||
hook_call(isis_hook_db_overload, area);
|
||||
@ -3213,6 +3219,109 @@ void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit)
|
||||
#endif /* ifndef FABRICD */
|
||||
}
|
||||
|
||||
void isis_area_overload_on_startup_set(struct isis_area *area,
|
||||
uint32_t 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)
|
||||
{
|
||||
|
||||
|
@ -142,6 +142,7 @@ struct isis_area {
|
||||
struct flags flags;
|
||||
struct thread *t_tick; /* LSP walker */
|
||||
struct thread *t_lsp_refresh[ISIS_LEVELS];
|
||||
struct thread *t_overload_on_startup_timer;
|
||||
struct timeval last_lsp_refresh_event[ISIS_LEVELS];
|
||||
struct thread *t_rlfa_rib_update;
|
||||
/* t_lsp_refresh is used in two ways:
|
||||
@ -180,7 +181,9 @@ struct isis_area {
|
||||
char is_type; /* level-1 level-1-2 or level-2-only */
|
||||
/* are we overloaded? */
|
||||
char overload_bit;
|
||||
bool overload_configured;
|
||||
uint32_t overload_counter;
|
||||
uint32_t overload_on_startup_time;
|
||||
/* L1/L2 router identifier for inter-area traffic */
|
||||
char attached_bit_send;
|
||||
char attached_bit_rcv_ignore;
|
||||
@ -290,6 +293,8 @@ void isis_area_invalidate_routes(struct isis_area *area, int levels);
|
||||
void isis_area_verify_routes(struct isis_area *area);
|
||||
|
||||
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);
|
||||
void isis_area_attached_bit_send_set(struct isis_area *area, bool attached_bit);
|
||||
void isis_area_attached_bit_receive_set(struct isis_area *area,
|
||||
bool attached_bit);
|
||||
@ -315,7 +320,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"
|
||||
|
@ -25,7 +25,7 @@
|
||||
"""
|
||||
test_isis_topo1.py: Test ISIS topology.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import functools
|
||||
import json
|
||||
import os
|
||||
@ -38,6 +38,11 @@ sys.path.append(os.path.join(CWD, "../"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
from lib import topotest
|
||||
from lib.common_config import (
|
||||
retry,
|
||||
stop_router,
|
||||
start_router,
|
||||
)
|
||||
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||
from lib.topolog import logger
|
||||
|
||||
@ -248,10 +253,12 @@ def test_isis_summary_json():
|
||||
for rname, router in tgen.routers().items():
|
||||
logger.info("Checking router %s", rname)
|
||||
json_output = tgen.gears[rname].vtysh_cmd("show isis summary json", isjson=True)
|
||||
assertmsg = "Test isis summary json failed in '{}' data '{}'".format(rname, json_output)
|
||||
assert json_output['vrf'] == "default", assertmsg
|
||||
assert json_output['areas'][0]['area'] == "1", assertmsg
|
||||
assert json_output['areas'][0]['levels'][0]['id'] != '3', assertmsg
|
||||
assertmsg = "Test isis summary json failed in '{}' data '{}'".format(
|
||||
rname, json_output
|
||||
)
|
||||
assert json_output["vrf"] == "default", assertmsg
|
||||
assert json_output["areas"][0]["area"] == "1", assertmsg
|
||||
assert json_output["areas"][0]["levels"][0]["id"] != "3", assertmsg
|
||||
|
||||
|
||||
def test_isis_interface_json():
|
||||
@ -265,15 +272,29 @@ def test_isis_interface_json():
|
||||
logger.info("Checking 'show isis interface json'")
|
||||
for rname, router in tgen.routers().items():
|
||||
logger.info("Checking router %s", rname)
|
||||
json_output = tgen.gears[rname].vtysh_cmd("show isis interface json", isjson=True)
|
||||
assertmsg = "Test isis interface json failed in '{}' data '{}'".format(rname, json_output)
|
||||
assert json_output['areas'][0]['circuits'][0]['interface']['name'] == rname+"-eth0", assertmsg
|
||||
json_output = tgen.gears[rname].vtysh_cmd(
|
||||
"show isis interface json", isjson=True
|
||||
)
|
||||
assertmsg = "Test isis interface json failed in '{}' data '{}'".format(
|
||||
rname, json_output
|
||||
)
|
||||
assert (
|
||||
json_output["areas"][0]["circuits"][0]["interface"]["name"]
|
||||
== rname + "-eth0"
|
||||
), assertmsg
|
||||
|
||||
for rname, router in tgen.routers().items():
|
||||
logger.info("Checking router %s", rname)
|
||||
json_output = tgen.gears[rname].vtysh_cmd("show isis interface detail json", isjson=True)
|
||||
assertmsg = "Test isis interface json failed in '{}' data '{}'".format(rname, json_output)
|
||||
assert json_output['areas'][0]['circuits'][0]['interface']['name'] == rname+"-eth0", assertmsg
|
||||
json_output = tgen.gears[rname].vtysh_cmd(
|
||||
"show isis interface detail json", isjson=True
|
||||
)
|
||||
assertmsg = "Test isis interface json failed in '{}' data '{}'".format(
|
||||
rname, json_output
|
||||
)
|
||||
assert (
|
||||
json_output["areas"][0]["circuits"][0]["interface"]["name"]
|
||||
== rname + "-eth0"
|
||||
), assertmsg
|
||||
|
||||
|
||||
def test_isis_neighbor_json():
|
||||
@ -284,19 +305,32 @@ def test_isis_neighbor_json():
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
#tgen.mininet_cli()
|
||||
# tgen.mininet_cli()
|
||||
logger.info("Checking 'show isis neighbor json'")
|
||||
for rname, router in tgen.routers().items():
|
||||
logger.info("Checking router %s", rname)
|
||||
json_output = tgen.gears[rname].vtysh_cmd("show isis neighbor json", isjson=True)
|
||||
assertmsg = "Test isis neighbor json failed in '{}' data '{}'".format(rname, json_output)
|
||||
assert json_output['areas'][0]['circuits'][0]['interface'] == rname+"-eth0", assertmsg
|
||||
json_output = tgen.gears[rname].vtysh_cmd(
|
||||
"show isis neighbor json", isjson=True
|
||||
)
|
||||
assertmsg = "Test isis neighbor json failed in '{}' data '{}'".format(
|
||||
rname, json_output
|
||||
)
|
||||
assert (
|
||||
json_output["areas"][0]["circuits"][0]["interface"] == rname + "-eth0"
|
||||
), assertmsg
|
||||
|
||||
for rname, router in tgen.routers().items():
|
||||
logger.info("Checking router %s", rname)
|
||||
json_output = tgen.gears[rname].vtysh_cmd("show isis neighbor detail json", isjson=True)
|
||||
assertmsg = "Test isis neighbor json failed in '{}' data '{}'".format(rname, json_output)
|
||||
assert json_output['areas'][0]['circuits'][0]['interface']['name'] == rname+"-eth0", assertmsg
|
||||
json_output = tgen.gears[rname].vtysh_cmd(
|
||||
"show isis neighbor detail json", isjson=True
|
||||
)
|
||||
assertmsg = "Test isis neighbor json failed in '{}' data '{}'".format(
|
||||
rname, json_output
|
||||
)
|
||||
assert (
|
||||
json_output["areas"][0]["circuits"][0]["interface"]["name"]
|
||||
== rname + "-eth0"
|
||||
), assertmsg
|
||||
|
||||
|
||||
def test_isis_database_json():
|
||||
@ -307,21 +341,246 @@ def test_isis_database_json():
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
#tgen.mininet_cli()
|
||||
# tgen.mininet_cli()
|
||||
logger.info("Checking 'show isis database json'")
|
||||
for rname, router in tgen.routers().items():
|
||||
logger.info("Checking router %s", rname)
|
||||
json_output = tgen.gears[rname].vtysh_cmd("show isis database json", isjson=True)
|
||||
assertmsg = "Test isis database json failed in '{}' data '{}'".format(rname, json_output)
|
||||
assert json_output['areas'][0]['area']['name'] == "1", assertmsg
|
||||
assert json_output['areas'][0]['levels'][0]['id'] != '3', assertmsg
|
||||
json_output = tgen.gears[rname].vtysh_cmd(
|
||||
"show isis database json", isjson=True
|
||||
)
|
||||
assertmsg = "Test isis database json failed in '{}' data '{}'".format(
|
||||
rname, json_output
|
||||
)
|
||||
assert json_output["areas"][0]["area"]["name"] == "1", assertmsg
|
||||
assert json_output["areas"][0]["levels"][0]["id"] != "3", assertmsg
|
||||
|
||||
for rname, router in tgen.routers().items():
|
||||
logger.info("Checking router %s", rname)
|
||||
json_output = tgen.gears[rname].vtysh_cmd("show isis database detail json", isjson=True)
|
||||
assertmsg = "Test isis database json failed in '{}' data '{}'".format(rname, json_output)
|
||||
assert json_output['areas'][0]['area']['name'] == "1", assertmsg
|
||||
assert json_output['areas'][0]['levels'][0]['id'] != '3', assertmsg
|
||||
json_output = tgen.gears[rname].vtysh_cmd(
|
||||
"show isis database detail json", isjson=True
|
||||
)
|
||||
assertmsg = "Test isis database json failed in '{}' data '{}'".format(
|
||||
rname, json_output
|
||||
)
|
||||
assert json_output["areas"][0]["area"]["name"] == "1", assertmsg
|
||||
assert json_output["areas"][0]["levels"][0]["id"] != "3", assertmsg
|
||||
|
||||
|
||||
def test_isis_overload_on_startup():
|
||||
"Check that overload on startup behaves as expected"
|
||||
|
||||
tgen = get_topogen()
|
||||
net = get_topogen().net
|
||||
overload_time = 120
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
logger.info("Testing overload on startup behavior")
|
||||
|
||||
# Configure set-overload-bit on-startup on r3
|
||||
r3 = tgen.gears["r3"]
|
||||
r3.vtysh_cmd(
|
||||
f"""
|
||||
configure
|
||||
router isis 1
|
||||
set-overload-bit on-startup {overload_time}
|
||||
"""
|
||||
)
|
||||
# Restart r3
|
||||
logger.info("Stop router")
|
||||
stop_router(tgen, "r3")
|
||||
logger.info("Start router")
|
||||
|
||||
tstamp_before_start_router = datetime.datetime.now()
|
||||
start_router(tgen, "r3")
|
||||
tstamp_after_start_router = datetime.datetime.now()
|
||||
startup_router_time = (
|
||||
tstamp_after_start_router - tstamp_before_start_router
|
||||
).total_seconds()
|
||||
|
||||
# Check that the overload bit is set in r3's LSP
|
||||
check_lsp_overload_bit("r3", "r3.00-00", "0/0/1")
|
||||
check_lsp_overload_bit("r1", "r3.00-00", "0/0/1")
|
||||
|
||||
# Attempt to unset overload bit while timer is still running
|
||||
r3.vtysh_cmd(
|
||||
"""
|
||||
configure
|
||||
router isis 1
|
||||
no set-overload-bit on-startup
|
||||
no set-overload-bit
|
||||
"""
|
||||
)
|
||||
|
||||
# Check overload bit is still set
|
||||
check_lsp_overload_bit("r1", "r3.00-00", "0/0/1")
|
||||
|
||||
# Check that overload bit is unset after timer completes
|
||||
check_lsp_overload_bit("r3", "r3.00-00", "0/0/0")
|
||||
tstamp_after_bit_unset = datetime.datetime.now()
|
||||
check_lsp_overload_bit("r1", "r3.00-00", "0/0/0")
|
||||
|
||||
# Collect time overloaded
|
||||
time_overloaded = (
|
||||
tstamp_after_bit_unset - tstamp_after_start_router
|
||||
).total_seconds()
|
||||
logger.info(f"Time Overloaded: {time_overloaded}")
|
||||
|
||||
# Use time it took to startup router as lower bound
|
||||
logger.info(
|
||||
f"Assert that overload time falls in range: {overload_time - startup_router_time} < {time_overloaded} <= {overload_time}"
|
||||
)
|
||||
result = overload_time - startup_router_time < time_overloaded <= overload_time
|
||||
assert result
|
||||
|
||||
|
||||
def test_isis_overload_on_startup_cancel_timer():
|
||||
"Check that overload on startup timer is cancelled when overload bit is set/unset"
|
||||
|
||||
tgen = get_topogen()
|
||||
net = get_topogen().net
|
||||
overload_time = 90
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
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"]
|
||||
r3.vtysh_cmd(
|
||||
f"""
|
||||
configure
|
||||
router isis 1
|
||||
set-overload-bit on-startup {overload_time}
|
||||
set-overload-bit
|
||||
"""
|
||||
)
|
||||
# Restart r3
|
||||
logger.info("Stop router")
|
||||
stop_router(tgen, "r3")
|
||||
logger.info("Start router")
|
||||
start_router(tgen, "r3")
|
||||
|
||||
# Check that the overload bit is set in r3's LSP
|
||||
check_lsp_overload_bit("r3", "r3.00-00", "0/0/1")
|
||||
|
||||
# Check that overload timer is running
|
||||
check_overload_timer("r3", True)
|
||||
|
||||
# Unset overload bit while timer is running
|
||||
r3.vtysh_cmd(
|
||||
"""
|
||||
configure
|
||||
router isis 1
|
||||
no set-overload-bit
|
||||
"""
|
||||
)
|
||||
|
||||
# Check that overload timer is cancelled
|
||||
check_overload_timer("r3", False)
|
||||
|
||||
# Check overload bit is unset
|
||||
check_lsp_overload_bit("r3", "r3.00-00", "0/0/0")
|
||||
|
||||
|
||||
def test_isis_overload_on_startup_override_timer():
|
||||
"Check that overload bit remains set after overload timer expires if overload bit is configured"
|
||||
|
||||
tgen = get_topogen()
|
||||
net = get_topogen().net
|
||||
overload_time = 60
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
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"]
|
||||
r3.vtysh_cmd(
|
||||
f"""
|
||||
configure
|
||||
router isis 1
|
||||
set-overload-bit on-startup {overload_time}
|
||||
set-overload-bit
|
||||
"""
|
||||
)
|
||||
# Restart r3
|
||||
logger.info("Stop router")
|
||||
stop_router(tgen, "r3")
|
||||
logger.info("Start router")
|
||||
start_router(tgen, "r3")
|
||||
|
||||
# Check that the overload bit is set in r3's LSP
|
||||
check_lsp_overload_bit("r3", "r3.00-00", "0/0/1")
|
||||
|
||||
# Check that overload timer is running
|
||||
check_overload_timer("r3", True)
|
||||
|
||||
# Check that overload timer expired
|
||||
check_overload_timer("r3", False)
|
||||
|
||||
# Check overload bit is still set
|
||||
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")
|
||||
|
||||
timer_running = "set_overload_on_start_timer" in thread_output
|
||||
if timer_running == timer_expected:
|
||||
return True
|
||||
return "Expected timer running status: {}".format(timer_expected)
|
||||
|
||||
|
||||
def check_overload_timer(router, timer_expected):
|
||||
"Verfiy overload bit in router's LSP"
|
||||
|
||||
assertmsg = _check_overload_timer(router, timer_expected)
|
||||
assert assertmsg is True, assertmsg
|
||||
|
||||
|
||||
def test_memory_leak():
|
||||
|
@ -1066,11 +1066,25 @@ module frr-isisd {
|
||||
"If true, identify as L1/L2 router for inter-area traffic.";
|
||||
}
|
||||
|
||||
leaf overload {
|
||||
type boolean;
|
||||
default "false";
|
||||
container overload {
|
||||
description
|
||||
"If true, avoid any transit traffic.";
|
||||
"Overload bit configuration.";
|
||||
leaf enabled {
|
||||
type boolean;
|
||||
default "false";
|
||||
description
|
||||
"If true, avoid any transit traffic.";
|
||||
}
|
||||
|
||||
leaf on-startup {
|
||||
type uint32 {
|
||||
range "0..86400";
|
||||
}
|
||||
units "seconds";
|
||||
default "0";
|
||||
description
|
||||
"The duration the overload bit should be set on startup.";
|
||||
}
|
||||
}
|
||||
|
||||
leaf metric-style {
|
||||
|
Loading…
Reference in New Issue
Block a user