[PATCH 14/15] MBO: Cellular Data Connection Preference only for cellular capable STAs
Andrei-Alexandru Bleortu
me at andrei-z.com
Sun Oct 4 03:42:07 PDT 2026
BSS_TM_REQ mbo=<reason>:<reassoc_delay>:<cell_pref> always added the
Cellular Data Connection Preference attribute to the request, and the
preference could not be left out. Wi-Fi Agile Multiband 3.5.2 lets the
AP include it only for a STA that has indicated an available cellular
data connection; for any other STA it says something about a
connection the STA does not have, yet the Transition Reason Code
attribute is mandatory in every BSS Transition Management Request.
Accept mbo=<reason>:<reassoc_delay> without a preference, and include a
given preference only for a STA that indicated a cellular data
connection. Since hostapd learns that only with MBO enabled, the test
that expects the preference now enables MBO on its AP.
Assisted-by: LLM
Signed-off-by: Andrei-Alexandru Bleortu <me at andrei-z.com>
---
src/ap/ctrl_iface_ap.c | 18 ++++++++++++------
tests/hwsim/test_wnm.py | 28 ++++++++++++++++++++++++++--
2 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index 57ec4f6ec..110ea3fb3 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -1793,17 +1793,19 @@ int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
#ifdef CONFIG_MBO
pos = os_strstr(cmd, "mbo=");
if (pos) {
- unsigned int mbo_reason, cell_pref, reassoc_delay;
+ unsigned int mbo_reason, cell_pref = 0, reassoc_delay;
+ bool cell_pref_set;
u8 *mbo_pos = mbo;
ret = sscanf(pos, "mbo=%u:%u:%u", &mbo_reason,
&reassoc_delay, &cell_pref);
- if (ret != 3) {
+ if (ret != 2 && ret != 3) {
wpa_printf(MSG_DEBUG,
- "MBO requires three arguments: mbo=<reason>:<reassoc_delay>:<cell_pref>");
+ "MBO requires two or three arguments: mbo=<reason>:<reassoc_delay>[:<cell_pref>]");
ret = -1;
goto fail;
}
+ cell_pref_set = ret == 3;
if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP) {
wpa_printf(MSG_DEBUG,
@@ -1834,9 +1836,13 @@ int hostapd_ctrl_iface_bss_tm_req(struct hostapd_data *hapd,
*mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
*mbo_pos++ = 1;
*mbo_pos++ = mbo_reason;
- *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
- *mbo_pos++ = 1;
- *mbo_pos++ = cell_pref;
+ /* Only for a STA that indicated a cellular data connection
+ * (Wi-Fi Agile Multiband 3.5.2) */
+ if (cell_pref_set && sta->cell_capa == MBO_CELL_CAPA_AVAILABLE) {
+ *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
+ *mbo_pos++ = 1;
+ *mbo_pos++ = cell_pref;
+ }
if (reassoc_delay) {
*mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
diff --git a/tests/hwsim/test_wnm.py b/tests/hwsim/test_wnm.py
index bbc876e46..664564a00 100644
--- a/tests/hwsim/test_wnm.py
+++ b/tests/hwsim/test_wnm.py
@@ -1162,7 +1162,7 @@ def test_wnm_bss_tm_errors(dev, apdev):
"BSS_TM_REQ %s neighbor=02:11:22:33:44:55,0,0,0,0,q" % addr,
"BSS_TM_REQ %s neighbor=02:11:22:33:44:55,0,0,0,0,0q" % addr,
"BSS_TM_REQ " + addr + " url=" + 256*'a',
- "BSS_TM_REQ %s url=foo mbo=1:2" % addr,
+ "BSS_TM_REQ %s url=foo mbo=1" % addr,
"BSS_TM_REQ %s url=foo mbo=100000:0:0" % addr,
"BSS_TM_REQ %s url=foo mbo=0:0:254" % addr,
"BSS_TM_REQ %s url=foo mbo=0:100000:0" % addr]
@@ -1877,10 +1877,34 @@ def test_wnm_action_proto_no_pmf(dev, apdev):
if ev is None:
raise Exception("Key Data not ignored")
+def test_wnm_bss_tm_req_mbo_no_cell(dev, apdev):
+ """WNM BSS transition request with MBO IE to a STA without cellular data"""
+ ssid = "test-wnm-mbo"
+ hapd = start_wnm_ap(apdev[0], rsn=True, pmf=True, ssid=ssid)
+ dev[0].connect(ssid, psk="12345678", key_mgmt="WPA-PSK-SHA256",
+ proto="WPA2", ieee80211w="2", scan_freq="2412")
+ addr = dev[0].own_addr()
+
+ # The Cellular Data Connection Preference is only for STAs that
+ # indicated a cellular data connection
+ for mbo in ("mbo=4:0:1", "mbo=4:0"):
+ if "OK" not in hapd.request("BSS_TM_REQ " + addr + " " + mbo):
+ raise Exception("BSS_TM_REQ with " + mbo + " failed")
+ ev = dev[0].wait_event(['MBO-TRANSITION-REASON',
+ 'MBO-CELL-PREFERENCE'], 1)
+ if ev is None or "MBO-TRANSITION-REASON" not in ev or \
+ "reason=4" not in ev:
+ raise Exception("No MBO-TRANSITION-REASON event: " + str(ev))
+ ev = dev[0].wait_event(['MBO-CELL-PREFERENCE'], 0.2)
+ if ev is not None:
+ raise Exception("Unexpected MBO-CELL-PREFERENCE event")
+ hapd.wait_event(['BSS-TM-RESP'], timeout=5)
+ dev[0].dump_monitor()
+
def test_wnm_bss_tm_req_with_mbo_ie(dev, apdev):
"""WNM BSS transition request with MBO IE and reassociation delay attribute"""
ssid = "test-wnm-mbo"
- hapd = start_wnm_ap(apdev[0], rsn=True, pmf=True, ssid=ssid)
+ hapd = start_wnm_ap(apdev[0], rsn=True, pmf=True, ssid=ssid, mbo=True)
bssid = apdev[0]['bssid']
if "OK" not in dev[0].request("SET mbo_cell_capa 1"):
raise Exception("Failed to set STA as cellular data capable")
--
2.47.3
More information about the Hostap
mailing list