2 # -*- coding: utf-8 eval: (blacken-mode 1) -*-
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # Copyright (c) 2021-2022, LabN Consulting, L.L.C.
9 test_ospf_clientapi.py: Test the OSPF client API.
19 from datetime
import datetime
, timedelta
22 from lib
.common_config
import (
26 shutdown_bringup_interface
,
30 from lib
.micronet
import Timeout
, comm_error
31 from lib
.topogen
import Topogen
, TopoRouter
32 from lib
.topotest
import interface_set_status
, json_cmp
34 pytestmark
= [pytest
.mark
.ospfd
]
36 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
37 TESTDIR
= os
.path
.abspath(CWD
)
39 CLIENTDIR
= os
.path
.abspath(os
.path
.join(CWD
, "../../../ospfclient"))
40 if not os
.path
.exists(CLIENTDIR
):
41 CLIENTDIR
= os
.path
.join(CWD
, "/usr/lib/frr")
43 assert os
.path
.exists(
44 os
.path
.join(CLIENTDIR
, "ospfclient.py")
45 ), "can't locate ospfclient.py"
59 @pytest.fixture(scope
="function", name
="tgen")
61 "Setup/Teardown the environment and provide tgen argument to tests"
62 nrouters
= request
.param
63 topodef
= {f
"sw{i}": (f
"r{i}", f
"r{i+1}") for i
in range(1, nrouters
)}
65 topodef
["sw4"] = ("r4", "r1")
67 tgen
= Topogen(topodef
, request
.module
.__name
__)
70 router_list
= tgen
.routers()
71 for _
, router
in router_list
.items():
72 router
.load_config(TopoRouter
.RD_ZEBRA
, "zebra.conf")
73 router
.load_config(TopoRouter
.RD_OSPF
, "ospfd.conf")
74 router
.net
.daemons_options
["ospfd"] = "--apiserver"
83 # Fixture that executes before each test
84 @pytest.fixture(autouse
=True)
85 def skip_on_failure(tgen
):
86 if tgen
.routers_have_failure():
87 pytest
.skip("skipped because of previous test failure")
95 @retry(retry_timeout
=45)
96 def verify_ospf_database(tgen
, dut
, input_dict
, cmd
="show ip ospf database json"):
98 show_ospf_json
= run_frr_cmd(dut
, cmd
, isjson
=True)
99 if not bool(show_ospf_json
):
100 return "ospf is not running"
101 result
= json_cmp(show_ospf_json
, input_dict
)
102 return str(result
) if result
else None
108 # logging.debug("READING 1 CHAR")
111 return buf
if buf
else None
113 # logging.debug("READ CHAR: '%s'", c)
118 def _wait_output(p
, regex
, maxwait
=120):
119 timeout
= Timeout(maxwait
)
120 while not timeout
.is_expired():
121 # line = p.stdout.readline()
122 line
= myreadline(p
.stdout
)
124 assert None, "EOF waiting for '{}'".format(regex
)
125 line
= line
.decode("utf-8")
128 logging
.debug("GOT LINE: '%s'", line
)
129 m
= re
.search(regex
, line
)
132 assert None, "Failed to get output matching '{}' withint {} actual {}s".format(
133 regex
, maxwait
, timeout
.elapsed()
142 def _test_reachability(tgen
, testbin
):
144 "1.0.0.0,2.0.0.0,4.0.0.0",
146 "1.0.0.0,2.0.0.0,4.0.0.0",
148 r2
= tgen
.gears
["r2"]
149 r3
= tgen
.gears
["r3"]
150 r4
= tgen
.gears
["r4"]
152 wait_args
= [f
"--wait={x}" for x
in waitlist
]
156 step("reachable: check for initial reachability")
158 ["/usr/bin/timeout", "120", testbin
, "-v", *wait_args
],
159 encoding
=None, # don't buffer
160 stdin
=subprocess
.DEVNULL
,
161 stdout
=subprocess
.PIPE
,
162 stderr
=subprocess
.STDOUT
,
164 _wait_output(p
, "SUCCESS: {}".format(waitlist
[0]))
166 step("reachable: check for modified reachability")
167 interface_set_status(r2
, "r2-eth0", False)
168 interface_set_status(r4
, "r4-eth1", False)
169 _wait_output(p
, "SUCCESS: {}".format(waitlist
[1]))
171 step("reachable: check for restored reachability")
172 interface_set_status(r2
, "r2-eth0", True)
173 interface_set_status(r4
, "r4-eth1", True)
174 _wait_output(p
, "SUCCESS: {}".format(waitlist
[2]))
175 except Exception as error
:
176 logging
.error("ERROR: %s", error
)
184 @pytest.mark
.parametrize("tgen", [4], indirect
=True)
185 def test_ospf_reachability(tgen
):
186 testbin
= os
.path
.join(TESTDIR
, "ctester.py")
187 rc
, o
, e
= tgen
.gears
["r2"].net
.cmd_status([testbin
, "--help"])
188 logging
.debug("%s --help: rc: %s stdout: '%s' stderr: '%s'", testbin
, rc
, o
, e
)
189 _test_reachability(tgen
, testbin
)
192 def _test_router_id(tgen
, testbin
):
193 r1
= tgen
.gears
["r1"]
200 mon_args
= [f
"--monitor={x}" for x
in waitlist
]
204 step("router id: check for initial router id")
206 ["/usr/bin/timeout", "120", testbin
, "-v", *mon_args
],
207 encoding
=None, # don't buffer
208 stdin
=subprocess
.DEVNULL
,
209 stdout
=subprocess
.PIPE
,
210 stderr
=subprocess
.STDOUT
,
212 _wait_output(p
, "SUCCESS: {}".format(waitlist
[0]))
214 step("router id: check for modified router id")
215 r1
.vtysh_multicmd("conf t\nrouter ospf\nospf router-id 1.1.1.1")
216 _wait_output(p
, "SUCCESS: {}".format(waitlist
[1]))
218 step("router id: check for restored router id")
219 r1
.vtysh_multicmd("conf t\nrouter ospf\nospf router-id 1.0.0.0")
220 _wait_output(p
, "SUCCESS: {}".format(waitlist
[2]))
221 except Exception as error
:
222 logging
.error("ERROR: %s", error
)
230 @pytest.mark
.parametrize("tgen", [2], indirect
=True)
231 def test_ospf_router_id(tgen
):
232 testbin
= os
.path
.join(TESTDIR
, "ctester.py")
233 rc
, o
, e
= tgen
.gears
["r1"].net
.cmd_status([testbin
, "--help"])
234 logging
.debug("%s --help: rc: %s stdout: '%s' stderr: '%s'", testbin
, rc
, o
, e
)
235 _test_router_id(tgen
, testbin
)
238 def _test_add_data(tgen
, apibin
):
239 "Test adding opaque data to domain"
241 r1
= tgen
.gears
["r1"]
243 step("add opaque: add opaque link local")
247 p
= r1
.popen([apibin
, "-v", "add,9,10.0.1.1,230,2,00000202"])
249 "routerId": "1.0.0.0",
252 "linkLocalOpaqueLsa": [
255 "advertisedRouter": "1.0.0.0",
256 "sequenceNumber": "80000001",
262 # Wait for it to show up
263 assert verify_ospf_database(tgen
, r1
, input_dict
) is None
266 "linkLocalOpaqueLsa": {
270 "linkStateId": "230.0.0.2",
271 "advertisingRouter": "1.0.0.0",
272 "lsaSeqNumber": "80000001",
273 "opaqueData": "00000202",
280 json_cmd
= "show ip ospf da opaque-link json"
281 assert verify_ospf_database(tgen
, r1
, input_dict
, json_cmd
) is None
283 step("reset client, add opaque area, verify link local flushing")
285 p
.send_signal(signal
.SIGINT
)
289 p
= r1
.popen([apibin
, "-v", "add,10,1.2.3.4,231,1,00010101"])
291 "routerId": "1.0.0.0",
294 "linkLocalOpaqueLsa": [
297 "advertisedRouter": "1.0.0.0",
298 "sequenceNumber": "80000001",
302 "areaLocalOpaqueLsa": [
305 "advertisedRouter": "1.0.0.0",
306 "sequenceNumber": "80000001",
312 # Wait for it to show up
313 assert verify_ospf_database(tgen
, r1
, input_dict
) is None
316 "areaLocalOpaqueLsa": {
320 "linkStateId": "231.0.0.1",
321 "advertisingRouter": "1.0.0.0",
322 "lsaSeqNumber": "80000001",
323 "opaqueData": "00010101",
330 json_cmd
= "show ip ospf da opaque-area json"
331 assert verify_ospf_database(tgen
, r1
, input_dict
, json_cmd
) is None
333 step("reset client, add opaque AS, verify area flushing")
335 p
.send_signal(signal
.SIGINT
)
340 p
= r1
.popen([apibin
, "-v", "add,11,232,3,deadbeaf01234567"])
342 "routerId": "1.0.0.0",
345 "areaLocalOpaqueLsa": [
348 "advertisedRouter": "1.0.0.0",
349 "sequenceNumber": "80000001",
355 "asExternalOpaqueLsa": [
358 "advertisedRouter": "1.0.0.0",
359 "sequenceNumber": "80000001",
363 # Wait for it to show up
364 assert verify_ospf_database(tgen
, r1
, input_dict
) is None
367 "asExternalOpaqueLsa": [
369 "linkStateId": "232.0.0.3",
370 "advertisingRouter": "1.0.0.0",
371 "lsaSeqNumber": "80000001",
372 "opaqueData": "deadbeaf01234567",
377 json_cmd
= "show ip ospf da opaque-as json"
378 assert verify_ospf_database(tgen
, r1
, input_dict
, json_cmd
) is None
380 step("stop client, verify AS flushing")
382 p
.send_signal(signal
.SIGINT
)
388 "routerId": "1.0.0.0",
389 "asExternalOpaqueLsa": [
392 "advertisedRouter": "1.0.0.0",
393 "sequenceNumber": "80000001",
398 # Wait for it to be flushed
399 assert verify_ospf_database(tgen
, r1
, input_dict
) is None
401 step("start client adding opaque domain, verify new sequence number and data")
404 p
= r1
.popen([apibin
, "-v", "add,11,232,3,ebadf00d"])
406 "routerId": "1.0.0.0",
407 "asExternalOpaqueLsa": [
410 "advertisedRouter": "1.0.0.0",
411 "sequenceNumber": "80000002",
415 assert verify_ospf_database(tgen
, r1
, input_dict
) is None
418 "asExternalOpaqueLsa": [
420 "linkStateId": "232.0.0.3",
421 "advertisingRouter": "1.0.0.0",
422 "lsaSeqNumber": "80000002",
423 "opaqueData": "ebadf00d",
428 json_cmd
= "show ip ospf da opaque-as json"
429 assert verify_ospf_database(tgen
, r1
, input_dict
, json_cmd
) is None
431 logging
.debug("sending interrupt to writer api client")
432 p
.send_signal(signal
.SIGINT
)
446 logging
.debug("cleanup: sending interrupt to writer api client")
451 @pytest.mark
.parametrize("tgen", [2], indirect
=True)
452 def test_ospf_opaque_add_data3(tgen
):
453 apibin
= os
.path
.join(CLIENTDIR
, "ospfclient.py")
454 rc
, o
, e
= tgen
.gears
["r2"].net
.cmd_status([apibin
, "--help"])
455 logging
.debug("%s --help: rc: %s stdout: '%s' stderr: '%s'", apibin
, rc
, o
, e
)
456 _test_add_data(tgen
, apibin
)
459 def _test_opaque_add_del(tgen
, apibin
):
460 "Test adding opaque data to domain"
462 r1
= tgen
.gears
["r1"]
463 r2
= tgen
.gears
["r2"]
467 # Log to our stdin, stderr
468 pout
= open(os
.path
.join(r1
.net
.logdir
, "r1/add-del.log"), "a+")
470 step("reachable: check for add notification")
472 ["/usr/bin/timeout", "120", apibin
, "-v", "--logtag=READER", "wait,120"],
473 encoding
=None, # don't buffer
474 stdin
=subprocess
.DEVNULL
,
475 stdout
=subprocess
.PIPE
,
476 stderr
=subprocess
.STDOUT
,
482 "add,9,10.0.1.1,230,1",
483 "add,9,10.0.1.1,230,2,00000202",
485 "add,10,1.2.3.4,231,1",
486 "add,10,1.2.3.4,231,2,0102030405060708",
489 "add,11,232,2,ebadf00d",
491 "del,9,10.0.1.1,230,2,0",
492 "del,10,1.2.3.4,231,2,1",
499 "linkLocalOpaqueLsa": [
502 "advertisedRouter": "1.0.0.0",
503 "sequenceNumber": "80000001",
508 "advertisedRouter": "1.0.0.0",
509 "sequenceNumber": "80000001",
513 "linkLocalOpaqueLsaCount": 2,
514 "areaLocalOpaqueLsa": [
517 "advertisedRouter": "1.0.0.0",
518 "sequenceNumber": "80000001",
523 "advertisedRouter": "1.0.0.0",
524 "sequenceNumber": "80000001",
528 "areaLocalOpaqueLsaCount": 2,
531 "asExternalOpaqueLsa": [
534 "advertisedRouter": "1.0.0.0",
535 "sequenceNumber": "80000001",
540 "advertisedRouter": "1.0.0.0",
541 "sequenceNumber": "80000001",
545 "asExternalOpaqueLsaCount": 2,
548 step("reachable: check for add LSAs")
549 json_cmd
= "show ip ospf da json"
550 assert verify_ospf_database(tgen
, r1
, add_input_dict
, json_cmd
) is None
551 assert verify_ospf_database(tgen
, r2
, add_input_dict
, json_cmd
) is None
555 "show ip ospf da opaque-link json",
556 "show ip ospf da opaque-area json",
557 "show ip ospf da opaque-as json",
559 add_detail_input_dict
= [
561 "linkLocalOpaqueLsa": {
565 "linkStateId": "230.0.0.1",
566 "advertisingRouter": "1.0.0.0",
567 "lsaSeqNumber": "80000001",
570 "opaqueDataLength": 0,
573 "linkStateId": "230.0.0.2",
574 "advertisingRouter": "1.0.0.0",
575 "lsaSeqNumber": "80000001",
579 "opaqueDataLength": 4,
586 "areaLocalOpaqueLsa": {
590 "linkStateId": "231.0.0.1",
591 "advertisingRouter": "1.0.0.0",
592 "lsaSeqNumber": "80000001",
595 "opaqueDataLength": 0,
598 "linkStateId": "231.0.0.2",
599 "advertisingRouter": "1.0.0.0",
600 "lsaSeqNumber": "80000001",
603 "opaqueDataLength": 8,
610 "asExternalOpaqueLsa": [
612 "linkStateId": "232.0.0.1",
613 "advertisingRouter": "1.0.0.0",
614 "lsaSeqNumber": "80000001",
617 "opaqueDataLength": 0,
620 "linkStateId": "232.0.0.2",
621 "advertisingRouter": "1.0.0.0",
622 "lsaSeqNumber": "80000001",
625 "opaqueDataLength": 4,
632 step("reachable: check for add LSA details: %s" % json_cmds
[i
])
634 verify_ospf_database(tgen
, r1
, add_detail_input_dict
[i
], json_cmds
[i
])
638 verify_ospf_database(tgen
, r2
, add_detail_input_dict
[i
], json_cmds
[i
])
643 # Wait for add notification
644 # RECV: LSA update msg for LSA 232.0.0.3 in area 0.0.0.0 seq 0x80000001 len 24 age 9
655 step("reachable: check for API add notification: %s" % ls_id
)
656 waitfor
= "RECV:.*update msg.*LSA {}.*age ([0-9]+)".format(ls_id
)
657 _
= _wait_output(pread
, waitfor
)
662 "linkLocalOpaqueLsa": [
665 "advertisedRouter": "1.0.0.0",
666 "sequenceNumber": "80000001",
671 "advertisedRouter": "1.0.0.0",
673 "sequenceNumber": "80000001",
677 "linkLocalOpaqueLsaCount": 2,
678 "areaLocalOpaqueLsa": [
681 "advertisedRouter": "1.0.0.0",
682 "sequenceNumber": "80000001",
687 "advertisedRouter": "1.0.0.0",
689 "sequenceNumber": "80000002",
693 "areaLocalOpaqueLsaCount": 2,
696 "asExternalOpaqueLsa": [
699 "advertisedRouter": "1.0.0.0",
701 "sequenceNumber": "80000001",
706 "advertisedRouter": "1.0.0.0",
707 "sequenceNumber": "80000001",
711 "asExternalOpaqueLsaCount": 2,
714 step("reachable: check for explicit withdrawal LSAs")
715 json_cmd
= "show ip ospf da json"
716 assert verify_ospf_database(tgen
, r1
, del_input_dict
, json_cmd
) is None
717 assert verify_ospf_database(tgen
, r2
, del_input_dict
, json_cmd
) is None
719 del_detail_input_dict
= [
721 "linkLocalOpaqueLsa": {
725 "linkStateId": "230.0.0.1",
726 "advertisingRouter": "1.0.0.0",
727 "lsaSeqNumber": "80000001",
730 "opaqueDataLength": 0,
733 "linkStateId": "230.0.0.2",
734 "advertisingRouter": "1.0.0.0",
736 "lsaSeqNumber": "80000001",
740 "opaqueDataLength": 4,
747 "areaLocalOpaqueLsa": {
751 "linkStateId": "231.0.0.1",
752 "advertisingRouter": "1.0.0.0",
753 "lsaSeqNumber": "80000001",
756 "opaqueDataLength": 0,
760 "linkStateId": "231.0.0.2",
761 "advertisingRouter": "1.0.0.0",
762 "lsaSeqNumber": "80000002",
766 "opaqueDataLength": 0,
773 "asExternalOpaqueLsa": [
775 "linkStateId": "232.0.0.1",
776 "advertisingRouter": "1.0.0.0",
778 "lsaSeqNumber": "80000001",
781 "opaqueDataLength": 0,
784 "linkStateId": "232.0.0.2",
785 "advertisingRouter": "1.0.0.0",
786 "lsaSeqNumber": "80000001",
789 "opaqueDataLength": 4,
796 step("reachable: check for delete LSA details: %s" % json_cmds
[i
])
798 verify_ospf_database(tgen
, r1
, del_detail_input_dict
[i
], json_cmds
[i
])
802 verify_ospf_database(tgen
, r2
, del_detail_input_dict
[i
], json_cmds
[i
])
811 del_detail_input_dict
= [
813 "linkLocalOpaqueLsa": {
817 "linkStateId": "230.0.0.1",
818 "advertisingRouter": "1.0.0.0",
820 "lsaSeqNumber": "80000001",
823 "opaqueDataLength": 0,
826 "linkStateId": "230.0.0.2",
827 "advertisingRouter": "1.0.0.0",
829 "lsaSeqNumber": "80000001",
833 "opaqueDataLength": 4,
840 "areaLocalOpaqueLsa": {
845 "linkStateId": "231.0.0.1",
846 "advertisingRouter": "1.0.0.0",
847 "lsaSeqNumber": "80000001",
850 "opaqueDataLength": 0,
854 "linkStateId": "231.0.0.2",
855 "advertisingRouter": "1.0.0.0",
856 "lsaSeqNumber": "80000002",
860 "opaqueDataLength": 0,
867 "asExternalOpaqueLsa": [
869 "linkStateId": "232.0.0.1",
870 "advertisingRouter": "1.0.0.0",
872 "lsaSeqNumber": "80000001",
875 "opaqueDataLength": 0,
878 "linkStateId": "232.0.0.2",
879 "advertisingRouter": "1.0.0.0",
881 "lsaSeqNumber": "80000001",
884 "opaqueDataLength": 4,
892 "reachable: check for post API shutdown delete LSA details: %s"
896 verify_ospf_database(tgen
, r1
, del_detail_input_dict
[i
], json_cmds
[i
])
900 verify_ospf_database(tgen
, r2
, del_detail_input_dict
[i
], json_cmds
[i
])
905 # step("reachable: check for flush/age out")
906 # # Wait for max age notification
907 # waitfor = "RECV:.*update msg.*LSA {}.*age 3600".format(ls_id)
908 # _wait_output(pread, waitfor)
918 step("reachable: check for API delete notification: %s" % ls_id
)
919 waitfor
= "RECV:.*delete msg.*LSA {}.*age".format(ls_id
)
920 _
= _wait_output(pread
, waitfor
)
937 @pytest.mark
.parametrize("tgen", [2], indirect
=True)
938 def test_ospf_opaque_delete_data3(tgen
):
939 apibin
= os
.path
.join(CLIENTDIR
, "ospfclient.py")
940 rc
, o
, e
= tgen
.gears
["r2"].net
.cmd_status([apibin
, "--help"])
941 logging
.debug("%s --help: rc: %s stdout: '%s' stderr: '%s'", apibin
, rc
, o
, e
)
942 _test_opaque_add_del(tgen
, apibin
)
945 def _test_opaque_add_restart_add(tgen
, apibin
):
946 "Test adding an opaque LSA and then restarting ospfd"
948 r1
= tgen
.gears
["r1"]
949 r2
= tgen
.gears
["r2"]
953 # Log to our stdin, stderr
954 pout
= open(os
.path
.join(r1
.net
.logdir
, "r1/add-del.log"), "a+")
956 step("reachable: check for add notification")
958 ["/usr/bin/timeout", "120", apibin
, "-v", "--logtag=READER", "wait,120"],
959 encoding
=None, # don't buffer
960 stdin
=subprocess
.DEVNULL
,
961 stdout
=subprocess
.PIPE
,
962 stderr
=subprocess
.STDOUT
,
968 "add,10,1.2.3.4,231,1", # seq = 80000001
970 "add,10,1.2.3.4,231,1,feedaceebeef", # seq = 80000002
977 "areaLocalOpaqueLsa": [
980 "advertisedRouter": "1.0.0.0",
981 "sequenceNumber": "80000002",
985 "areaLocalOpaqueLsaCount": 1,
989 step("Wait for the Opaque LSA to be distributed")
990 json_cmd
= "show ip ospf da json"
991 assert verify_ospf_database(tgen
, r1
, add_input_dict
, json_cmd
) is None
992 assert verify_ospf_database(tgen
, r2
, add_input_dict
, json_cmd
) is None
994 step("Shutdown the interface on r1 to isolate it for r2")
995 shutdown_bringup_interface(tgen
, "r1", "r1-eth0", False)
998 step("Reset the client")
999 p
.send_signal(signal
.SIGINT
)
1004 # Verify the OLD LSA is still there unchanged on R2
1005 assert verify_ospf_database(tgen
, r2
, add_input_dict
, json_cmd
) is None
1007 step("Kill ospfd on R1")
1008 kill_router_daemons(tgen
, "r1", ["ospfd"])
1011 step("Bring ospfd on R1 back up")
1012 start_router_daemons(tgen
, "r1", ["ospfd"])
1014 # This will start off with sequence num 80000001
1015 # But should advance to 80000003 when we reestablish with r2
1020 "add,10,1.2.3.4,231,1,feedaceecafebeef", # seq=80000001
1025 # verify the old value on r2 doesn't change yet
1027 assert verify_ospf_database(tgen
, r2
, add_input_dict
, json_cmd
) is None
1029 json_cmd
= "show ip ospf da opaque-area json"
1030 new_add_input_dict
= {
1031 "areaLocalOpaqueLsa": {
1035 "linkStateId": "231.0.0.1",
1036 "advertisingRouter": "1.0.0.0",
1037 "lsaSeqNumber": "80000001",
1040 "opaqueDataLength": 8,
1046 # verify new value with initial seq number on r1
1047 assert verify_ospf_database(tgen
, r1
, new_add_input_dict
, json_cmd
) is None
1049 step("Bring the interface on r1 back up for connection to r2")
1050 shutdown_bringup_interface(tgen
, "r1", "r1-eth0", True)
1052 step("Verify area opaque LSA refresh")
1054 # Update the expected value to sequence number rev and new checksum
1055 update_dict
= new_add_input_dict
["areaLocalOpaqueLsa"]["areas"]["1.2.3.4"][0]
1056 update_dict
["lsaSeqNumber"] = "80000003"
1057 update_dict
["checksum"] = "cb27"
1059 # should settle on the same value now.
1060 assert verify_ospf_database(tgen
, r1
, new_add_input_dict
, json_cmd
) is None
1061 assert verify_ospf_database(tgen
, r2
, new_add_input_dict
, json_cmd
) is None
1063 step("Shutdown the interface on r1 to isolate it for r2")
1064 shutdown_bringup_interface(tgen
, "r1", "r1-eth0", False)
1067 step("Reset the client")
1068 p
.send_signal(signal
.SIGINT
)
1073 step("Kill ospfd on R1")
1074 kill_router_daemons(tgen
, "r1", ["ospfd"])
1077 step("Bring ospfd on R1 back up")
1078 start_router_daemons(tgen
, "r1", ["ospfd"])
1080 step("Bring the interface on r1 back up for connection to r2")
1081 shutdown_bringup_interface(tgen
, "r1", "r1-eth0", True)
1083 step("Verify area opaque LSA Purging")
1084 json_cmd
= "show ip ospf da opaque-area json"
1085 add_detail_input_dict
= {
1086 "areaLocalOpaqueLsa": {
1091 "linkStateId": "231.0.0.1",
1092 "advertisingRouter": "1.0.0.0",
1093 "lsaSeqNumber": "80000003",
1096 "opaqueDataLength": 8,
1102 assert verify_ospf_database(tgen
, r1
, add_detail_input_dict
, json_cmd
) is None
1103 assert verify_ospf_database(tgen
, r2
, add_detail_input_dict
, json_cmd
) is None
1104 step("Verify Area Opaque LSA removal after timeout (60 seconds)")
1106 json_cmd
= "show ip ospf da opaque-area json"
1107 timeout_detail_input_dict
= {
1108 "areaLocalOpaqueLsa": {
1115 verify_ospf_database(tgen
, r1
, timeout_detail_input_dict
, json_cmd
) is None
1118 verify_ospf_database(tgen
, r2
, timeout_detail_input_dict
, json_cmd
) is None
1137 @pytest.mark
.parametrize("tgen", [2], indirect
=True)
1138 def test_ospf_opaque_restart(tgen
):
1139 apibin
= os
.path
.join(CLIENTDIR
, "ospfclient.py")
1140 rc
, o
, e
= tgen
.gears
["r2"].net
.cmd_status([apibin
, "--help"])
1141 logging
.debug("%s --help: rc: %s stdout: '%s' stderr: '%s'", apibin
, rc
, o
, e
)
1142 _test_opaque_add_restart_add(tgen
, apibin
)
1145 if __name__
== "__main__":
1146 args
= ["-s"] + sys
.argv
[1:]
1147 sys
.exit(pytest
.main(args
))