From 44ade8b761e7cdb55297a2c906ffd1223e3d5274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Fri, 6 Mar 2026 08:41:23 +0100 Subject: [PATCH] Wi-Fi: Add support for band steering --- buildroot | 2 +- package/feature-wifi/Config.in | 1 + src/confd/src/hardware.c | 76 ++++++++++++++++++++++++- src/confd/yang/confd/infix-if-wifi.yang | 28 +++++++++ 4 files changed, 105 insertions(+), 2 deletions(-) diff --git a/buildroot b/buildroot index a40d6926..d758952b 160000 --- a/buildroot +++ b/buildroot @@ -1 +1 @@ -Subproject commit a40d69265ea75afd4a1833e1f6400195b12e67a5 +Subproject commit d758952b3e9032975a0049f44724f80cb29d949b diff --git a/package/feature-wifi/Config.in b/package/feature-wifi/Config.in index ecd4c933..6258d9d7 100644 --- a/package/feature-wifi/Config.in +++ b/package/feature-wifi/Config.in @@ -11,6 +11,7 @@ config BR2_PACKAGE_FEATURE_WIFI select BR2_PACKAGE_HOSTAPD_WPA3 select BR2_PACKAGE_HOSTAPD_WPS select BR2_PACKAGE_HOSTAPD_WNM + select BR2_PACKAGE_HOSTAPD_MBO select BR2_PACKAGE_IW help Enables WiFi in Infix. Enables all requried applications. diff --git a/src/confd/src/hardware.c b/src/confd/src/hardware.c index 78efd7e5..936108da 100644 --- a/src/confd/src/hardware.c +++ b/src/confd/src/hardware.c @@ -219,6 +219,51 @@ static const char *resolve_mobility_domain(const char *mobility_domain, const ch return hash_result; } +/* + * Find an AP interface on a higher-band radio (5/6 GHz) advertising the + * same SSID as the caller's 2.4 GHz BSS. Used to emit + * no_probe_resp_if_seen_on=, which suppresses 2.4 GHz probe responses to + * clients that have recently probed the 5/6 GHz twin, forcing dual-band + * clients to discover the higher band. 2.4-only clients are unaffected: + * hostapd only suppresses if it has actually seen the MAC on the listed + * interface, so a 2.4-only client always gets a probe response. + * + * Returns a pointer into the config tree (do not free) or NULL. + */ +static const char *wifi_find_higher_band_twin(struct lyd_node *config, + const char *current_band, + const char *current_ssid) +{ + struct lyd_node *cifs, *cif; + + if (strcmp(current_band, "2.4GHz")) + return NULL; + + cifs = lydx_get_descendant(config, "interfaces", "interface", NULL); + LYX_LIST_FOR_EACH(cifs, cif, "interface") { + struct lyd_node *wifi, *ap, *radio_node; + const char *radio, *ssid, *band; + + wifi = lydx_get_child(cif, "wifi"); + if (!wifi) + continue; + ap = lydx_get_child(wifi, "access-point"); + if (!ap) + continue; + ssid = lydx_get_cattr(ap, "ssid"); + if (strcmp(ssid, current_ssid)) + continue; + radio = lydx_get_cattr(wifi, "radio"); + radio_node = lydx_get_xpathf(config, + "/hardware/component[name='%s']/wifi-radio", radio); + band = lydx_get_cattr(radio_node, "band"); + if (!strcmp(band, "5GHz") || !strcmp(band, "6GHz")) + return lydx_get_cattr(cif, "name"); + } + + return NULL; +} + static int wifi_find_interfaces_on_radio(struct lyd_node *ifs, const char *radio_name, struct lyd_node ***iface_list, int *count) { @@ -302,7 +347,7 @@ static void wifi_gen_ssid_config(FILE *hostapd, struct lyd_node *cif, struct lyd const char *ssid, *hidden, *security_mode, *secret_name; const char *mobility_domain, *mobility_domain_raw; const char *nas_identifier_cfg; - bool enable_80211k, enable_80211r, enable_80211v; + bool enable_80211k, enable_80211r, enable_80211v, enable_mbo; unsigned char *secret = NULL; const char *ifname; char nas_identifier_default[300]; @@ -326,6 +371,14 @@ static void wifi_gen_ssid_config(FILE *hostapd, struct lyd_node *cif, struct lyd enable_80211k = dot11k != NULL; enable_80211r = dot11r != NULL; enable_80211v = dot11v != NULL; + if (dot11v) { + const char *band_steering = lydx_get_cattr(dot11v, "band-steering"); + + enable_mbo = !band_steering || !strcmp(band_steering, "true"); + } else { + enable_mbo = false; + } + /* Set BSSID if custom MAC is configured */ @@ -457,6 +510,27 @@ static void wifi_gen_ssid_config(FILE *hostapd, struct lyd_node *cif, struct lyd fprintf(hostapd, "okc=1\n"); } + /* MBO: Multi-Band Operation (band steering, needs 802.11v above) */ + if (enable_mbo) { + const char *twin; + + fprintf(hostapd, "mbo=1\n"); + + /* Required for no_probe_resp_if_seen_on below: without it + * hostapd keeps no sta_track list, so the twin radio never + * knows which clients it has seen. Radio-level, emit once + * in the main section, never per BSS. */ + if (!is_bss) + fprintf(hostapd, "track_sta_max_num=100\n"); + + /* Active band steering: on a 2.4 GHz BSS, suppress probe + * responses to clients recently seen on the same-SSID 5/6 + * GHz BSS, nudging dual-band clients to the higher band. */ + twin = wifi_find_higher_band_twin(config, band, ssid); + if (twin) + fprintf(hostapd, "no_probe_resp_if_seen_on=%s\n", twin); + } + free(secret); } diff --git a/src/confd/yang/confd/infix-if-wifi.yang b/src/confd/yang/confd/infix-if-wifi.yang index 95cae206..2e1b323e 100644 --- a/src/confd/yang/confd/infix-if-wifi.yang +++ b/src/confd/yang/confd/infix-if-wifi.yang @@ -48,6 +48,12 @@ submodule infix-if-wifi { - Security: WPA2/WPA3 with keystore integration - Operational state: Connection status, RSSI, client lists"; + revision 2026-03-04 { + description + "Add band-steering (MBO) support and OKC configuration."; + reference "internal"; + } + revision 2026-02-12 { description "Add support for roaming, by adding support for 802.11v/k/r" @@ -523,6 +529,28 @@ submodule infix-if-wifi { Allows APs to suggest better APs to clients, improving network-assisted roaming decisions."; + + leaf band-steering { + type boolean; + default true; + description + "Multi-Band Operation (MBO) band steering. + + Signals band preferences to capable clients, + encouraging dual-band devices to prefer 5GHz + over 2.4GHz when signal quality permits. + + MBO steers clients via 802.11v BSS Transition + Management, hence its placement under dot11v; + enabling dot11v enables band steering by default. + + Only meaningful when the same SSID is offered on + two or more bands (an access-point per radio); a + single-band BSS has no other band to steer toward. + + Safe to leave enabled (default) - only activates + when both AP and client support MBO."; + } } leaf okc {