diff --git a/buildroot b/buildroot index 75b8cfffb..01ba698a1 160000 --- a/buildroot +++ b/buildroot @@ -1 +1 @@ -Subproject commit 75b8cfffbfde511aeb0e2650b769fc03b55c9403 +Subproject commit 01ba698a1bc218414912602cd63d33037af3888a diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index bc12e39b3..1111e32c4 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -3,6 +3,13 @@ Change Log All notable changes to the project are documented in this file. +[v26.09.0][UNRELEASED] +------------------------- + +### Changes + +- Upgrade FRR to 10.5.5 + [v26.08.0][] - 2026-09-01 ------------------------- @@ -2271,6 +2278,7 @@ Supported YANG models in addition to those used by sysrepo and netopeer: [buildroot]: https://buildroot.org/ [UNRELEASED]: https://github.com/kernelkit/infix/compare/v26.08.0...HEAD +[v26.09.0]: https://github.com/kernelkit/infix/compare/v26.08.0...v26.09.0 [v26.08.0]: https://github.com/kernelkit/infix/compare/v26.06.0...v26.08.0 [v26.06.0]: https://github.com/kernelkit/infix/compare/v26.05.0...v26.06.0 [v26.05.0]: https://github.com/kernelkit/infix/compare/v26.04.0...v26.05.0 diff --git a/patches/frr/10.5.4/0001-Libyang4-compat.patch b/patches/frr/10.5.5/0001-Libyang4-compat.patch similarity index 100% rename from patches/frr/10.5.4/0001-Libyang4-compat.patch rename to patches/frr/10.5.5/0001-Libyang4-compat.patch diff --git a/patches/frr/10.5.4/0002-Failed-without-c-23-this-adds-compatibility-layer.patch b/patches/frr/10.5.5/0002-Failed-without-c-23-this-adds-compatibility-layer.patch similarity index 100% rename from patches/frr/10.5.4/0002-Failed-without-c-23-this-adds-compatibility-layer.patch rename to patches/frr/10.5.5/0002-Failed-without-c-23-this-adds-compatibility-layer.patch diff --git a/patches/frr/10.5.4/0003-zebra-don-t-resolve-nexthop-via-inactive-connected-r.patch b/patches/frr/10.5.5/0003-zebra-don-t-resolve-nexthop-via-inactive-connected-r.patch similarity index 100% rename from patches/frr/10.5.4/0003-zebra-don-t-resolve-nexthop-via-inactive-connected-r.patch rename to patches/frr/10.5.5/0003-zebra-don-t-resolve-nexthop-via-inactive-connected-r.patch diff --git a/test/case/hardware/watchdog/test.py b/test/case/hardware/watchdog/test.py index 3c4d66dff..a3d3e0be8 100755 --- a/test/case/hardware/watchdog/test.py +++ b/test/case/hardware/watchdog/test.py @@ -12,7 +12,7 @@ """ import base64 import infamy -from infamy.util import parallel +from infamy.util import parallel, until import json import subprocess import time @@ -24,8 +24,11 @@ lambda: env.attach("target", "mgmt", "ssh")) with test.step("Verify the presence of a watchdog device"): - wctl = tgtssh.run(["watchdogctl"], stdout=subprocess.PIPE) - conf = json.loads(wctl.stdout) + def status(): + wctl = tgtssh.run(["watchdogctl"], stdout=subprocess.PIPE, check=True) + return json.loads(wctl.stdout) + + conf = until(status) dogs = [ dog for dog in conf.get("device", []) if dog.get("name", "") == "/dev/watchdog" ] if len(dogs) < 1: diff --git a/test/case/interfaces/wireguard_multipoint/test.py b/test/case/interfaces/wireguard_multipoint/test.py index 0562fee58..a6fd11437 100755 --- a/test/case/interfaces/wireguard_multipoint/test.py +++ b/test/case/interfaces/wireguard_multipoint/test.py @@ -472,7 +472,9 @@ def configure_client2(dut): _, hserver = env.ltop.xlate("host", "data2") with test.step("Configure server, client1 and client2"): - util.parallel(lambda: configure_server(server), lambda: configure_client1(client1), lambda: configure_client2(client2)) + configure_server(server) + util.parallel(lambda: configure_client1(client1), + lambda: configure_client2(client2)) with infamy.IsolatedMacVlan(hserver) as nsserver, infamy.IsolatedMacVlan(hclient1) as nsclient1: nsserver.addip("192.168.0.1") @@ -485,25 +487,25 @@ def configure_client2(dut): nsclient1.addroute("default", "2001:db8:3c4d:01::2", proto="ipv6") with test.step("Verify IPv4 connectivity with ping 10.0.0.1, 10.0.0.2 and 10.0.0.3 from host:data1"): - util.parallel(lambda: nsclient1.must_reach("10.0.0.1"), - lambda: nsclient1.must_reach("10.0.0.2"), - lambda: nsclient1.must_reach("10.0.0.3")) + util.parallel(lambda: nsclient1.must_reach("10.0.0.1", timeout=15), + lambda: nsclient1.must_reach("10.0.0.2", timeout=15), + lambda: nsclient1.must_reach("10.0.0.3", timeout=15)) with test.step("Verify IPv4 connectivity with ping 10.0.0.1 and 10.0.0.2 from host:data2"): - util.parallel(lambda: nsserver.must_reach("10.0.0.1"), - lambda: nsserver.must_reach("10.0.0.2")) + util.parallel(lambda: nsserver.must_reach("10.0.0.1", timeout=15), + lambda: nsserver.must_reach("10.0.0.2", timeout=15)) with test.step("Verify host:data2 can not ping 10.0.0.3"): nsserver.must_not_reach("10.0.0.3") # Not in allowed IPs with test.step("Verify IPv6 connectivity with ping fd00:0::1, fd00:0::2 and fd00:0::3 from host:data1"): - util.parallel(lambda: nsclient1.must_reach("fd00:0::1"), - lambda: nsclient1.must_reach("fd00:0::2"), - lambda: nsclient1.must_reach("fd00:0::3")) + util.parallel(lambda: nsclient1.must_reach("fd00:0::1", timeout=15), + lambda: nsclient1.must_reach("fd00:0::2", timeout=15), + lambda: nsclient1.must_reach("fd00:0::3", timeout=15)) with test.step("Verify IPv6 connectivity with ping fd00:0:1 and fd00:0:2 from host:data2"): - util.parallel(lambda: nsserver.must_reach("fd00:0::1"), - lambda: nsserver.must_reach("fd00:0::2")) + util.parallel(lambda: nsserver.must_reach("fd00:0::1", timeout=15), + lambda: nsserver.must_reach("fd00:0::2", timeout=15)) with test.step("Verify host:data2 can not ping fd00:0::3"): nsserver.must_not_reach("fd00:0::3") # Not in allowed IPs diff --git a/test/case/interfaces/wireguard_roadwarrior/test.py b/test/case/interfaces/wireguard_roadwarrior/test.py index 232cfdcf1..5d6a5294a 100755 --- a/test/case/interfaces/wireguard_roadwarrior/test.py +++ b/test/case/interfaces/wireguard_roadwarrior/test.py @@ -329,7 +329,9 @@ def configure_client(client, client_num, private_key, public_key, server_pubkey) with test.step("Configure DUTs"): util.parallel( lambda: configure_server(server, server_public_key, server_private_key, client1_public_key, client2_public_key), - lambda: configure_router(router), + lambda: configure_router(router) + ) + util.parallel( lambda: configure_client(client1, 1, client1_private_key, client1_public_key, server_public_key), lambda: configure_client(client2, 2, client2_private_key, client2_public_key, server_public_key) ) @@ -352,8 +354,8 @@ def configure_client(client, client_num, private_key, public_key, server_pubkey) with test.step("Verify IPv4 connectivity with ping 192.168.0.2 from host:data1 and host:data2"): util.parallel( - lambda: ns_client1.must_reach("192.168.0.2"), - lambda: ns_client2.must_reach("192.168.0.2") + lambda: ns_client1.must_reach("192.168.0.2", timeout=15), + lambda: ns_client2.must_reach("192.168.0.2", timeout=15) ) test.succeed() diff --git a/test/case/meta/bootorder.py b/test/case/meta/bootorder.py index a82d4c7b1..68c4e98a5 100755 --- a/test/case/meta/bootorder.py +++ b/test/case/meta/bootorder.py @@ -1,16 +1,20 @@ #!/usr/bin/env python3 import infamy +from infamy.util import parallel with infamy.Test() as test: with test.step("Discover topology and attach to available DUTs"): env = infamy.Env(False) ctrl = env.ptop.get_ctrl() - duts = {} - duts_state = {} - for ix in env.ptop.get_infixen(): + + def attach(ix): cport, ixport = env.ptop.get_mgmt_link(ctrl, ix) print(f"Attaching to {ix}:{ixport} via {ctrl}:{cport}") - duts[ix] = env.attach(ix, ixport) + return env.attach(ix, ixport) + + infixen = env.ptop.get_infixen() + duts = dict(zip(infixen, parallel(*(lambda ix=ix: attach(ix) + for ix in infixen)))) with test.step("Verify bootorder"): for name, tgt in duts.items(): diff --git a/test/case/meta/check-version.py b/test/case/meta/check-version.py index 1ec8570a3..72e379f40 100755 --- a/test/case/meta/check-version.py +++ b/test/case/meta/check-version.py @@ -1,17 +1,21 @@ #!/usr/bin/env python3 import infamy +from infamy.util import parallel import os with infamy.Test() as test: with test.step("Discover topology and attach to available DUTs"): env = infamy.Env(False) ctrl = env.ptop.get_ctrl() - duts = {} - duts_state = {} - for ix in env.ptop.get_infixen(): + + def attach(ix): cport, ixport = env.ptop.get_mgmt_link(ctrl, ix) print(f"Attaching to {ix}:{ixport} via {ctrl}:{cport}") - duts[ix] = env.attach(ix, ixport) + return env.attach(ix, ixport) + + infixen = env.ptop.get_infixen() + duts = dict(zip(infixen, parallel(*(lambda ix=ix: attach(ix) + for ix in infixen)))) with test.step("Verify software version"): expected=os.environ.get("VERSION") diff --git a/test/case/meta/play.py b/test/case/meta/play.py index 6046be5ae..2eeace309 100755 --- a/test/case/meta/play.py +++ b/test/case/meta/play.py @@ -3,6 +3,7 @@ import json import infamy +from infamy.util import parallel def jq(yangdata): print(json.dumps(yangdata, indent=True)) @@ -11,9 +12,13 @@ def jq(yangdata): ctrl = env.ptop.get_ctrl() infixen = env.ptop.get_infixen() -for ix in infixen: + +def attach(ix): cport, ixport = env.ptop.get_mgmt_link(ctrl, ix) print(f"Attaching to {ix}:{ixport} via {ctrl}:{cport}") - exec(f"{ix} = env.attach(\"{ix}\", \"{ixport}\")") + return env.attach(ix, ixport) + +globals().update(zip(infixen, parallel(*(lambda ix=ix: attach(ix) + for ix in infixen)))) print("\nGLHF") diff --git a/test/case/routing/ospf_default_route_advertise/test.py b/test/case/routing/ospf_default_route_advertise/test.py index 1767336fd..c177f8dc4 100755 --- a/test/case/routing/ospf_default_route_advertise/test.py +++ b/test/case/routing/ospf_default_route_advertise/test.py @@ -276,14 +276,14 @@ def set_redistribute_default_always(target): until(lambda: route.ipv4_route_exist(R2, "0.0.0.0/0", proto="ietf-ospf:ospfv2"), attempts=200) until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-ospf:ospfv2"), attempts=200) until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-ospf:ospfv2"), attempts=200) + until(lambda: route.ipv4_route_exist(R1, "192.168.20.0/24", proto="ietf-ospf:ospfv2"), attempts=200) with test.step("Verify connectivity from PC:data2 to 10.10.10.10"): _, hport0 = env.ltop.xlate("PC", "data2") with infamy.IsolatedMacVlan(hport0) as ns0: ns0.addip("192.168.20.2") ns0.addroute("0.0.0.0/0", "192.168.20.1") - #breakpoint() - ns0.must_reach("10.10.10.10") + ns0.must_reach("10.10.10.10", timeout=15) with test.step("Disable link PC:data1 <--> R1:data (take default gateway down)"): disable_interface(R1, R1data) @@ -311,6 +311,7 @@ def set_redistribute_default_always(target): print("Waiting for OSPF routes...") until(lambda: route.ipv4_route_exist(R2, "192.168.100.1/32", proto="ietf-ospf:ospfv2"), attempts=200) until(lambda: route.ipv4_route_exist(R1, "192.168.200.1/32", proto="ietf-ospf:ospfv2"), attempts=200) + until(lambda: route.ipv4_route_exist(R1, "192.168.20.0/24", proto="ietf-ospf:ospfv2"), attempts=200) until(lambda: route.ipv4_route_exist(R2, "0.0.0.0/0", proto="ietf-ospf:ospfv2"), attempts=200) with test.step("Verify connectivity from PC:data2 to 10.10.10.10"): @@ -318,6 +319,6 @@ def set_redistribute_default_always(target): with infamy.IsolatedMacVlan(hport0) as ns0: ns0.addip("192.168.20.2") ns0.addroute("0.0.0.0/0", "192.168.20.1") - ns0.must_reach("10.10.10.10") + ns0.must_reach("10.10.10.10", timeout=15) test.succeed() diff --git a/test/case/services/mdns/mdns_allow_deny/test.py b/test/case/services/mdns/mdns_allow_deny/test.py index 0311d9168..6feea7cbf 100755 --- a/test/case/services/mdns/mdns_allow_deny/test.py +++ b/test/case/services/mdns/mdns_allow_deny/test.py @@ -12,6 +12,7 @@ """ import re import infamy +from infamy.util import parallel def mdns_scan(): @@ -64,8 +65,8 @@ def check(expected, allow=None, deny=None): with infamy.Test() as test: with test.step("Set up topology and attach to target DUT"): env = infamy.Env() - dut = env.attach("dut", "mgmt") - ssh = env.attach("dut", "mgmt", "ssh") + dut, ssh = parallel(lambda: env.attach("dut", "mgmt"), + lambda: env.attach("dut", "mgmt", "ssh")) _, p1 = env.ltop.xlate("dut", "p1") _, p2 = env.ltop.xlate("dut", "p2") _, p3 = env.ltop.xlate("dut", "p3") diff --git a/test/case/system/factory_config/test.py b/test/case/system/factory_config/test.py index ecbfb7593..5852979d1 100755 --- a/test/case/system/factory_config/test.py +++ b/test/case/system/factory_config/test.py @@ -18,7 +18,7 @@ def factory_hostname(tgtssh): """Read the hostname the factory-config will boot with.""" - cfg = json.loads(tgtssh.runsh(f"cat {FACTORY}").stdout) + cfg = json.loads(tgtssh.runsh(f"cat {FACTORY}", check=True).stdout) return cfg.get("ietf-system:system", {}).get("hostname") def cleanup(env): diff --git a/test/infamy/ssh.py b/test/infamy/ssh.py index 2db6bde56..4714ac934 100644 --- a/test/infamy/ssh.py +++ b/test/infamy/ssh.py @@ -70,6 +70,9 @@ def __init__(self, name: str, location: Location, wait: bool=True): self.location = location if wait: util.until(lambda: ssh_syn(location.host, location.port)) + util.until(lambda: self.run("true", stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL).returncode == 0, + attempts=30) def __str__(self): nm = f"{self.name}"