From c53e926852d295c7069df2d0e58045e48d4b1025 Mon Sep 17 00:00:00 2001 From: Sriram R Date: Fri, 10 Nov 2023 16:13:53 +0530 Subject: [PATCH] hostapd: add emlsr support Use the Parsed eml and mld capability sub field present in common info field of Multi-Link element from association request sent by non-AP MLD. These eml capabilities are sent to the target driver. Also, introduce 'disable_eml_cap' conf to disable advertisement of eml caps Signed-off-by: Ramasamy Kaliappan Signed-off-by: Sriram R --- hostapd/config_file.c | 2 ++ hostapd/hostapd.conf | 4 ++++ src/ap/ap_config.h | 1 + src/ap/ap_drv_ops.c | 5 ++++- src/ap/ap_drv_ops.h | 3 ++- src/ap/ieee802_11.c | 8 +++++++- src/ap/ieee802_11_eht.c | 12 ++++++++---- src/ap/sta_info.c | 7 ++++++- src/drivers/driver.h | 2 ++ src/drivers/driver_nl80211.c | 14 ++++++++++++++ 10 files changed, 50 insertions(+), 8 deletions(-) --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4802,6 +4802,8 @@ static int hostapd_config_fill(struct ho conf->punct_acs_threshold = val; } else if (os_strcmp(buf, "mld_ap") == 0) { bss->mld_ap = !!atoi(pos); + } else if (os_strcmp(buf, "disable_eml_cap") == 0) { + bss->disable_eml_cap = atoi(pos); } else if (os_strcmp(buf, "ru_punct_acs_threshold") == 0) { conf->ru_punct_acs_threshold = atoi(pos); if (conf->ru_punct_acs_threshold > 100) { --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1097,6 +1097,10 @@ wmm_ac_vo_acm=0 # Default is 0, indicates that ACS algorithm should not puncture any channel. #ru_punct_acs_threshold=75 +#disable_eml_cap: Boolean(0/1) to disable eml capabilities +# advertising in management frame. +#disable_eml_cap=1 + ##### IEEE 802.1X-2004 related configuration ################################## # Require IEEE 802.1X authorization --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -954,6 +954,7 @@ struct hostapd_bss_config { /* The MLD ID to which the AP MLD is affiliated with */ u8 mld_id; bool is_bonded_iface_enabled; + u8 disable_eml_cap; #endif /* CONFIG_IEEE80211BE */ enum { FILS_UBPR_USER_DISABLED, --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -430,7 +430,7 @@ int hostapd_sta_add(struct hostapd_data u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, int set, const u8 *link_addr, bool mld_link_sta, const struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab, - size_t eht_240mhz_len) + size_t eht_240mhz_len, u16 eml_cap, u16 mld_cap) { struct hostapd_sta_add_params params; @@ -472,6 +472,8 @@ int hostapd_sta_add(struct hostapd_data params.mld_link_id = hapd->mld_link_id; params.mld_link_addr = link_addr; params.mld_link_sta = mld_link_sta; + params.eml_cap = eml_cap; + params.mld_cap = mld_cap; } #endif /* CONFIG_IEEE80211BE */ --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -49,7 +49,7 @@ int hostapd_sta_add(struct hostapd_data u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, int set, const u8 *link_addr, bool mld_link_sta, const struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab, - size_t eht_240mhz_len); + size_t eht_240mhz_len, u16 eml_cap, u16 mld_cap); int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, size_t elem_len); --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -4631,6 +4631,8 @@ static int add_associated_sta(struct hos int set = 1; const u8 *mld_link_addr = NULL; bool mld_link_sta = false; + u16 eml_cap = 0; + u16 mld_cap = 0; #ifdef CONFIG_IEEE80211BE if (hapd->conf->mld_ap && sta->mld_info.mld_sta) { @@ -4641,6 +4643,9 @@ static int add_associated_sta(struct hos if (hapd->mld_link_id != sta->mld_assoc_link_id) set = 0; + + eml_cap = sta->mld_info.common_info.eml_capa; + mld_cap = sta->mld_info.common_info.mld_capa; } #endif /* CONFIG_IEEE80211BE */ @@ -4735,7 +4740,8 @@ static int add_associated_sta(struct hos sta->vht_opmode, sta->p2p_ie ? 1 : 0, set, mld_link_addr, mld_link_sta, sta->flags & WLAN_STA_EHT? sta->eht_240mhz_capab : NULL, - sta->flags & WLAN_STA_EHT? sta->eht_240mhz_len : 0)) { + sta->flags & WLAN_STA_EHT? sta->eht_240mhz_len : 0, + eml_cap, mld_cap)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, "Could not %s STA to kernel driver", --- a/src/ap/ieee802_11_eht.c +++ b/src/ap/ieee802_11_eht.c @@ -574,11 +574,16 @@ u8 * hostapd_eid_eht_basic_ml(struct hos control = MULTI_LINK_CONTROL_TYPE_BASIC | BASIC_MULTI_LINK_CTRL_PRES_LINK_ID | BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT | - BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA | BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA; + if (!hapd->conf->disable_eml_cap) + control |= BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA; + common_info_len = MLE_COMMON_INFO_LEN; + if (hapd->conf->disable_eml_cap) + common_info_len -= 2; + if (include_mld_id) { /* AP MLD ID */ control |= BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID; @@ -598,9 +603,11 @@ u8 * hostapd_eid_eht_basic_ml(struct hos /* Currently hard code the BSS Parameters Change Count to 0x1 */ wpabuf_put_u8(buf, 0x1); - wpa_printf(MSG_DEBUG, "MLD: EML Capabilities=0x%x", - hapd->iface->mld_eml_capa); - wpabuf_put_le16(buf, hapd->iface->mld_eml_capa); + if (!hapd->conf->disable_eml_cap) { + wpa_printf(MSG_DEBUG, "MLD: EML Capabilities=0x%x", + hapd->iface->mld_eml_capa); + wpabuf_put_le16(buf, hapd->iface->mld_eml_capa); + } wpa_printf(MSG_DEBUG, "MLD: MLD Capabilities and Operations=0x%x", hapd->iface->mld_mld_capa); @@ -768,6 +775,10 @@ size_t hostapd_eid_eht_basic_ml_len(stru len += 2; /* Common info len for Basic MLE */ len += MLE_COMMON_INFO_LEN; + + if (hapd->conf->disable_eml_cap) + len -= 2; + if (include_mld_id) len++; --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -1657,6 +1657,8 @@ int ap_sta_re_add(struct hostapd_data *h { const u8 *mld_link_addr = NULL; bool mld_link_sta = false; + u16 eml_cap = 0; + u16 mld_cap = 0; /* * If a station that is already associated to the AP, is trying to @@ -1672,6 +1674,8 @@ int ap_sta_re_add(struct hostapd_data *h mld_link_sta = sta->mld_assoc_link_id != mld_link_id; mld_link_addr = sta->mld_info.links[mld_link_id].peer_addr; + eml_cap = sta->mld_info.common_info.eml_capa; + mld_cap = sta->mld_info.common_info.mld_capa; } #endif /* CONFIG_IEEE80211BE */ @@ -1684,7 +1688,8 @@ int ap_sta_re_add(struct hostapd_data *h sta->supported_rates_len, 0, NULL, NULL, NULL, 0, NULL, 0, NULL, sta->flags, 0, 0, 0, 0, - mld_link_addr, mld_link_sta, NULL, 0)) { + mld_link_addr, mld_link_sta, NULL, 0, + eml_cap, mld_cap)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -2611,6 +2611,8 @@ struct hostapd_sta_add_params { const u8 *mld_link_addr; const struct ieee80211_240mhz_vendor_oper *eht_240mhz_capab; size_t eht_240mhz_len; + u16 eml_cap; + u16 mld_cap; }; struct mac_address { --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5860,6 +5860,20 @@ static int wpa_driver_nl80211_sta_add(vo goto fail; } + if (params->eml_cap) { + wpa_printf(MSG_DEBUG, " * eml_cap =%u", params->eml_cap); + if (nla_put_u16(msg, NL80211_ATTR_EML_CAPABILITY, + params->eml_cap)) + goto fail; + } + + if (params->mld_cap) { + wpa_printf(MSG_DEBUG, " * mld_cap=%u", params->mld_cap); + if (nla_put_u16(msg, NL80211_ATTR_MLD_CAPA_AND_OPS, + params->mld_cap)) + goto fail; + } + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret)