diff options
Diffstat (limited to 'tests/topotests/ospfapi/test_ospf_clientapi.py')
| -rw-r--r-- | tests/topotests/ospfapi/test_ospf_clientapi.py | 840 |
1 files changed, 816 insertions, 24 deletions
diff --git a/tests/topotests/ospfapi/test_ospf_clientapi.py b/tests/topotests/ospfapi/test_ospf_clientapi.py index b01c96226e..49dd34d650 100644 --- a/tests/topotests/ospfapi/test_ospf_clientapi.py +++ b/tests/topotests/ospfapi/test_ospf_clientapi.py @@ -17,14 +17,27 @@ import subprocess import sys import time from datetime import datetime, timedelta +from functools import partial import pytest - -from lib.common_config import retry, run_frr_cmd, step +from lib.common_config import ( + kill_router_daemons, + retry, + run_frr_cmd, + shutdown_bringup_interface, + start_router_daemons, + step, +) from lib.micronet import Timeout, comm_error from lib.topogen import Topogen, TopoRouter from lib.topotest import interface_set_status, json_cmp +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + pytestmark = [pytest.mark.ospfd] CWD = os.path.dirname(os.path.realpath(__file__)) @@ -264,7 +277,9 @@ def _test_add_data(tgen, apibin): "linkStateId": "230.0.0.2", "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000001", - "opaqueData": "00000202", + "opaqueValues": { + "opaqueData": "00000202" + } }, ], } @@ -314,7 +329,9 @@ def _test_add_data(tgen, apibin): "linkStateId": "231.0.0.1", "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000001", - "opaqueData": "00010101", + "opaqueValues": { + "opaqueData": "00010101", + } }, ], } @@ -363,7 +380,9 @@ def _test_add_data(tgen, apibin): "linkStateId": "232.0.0.3", "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000001", - "opaqueData": "deadbeaf01234567", + "opaqueValues": { + "opaqueData": "deadbeaf01234567", + } }, ] } @@ -414,7 +433,9 @@ def _test_add_data(tgen, apibin): "linkStateId": "232.0.0.3", "advertisingRouter": "1.0.0.0", "lsaSeqNumber": "80000002", - "opaqueData": "ebadf00d", + "opaqueValues": { + "opaqueData": "ebadf00d", + } }, ] } @@ -561,7 +582,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "76bf", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "linkStateId": "230.0.0.2", @@ -570,7 +591,7 @@ def _test_opaque_add_del(tgen, apibin): "checksum": "8aa2", "length": 24, "opaqueId": 2, - "opaqueDataLength": 4, + "opaqueLength": 4, }, ] } @@ -586,7 +607,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "5bd8", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "linkStateId": "231.0.0.2", @@ -594,7 +615,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "7690", "length": 28, - "opaqueDataLength": 8, + "opaqueLength": 8, }, ], }, @@ -608,7 +629,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "5ed5", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "linkStateId": "232.0.0.2", @@ -616,7 +637,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "d9bd", "length": 24, - "opaqueDataLength": 4, + "opaqueLength": 4, }, ], }, @@ -721,7 +742,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "76bf", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "linkStateId": "230.0.0.2", @@ -731,7 +752,7 @@ def _test_opaque_add_del(tgen, apibin): "checksum": "8aa2", "length": 24, "opaqueId": 2, - "opaqueDataLength": 4, + "opaqueLength": 4, }, ] } @@ -747,7 +768,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "5bd8", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "lsaAge": 3600, @@ -757,7 +778,7 @@ def _test_opaque_add_del(tgen, apibin): "checksum": "4fe2", # data removed "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, ], }, @@ -772,7 +793,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "5ed5", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "linkStateId": "232.0.0.2", @@ -780,7 +801,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "d9bd", "length": 24, - "opaqueDataLength": 4, + "opaqueLength": 4, }, ], }, @@ -814,7 +835,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "76bf", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "linkStateId": "230.0.0.2", @@ -824,7 +845,7 @@ def _test_opaque_add_del(tgen, apibin): "checksum": "8aa2", "length": 24, "opaqueId": 2, - "opaqueDataLength": 4, + "opaqueLength": 4, }, ] } @@ -841,7 +862,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "5bd8", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "lsaAge": 3600, @@ -851,7 +872,7 @@ def _test_opaque_add_del(tgen, apibin): "checksum": "4fe2", # data removed "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, ], }, @@ -866,7 +887,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "5ed5", "length": 20, - "opaqueDataLength": 0, + "opaqueLength": 0, }, { "linkStateId": "232.0.0.2", @@ -875,7 +896,7 @@ def _test_opaque_add_del(tgen, apibin): "lsaSeqNumber": "80000001", "checksum": "d9bd", "length": 24, - "opaqueDataLength": 4, + "opaqueLength": 4, }, ], }, @@ -936,6 +957,777 @@ 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", # seq = 80000001 + "wait, 5", + "add,10,1.2.3.4,231,1,feedaceebeef", # seq = 80000002 + "wait, 5", + ] + ) + add_input_dict = { + "areas": { + "1.2.3.4": { + "areaLocalOpaqueLsa": [ + { + "lsId": "231.0.0.1", + "advertisedRouter": "1.0.0.0", + "sequenceNumber": "80000002", + "checksum": "cd26", + }, + ], + "areaLocalOpaqueLsaCount": 1, + }, + }, + } + step("Wait for the Opaque LSA to be distributed") + 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 + + # Verify the OLD LSA is still there unchanged on R2 + assert verify_ospf_database(tgen, r2, add_input_dict, json_cmd) is 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"]) + + # This will start off with sequence num 80000001 + # But should advance to 80000003 when we reestablish with r2 + p = r1.popen( + [ + apibin, + "-v", + "add,10,1.2.3.4,231,1,feedaceecafebeef", # seq=80000001 + "wait, 5", + ] + ) + + # verify the old value on r2 doesn't change yet + time.sleep(2) + assert verify_ospf_database(tgen, r2, add_input_dict, json_cmd) is None + + json_cmd = "show ip ospf da opaque-area json" + new_add_input_dict = { + "areaLocalOpaqueLsa": { + "areas": { + "1.2.3.4": [ + { + "linkStateId": "231.0.0.1", + "advertisingRouter": "1.0.0.0", + "lsaSeqNumber": "80000001", + "checksum": "b07a", + "length": 28, + "opaqueLength": 8, + }, + ], + }, + }, + } + # verify new value with initial seq number on r1 + assert verify_ospf_database(tgen, r1, new_add_input_dict, json_cmd) is None + + 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") + + # Update the expected value to sequence number rev and new checksum + update_dict = new_add_input_dict["areaLocalOpaqueLsa"]["areas"]["1.2.3.4"][0] + update_dict["lsaSeqNumber"] = "80000003" + update_dict["checksum"] = "cb27" + + # should settle on the same value now. + assert verify_ospf_database(tgen, r1, new_add_input_dict, json_cmd) is None + assert verify_ospf_database(tgen, r2, new_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"]) + + 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": "80000003", + "checksum": "cb27", + "length": 28, + "opaqueLength": 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) + + +def _test_opaque_interface_disable(tgen, apibin): + "Test disabling opaque capability on an interface" + + r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] + tc_name = "opaque_interface_disable" + + p = None + pread = None + # Log to our stdin, stderr + pout = open(os.path.join(r1.net.logdir, "r1/intf-disable.log"), "a+") + try: + # STEP 1 in test_ospf_opaque_interface_disable and STEP 56 in CI tests + step("Disable OSPF opaque LSA Copability on r1's interface to r2") + r1.vtysh_multicmd("conf t\ninterface r1-eth0\nno ip ospf capability opaque") + time.sleep(15) + + # STEP 2 in test_ospf_opaque_interface_disable and STEP 57 in CI tests + step("Verify the r1 configuration of 'no ip ospf capability opaque'") + no_capability_opaque_cfg = ( + tgen.net["r1"] + .cmd( + 'vtysh -c "show running ospfd" | grep "^ no ip ospf capability opaque"' + ) + .rstrip() + ) + assertmsg = ( + "'no ip ospf capability opaque' applied, but not present in configuration" + ) + assert no_capability_opaque_cfg == " no ip ospf capability opaque", assertmsg + + # STEP 3 in test_ospf_opaque_interface_disable and STEP 58 in CI tests + step("Verify the ospf opaque option is not applied to the r1 interface") + r1_interface_without_opaque = { + "interfaces": { + "r1-eth0": { + "ifUp": True, + "ospfEnabled": True, + "ipAddress": "10.0.1.1", + "ospfIfType": "Broadcast", + "opaqueCapable": False, + } + } + } + r1_interface_with_opaque = { + "interfaces": { + "r1-eth0": { + "ifUp": True, + "ospfEnabled": True, + "ipAddress": "10.0.1.1", + "ospfIfType": "Broadcast", + "opaqueCapable": True, + } + } + } + test_func = partial( + topotest.router_json_cmp, + r1, + "show ip ospf interface json", + r1_interface_without_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF interface doesn't have opaque capability disabled" + assert result is None, assertmsg + + r1_neighbor_without_opaque = { + "neighbors": { + "2.0.0.0": [ + { + "optionsList": "*|-|-|-|-|-|E|-", + } + ] + } + } + r2_neighbor_without_opaque = { + "neighbors": { + "1.0.0.0": [ + { + "optionsList": "*|-|-|-|-|-|E|-", + } + ] + } + } + # STEP 4 in test_ospf_opaque_interface_disable and STEP 59 in CI tests + step("Verify that the r1 neighbor options don't include opaque") + test_func = partial( + topotest.router_json_cmp, + r1, + "show ip ospf neighbor detail json", + r1_neighbor_without_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF neighbor has opaque option in optionsList" + assert result is None, assertmsg + + # STEP 5 in test_ospf_opaque_interface_disable and STEP 60 in CI tests + step("Verify that the r1 neighbor options don't include opaque") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf neighbor detail json", + r2_neighbor_without_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF neighbor has opaque option in optionsList" + assert result is None, assertmsg + + # STEP 6 in test_ospf_opaque_interface_disable and STEP 61 in CI tests + step( + "Verify no r2 configuration of 'no ip ospf capability opaque' in r2 configuration" + ) + rc, _, _ = tgen.net["r2"].cmd_status( + "show running ospfd | grep -q 'ip ospf capability opaque'", warn=False + ) + assertmsg = "'no ip ospf capability opaque' not applied, but not present in r2 configuration" + assert rc, assertmsg + + # STEP 7 in test_ospf_opaque_interface_disable and STEP 62 in CI tests + step("Verify the ospf opaque option is applied to the r2 interface") + r2_interface_without_opaque = { + "interfaces": { + "r2-eth0": { + "ifUp": True, + "ospfEnabled": True, + "ipAddress": "10.0.1.2", + "ospfIfType": "Broadcast", + "opaqueCapable": False, + } + } + } + r2_interface_with_opaque = { + "interfaces": { + "r2-eth0": { + "ifUp": True, + "ospfEnabled": True, + "ipAddress": "10.0.1.2", + "ospfIfType": "Broadcast", + "opaqueCapable": True, + } + } + } + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf interface json", + r2_interface_with_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF interface has opaque capability disabled" + assert result is None, assertmsg + + # STEP 8 in test_ospf_opaque_interface_disable and STEP 63 in CI tests + step("Install opaque LSAs on r1") + 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,9,10.0.1.1,230,1,feedaceedeadbeef", + "add,10,1.2.3.4,231,1,feedaceecafebeef", + "add,11,232,1,feedaceebaddbeef", + "wait,20", + ] + ) + opaque_LSAs_in_database = { + "areas": { + "1.2.3.4": { + "linkLocalOpaqueLsa": [ + { + "lsId": "230.0.0.1", + "advertisedRouter": "1.0.0.0", + "sequenceNumber": "80000001", + }, + ], + "linkLocalOpaqueLsaCount": 1, + "areaLocalOpaqueLsa": [ + { + "lsId": "231.0.0.1", + "advertisedRouter": "1.0.0.0", + "sequenceNumber": "80000001", + }, + ], + "areaLocalOpaqueLsaCount": 1, + }, + }, + "asExternalOpaqueLsa": [ + { + "lsId": "232.0.0.1", + "advertisedRouter": "1.0.0.0", + "sequenceNumber": "80000001", + }, + ], + "asExternalOpaqueLsaCount": 1, + } + opaque_area_empty_database = { + "routerId": "2.0.0.0", + "areaLocalOpaqueLsa": {"areas": {"1.2.3.4": []}}, + } + + # STEP 9 in test_ospf_opaque_interface_disable and STEP 64 in CI tests + step("Check that LSAs are added on r1") + test_func = partial( + topotest.router_json_cmp, + r1, + "show ip ospf database json", + opaque_LSAs_in_database, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF database doesn't contain opaque LSAs" + assert result is None, assertmsg + + # STEP 10 in test_ospf_opaque_interface_disable and STEP 65 in CI tests + step("Check that LSAs are not added on r2") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf database opaque-area json", + opaque_area_empty_database, + True, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF area database contains opaque LSAs" + assert result is None, assertmsg + + # STEP 11 in test_ospf_opaque_interface_disable and STEP 66 in CI tests + step("Enable OSPF opaque LSA Copability on r1's interface to r2") + r1.vtysh_multicmd("conf t\ninterface r1-eth0\nip ospf capability opaque") + time.sleep(15) + + # STEP 12 in test_ospf_opaque_interface_disable and STEP 67 in CI tests + step("Verify no r1 configuration of 'no ip ospf capability opaque'") + rc, _, _ = tgen.net["r1"].cmd_status( + "show running ospfd | grep -q 'ip ospf capability opaque'", warn=False + ) + assertmsg = "'no ip ospf capability opaque' not applied, but not present in r1 configuration" + assert rc, assertmsg + + # STEP 13 in test_ospf_opaque_interface_disable and STEP 68 in CI tests + step("Verify the ospf opaque option is applied to the r1 interface") + test_func = partial( + topotest.router_json_cmp, + r1, + "show ip ospf interface json", + r1_interface_with_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF interface doesn't have opaque capability disabled" + assert result is None, assertmsg + + r1_neighbor_with_opaque = { + "neighbors": { + "2.0.0.0": [ + { + "optionsList": "*|O|-|-|-|-|E|-", + } + ] + } + } + r2_neighbor_with_opaque = { + "neighbors": { + "1.0.0.0": [ + { + "optionsList": "*|O|-|-|-|-|E|-", + } + ] + } + } + # STEP 14 in test_ospf_opaque_interface_disable and STEP 69 in CI tests + step("Verify that the r1 neighbor options include opaque") + test_func = partial( + topotest.router_json_cmp, + r1, + "show ip ospf neighbor detail json", + r1_neighbor_with_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF neighbor doesn't have opaque option in optionsList" + assert result is None, assertmsg + + # STEP 15 in test_ospf_opaque_interface_disable and STEP 70 in CI tests + step("Verify that the r2 neighbor options include opaque") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf neighbor detail json", + r2_neighbor_with_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF neighbor doesn't have opaque option in optionsList" + assert result is None, assertmsg + + # STEP 16 in test_ospf_opaque_interface_disable and STEP 71 in CI tests + step("Check that LSAs are now added to r2") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf database json", + opaque_LSAs_in_database, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF database doesn't contains opaque LSAs" + assert result is None, assertmsg + + # STEP 17 in test_ospf_opaque_interface_disable and STEP 72 in CI tests + step( + "Disable Opaque Capability on r2's interface to r1 using the interface address" + ) + r2.vtysh_multicmd( + "conf t\ninterface r2-eth0\nno ip ospf capability opaque 10.0.1.2" + ) + + # STEP 18 in test_ospf_opaque_interface_disable and STEP 73 in CI tests + step("Clear the OSPF process on r2 to clear the OSPF LSDB") + r2.vtysh_multicmd("clear ip ospf process") + time.sleep(15) + + # STEP 19 in test_ospf_opaque_interface_disable and STEP 74 in CI tests + step("Verify the r2 configuration of 'no ip ospf capability opaque 10.0.1.2'") + no_capability_opaque_cfg = ( + tgen.net["r2"] + .cmd_nostatus( + 'vtysh -c "show running ospfd" | grep "^ no ip ospf capability opaque 10.0.1.2"' + ) + .rstrip() + ) + assertmsg = "'no ip ospf capability opaque 10.0.1.2' applied, but not present in configuration" + assert ( + no_capability_opaque_cfg == " no ip ospf capability opaque 10.0.1.2" + ), assertmsg + + # STEP 20 in test_ospf_opaque_interface_disable and STEP 75 in CI tests + step("Verify the ospf opaque option is not applied to the r2 interface") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf interface json", + r2_interface_without_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF interface doesn't have opaque capability disabled" + assert result is None, assertmsg + + # STEP 21 in test_ospf_opaque_interface_disable and STEP 76 in CI tests + step("Verify that the r1 neighbor options don't include opaque") + test_func = partial( + topotest.router_json_cmp, + r1, + "show ip ospf neighbor detail json", + r1_neighbor_without_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF neighbor has opaque option in optionsList" + assert result is None, assertmsg + + # STEP 22 in test_ospf_opaque_interface_disable and STEP 77 in CI tests + step("Verify that the r2 neighbor options don't include opaque") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf neighbor detail json", + r2_neighbor_without_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF neighbor has opaque option in optionsList" + assert result is None, assertmsg + + # STEP 23 in test_ospf_opaque_interface_disable and STEP 78 in CI tests + step("Verify that r1 still has the opaque LSAs") + test_func = partial( + topotest.router_json_cmp, + r1, + "show ip ospf database json", + opaque_LSAs_in_database, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF database doesn't contain opaque LSAs" + assert result is None, assertmsg + + # STEP 24 in test_ospf_opaque_interface_disable and STEP 79 in CI tests + step("Verify that r2 doesn't have the opaque LSAs") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf database opaque-area json", + opaque_area_empty_database, + True, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF area database contains opaque LSAs" + assert result is None, assertmsg + + # STEP 25 in test_ospf_opaque_interface_disable and STEP 80 in CI tests + step("Remove the 'no ip ospf capability opaque 10.0.1.2' config from r2 ") + r2.vtysh_multicmd( + "conf t\ninterface r2-eth0\nip ospf capability opaque 10.0.1.2" + ) + time.sleep(15) + + # STEP 26 in test_ospf_opaque_interface_disable and STEP 81 in CI tests + step("Verify the r2 removal of 'no ip ospf capability opaque 10.0.1.2'") + rc, _, _ = tgen.net["r2"].cmd_status( + "show running ospfd | grep -q 'ip ospf capability opaque'", warn=False + ) + assertmsg = "'no ip ospf capability opaque' not applied, but not present in r2 configuration" + assert rc, assertmsg + + # STEP 27 in test_ospf_opaque_interface_disable and STEP 82 in CI tests + step("Verify the ospf opaque option is applied to the r2 interface") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf interface json", + r2_interface_with_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF interface doesn't have opaque capability disabled" + assert result is None, assertmsg + + # STEP 28 in test_ospf_opaque_interface_disable and STEP 83 in CI tests + step("Verify that the r2 neighbor options include opaque") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf neighbor detail json", + r2_neighbor_with_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF neighbor doesn't have opaque option in optionsList" + assert result is None, assertmsg + + # STEP 29 in test_ospf_opaque_interface_disable and STEP 84 in CI tests + step("Verify that the r1 neighbor options include opaque") + test_func = partial( + topotest.router_json_cmp, + r1, + "show ip ospf neighbor detail json", + r1_neighbor_with_opaque, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r1 OSPF neighbor doesn't have opaque option in optionsList" + assert result is None, assertmsg + + # STEP 30 in test_ospf_opaque_interface_disable and STEP 85 in CLI tests + step("Verify that r2 now has the opaque LSAs") + test_func = partial( + topotest.router_json_cmp, + r2, + "show ip ospf database json", + opaque_LSAs_in_database, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assertmsg = "r2 OSPF database doesn't contain opaque LSAs" + assert result is None, assertmsg + + 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_interface_disable(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_interface_disable(tgen, apibin) + + +def _test_opaque_link_local_lsa_crash(tgen, apibin): + "Test disabling opaque capability on an interface" + + r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] + tc_name = "opaque_interface_disable" + + p = None + # Log to our stdin, stderr + pout = open(os.path.join(r1.net.logdir, "r1/intf-disable.log"), "a+") + try: + step("Add a link-local opaque LSA for r1-eth0") + pread = r1.popen([apibin, "-v", "add,9,10.0.1.1,230,1,feedaceedeadbeef"]) + + input_dict = { + "linkLocalOpaqueLsa": { + "areas": { + "1.2.3.4": [ + { + "linkStateId": "230.0.0.1", + "advertisingRouter": "1.0.0.0", + "lsaSeqNumber": "80000001", + "opaqueValues": { + "opaqueData": "feedaceedeadbeef", + } + }, + ], + } + }, + } + + # verify content + json_cmd = "show ip ospf da opaque-link json" + assert verify_ospf_database(tgen, r1, input_dict, json_cmd) is None + + step("Shut down r1-eth0 and verify there is no crash") + r1.vtysh_multicmd("conf t\ninterface r1-eth0\nshut") + time.sleep(2) + + step("Bring r1-eth0 back up and verify there is no crash") + r1.vtysh_multicmd("conf t\ninterface r1-eth0\nno shut") + + step("Add another link-local opaque LSA for r1-eth0") + pread = r1.popen([apibin, "-v", "add,9,10.0.1.1,230,1,feedaceecafebeef"]) + + input_dict = { + "linkLocalOpaqueLsa": { + "areas": { + "1.2.3.4": [ + { + "linkStateId": "230.0.0.1", + "advertisingRouter": "1.0.0.0", + "lsaSeqNumber": "80000001", + "opaqueValues": { + "opaqueData": "feedaceecafebeef", + } + }, + ], + } + }, + } + # verify content + json_cmd = "show ip ospf da opaque-link json" + assert verify_ospf_database(tgen, r1, input_dict, json_cmd) is None + + except Exception: + if p: + p.terminate() + if p.wait(): + comm_error(p) + p = None + raise + finally: + if p: + p.terminate() + p.wait() + p = None + + +@pytest.mark.parametrize("tgen", [2], indirect=True) +def test_ospf_opaque_link_local_lsa_crash(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_link_local_lsa_crash(tgen, apibin) + + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) |
