[PATCH] AP: send TTLM if a link is indicated as disabled
Benjamin Berg
benjamin at sipsolutions.net
Thu Oct 30 05:29:57 PDT 2025
From: Benjamin Berg <benjamin.berg at intel.com>
When a link is indicated as disabled, then a corresponding TTLM should
be sent. Add the appropriate code to generate the TTLM.
Co-authored-by: Ilan Peer <ilan.peer at intel.com>
Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
Hi,
we are going to queue some mac80211 fixes for TTLM handling during
association. Without this fix, the eht_mld_owe_two_links_one_disabled
hwsim test will start failing as mac80211 does not know that the second
link is disabled.
Benjamin
---
src/ap/beacon.c | 12 ++++++++
src/ap/ieee802_11.c | 4 +++
src/ap/ieee802_11.h | 3 ++
src/ap/ieee802_11_eht.c | 57 ++++++++++++++++++++++++++++++++++++
src/common/ieee802_11_defs.h | 10 +++++++
5 files changed, 86 insertions(+)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 5a99611197..9ffff4f7d2 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -797,6 +797,10 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
* switch */
buflen += 6;
}
+
+ if (hapd->conf->mld_ap)
+ buflen += hostapd_eid_eht_ml_tid_to_link_map_len(
+ hapd);
}
#endif /* CONFIG_IEEE80211BE */
@@ -966,6 +970,9 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
pos = hostapd_eid_eht_capab(hapd, pos, IEEE80211_MODE_AP);
pos = hostapd_eid_eht_operation(hapd, pos);
+
+ if (hapd->conf->mld_ap)
+ pos = hostapd_eid_eht_ml_tid_to_link_map(hapd, pos);
}
#endif /* CONFIG_IEEE80211BE */
@@ -2256,6 +2263,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
*/
if (hapd->conf->mld_ap) {
tail_len += 256;
+ tail_len +=
+ hostapd_eid_eht_ml_tid_to_link_map_len(hapd);
/* for Max Channel Switch Time element during channel
* switch */
@@ -2444,6 +2453,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_eht_capab(hapd, tailpos,
IEEE80211_MODE_AP);
tailpos = hostapd_eid_eht_operation(hapd, tailpos);
+ if (hapd->conf->mld_ap)
+ tailpos = hostapd_eid_eht_ml_tid_to_link_map(hapd,
+ tailpos);
}
#endif /* CONFIG_IEEE80211BE */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index dc3b397c5f..49731cc965 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -5411,6 +5411,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
buflen += 3 + sizeof(struct ieee80211_eht_operation);
if (hapd->iconf->punct_bitmap)
buflen += EHT_OPER_DISABLED_SUBCHAN_BITMAP_SIZE;
+ if (ap_sta_is_mld(hapd, sta))
+ buflen += hostapd_eid_eht_ml_tid_to_link_map_len(hapd);
}
#endif /* CONFIG_IEEE80211BE */
@@ -5572,6 +5574,8 @@ rsnxe_done:
p = hostapd_eid_eht_ml_assoc(hapd, sta, p);
p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP);
p = hostapd_eid_eht_operation(hapd, p);
+ if (ap_sta_is_mld(hapd, sta))
+ p = hostapd_eid_eht_ml_tid_to_link_map(hapd, p);
}
#endif /* CONFIG_IEEE80211BE */
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index 77704faaec..4764dc8ab8 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -323,4 +323,7 @@ void hostapd_link_reconf_resp_tx_status(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len, int ok);
+size_t hostapd_eid_eht_ml_tid_to_link_map_len(struct hostapd_data *hapd);
+u8 *hostapd_eid_eht_ml_tid_to_link_map(struct hostapd_data *hapd, u8 *eid);
+
#endif /* IEEE802_11_H */
diff --git a/src/ap/ieee802_11_eht.c b/src/ap/ieee802_11_eht.c
index ac36c9c48c..9a88dace4c 100644
--- a/src/ap/ieee802_11_eht.c
+++ b/src/ap/ieee802_11_eht.c
@@ -2748,3 +2748,60 @@ void ieee802_11_rx_protected_eht_action(struct hostapd_data *hapd,
"MLD: Unsupported Protected EHT Action %u from " MACSTR
" discarded", action, MAC2STR(mgmt->sa));
}
+
+
+size_t hostapd_eid_eht_ml_tid_to_link_map_len(struct hostapd_data *hapd)
+{
+ if (!hapd->conf->mld_ap)
+ return 0;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ /*
+ * Allocate enough space for mld_indicate_disabled. i.e.:
+ * EID, Length and extended EID (3) +
+ * control including presence bitmap (2) + 8 * 2 byte link mappings
+ */
+ return 3 + 2 + 8 * 2;
+#else
+ return 0;
+#endif /* CONFIG_TESTING_OPTIONS */
+}
+
+
+u8 *hostapd_eid_eht_ml_tid_to_link_map(struct hostapd_data *hapd, u8 *eid)
+{
+#ifdef CONFIG_TESTING_OPTIONS
+ struct hostapd_data *other_hapd;
+ bool need_ttlm = false;
+ u16 ttlm = 0;
+#endif
+ u8 *pos = eid;
+
+ if (!hapd->conf->mld_ap)
+ return eid;
+
+#ifdef CONFIG_TESTING_OPTIONS
+ for_each_mld_link(other_hapd, hapd) {
+ if (other_hapd->conf->mld_indicate_disabled)
+ need_ttlm = true;
+ else
+ ttlm |= BIT(other_hapd->mld_link_id);
+ }
+
+ if (need_ttlm) {
+ *pos++ = WLAN_EID_EXTENSION;
+ /* ext EID + 2 bytes control + 8 * link mappings */
+ *pos++ = 1 + 2 + 8 * 2;
+ *pos++ = WLAN_EID_EXT_TID_TO_LINK_MAPPING;
+ *pos++ = EHT_TID_TO_LINK_MAP_DIRECTION_BOTH;
+ *pos++ = 0xff; /* link mapping presence bitmap */
+
+ for (int i = 0; i < 8; i++) {
+ WPA_PUT_LE16(pos, ttlm);
+ pos += 2;
+ }
+ }
+#endif /* CONFIG_TESTING_OPTIONS */
+
+ return pos;
+}
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 1d803660ca..9d8d0c2c56 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -3103,6 +3103,16 @@ enum scs_direction {
#define EHT_QOS_CONTROL_INFO_PRESENCE_MASK_OFFSET 9
#define EHT_QOS_CONTROL_INFO_LINK_ID_OFFSET 25
+/* IEEE P802.11REVmf/D1.0, 9.4.2.325 (TID-To-Link Mapping element) */
+#define EHT_TID_TO_LINK_MAP_DIRECTION_DOWN 0
+#define EHT_TID_TO_LINK_MAP_DIRECTION_UP 1
+#define EHT_TID_TO_LINK_MAP_DIRECTION_BOTH 2
+#define EHT_TID_TO_LINK_MAP_DIRECTION_MSK 0x03
+#define EHT_TID_TO_LINK_MAP_DEFAULT 0x04
+#define EHT_TID_TO_LINK_MAP_SWITCH_TIME_PRESENT 0x08
+#define EHT_TID_TO_LINK_MAP_EXPECT_DUR_PRESENT 0x10
+#define EHT_TID_TO_LINK_MAP_LINK_MAPPING_SIZE 0x20
+
/*
* IEEE P802.11be/D4.0, 9.4.2.316 QoS Characteristics element,
* Presence Bitmap Of Additional Parameters
--
2.51.0
More information about the Hostap
mailing list