test: new test, verify degraded link aggregate members in LACP mode

Verify connectivity from host to the second DUT via the first, over a
link aggregate.  Both aggregate member links are connected to a TPMR
link breaker to hide link down from the DUTs.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2025-02-12 23:21:08 +01:00
committed by Tobias Waldekranz
parent 4260d24143
commit cf16efe499
8 changed files with 324 additions and 0 deletions
+2
View File
@@ -35,6 +35,8 @@ include::dual_bridge/Readme.adoc[]
include::lag_basic/Readme.adoc[]
include::lag_failure/Readme.adoc[]
include::igmp_basic/Readme.adoc[]
include::igmp_vlan/Readme.adoc[]
@@ -38,6 +38,9 @@
- name: lag_basic
case: lag_basic/test.py
- name: lag_failure
case: lag_failure/test.py
- name: bridge_fwd_sgl_dut
case: bridge_fwd_sgl_dut/test.py
+1
View File
@@ -0,0 +1 @@
lag_failure.adoc
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 473 KiB

@@ -0,0 +1,42 @@
=== LACP Aggregate w/ Degraded Link
==== Description
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
ifdef::topdoc[]
image::../../test/case/ietf_interfaces/lag_failure/lag-failure.svg[]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::lag_failure/lag-failure.svg[]
endif::testgroup[]
ifndef::testgroup[]
image::lag-failure.svg[]
endif::testgroup[]
endif::topdoc[]
The host verifies connectivity with dut2 via dut1 over the aggregate for
each failure mode step using the `mon` interface.
==== Topology
ifdef::topdoc[]
image::{topdoc}../../test/case/ietf_interfaces/lag_failure/topology.svg[LACP Aggregate w/ Degraded Link topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::lag_failure/topology.svg[LACP Aggregate w/ Degraded Link topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[LACP Aggregate w/ Degraded Link topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUTs
. Set up link aggregate, lag0, between dut1 and dut2
. Initial connectivity check ...
. Verify failure modes
<<<
+143
View File
@@ -0,0 +1,143 @@
#!/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[]
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
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()
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()
@@ -0,0 +1,36 @@
graph "lag" {
layout="neato";
overlap="false";
esep="+23";
node [shape=record, fontsize=12, fontname="DejaVu Sans Mono, Book"];
edge [color="cornflowerblue", penwidth="2", fontname="DejaVu Serif, Book"];
host [
label="{{ <mgmt1> mgmt1 | <mon> mon | <lb1a> lb1a | <lb2a> lb2a | <lb2b> lb2b | <lb1b> lb1b | <mgmt2> mgmt2 } | host}",
pos="9,0!",
requires="controller",
];
dut1 [
label="{ dut1\l | { <mgmt> mgmt | <mon> mon | <link1> link1 | <link2> link2 } }",
pos="0,6!",
requires="infix",
];
dut2 [
label="{ dut2\r | { <link2> link2 | <link1> link1 | <mgmt> mgmt } }",
pos="18,6!",
requires="infix",
];
host:mgmt1 -- dut1:mgmt [requires="mgmt", color=lightgray]
host:mon -- dut1:mon // Monitor connection to dut2 via dut1
host:mgmt2 -- dut2:mgmt [requires="mgmt", color=lightgrey]
dut1:link1 -- host:lb1a [requires="ieee-mc", color=black, fontcolor=black]
host:lb1b -- dut2:link1 [requires="ieee-mc", color=black, fontcolor=black]
dut1:link2 -- host:lb2a [requires="ieee-mc", color=black, fontcolor=black]
host:lb2b -- dut2:link2 [requires="ieee-mc", color=black, fontcolor=black]
}
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Title: lag Pages: 1 -->
<svg width="484pt" height="152pt"
viewBox="0.00 0.00 484.03 151.51" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 147.51)">
<title>lag</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-147.51 480.03,-147.51 480.03,4 -4,4"/>
<!-- host -->
<g id="node1" class="node">
<title>host</title>
<polygon fill="none" stroke="black" points="80.27,-0.5 80.27,-42.5 415.27,-42.5 415.27,-0.5 80.27,-0.5"/>
<text text-anchor="middle" x="107.27" y="-28.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">mgmt1</text>
<polyline fill="none" stroke="black" points="134.27,-21.5 134.27,-42.5 "/>
<text text-anchor="middle" x="153.77" y="-28.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">mon</text>
<polyline fill="none" stroke="black" points="173.27,-21.5 173.27,-42.5 "/>
<text text-anchor="middle" x="196.77" y="-28.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">lb1a</text>
<polyline fill="none" stroke="black" points="220.27,-21.5 220.27,-42.5 "/>
<text text-anchor="middle" x="243.77" y="-28.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">lb2a</text>
<polyline fill="none" stroke="black" points="267.27,-21.5 267.27,-42.5 "/>
<text text-anchor="middle" x="290.77" y="-28.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">lb2b</text>
<polyline fill="none" stroke="black" points="314.27,-21.5 314.27,-42.5 "/>
<text text-anchor="middle" x="337.77" y="-28.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">lb1b</text>
<polyline fill="none" stroke="black" points="361.27,-21.5 361.27,-42.5 "/>
<text text-anchor="middle" x="388.27" y="-28.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">mgmt2</text>
<polyline fill="none" stroke="black" points="80.27,-21.5 415.27,-21.5 "/>
<text text-anchor="middle" x="247.77" y="-7.9" font-family="DejaVu Sans Mono, Book" font-size="12.00">host</text>
</g>
<!-- dut1 -->
<g id="node2" class="node">
<title>dut1</title>
<polygon fill="none" stroke="black" points="0,-101.01 0,-143.01 194,-143.01 194,-101.01 0,-101.01"/>
<text text-anchor="start" x="8" y="-129.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">dut1</text>
<polyline fill="none" stroke="black" points="0,-122.01 194,-122.01 "/>
<text text-anchor="middle" x="23.5" y="-108.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">mgmt</text>
<polyline fill="none" stroke="black" points="47,-101.01 47,-122.01 "/>
<text text-anchor="middle" x="66.5" y="-108.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">mon</text>
<polyline fill="none" stroke="black" points="86,-101.01 86,-122.01 "/>
<text text-anchor="middle" x="113" y="-108.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">link1</text>
<polyline fill="none" stroke="black" points="140,-101.01 140,-122.01 "/>
<text text-anchor="middle" x="167" y="-108.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">link2</text>
</g>
<!-- host&#45;&#45;dut1 -->
<g id="edge1" class="edge">
<title>host:mgmt1&#45;&#45;dut1:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M106.77,-42.5C106.77,-42.5 23,-101.01 23,-101.01"/>
</g>
<!-- host&#45;&#45;dut1 -->
<g id="edge2" class="edge">
<title>host:mon&#45;&#45;dut1:mon</title>
<path fill="none" stroke="cornflowerblue" stroke-width="2" d="M153.77,-42.5C153.77,-42.5 66,-101.01 66,-101.01"/>
</g>
<!-- dut2 -->
<g id="node3" class="node">
<title>dut2</title>
<polygon fill="none" stroke="black" points="321.03,-101.01 321.03,-143.01 476.03,-143.01 476.03,-101.01 321.03,-101.01"/>
<text text-anchor="end" x="468.03" y="-129.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">dut2</text>
<polyline fill="none" stroke="black" points="321.03,-122.01 476.03,-122.01 "/>
<text text-anchor="middle" x="348.03" y="-108.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">link2</text>
<polyline fill="none" stroke="black" points="375.03,-101.01 375.03,-122.01 "/>
<text text-anchor="middle" x="402.03" y="-108.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">link1</text>
<polyline fill="none" stroke="black" points="429.03,-101.01 429.03,-122.01 "/>
<text text-anchor="middle" x="452.53" y="-108.41" font-family="DejaVu Sans Mono, Book" font-size="12.00">mgmt</text>
</g>
<!-- host&#45;&#45;dut2 -->
<g id="edge3" class="edge">
<title>host:mgmt2&#45;&#45;dut2:mgmt</title>
<path fill="none" stroke="lightgrey" stroke-width="2" d="M388.77,-42.5C388.77,-42.5 452.53,-101.01 452.53,-101.01"/>
</g>
<!-- host&#45;&#45;dut2 -->
<g id="edge5" class="edge">
<title>host:lb1b&#45;&#45;dut2:link1</title>
<path fill="none" stroke="black" stroke-width="2" d="M337.77,-42.5C337.77,-42.5 402.53,-101.01 402.53,-101.01"/>
</g>
<!-- host&#45;&#45;dut2 -->
<g id="edge7" class="edge">
<title>host:lb2b&#45;&#45;dut2:link2</title>
<path fill="none" stroke="black" stroke-width="2" d="M290.77,-42.5C290.77,-42.5 320.53,-111.01 320.53,-111.01"/>
</g>
<!-- dut1&#45;&#45;host -->
<g id="edge4" class="edge">
<title>dut1:link1&#45;&#45;host:lb1a</title>
<path fill="none" stroke="black" stroke-width="2" d="M113,-101.01C113,-101.01 196.77,-42.5 196.77,-42.5"/>
</g>
<!-- dut1&#45;&#45;host -->
<g id="edge6" class="edge">
<title>dut1:link2&#45;&#45;host:lb2a</title>
<path fill="none" stroke="black" stroke-width="2" d="M194,-111.01C194,-111.01 243.77,-42.5 243.77,-42.5"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB