mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-05 15:13:02 +02:00
This commit greatly simplifies AsciiDoc image references in generated Readme.adoc files. The two focused use-cases that remain after this change are working references in: - Generated output/images/test-report.pdf - Viewing test's Readme.adoc from GitHub Previously we aimed to have working images also when the test's Readme was included in the parent directory's Readme.adoc. This, however, is not supported as of this commit. It seems unlikely also to ever be a supported feature of AsciiDoc on GitHub, for details, see the following issue: <https://github.com/github/markup/issues/1095> Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
145 lines
4.4 KiB
Python
Executable File
145 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
r"""LACP Aggregate w/ Degraded Link
|
|
|
|
Verify communication over an LACP link aggregate when individual member
|
|
links stop forwarding traffic, without carrier loss.
|
|
|
|
.Logical network setup, link breakers (lb1 & lb2) here managed by host PC
|
|
image::lag-failure.svg[align=center, scaledwidth=75%]
|
|
|
|
The host verifies connectivity with dut2 via dut1 over the aggregate for
|
|
each failure mode step using the `mon` interface.
|
|
|
|
"""
|
|
from time import time
|
|
import infamy
|
|
import infamy.lag
|
|
from infamy.netns import TPMR
|
|
from infamy.util import parallel
|
|
|
|
IPH = "192.168.2.1"
|
|
IP1 = "192.168.2.41"
|
|
IP2 = "192.168.2.42"
|
|
|
|
|
|
class LinkBreaker:
|
|
"""Encapsulates TPMR based link-breakers."""
|
|
|
|
def __init__(self, sys, netns):
|
|
self.net = netns
|
|
self.lb1 = TPMR(sys.ltop.xlate("host", "lb1a")[1],
|
|
sys.ltop.xlate("host", "lb1b")[1]).start()
|
|
self.lb2 = TPMR(sys.ltop.xlate("host", "lb2a")[1],
|
|
sys.ltop.xlate("host", "lb2b")[1]).start()
|
|
|
|
def forward(self, lb1, lb2):
|
|
"""Set link breakers in forwarding or blocking state."""
|
|
getattr(self.lb1, lb1)()
|
|
getattr(self.lb2, lb2)()
|
|
|
|
def fail_check(self, peer):
|
|
"""Verify connectivity with a given peer during failure."""
|
|
sequence = [
|
|
("forward", "forward"),
|
|
("forward", "block"),
|
|
("block", "forward"),
|
|
("forward", "forward")
|
|
]
|
|
|
|
total_start = time()
|
|
print(f"{'LB1':<8} | {'LB2':<8} | {'Status':<8}")
|
|
print("---------|----------|---------")
|
|
|
|
for lb1, lb2 in sequence:
|
|
state_start = time()
|
|
try:
|
|
print(f"{lb1:<8} | {lb2:<8} | {'...':<8}", end="\r# ")
|
|
self.forward(lb1, lb2)
|
|
self.net.must_reach(peer, timeout=30)
|
|
print(f"{lb1:<8} | {lb2:<8} | {'OK':<8} in "
|
|
f"{time() - state_start:.2f}s")
|
|
except Exception as e:
|
|
print(f"{lb1:<8} | {lb2:<8} | {'FAIL':<8} after "
|
|
f"{time() - state_start:.2f}s")
|
|
print(f"\nError encountered: {e}")
|
|
print(f"Link breakers were in state: LB1='{lb1}', LB2='{lb2}'")
|
|
raise
|
|
|
|
print(f"Total time: {time() - total_start:.2f}s")
|
|
|
|
|
|
def net_init(host, addr):
|
|
"""Set up DUT network, dut1 bridges host port with lag0"""
|
|
if host:
|
|
net = [{
|
|
"name": "br0",
|
|
"type": "infix-if-type:bridge",
|
|
"ipv4": {
|
|
"address": [{"ip": addr, "prefix-length": 24}]
|
|
}
|
|
}, {
|
|
"name": host,
|
|
"bridge-port": {"bridge": "br0"}
|
|
}, {
|
|
"name": "lag0",
|
|
"bridge-port": {"bridge": "br0"}
|
|
}]
|
|
else:
|
|
net = [{
|
|
"name": "lag0",
|
|
"ipv4": {
|
|
"address": [{"ip": addr, "prefix-length": 24}]
|
|
}
|
|
}]
|
|
return net
|
|
|
|
|
|
def dut_init(dut, addr, peer):
|
|
"""Configure each DUT specific according to LAG mode and peer"""
|
|
net = net_init(dut["mon"], addr)
|
|
|
|
dut.put_config_dict("ietf-interfaces", {
|
|
"interfaces": {
|
|
"interface": [{
|
|
"name": "lag0",
|
|
"type": "infix-if-type:lag",
|
|
"lag": {
|
|
"mode": "lacp",
|
|
"lacp": {"rate": "fast"},
|
|
"link-monitor": {"interval": 100}
|
|
}
|
|
}, {
|
|
"name": dut["link1"],
|
|
"lag-port": {"lag": "lag0"}
|
|
}, {
|
|
"name": dut["link2"],
|
|
"lag-port": {"lag": "lag0"}
|
|
}] + net
|
|
}
|
|
})
|
|
|
|
|
|
with infamy.Test() as test:
|
|
with test.step("Set up topology and attach to target DUTs"):
|
|
env = infamy.Env(edge_mappings=infamy.lag.edge_mappings)
|
|
dut1 = env.attach("dut1")
|
|
dut2 = env.attach("dut2")
|
|
|
|
_, mon = env.ltop.xlate("host", "mon")
|
|
with infamy.IsolatedMacVlan(mon) as ns:
|
|
lb = LinkBreaker(env, ns)
|
|
ns.addip(IPH)
|
|
|
|
print(f"Setting up lag0 in LACP mode between {dut1} and {dut2}")
|
|
with test.step("Set up link aggregate, lag0, between dut1 and dut2"):
|
|
parallel(lambda: dut_init(dut1, IP1, IP2),
|
|
lambda: dut_init(dut2, IP2, IP1))
|
|
|
|
with test.step("Initial connectivity check ..."):
|
|
ns.must_reach(IP2, timeout=30)
|
|
|
|
with test.step("Verify failure modes"):
|
|
lb.fail_check(IP2)
|
|
|
|
test.succeed()
|