Skip to content

Commit 9c92396

Browse files
committed
tests: topotests/ospf_topo1: cover new per-leaf CLI conversions
Extends test_ospf_per_iface_cli_routes_through_yang to exercise `ip ospf network point-to-point` and the v3 equivalent alongside the other per-interface CLIs, and adds dedicated CLI tests for the new YANG-routed paths: * test_ospf_network_dmvpn_falls_back_to_legacy -- confirms the FRR-augment fallback for `ip ospf network point-to-point dmvpn` keeps producing the expected running-config text and that `no ip ospf network` unwinds both the legacy and the YANG- backed state cleanly. * test_ospf_distance_cli_routes_through_yang -- cycles `distance 137` / `no distance` and the three-scope `distance ospf intra-area X inter-area Y external Z` / `no distance ospf` on ospfd and asserts the running-config cycles in and out as expected. v3 path coverage stays in test_ospf_yang_preference_config because legacy distance on OSPF6_NODE additionally calls ospf6_restart_spf, which trips a pre-existing ospf6_route_remove_all use-after-free with a populated route table. Coverage for the area attachment and area range CLI conversions (`ip ospf area`, `ipv6 ospf6 area`, `area X range PREFIX [...]`) relies on the existing test_ospf_yang_area_interface_*_config / area_ranges_config tests, which exercise the same YANG list-create / leaf-modify path via `mgmt set-config`; a dedicated legacy-CLI fixture would require a topology without `network <prefix> area X` statements and is left for a follow-up. Signed-off-by: Eric Parsonage <eric@eparsonage.com>
1 parent 446b399 commit 9c92396

1 file changed

Lines changed: 116 additions & 6 deletions

File tree

tests/topotests/ospf_topo1/test_ospf_topo1.py

Lines changed: 116 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,69 @@ def _set_yang_area_attrs(router, protocol_type, area_id, attrs):
691691
router.vtysh_cmd("\n".join(lines))
692692

693693

