From 3459c54ac78b54aa4cb3fda1ceb8dfaa01ea9400 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Fri, 14 Jun 2019 16:49:21 +0200 Subject: [PATCH] mesh: Add support for HE mode Mesh points can partially support HE features (when requiring no controlling STA/AP) as long as hardware supports it. The kernel just requires support for HE mesh and wpa_supplicant can forward the peer capabilities to the kernel for further processing. Signed-off-by: Sven Eckelmann --- src/drivers/driver.h | 3 ++- wpa_supplicant/ap.c | 5 +++++ wpa_supplicant/mesh.c | 3 +++ wpa_supplicant/mesh_mpm.c | 32 +++++++++++++++++++++++++++++++ wpa_supplicant/wpa_supplicant.c | 9 +++++++-- wpa_supplicant/wpa_supplicant_i.h | 20 +++++++++++++++++++ 6 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index ee11387e9..8a5cdb8e9 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -185,6 +185,7 @@ struct hostapd_channel_data { #define HE_MAX_MAC_CAPAB_SIZE 6 #define HE_MAX_PHY_CAPAB_SIZE 11 #define HE_MAX_MCS_CAPAB_SIZE 12 +#define HE_MAX_PPET_CAPAB_SIZE 25 /** * struct he_capabilities - IEEE 802.11ax HE capabilities @@ -194,7 +195,7 @@ struct he_capabilities { u8 phy_cap[HE_MAX_PHY_CAPAB_SIZE]; u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE]; u8 mcs[HE_MAX_MCS_CAPAB_SIZE]; - u8 ppet[25]; + u8 ppet[HE_MAX_PPET_CAPAB_SIZE]; }; #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index eea5b4e59..4e3c2814d 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -239,6 +239,11 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, conf->vht_capab |= mode->vht_capab; wpas_conf_ap_vht(wpa_s, ssid, conf, mode); } + + if (mode->he_capab[wpas_mode_to_ieee80211_mode( + ssid->mode)].he_supported && + ssid->he) + conf->ieee80211ax = 1; } } diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index 1068a5598..7354c1b79 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -456,6 +456,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, ibss_mesh_setup_freq(wpa_s, ssid, ¶ms->freq); wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled; wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled; + wpa_s->mesh_he_enabled = !!params->freq.he_enabled; if (params->freq.ht_enabled && params->freq.sec_channel_offset) ssid->ht40 = params->freq.sec_channel_offset; @@ -480,6 +481,8 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, break; } } + if (wpa_s->mesh_he_enabled) + ssid->he = 1; if (ssid->beacon_int > 0) params->beacon_int = ssid->beacon_int; else if (wpa_s->conf->beacon_int > 0) diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 9d6ab8da1..4a163b6eb 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -245,6 +245,16 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, 2 + 5; /* VHT Operation */ } #endif /* CONFIG_IEEE80211AC */ +#ifdef CONFIG_IEEE80211AX + if (type != PLINK_CLOSE && wpa_s->mesh_he_enabled) { + buf_len += 3 + + HE_MAX_MAC_CAPAB_SIZE + + HE_MAX_PHY_CAPAB_SIZE + + HE_MAX_MCS_CAPAB_SIZE + + HE_MAX_PPET_CAPAB_SIZE; + buf_len += 3 + sizeof(struct ieee80211_he_operation); + } +#endif /* CONFIG_IEEE80211AX */ if (type != PLINK_CLOSE) buf_len += conf->rsn_ie_len; /* RSN IE */ #ifdef CONFIG_OCV @@ -362,6 +372,21 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, wpabuf_put_data(buf, vht_capa_oper, pos - vht_capa_oper); } #endif /* CONFIG_IEEE80211AC */ +#ifdef CONFIG_IEEE80211AX + if (type != PLINK_CLOSE && wpa_s->mesh_he_enabled) { + u8 he_capa_oper[3 + + HE_MAX_MAC_CAPAB_SIZE + + HE_MAX_PHY_CAPAB_SIZE + + HE_MAX_MCS_CAPAB_SIZE + + HE_MAX_PPET_CAPAB_SIZE + + 3 + sizeof(struct ieee80211_he_operation)]; + + pos = hostapd_eid_he_capab(bss, he_capa_oper, + IEEE80211_MODE_MESH); + pos = hostapd_eid_he_operation(bss, pos); + wpabuf_put_data(buf, he_capa_oper, pos - he_capa_oper); + } +#endif /* CONFIG_IEEE80211AX */ #ifdef CONFIG_OCV if (type != PLINK_CLOSE && conf->ocv) { @@ -725,6 +750,11 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, set_sta_vht_opmode(data, sta, elems->vht_opmode_notif); #endif /* CONFIG_IEEE80211AC */ +#ifdef CONFIG_IEEE80211AX + copy_sta_he_capab(data, sta, IEEE80211_MODE_MESH, + elems->he_capabilities, elems->he_capabilities_len); +#endif /* CONFIG_IEEE80211AX */ + if (hostapd_get_aid(data, sta) < 0) { wpa_msg(wpa_s, MSG_ERROR, "No AIDs available"); ap_free_sta(data, sta); @@ -742,6 +772,8 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, params.listen_interval = 100; params.ht_capabilities = sta->ht_capabilities; params.vht_capabilities = sta->vht_capabilities; + params.he_capab = sta->he_capab; + params.he_capab_len = sta->he_capab_len; params.flags |= WPA_STA_WMM; params.flags_mask |= WPA_STA_AUTHENTICATED; if (conf->security == MESH_CONF_SEC_NONE) { diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 1e1123474..be45f2e38 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2140,6 +2140,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, const struct wpa_ssid *ssid, struct hostapd_freq_params *freq) { + int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode); enum hostapd_hw_mode hw_mode; struct hostapd_hw_modes *mode = NULL; int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, @@ -2203,6 +2204,9 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, if (!mode) return; + /* HE can work without HT + VHT */ + freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; + #ifdef CONFIG_HT_OVERRIDES if (ssid->disable_ht) { freq->ht_enabled = 0; @@ -2409,9 +2413,10 @@ skip_ht40: if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, freq->channel, freq->ht_enabled, - vht_freq.vht_enabled, 0, + vht_freq.vht_enabled, freq->he_enabled, freq->sec_channel_offset, - chwidth, seg0, seg1, vht_caps, NULL) != 0) + chwidth, seg0, seg1, vht_caps, + &mode->he_capab[ieee80211_mode]) != 0) return; *freq = vht_freq; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index b51390ba3..204cf60f3 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -823,6 +823,7 @@ struct wpa_supplicant { unsigned int mesh_if_created:1; unsigned int mesh_ht_enabled:1; unsigned int mesh_vht_enabled:1; + unsigned int mesh_he_enabled:1; struct wpa_driver_mesh_join_params *mesh_params; #ifdef CONFIG_PMKSA_CACHE_EXTERNAL /* struct external_pmksa_cache::list */ @@ -1464,6 +1465,25 @@ static inline int network_is_persistent_group(struct wpa_ssid *ssid) return ssid->disabled == 2 && ssid->p2p_persistent_group; } + +static inline int wpas_mode_to_ieee80211_mode(enum wpas_mode mode) +{ + switch (mode) { + default: + case WPAS_MODE_INFRA: + return IEEE80211_MODE_INFRA; + case WPAS_MODE_IBSS: + return IEEE80211_MODE_IBSS; + case WPAS_MODE_AP: + case WPAS_MODE_P2P_GO: + case WPAS_MODE_P2P_GROUP_FORMATION: + return IEEE80211_MODE_AP; + case WPAS_MODE_MESH: + return IEEE80211_MODE_MESH; + } +} + + int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);