]> git.puffer.fish Git - matthieu/frr.git/commitdiff
isisd: Add expected behavior with set-overload-bit
authorIsabella de Leon <ideleon@microsoft.com>
Wed, 12 Oct 2022 17:52:27 +0000 (10:52 -0700)
committerIsabella de Leon <ideleon@microsoft.com>
Wed, 12 Oct 2022 17:52:27 +0000 (10:52 -0700)
Signed-off-by: Isabella de Leon <ideleon@microsoft.com>
doc/user/isisd.rst
isisd/isis_lsp.c
isisd/isis_nb_config.c
isisd/isisd.c
isisd/isisd.h
tests/topotests/isis_topo1/test_isis_topo1.py

index 8f9afd313533668a0314cf5019bcdc941cdb44f2..2b114ad127f58c1d6c6d387d8a85c944b17c16bd 100644 (file)
@@ -85,7 +85,7 @@ writing, *isisd* does not support multiple ISIS processes.
 
 .. clicmd:: set-overload-bit on-startup (0-86400)
 
-   Set overload bit on startup for the specified duration, in seconds.
+   Set overload bit on startup for the specified duration, in seconds. Reference: :rfc:`3277`
 
 .. clicmd:: purge-originator
 
index fbf559713f347431b8df7a51769b13122f07d83f..2dc6f15c79a467f4b57fce5b2961e54aecd34892 100644 (file)
@@ -448,7 +448,10 @@ void set_overload_on_start_timer(struct thread *thread)
        assert(area);
 
        area->t_overload_on_startup_timer = NULL;
-       isis_area_overload_bit_set(area, false);
+
+       /* 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)
index 14a66d25687c31e809b77356885383a5cb95397f..214209e6472d9965cc9bf5bd1b7171b629489e9d 100644 (file)
@@ -350,6 +350,8 @@ int isis_instance_overload_enabled_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;
index 3ba00e6bf0fc8cb95c15f0a9113047f29adbe3e9..d59a411843508cf90b8ce634a9712bc801af9daf 100644 (file)
@@ -3190,9 +3190,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);
index f1f92b36518dea179f660b072a3d6cd0e9d869f1..81877f7455ffa0feec3659f0c9ff209c15903f91 100644 (file)
@@ -181,6 +181,7 @@ 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 */
index bfcca5fd59cac379f0107be567b1a79e35dbc90b..519ebba0cdefae30579b6cc801add657d4d97c9d 100644 (file)
@@ -368,6 +368,7 @@ def test_isis_database_json():
 
 def test_isis_overload_on_startup():
     "Check that overload on startup behaves as expected"
+
     tgen = get_topogen()
     net = get_topogen().net
     overload_time = 120
@@ -464,6 +465,124 @@ def 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"
+
+    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_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():
     "Run the memory leak test and report results."
     tgen = get_topogen()