From: Benjamin Berg Date: Thu, 30 Oct 2025 12:29:57 +0000 (+0100) Subject: AP MLD: Send TTLM if a link is indicated as disabled X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb553a998f96b68dacbf8ca4a878f51e7e0779a5;p=thirdparty%2Fhostap.git AP MLD: Send TTLM if a link is indicated as disabled 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 Signed-off-by: Benjamin Berg Signed-off-by: Ilan Peer --- diff --git a/src/ap/beacon.c b/src/ap/beacon.c index 90224211b..7a0924db7 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -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 */ diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index a31673007..bf38537e2 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -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 */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 77704faae..7c173207f 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 feeb77ebe..e5ee5c042 100644 --- a/src/ap/ieee802_11_eht.c +++ b/src/ap/ieee802_11_eht.c @@ -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; +} diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index b5857c00a..ffa6cccf8 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -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)