mirror of
https://github.com/dtzp555-max/aci-sim.git
synced 2026-07-19 09:46:33 +00:00
fix(isn): flip sub-interface naming to real-gear conventions (v0.19.1)
Owner review of the v0.19.0 demo + Cisco docs/real spine CLI verification: ACI spines name the VLAN-4 sub-if after the PORT (eth1/49.49, cf. Eth1/29.29-style in show ip ospf neighbors vrf overlay-1); the ISN Nexus names its dot1q-4 sub-if after the VLAN (Ethernet1/1.4). v0.19.0 had the two conventions swapped. 908 tests green.
This commit is contained in:
@@ -91,8 +91,9 @@ class TestIsnDefaults:
|
||||
# PR-22 — ISN OSPF sub-interface + ISN CSW LLDP neighbor
|
||||
#
|
||||
# Real ACI multi-site spines carry the ISN-facing OSPF address on a routed
|
||||
# VLAN-4 sub-interface (e.g. "eth1/49.4"), not the bare physical port, and
|
||||
# the ISN switch advertises LLDP on that physical port. autoACI's Topology
|
||||
# VLAN-4 sub-interface NAMED AFTER THE PORT (e.g. "eth1/49.49" — real spine
|
||||
# CLI shows Eth1/29.29-style names; only the ISN Nexus side names its dot1q-4
|
||||
# sub-if ".4", e.g. "Ethernet1/1.4"), not the bare physical port. autoACI's Topology
|
||||
# "Fabric (physical)" view stitches these together: ospfIf (port + local IP)
|
||||
# + ospfAdjEp (remote IP) + lldpAdjEp (CSW-side port/name).
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -106,7 +107,7 @@ class TestIsnOspfSubInterfaceAndLldp:
|
||||
assert ospf_ifs, "expected at least one ospfIf"
|
||||
spine_ids = sorted(n.id for n in site.spine_nodes())
|
||||
for si, sid in enumerate(spine_ids):
|
||||
expected_id = f"eth1/{49 + si}.4"
|
||||
expected_id = f"eth1/{49 + si}.{49 + si}"
|
||||
mo = next(
|
||||
m for m in ospf_ifs
|
||||
if m.dn == f"topology/pod-{site.pod}/node-{sid}/sys/ospf/inst-default/dom-overlay-1/if-[{expected_id}]"
|
||||
@@ -127,7 +128,7 @@ class TestIsnOspfSubInterfaceAndLldp:
|
||||
store = orchestrator.build_site(repo_topo, site)
|
||||
spine_ids = sorted(n.id for n in site.spine_nodes())
|
||||
for si, sid in enumerate(spine_ids):
|
||||
expected_segment = f"if-[eth1/{49 + si}.4]"
|
||||
expected_segment = f"if-[eth1/{49 + si}.{49 + si}]"
|
||||
adj = next(
|
||||
m for m in store.by_class("ospfAdjEp")
|
||||
if f"/node-{sid}/" in m.dn and expected_segment in m.dn
|
||||
@@ -146,7 +147,7 @@ class TestIsnOspfSubInterfaceAndLldp:
|
||||
if m.dn == f"topology/pod-{site.pod}/node-{sid}/sys/lldp/inst/if-[{local_port}]/adj-1"
|
||||
)
|
||||
assert adj.attrs["sysName"] == f"ISN-CSW{site.id}"
|
||||
assert adj.attrs["portIdV"] == f"Ethernet1/{si + 1}"
|
||||
assert adj.attrs["portIdV"] == f"Ethernet1/{si + 1}.4"
|
||||
assert adj.attrs["mgmtIp"] == f"172.16.{site.id}.254"
|
||||
|
||||
def test_single_site_fabric_builds_no_isn_ospf_or_lldp(self) -> None:
|
||||
|
||||
@@ -406,10 +406,11 @@ def test_ospf_adj_ep_sits_on_an_ospf_if(store_name, request):
|
||||
@pytest.mark.parametrize("store_name", _ALL_STORES)
|
||||
def test_ospf_if_references_real_port(store_name, request):
|
||||
"""ospfIf is now the routed VLAN-4 sub-interface of the spine's ISN
|
||||
uplink port (id/dn end in ".4", e.g. "eth1/49.4") — real LLDP/physical
|
||||
port state stays on the base port, so this resolves the underlying
|
||||
l1PhysIf via the base port (ifId.split('.')[0]), same fallback autoACI's
|
||||
topology code uses."""
|
||||
uplink port, named after the port per real ACI convention (e.g.
|
||||
"eth1/49.49" — cf. Eth1/29.29-style names in real spine CLI) — real
|
||||
LLDP/physical port state stays on the base port, so this resolves the
|
||||
underlying l1PhysIf via the base port (ifId.split('.')[0]), same
|
||||
fallback autoACI's topology code uses."""
|
||||
store = request.getfixturevalue(store_name)
|
||||
ports = _l1physif_ports(store)
|
||||
ifs = store.by_class("ospfIf")
|
||||
@@ -418,8 +419,10 @@ def test_ospf_if_references_real_port(store_name, request):
|
||||
m = re.search(r"/node-(\d+)/sys/ospf/.*?/if-\[([^\]]+)\]", ospf_if.dn)
|
||||
assert m is not None, f"unparsable ospfIf dn {ospf_if.dn!r}"
|
||||
node_id, port_id = int(m.group(1)), m.group(2)
|
||||
assert port_id.endswith(".4"), f"ospfIf {ospf_if.dn!r} id {port_id!r} is not a VLAN-4 sub-if"
|
||||
base_port = port_id.split(".")[0]
|
||||
base_port, _, sub_num = port_id.partition(".")
|
||||
assert sub_num == base_port.split("/")[-1], (
|
||||
f"ospfIf {ospf_if.dn!r} id {port_id!r} is not a port-named sub-if"
|
||||
)
|
||||
assert base_port in ports.get(node_id, set()), (
|
||||
f"ospfIf {ospf_if.dn!r} references base port {base_port!r} on node "
|
||||
f"{node_id}, which has no matching l1PhysIf"
|
||||
|
||||
@@ -127,9 +127,10 @@ def test_l3out_path_att_references_real_port(store_name, request):
|
||||
@pytest.mark.parametrize("store_name", ["store_a", "store_b"])
|
||||
def test_ospf_adjacency_references_real_port(store_name, request):
|
||||
"""ospfAdjEp nests under the ospfIf's VLAN-4 sub-if segment
|
||||
(if-[eth1/{49+si}.4]); resolve the underlying l1PhysIf via the base port
|
||||
(ifId.split('.')[0]) — same fallback autoACI's topology code uses since
|
||||
real LLDP/physical state stays on the base port, not the sub-if."""
|
||||
(if-[eth1/{49+si}.{49+si}], port-named per real ACI convention); resolve
|
||||
the underlying l1PhysIf via the base port (ifId.split('.')[0]) — same
|
||||
fallback autoACI's topology code uses since real LLDP/physical state
|
||||
stays on the base port, not the sub-if."""
|
||||
store = request.getfixturevalue(store_name)
|
||||
ports = _l1physif_ports(store)
|
||||
adjs = list(store.by_class("ospfAdjEp"))
|
||||
@@ -138,8 +139,10 @@ def test_ospf_adjacency_references_real_port(store_name, request):
|
||||
m = re.search(r"/node-(\d+)/sys/ospf/.*?/if-\[([^\]]+)\]", adj.dn)
|
||||
assert m is not None, f"unparsable ospfAdjEp dn {adj.dn!r}"
|
||||
node_id, port_id = int(m.group(1)), m.group(2)
|
||||
assert port_id.endswith(".4"), f"ospfAdjEp {adj.dn!r} port {port_id!r} is not a VLAN-4 sub-if"
|
||||
base_port = port_id.split(".")[0]
|
||||
base_port, _, sub_num = port_id.partition(".")
|
||||
assert sub_num == base_port.split("/")[-1], (
|
||||
f"ospfAdjEp {adj.dn!r} port {port_id!r} is not a port-named sub-if"
|
||||
)
|
||||
assert base_port in ports.get(node_id, set()), (
|
||||
f"ospfAdjEp {adj.dn!r} references base port {base_port!r} on node {node_id}, "
|
||||
f"which has no matching l1PhysIf (has {ports.get(node_id)})"
|
||||
|
||||
Reference in New Issue
Block a user