Skip to content

Commit

Permalink
test: add support for verifying basic lag setup
Browse files Browse the repository at this point in the history
Verify connectivity from host to the second DUT via the first, over a
link aggregate.  The lag starts in static mode and then changes to an
LACP aggregate.  This verifies not just basic aggregate functionality,
but also changing mode, which is quite tricky to get right.

Signed-off-by: Joachim Wiberg <[email protected]>
  • Loading branch information
troglobit committed Dec 16, 2024
1 parent 13d1047 commit bbec2cb
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 0 deletions.
2 changes: 2 additions & 0 deletions test/case/ietf_interfaces/Readme.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ include::bridge_vlan_separation/Readme.adoc[]

include::dual_bridge/Readme.adoc[]

include::lag_basic/Readme.adoc[]

include::igmp_basic/Readme.adoc[]

include::igmp_vlan/Readme.adoc[]
Expand Down
3 changes: 3 additions & 0 deletions test/case/ietf_interfaces/ietf_interfaces.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
- name: ipv4_autoconf
case: ipv4_autoconf/test.py

- name: lag_basic
case: lag_basic/test.py

- name: bridge_fwd_sgl_dut
case: bridge_fwd_sgl_dut/test.py

Expand Down
40 changes: 40 additions & 0 deletions test/case/ietf_interfaces/lag_basic/Readme.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
=== Ling Aggregation Basic
==== Description
Verify communication over a link aggregate in static and LACP operating
modes during basic failure scenarios.

.Internal network setup, PC verifies connectivity with dut2 via dut1
ifdef::topdoc[]
image::../../test/case/ietf_interfaces/lag_basic/lag-basic.svg[Internal networks]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::lag_basic/lag-basic.svg[Internal networks]
endif::testgroup[]
ifndef::testgroup[]
image::lag-basic.svg[Internal networks]
endif::testgroup[]
endif::topdoc[]

==== Topology
ifdef::topdoc[]
image::../../test/case/ietf_interfaces/lag_basic/topology.svg[Ling Aggregation Basic topology]
endif::topdoc[]
ifndef::topdoc[]
ifdef::testgroup[]
image::lag_basic/topology.svg[Ling Aggregation Basic topology]
endif::testgroup[]
ifndef::testgroup[]
image::topology.svg[Ling Aggregation Basic topology]
endif::testgroup[]
endif::topdoc[]
==== Test sequence
. Set up topology and attach to target DUTs
. Set up static link aggregate, lag0, on dut1 and dut2
. Verify failure modes for static mode
. Set up LACP link aggregate, lag0, on dut1 and dut2
. Verify failure modes for lacp mode


<<<

4 changes: 4 additions & 0 deletions test/case/ietf_interfaces/lag_basic/lag-basic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
144 changes: 144 additions & 0 deletions test/case/ietf_interfaces/lag_basic/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/env python3
r"""Ling Aggregation Basic
Verify communication over a link aggregate in static and LACP operating
modes during basic failure scenarios.
.Internal network setup, PC verifies connectivity with dut2 via dut1
image::lag-basic.svg[Internal networks]
"""
import infamy
from infamy.util import parallel, until


class DumbLinkBreaker:
"""Encapsulates basic, dumb link-breaking ops over SSH."""

def __init__(self, env, dut, ns):
self.env = env
self.dut = dut
self.ns = ns
self.tgt = env.attach(dut, "mgmt", "ssh")

def set_link(self, link, updown):
"""Set link up or down."""
_, port = self.env.ltop.xlate(self.dut, link)
self.tgt.runsh(f"ip link set {port} {updown}")

def fail_check(self, peer):
"""Verify connectivity with a given peer during failure."""
sequence = [
[("link1", "up"), ("link2", "up")],
[("link1", "down"), ("link2", "up")],
[("link1", "up"), ("link2", "down")],
[("link1", "up"), ("link2", "up")]
]

for state in sequence:
for link, updown in state:
self.set_link(link, updown)
self.ns.must_reach(peer)


def lag_init(dut, mode):
"""Set up link aggregate on dut"""
_, link1 = env.ltop.xlate(dut.name, "link1")
_, link2 = env.ltop.xlate(dut.name, "link2")

try:
_, dmon = env.ltop.xlate(dut.name, "mon")
except TypeError:
dmon = None

if dmon:
# dut1
extra = [
{
"name": "br0",
"type": "infix-if-type:bridge",
"enabled": True
}, {
"name": dmon,
"infix-interfaces:bridge-port": {
"bridge": "br0",
}
}, {
"name": "lag0",
"infix-interfaces:bridge-port": {
"bridge": "br0",
}
}
]
else:
# dut2
extra = [
{
"name": "lag0",
"ietf-ip:ipv4": {
"address": [
{
"ip": "192.168.2.42",
"prefix-length": 24
}
]
}
}
]

dut.put_config_dicts({
"ietf-interfaces": {
"interfaces": {
"interface": [
{
"name": "lag0",
"type": "infix-if-type:lag",
"enabled": True,
"lag": {
"mode": mode
}
}, {
"name": link1,
"enabled": True,
"infix-interfaces:lag-port": {
"lag": "lag0"
}
}, {
"name": link2,
"enabled": True,
"infix-interfaces:lag-port": {
"lag": "lag0"
}
}
] + extra
}
}
})


with infamy.Test() as test:
with test.step("Set up topology and attach to target DUTs"):
env = infamy.Env()
dut1 = env.attach("dut1", "mgmt")
dut2 = env.attach("dut2", "mgmt")

_, mon = env.ltop.xlate("host", "mon")
with infamy.IsolatedMacVlan(mon) as ns:
lb = DumbLinkBreaker(env, "dut1", ns)
ns.addip("192.168.2.1")

with test.step("Set up static link aggregate, lag0, on dut1 and dut2"):
parallel(lambda: lag_init(dut1, "static"),
lambda: lag_init(dut2, "static"))

with test.step("Verify failure modes for static mode"):
lb.fail_check("192.168.2.42")

with test.step("Set up LACP link aggregate, lag0, on dut1 and dut2"):
parallel(lambda: lag_init(dut1, "lacp"),
lambda: lag_init(dut2, "lacp"))

with test.step("Verify failure modes for lacp mode"):
lb.fail_check("192.168.2.42")

test.succeed()
33 changes: 33 additions & 0 deletions test/case/ietf_interfaces/lag_basic/topology.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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="host | { <mgmt1> mgmt1 | <mon> mon | \n\n\n\n | <mgmt2> mgmt2 }",
pos="0,15!",
kind="controller",
];

dut1 [
label="{ <mgmt> mgmt | <mon> mon } | { dut1\r | { <link1> link1 | <link2> link2 } }",
pos="2,15.25!",
kind="infix",
];

dut2 [
label="<mgmt> mgmt | { { <link1> link1 | <link2> link2 } | dut2\r }",
pos="2,14.75!",
kind="infix",
];

host:mgmt1 -- dut1:mgmt [kind=mgmt, color=lightgray]
host:mon -- dut1:mon // Monitor connection to dut2 via dut1
host:mgmt2 -- dut2:mgmt [kind=mgmt color=lightgrey]

dut1:link1 -- dut2:link1 [color=black, fontcolor=black, penwidth=3]
dut1:link2 -- dut2:link2 [color=black, fontcolor=black, penwidth=3]
}
76 changes: 76 additions & 0 deletions test/case/ietf_interfaces/lag_basic/topology.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit bbec2cb

Please sign in to comment.