* switch */
buflen += 6;
}
+
+ if (hapd->conf->mld_ap)
+ buflen += hostapd_eid_eht_ml_tid_to_link_map_len(
+ hapd);
}
#endif /* CONFIG_IEEE80211BE */
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 */
*/
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 */
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 */
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 */
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 */
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 */
"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;
+}
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)