feat(isn): VLAN-4 routed sub-interface + addr on spine ISN ospfIf; ISN-CSW LLDP neighbor (v0.19.0)

Real ACI multi-site spines carry the OSPF address toward the ISN on a
routed sub-interface, not the bare port: ospfIf id/dn are now
eth1/{49+si}.4 with addr=172.16.{site}.{si+1}/24 (same /24 as the
existing .254 peer); ospfAdjEp nests under the sub-if. Each spine ISN
uplink physical port also gets an ISN-CSW lldpAdjEp/cdpAdjEp
(sysName ISN-CSW{site}, portIdV Ethernet1/{si+1}, model N9K-C9364C,
locally-administered 02:1B:0D MAC hashed from site.id). Single-site
fabrics build none of this. Closes the autoACI Fabric (physical) gap
where spine uplink rows showed blank Local IP / Neighbor Port.
908 tests green.
This commit is contained in:
dtzp555-max
2026-07-07 08:17:23 +10:00
parent ff838e2467
commit f6c95a0105
12 changed files with 257 additions and 21 deletions
+8 -2
View File
@@ -126,6 +126,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."""
store = request.getfixturevalue(store_name)
ports = _l1physif_ports(store)
adjs = list(store.by_class("ospfAdjEp"))
@@ -134,8 +138,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 in ports.get(node_id, set()), (
f"ospfAdjEp {adj.dn!r} references {port_id!r} on node {node_id}, "
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]
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)})"
)