694+
def test_ospf_distance_cli_routes_through_yang():
695+
"""The legacy single-value `distance N` / `no distance` and multi-value
696+
`distance ospf intra-area X inter-area Y external Z` / `no distance ospf`
697+
forms continue to work via vtysh but now route through the ietf-ospf
698+
YANG `/preference/all` and `/preference/{intra-area,inter-area,external}`
699+
leaves. Verify by issuing the legacy CLI and confirming the daemon's
700+
running-config reflects the change exactly as before.
701+
702+
The OSPFv3 path is covered indirectly by test_ospf_yang_preference_config;
703+
legacy `distance` invocations in OSPF6_NODE additionally trigger
704+
ospf6_restart_spf, which trips a pre-existing ospf6_route_remove_all
705+
use-after-free when the route table is populated, so this test sticks
706+
to OSPFv2 for the legacy CLI."""
707+
tgen = get_topogen()
708+
if tgen.routers_have_failure():
709+
pytest.skip("skipped because of router(s) failure")
710+
711+
r1 = tgen.gears["r1"]
712+
daemon = "ospfd"
713+
router_block = "router ospf"
714+
cli_proto = "ospf"
715+
716+
# single-value scope (preference/all)
717+
r1.vtysh_cmd(
718+
"configure terminal\n" "{}\n" " distance 137\n".format(router_block)
719+
)
720+
running = r1.vtysh_cmd("show running-config {}".format(daemon))
721+
assert " distance 137" in running, running
722+
723+
r1.vtysh_cmd(
724+
"configure terminal\n" "{}\n" " no distance\n".format(router_block)
725+
)
726+
running = r1.vtysh_cmd("show running-config {}".format(daemon))
727+
assert "distance 137" not in running, running
728+
729+
# multi-value scope (preference/intra-area + /inter-area + /external)
730+
r1.vtysh_cmd(
731+
"configure terminal\n"
732+
"{}\n"
733+
" distance {} intra-area 21 inter-area 22 external 23\n".format(
734+
router_block, cli_proto
735+
)
736+
)
737+
running = r1.vtysh_cmd("show running-config {}".format(daemon))
738+
assert (
739+
"distance {} intra-area 21".format(cli_proto) in running
740+
), "expected 'distance {} intra-area 21' in {} running-config, got:\n{}".format(
741+
cli_proto, daemon, running
742+
)
743+
assert "inter-area 22" in running, running
744+
assert "external 23" in running, running
745+
746+
r1.vtysh_cmd(
747+
"configure terminal\n"
748+
"{}\n"
749+
" no distance {}\n".format(router_block, cli_proto)
750+
)
751+
running = r1.vtysh_cmd("show running-config {}".format(daemon))
752+
assert "intra-area 21" not in running, running
753+
assert "inter-area 22" not in running, running
754+
assert "external 23" not in running, running
755+
756+
694757
def test_ospf_area_cli_routes_through_yang():
695758
"""The legacy `area X stub`, `area X stub no-summary`, `area X
696759
default-cost N`, and their `no` forms continue to work via vtysh but
@@ -1021,12 +1084,13 @@ def test_ospf_per_iface_cli_routes_through_yang():
10211084
Drives `ip ospf cost N`, `ip ospf hello-interval N`, `ip ospf
10221085
dead-interval N`, `ip ospf priority N`, `ip ospf mtu-ignore`,
10231086
`ip ospf passive`, `ip ospf retransmit-interval N`, `ip ospf
1024-
transmit-delay N` and their v3 siblings via vtysh on r1-eth1
1025-
(which the fixture already attached to area 0 for both
1026-
daemons), confirms each lands in running-config, then unwinds
1027-
via the corresponding `no` form. Covers both the conversion
1028-
of the main DEFUN to DEFPY_YANG and the routing through the
1029-
NB callbacks landed in the per-interface slices.
1087+
transmit-delay N`, `ip ospf network point-to-point` and their
1088+
v3 siblings via vtysh on r1-eth1 (which the fixture already
1089+
attached to area 0 for both daemons), confirms each lands in
1090+
running-config, then unwinds via the corresponding `no` form.
1091+
Covers both the conversion of the main DEFUN to DEFPY_YANG and
1092+
the routing through the NB callbacks landed in the per-interface
1093+
slices.
10301094
"""
10311095
tgen = get_topogen()
10321096
if tgen.routers_have_failure():
@@ -1046,6 +1110,7 @@ def test_ospf_per_iface_cli_routes_through_yang():
10461110
" ip ospf passive\n"
10471111
" ip ospf retransmit-interval 23\n"
10481112
" ip ospf transmit-delay 31\n"
1113+
" ip ospf network point-to-point\n"
10491114
)
10501115
running = r1.vtysh_cmd("show running-config ospfd")
10511116
for expected in (
@@ -1057,6 +1122,7 @@ def test_ospf_per_iface_cli_routes_through_yang():
10571122
"ip ospf passive",
10581123
"ip ospf retransmit-interval 23",
10591124
"ip ospf transmit-delay 31",
1125+
"ip ospf network point-to-point",
10601126
):
10611127
assert (
10621128
expected in running
@@ -1075,6 +1141,7 @@ def test_ospf_per_iface_cli_routes_through_yang():
10751141
" no ip ospf passive\n"
10761142
" no ip ospf retransmit-interval\n"
10771143
" no ip ospf transmit-delay\n"
1144+
" no ip ospf network\n"
10781145
)
10791146
running = r1.vtysh_cmd("show running-config ospfd")
10801147
for unexpected in (
@@ -1086,6 +1153,7 @@ def test_ospf_per_iface_cli_routes_through_yang():
10861153
"ip ospf passive",
10871154
"ip ospf retransmit-interval 23",
10881155
"ip ospf transmit-delay 31",
1156+
"ip ospf network point-to-point",
10891157
):
10901158
assert (
10911159
unexpected not in running
@@ -1103,6 +1171,7 @@ def test_ospf_per_iface_cli_routes_through_yang():
11031171
" ipv6 ospf6 passive\n"
11041172
" ipv6 ospf6 retransmit-interval 23\n"
11051173
" ipv6 ospf6 transmit-delay 31\n"
1174+
" ipv6 ospf6 network point-to-point\n"
11061175
)
11071176
running = r1.vtysh_cmd("show running-config ospf6d")
11081177
for expected in (
@@ -1114,6 +1183,7 @@ def test_ospf_per_iface_cli_routes_through_yang():
11141183
"ipv6 ospf6 passive",
11151184
"ipv6 ospf6 retransmit-interval 23",
11161185
"ipv6 ospf6 transmit-delay 31",
1186+
"ipv6 ospf6 network point-to-point",
11171187
):
11181188
assert (
11191189
expected in running
@@ -1132,6 +1202,7 @@ def test_ospf_per_iface_cli_routes_through_yang():
11321202
" no ipv6 ospf6 passive\n"
11331203
" no ipv6 ospf6 retransmit-interval\n"
11341204
" no ipv6 ospf6 transmit-delay\n"
1205+
" no ipv6 ospf6 network\n"
11351206
)
11361207
running = r1.vtysh_cmd("show running-config ospf6d")
11371208
for unexpected in (
@@ -1143,6 +1214,7 @@ def test_ospf_per_iface_cli_routes_through_yang():
11431214
"ipv6 ospf6 passive",
11441215
"ipv6 ospf6 retransmit-interval 23",
11451216
"ipv6 ospf6 transmit-delay 31",
1217+
"ipv6 ospf6 network point-to-point",
11461218
):
11471219
assert (
11481220
unexpected not in running
@@ -1158,6 +1230,44 @@ def test_ospf_per_iface_cli_routes_through_yang():
11581230
)
11591231

