]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Send TTLM if a link is indicated as disabled
authorBenjamin Berg <benjamin.berg@intel.com>
Thu, 30 Oct 2025 12:29:57 +0000 (13:29 +0100)
committerJouni Malinen <j@w1.fi>
Sun, 25 Jan 2026 17:12:21 +0000 (19:12 +0200)
When a link is indicated as disabled, a corresponding TTLM should be
sent. Add the appropriate code to generate the TTLM in the testing cases
where hostapd is explicitly configured with mld_indicate_disabled=1.

Co-authored-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
src/ap/beacon.c
src/ap/ieee802_11.c
src/ap/ieee802_11.h
src/ap/ieee802_11_eht.c
src/common/ieee802_11_defs.h

index 90224211b31278ffcfb1e58abd50884eaec9f833..7a0924db7eaa910611ab20d9de0575dbdba03c39 100644 (file)
@@ -798,6 +798,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 */
 
@@ -967,6 +971,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 */
 
@@ -2278,6 +2285,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 */
@@ -2466,6 +2475,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 */
 
index a3167300743c58545d3fb826b22cbcc812eff831..bf38537e2facf2ae77517717ff38d864d32acee3 100644 (file)
@@ -5423,6 +5423,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 */
 
@@ -5582,6 +5584,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 */
 
index 77704faaeccb2b7fc9e2375fca6bc1f6ef58892f..7c173207f8007e1f14cda037531866dad6604e3c 100644 (file)
@@ -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 */
index feeb77ebea039703e1b90fcba1adf1158f054e01..e5ee5c042448c3c16e1a13de0d2f7447448e5ef1 100644 (file)
@@ -2749,3 +2749,62 @@ 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.:
+        *  Element ID, Length, and Element ID Extension (3) +
+        *  Control including presence bitmap (2) + 8 * 2 byte link mappings
+        */
+       return 3 + 2 + 8 * 2;
+#else /* CONFIG_TESTING_OPTIONS */
+       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 /* CONFIG_TESTING_OPTIONS */
+       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) {
+               int i;
+
+               *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 (i = 0; i < 8; i++) {
+                       WPA_PUT_LE16(pos, ttlm);
+                       pos += 2;
+               }
+       }
+#endif /* CONFIG_TESTING_OPTIONS */
+
+       return pos;
+}
index b5857c00a42577a6ffcd0832aca5cb8cc3016c4e..ffa6cccf870836b99aca7cdbd8a6a47162779d38 100644 (file)
@@ -3106,6 +3106,17 @@ enum scs_request_type {
        SCS_REQ_CHANGE = 2,
 };
 
+/* IEEE Std 802.11be-2024, 9.4.2.324 (TID-To-Link Mapping element)
+ * Figure 9-1074ax (TID-TO-Link Mapping Control field format) */
+#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 Std 802.11be-2024, 9.4.2.326 QoS Characteristics element,
  * Table 9-417w (Direction subfield encoding)