summaryrefslogtreecommitdiff
path: root/tests/topotests/ospfapi/test_ospf_clientapi.py
diff options
context:
space:
mode:
authorAcee <aceelindem@gmail.com>2023-05-09 16:51:03 -0400
committerMergify <37929162+mergify[bot]@users.noreply.github.com>2023-05-10 20:52:06 +0000
commit947b69eb17d0344b4e5a9ea8388ece4481200edd (patch)
treef5ad5e4dfad830d82de114513df84444a34e5ae8 /tests/topotests/ospfapi/test_ospf_clientapi.py
parentdcaac2a2a559c80ba13b5a38a98438d101e0cad7 (diff)
ospfd: OSPF opaque LSA stale processing fix and topotests.
1. Fix OSPF opaque LSA processing to preserve the stale opaque LSAs in the Link State Database for 60 seconds consistent with what is done for other LSA types. 2. Add a topotest that tests for cases where ospfd is restarted and a stale OSPF opaque LSA exists in the OSPF routing domain both when the LSA is purged and when the LSA is reoriginagted with a more recent instance. Signed-off-by: Acee <aceelindem@gmail.com> (cherry picked from commit 4e7eb1e62ce54ebcf78622682de962fdeff20b80)
Diffstat (limited to 'tests/topotests/ospfapi/test_ospf_clientapi.py')
-rw-r--r--tests/topotests/ospfapi/test_ospf_clientapi.py195
1 files changed, 194 insertions, 1 deletions
diff --git a/tests/topotests/ospfapi/test_ospf_clientapi.py b/tests/topotests/ospfapi/test_ospf_clientapi.py
index 85c30b473e..a7179c554e 100644
--- a/tests/topotests/ospfapi/test_ospf_clientapi.py
+++ b/tests/topotests/ospfapi/test_ospf_clientapi.py
@@ -33,7 +33,15 @@ from datetime import datetime, timedelta
import pytest
-from lib.common_config import retry, run_frr_cmd, step
+from lib.common_config import (
+ retry,
+ run_frr_cmd,
+ step,
+ kill_router_daemons,
+ start_router_daemons,
+ shutdown_bringup_interface,
+)
+
from lib.micronet import Timeout, comm_error
from lib.topogen import Topogen, TopoRouter
from lib.topotest import interface_set_status, json_cmp
@@ -949,6 +957,191 @@ def test_ospf_opaque_delete_data3(tgen):
_test_opaque_add_del(tgen, apibin)
+def _test_opaque_add_restart_add(tgen, apibin):
+ "Test adding an opaque LSA and then restarting ospfd"
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ p = None
+ pread = None
+ # Log to our stdin, stderr
+ pout = open(os.path.join(r1.net.logdir, "r1/add-del.log"), "a+")
+ try:
+ step("reachable: check for add notification")
+ pread = r2.popen(
+ ["/usr/bin/timeout", "120", apibin, "-v", "--logtag=READER", "wait,120"],
+ encoding=None, # don't buffer
+ stdin=subprocess.DEVNULL,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ )
+ p = r1.popen(
+ [
+ apibin,
+ "-v",
+ "add,10,1.2.3.4,231,1",
+ "add,10,1.2.3.4,231,1,feedaceebeef",
+ "wait, 5",
+ "add,10,1.2.3.4,231,1,feedaceedeadbeef",
+ "wait, 5",
+ "add,10,1.2.3.4,231,1,feedaceebaddbeef",
+ "wait, 5",
+ ]
+ )
+ add_input_dict = {
+ "areas": {
+ "1.2.3.4": {
+ "areaLocalOpaqueLsa": [
+ {
+ "lsId": "231.0.0.1",
+ "advertisedRouter": "1.0.0.0",
+ "sequenceNumber": "80000004",
+ "checksum": "3128",
+ },
+ ],
+ "areaLocalOpaqueLsaCount": 1,
+ },
+ },
+ }
+ step("Check for add LSAs")
+ json_cmd = "show ip ospf da json"
+ assert verify_ospf_database(tgen, r1, add_input_dict, json_cmd) is None
+ assert verify_ospf_database(tgen, r2, add_input_dict, json_cmd) is None
+
+ step("Shutdown the interface on r1 to isolate it for r2")
+ shutdown_bringup_interface(tgen, "r1", "r1-eth0", False)
+
+ time.sleep(2)
+ step("Reset the client")
+ p.send_signal(signal.SIGINT)
+ time.sleep(2)
+ p.wait()
+ p = None
+
+ step("Kill ospfd on R1")
+ kill_router_daemons(tgen, "r1", ["ospfd"])
+ time.sleep(2)
+
+ step("Bring ospfd on R1 back up")
+ start_router_daemons(tgen, "r1", ["ospfd"])
+
+ p = r1.popen(
+ [
+ apibin,
+ "-v",
+ "add,10,1.2.3.4,231,1",
+ "add,10,1.2.3.4,231,1,feedaceecafebeef",
+ "wait, 5",
+ ]
+ )
+
+ step("Bring the interface on r1 back up for connection to r2")
+ shutdown_bringup_interface(tgen, "r1", "r1-eth0", True)
+
+ step("Verify area opaque LSA refresh")
+ json_cmd = "show ip ospf da opaque-area json"
+ add_detail_input_dict = {
+ "areaLocalOpaqueLsa": {
+ "areas": {
+ "1.2.3.4": [
+ {
+ "linkStateId": "231.0.0.1",
+ "advertisingRouter": "1.0.0.0",
+ "lsaSeqNumber": "80000005",
+ "checksum": "a87e",
+ "length": 28,
+ "opaqueDataLength": 8,
+ },
+ ],
+ },
+ },
+ }
+ assert verify_ospf_database(tgen, r1, add_detail_input_dict, json_cmd) is None
+ assert verify_ospf_database(tgen, r2, add_detail_input_dict, json_cmd) is None
+
+ step("Shutdown the interface on r1 to isolate it for r2")
+ shutdown_bringup_interface(tgen, "r1", "r1-eth0", False)
+
+ time.sleep(2)
+ step("Reset the client")
+ p.send_signal(signal.SIGINT)
+ time.sleep(2)
+ p.wait()
+ p = None
+
+ step("Kill ospfd on R1")
+ kill_router_daemons(tgen, "r1", ["ospfd"])
+ time.sleep(2)
+
+ step("Bring ospfd on R1 back up")
+ start_router_daemons(tgen, "r1", ["ospfd"])
+
+ step("Bring the interface on r1 back up for connection to r2")
+ shutdown_bringup_interface(tgen, "r1", "r1-eth0", True)
+
+ step("Verify area opaque LSA Purging")
+ json_cmd = "show ip ospf da opaque-area json"
+ add_detail_input_dict = {
+ "areaLocalOpaqueLsa": {
+ "areas": {
+ "1.2.3.4": [
+ {
+ "lsaAge": 3600,
+ "linkStateId": "231.0.0.1",
+ "advertisingRouter": "1.0.0.0",
+ "lsaSeqNumber": "80000005",
+ "checksum": "a87e",
+ "length": 28,
+ "opaqueDataLength": 8,
+ },
+ ],
+ },
+ },
+ }
+ assert verify_ospf_database(tgen, r1, add_detail_input_dict, json_cmd) is None
+ assert verify_ospf_database(tgen, r2, add_detail_input_dict, json_cmd) is None
+ step("Verify Area Opaque LSA removal after timeout (60 seconds)")
+ time.sleep(60)
+ json_cmd = "show ip ospf da opaque-area json"
+ timeout_detail_input_dict = {
+ "areaLocalOpaqueLsa": {
+ "areas": {
+ "1.2.3.4": [],
+ },
+ },
+ }
+ assert (
+ verify_ospf_database(tgen, r1, timeout_detail_input_dict, json_cmd) is None
+ )
+ assert (
+ verify_ospf_database(tgen, r2, timeout_detail_input_dict, json_cmd) is None
+ )
+
+ except Exception:
+ if p:
+ p.terminate()
+ if p.wait():
+ comm_error(p)
+ p = None
+ raise
+ finally:
+ if pread:
+ pread.terminate()
+ pread.wait()
+ if p:
+ p.terminate()
+ p.wait()
+
+
+@pytest.mark.parametrize("tgen", [2], indirect=True)
+def test_ospf_opaque_restart(tgen):
+ apibin = os.path.join(CLIENTDIR, "ospfclient.py")
+ rc, o, e = tgen.gears["r2"].net.cmd_status([apibin, "--help"])
+ logging.debug("%s --help: rc: %s stdout: '%s' stderr: '%s'", apibin, rc, o, e)
+ _test_opaque_add_restart_add(tgen, apibin)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))