11601232

1233+
def test_ospf_network_dmvpn_falls_back_to_legacy():
1234+
"""`ip ospf network point-to-point dmvpn` keeps working via the
1235+
legacy direct-mutation path because RFC 9129's interface-type
1236+
enum doesn't model the FRR-specific dmvpn flag.
1237+
1238+
The DEFPY_YANG body classifies the FRR-modifier as out-of-scope
1239+
for YANG and falls through to ospf_network_legacy_apply. This
1240+
test confirms the running-config still shows the dmvpn modifier
1241+
after the conversion.
1242+
"""
1243+
tgen = get_topogen()
1244+
if tgen.routers_have_failure():
1245+
pytest.skip("skipped because of router(s) failure")
1246+
1247+
r1 = tgen.gears["r1"]
1248+
1249+
r1.vtysh_cmd(
1250+
"configure terminal\n"
1251+
"interface r1-eth1\n"
1252+
" ip ospf network point-to-point dmvpn\n"
1253+
)
1254+
running = r1.vtysh_cmd("show running-config ospfd")
1255+
assert "ip ospf network point-to-point dmvpn" in running, (
1256+
"expected 'ip ospf network point-to-point dmvpn' in running-config "
1257+
"after legacy CLI set, got:\n" + running
1258+
)
1259+
1260+
r1.vtysh_cmd(
1261+
"configure terminal\n"
1262+
"interface r1-eth1\n"
1263+
" no ip ospf network\n"
1264+
)
1265+
running = r1.vtysh_cmd("show running-config ospfd")
1266+
assert "ip ospf network" not in running, (
1267+
"ip ospf network should be removed after CLI no form, got:\n" + running
1268+
)
1269+
1270+
11611271
def test_ospf_yang_preference_config():
11621272
"""per-instance preference (admin distance) round-trip via mgmtd.
11631273

0 commit comments

Comments
 (0)