From 84dfaf7c03e67e2e72fee55f27a86dbe4592398e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Wed, 24 Jun 2026 16:13:53 +0200 Subject: [PATCH 1/5] buildroot: Add missing MBO feature in hostapd --- buildroot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildroot b/buildroot index 707ade3a..dd816b92 160000 --- a/buildroot +++ b/buildroot @@ -1 +1 @@ -Subproject commit 707ade3a8985c5531e69a1fab23e0de42df8a487 +Subproject commit dd816b92336b46726c5618a81d3d42cab3b8d338 From d0d95f4098655e0518b4e9235751008397715330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Sun, 28 Jun 2026 21:01:42 +0200 Subject: [PATCH 2/5] confd: wifi: Fix issue with reconfigure modes on a wifi radio The previous mode was not teardowned correctly --- src/confd/src/hardware.c | 26 ++++++++++++++++++++++++-- src/confd/src/if-wifi.c | 19 +++++-------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/confd/src/hardware.c b/src/confd/src/hardware.c index 816396bd..f2dbb338 100644 --- a/src/confd/src/hardware.c +++ b/src/confd/src/hardware.c @@ -1379,8 +1379,32 @@ int hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct l * all radio configs, so band edits and radio add/remove both apply. */ if (wifi_changed && event == SR_EV_DONE) { + struct lyd_node *cifs; glob_t gl = { 0 }; + size_t i; + /* Need to remove old hostapd config files, for radios not used anymore */ + cifs = lydx_get_descendant(config, "interfaces", "interface", NULL); + if (glob("/etc/hostapd-*.conf", 0, NULL, &gl) == 0) { + for (i = 0; i < gl.gl_pathc; i++) { + char radio[64], **aps = NULL; + int n = 0, j; + + if (sscanf(gl.gl_pathv[i], "/etc/hostapd-%63[^.].conf", radio) != 1) + continue; + wifi_find_radio_aps(cifs, radio, &aps, &n); + for (j = 0; j < n; j++) + free(aps[j]); + free(aps); + if (!n) { + unlink(gl.gl_pathv[i]); + erasef(HOSTAPD_CONF_NEXT, radio); + } + } + globfree(&gl); + } + + gl = (glob_t){ 0 }; if (glob("/etc/hostapd-*.conf", 0, NULL, &gl) == 0 && gl.gl_pathc > 0) { FILE *fp; @@ -1389,8 +1413,6 @@ int hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct l ERRNO("Could not open " HOSTAPD_SERVICE); rc = SR_ERR_INTERNAL; } else { - size_t i; - fprintf(fp, "# Generated by confd, do not edit.\n"); fprintf(fp, "service name:hostapd \\\n"); fprintf(fp, "\t[2345] hostapd -P /run/hostapd.pid"); diff --git a/src/confd/src/if-wifi.c b/src/confd/src/if-wifi.c index 21baf77c..84653dfa 100644 --- a/src/confd/src/if-wifi.c +++ b/src/confd/src/if-wifi.c @@ -540,7 +540,6 @@ out: */ int wifi_del_iface(struct lyd_node *dif, struct dagger *net) { - struct lyd_node *wifi; const char *ifname; FILE *iw; @@ -553,22 +552,14 @@ int wifi_del_iface(struct lyd_node *dif, struct dagger *net) } fprintf(iw, "# Generated by Infix confd - WiFi Interface Deletion\n"); + + erasef(WPA_SUPPLICANT_CONF, ifname); + fprintf(iw, "initctl -bfq disable mesh@%s\n", ifname); + fprintf(iw, "initctl -bfq disable wifi@%s\n", ifname); + fprintf(iw, "ip link set %s down\n", ifname); fprintf(iw, "iw dev %s disconnect 2>/dev/null\n", ifname); fprintf(iw, "iw dev %s del 2>/dev/null || ip link del %s 2>/dev/null || true\n", ifname, ifname); - - wifi = lydx_get_child(dif, "wifi"); - if (wifi) { - int mode = wifi_get_mode(wifi); - - if (mode == wifi_mesh) { - erasef(WPA_SUPPLICANT_CONF, ifname); - fprintf(iw, "initctl -bfq disable mesh@%s\n", ifname); - } else if (mode != wifi_ap) { - erasef(WPA_SUPPLICANT_CONF, ifname); - fprintf(iw, "initctl -bfq disable wifi@%s\n", ifname); - } - } fclose(iw); return SR_ERR_OK; From 9b41139066bee08a1993ceda9d1d1df34179d1d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Mon, 29 Jun 2026 14:25:56 +0200 Subject: [PATCH 3/5] test: netns: refactor must_receive Parameter was called `timeout` but it was used as a duration, how long it should fetch packets to match on. --- test/case/routing/ospf_unnumbered_interface/test.py | 2 +- test/infamy/netns.py | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/test/case/routing/ospf_unnumbered_interface/test.py b/test/case/routing/ospf_unnumbered_interface/test.py index d03daffa..895801a0 100755 --- a/test/case/routing/ospf_unnumbered_interface/test.py +++ b/test/case/routing/ospf_unnumbered_interface/test.py @@ -186,7 +186,7 @@ with infamy.Test() as test: with test.step("Verify there are no OSPF HELLO packets on PC:data"): assert(route.ospf_get_interface_passive(R1, "0.0.0.0", R1data)) print("Verify that no hello packets are recieved from passive interfaces") - ns0.must_not_receive("ip proto 89", timeout=15) # Default hello time 10s + ns0.must_not_receive("ip proto 89", duration=15) # Default hello time 10s with test.step("Test connectivity from PC:data to 192.168.200.1"): ns0.must_reach("192.168.200.1") diff --git a/test/infamy/netns.py b/test/infamy/netns.py index 8ac0414d..c1bb678e 100644 --- a/test/infamy/netns.py +++ b/test/infamy/netns.py @@ -62,6 +62,7 @@ class IsolatedMacVlans: self.ifmap, self.lo, self.set_up = ifmap, lo, set_up self.mode = mode self.ping_timeout = env.ENV.attr("ping_timeout", 5) + self.default_receive_duration = env.ENV.attr("default_receive_duration", 10) def start(self): self.sleeper = subprocess.Popen(["unshare", "-r", "-n", "sh", "-c", @@ -86,7 +87,7 @@ class IsolatedMacVlans: if self.set_up: self.run(["ip", "link", "set", "dev", ifname, "up"]) - + except Exception as e: self.__exit__(None, None, None) raise e @@ -272,11 +273,11 @@ class IsolatedMacVlans: raise Exception(res) - def must_receive(self, expr, ifname, timeout=None, must=True): - timeout = timeout if timeout else self.ping_timeout + def must_receive(self, expr, ifname, duration=None, must=True): + duration = duration if duration else self.default_receive_duration tshark = self.run(["tshark", "-nl", f"-i{ifname}", - f"-aduration:{timeout}", "-c1", expr], + f"-aduration:{duration}", "-c1", expr], stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -336,9 +337,9 @@ class IsolatedMacVlan(IsolatedMacVlans): return super().addip(ifname=self._ifname, addr=addr, prefix_length=prefix_length, proto=proto) - def must_receive(self, expr, timeout=None, ifname=None, must=True): + def must_receive(self, expr, duration=None, ifname=None, must=True): ifname = ifname if ifname else self._ifname - return super().must_receive(expr=expr, ifname=ifname, timeout=timeout, must=must) + return super().must_receive(expr=expr, ifname=ifname, duration=duration, must=must) def pcap(self, expr, ifname=None): ifname = ifname if ifname else self._ifname From 2744e6ee851bcc0ad586a069a86d34cc0c0edee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Mon, 29 Jun 2026 14:27:37 +0200 Subject: [PATCH 4/5] test: Whitespace --- test/case/interfaces/static_multicast_filters/test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/case/interfaces/static_multicast_filters/test.py b/test/case/interfaces/static_multicast_filters/test.py index dfa54c02..e714819c 100755 --- a/test/case/interfaces/static_multicast_filters/test.py +++ b/test/case/interfaces/static_multicast_filters/test.py @@ -133,7 +133,7 @@ with infamy.Test() as test: print("Starting IPv4 multicast sender") with mcast.MCastSender(send_ns, ipv4_multicast_group): - + with test.step("Verify that 224.1.1.1 is flooded to host:data2 and host:data3"): infamy.parallel( lambda: receive_ns.must_receive(f"ip dst {ipv4_multicast_group}"), @@ -150,10 +150,10 @@ with infamy.Test() as test: nojoin_ns.must_not_receive(f"ip dst {ipv4_multicast_group}") with test.step("Start MAC multicast sender on host:data1, group 01:00:00:01:02:03"): - + print("Starting MAC multicast sender") with mcast.MacMCastSender(send_ns, mac_multicast_group): - + with test.step("Verify MAC multicast 01:00:00:01:02:03 is flooded to host:data2 and host:data3"): infamy.parallel( lambda: receive_ns.must_receive(f"ether dst {mac_multicast_group}"), @@ -162,10 +162,10 @@ with infamy.Test() as test: with test.step("Enable MAC multicast filter on host:data2, group 01:00:00:01:02:03"): set_static_multicast_filter(target, mac_multicast_group, mreceive) until(lambda: iface.exist_bridge_multicast_filter(target, mac_multicast_group, mreceive, "br0")) - + with test.step("Verify that the MAC group is still forwarded to host:data2"): receive_ns.must_receive(f"ether dst {mac_multicast_group}"), - + with test.step("Verify that the MAC group is no longer forwarded to host:data3"): nojoin_ns.must_not_receive(f"ether dst {mac_multicast_group}") From 1b11bae8eb1b99a0fe60300b655fb089117927f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Mon, 29 Jun 2026 14:27:54 +0200 Subject: [PATCH 5/5] test: static_multicast_filters: Fix indendation --- .../static_multicast_filters/test.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/case/interfaces/static_multicast_filters/test.py b/test/case/interfaces/static_multicast_filters/test.py index e714819c..309ad795 100755 --- a/test/case/interfaces/static_multicast_filters/test.py +++ b/test/case/interfaces/static_multicast_filters/test.py @@ -143,11 +143,11 @@ with infamy.Test() as test: set_static_multicast_filter(target, ipv4_multicast_group, mreceive) until(lambda: iface.exist_bridge_multicast_filter(target, ipv4_multicast_group, mreceive, "br0")) - with test.step("Verify that the group is still forwarded to host:data2"): - receive_ns.must_receive(f"ip dst {ipv4_multicast_group}") + with test.step("Verify that the group is still forwarded to host:data2"): + receive_ns.must_receive(f"ip dst {ipv4_multicast_group}") - with test.step("Verify that the group is no longer forwarded to host:data3"): - nojoin_ns.must_not_receive(f"ip dst {ipv4_multicast_group}") + with test.step("Verify that the group is no longer forwarded to host:data3"): + nojoin_ns.must_not_receive(f"ip dst {ipv4_multicast_group}") with test.step("Start MAC multicast sender on host:data1, group 01:00:00:01:02:03"): @@ -158,15 +158,15 @@ with infamy.Test() as test: infamy.parallel( lambda: receive_ns.must_receive(f"ether dst {mac_multicast_group}"), lambda: nojoin_ns.must_receive(f"ether dst {mac_multicast_group}")) - + with test.step("Enable MAC multicast filter on host:data2, group 01:00:00:01:02:03"): set_static_multicast_filter(target, mac_multicast_group, mreceive) until(lambda: iface.exist_bridge_multicast_filter(target, mac_multicast_group, mreceive, "br0")) - with test.step("Verify that the MAC group is still forwarded to host:data2"): - receive_ns.must_receive(f"ether dst {mac_multicast_group}"), + with test.step("Verify that the MAC group is still forwarded to host:data2"): + receive_ns.must_receive(f"ether dst {mac_multicast_group}") - with test.step("Verify that the MAC group is no longer forwarded to host:data3"): - nojoin_ns.must_not_receive(f"ether dst {mac_multicast_group}") + with test.step("Verify that the MAC group is no longer forwarded to host:data3"): + nojoin_ns.must_not_receive(f"ether dst {mac_multicast_group}") test.succeed()