[PATCH] AP: send TTLM if a link is indicated as disabled
Benjamin Berg
benjamin at sipsolutions.net
Tue Jan 20 01:45:04 PST 2026
Hi,
note that the relevant patches got merged into wireless, so the test is
currently failing.
For reference:
https://patch.msgid.link/20260118093904.754e057896a5.Ifd06f5ef839a93bfd54d0593dc932870f95f3242@changeid
Benjamin
On Thu, 2025-10-30 at 13:29 +0100, Benjamin Berg wrote:
> 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_l
> en(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
More information about the Hostap
mailing list