Add VHT support for Mesh

Mesh Points themselves have capability to support VHT as long as
hardware supports it. However, supporting VHT in mesh mode was disabled
because no one had clearly tested and confirmed its functionality. Since
VHT80 has now been verified to work with ath10k QCA988X driver and
mac80211_hwsim, enable VHT support in mesh mode.

Signed-off-by: Peter Oh <poh@qca.qualcomm.com>
This commit is contained in:
Peter Oh 2015-11-10 11:01:20 -08:00 committed by Jouni Malinen
parent a73c984261
commit a65efbfb24
4 changed files with 58 additions and 6 deletions

View file

@ -323,6 +323,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
params.meshid_len = ssid->ssid_len;
ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled;
wpa_s->mesh_vht_enabled = !!params.freq.vht_enabled;
if (ssid->beacon_int > 0)
params.beacon_int = ssid->beacon_int;
else if (wpa_s->conf->beacon_int > 0)

View file

@ -212,9 +212,6 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
struct hostapd_data *bss = ifmsh->bss[0];
struct mesh_conf *conf = ifmsh->mconf;
u8 supp_rates[2 + 2 + 32];
#ifdef CONFIG_IEEE80211N
u8 ht_capa_oper[2 + 26 + 2 + 22];
#endif /* CONFIG_IEEE80211N */
u8 *pos, *cat;
u8 ie_len, add_plid = 0;
int ret;
@ -239,6 +236,12 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
2 + 22; /* HT operation */
}
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) {
buf_len += 2 + 12 + /* VHT Capabilities */
2 + 5; /* VHT Operation */
}
#endif /* CONFIG_IEEE80211AC */
if (type != PLINK_CLOSE)
buf_len += conf->rsn_ie_len; /* RSN IE */
@ -334,11 +337,22 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_IEEE80211N
if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) {
u8 ht_capa_oper[2 + 26 + 2 + 22];
pos = hostapd_eid_ht_capabilities(bss, ht_capa_oper);
pos = hostapd_eid_ht_operation(bss, pos);
wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper);
}
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) {
u8 vht_capa_oper[2 + 12 + 2 + 5];
pos = hostapd_eid_vht_capabilities(bss, vht_capa_oper);
pos = hostapd_eid_vht_operation(bss, pos);
wpabuf_put_data(buf, vht_capa_oper, pos - vht_capa_oper);
}
#endif /* CONFIG_IEEE80211AC */
if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
wpa_msg(wpa_s, MSG_INFO,
@ -564,6 +578,11 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
update_ht_state(data, sta);
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
copy_sta_vht_capab(data, sta, elems->vht_capabilities);
set_sta_vht_opmode(data, sta, elems->vht_opmode_notif);
#endif /* CONFIG_IEEE80211AC */
if (hostapd_get_aid(data, sta) < 0) {
wpa_msg(wpa_s, MSG_ERROR, "No AIDs available");
ap_free_sta(data, sta);
@ -579,6 +598,7 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s,
params.aid = sta->aid;
params.listen_interval = 100;
params.ht_capabilities = sta->ht_capabilities;
params.vht_capabilities = sta->vht_capabilities;
params.flags |= WPA_STA_WMM;
params.flags_mask |= WPA_STA_AUTHENTICATED;
if (conf->security == MESH_CONF_SEC_NONE) {

View file

@ -1722,6 +1722,36 @@ static int bss_is_ibss(struct wpa_bss *bss)
}
static int drv_supports_vht(struct wpa_supplicant *wpa_s,
const struct wpa_ssid *ssid)
{
enum hostapd_hw_mode hw_mode;
struct hostapd_hw_modes *mode = NULL;
u8 channel;
int i;
#ifdef CONFIG_HT_OVERRIDES
if (ssid->disable_ht)
return 0;
#endif /* CONFIG_HT_OVERRIDES */
hw_mode = ieee80211_freq_to_chan(ssid->frequency, &channel);
if (hw_mode == NUM_HOSTAPD_MODES)
return 0;
for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) {
if (wpa_s->hw.modes[i].mode == hw_mode) {
mode = &wpa_s->hw.modes[i];
break;
}
}
if (!mode)
return 0;
return mode->vht_capab != 0;
}
void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
const struct wpa_ssid *ssid,
struct hostapd_freq_params *freq)
@ -1885,12 +1915,12 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
"IBSS/mesh: setup freq channel %d, sec_channel_offset %d",
freq->channel, freq->sec_channel_offset);
/* Not sure if mesh is ready for VHT */
if (ssid->mode != WPAS_MODE_IBSS)
if (!drv_supports_vht(wpa_s, ssid))
return;
/* For IBSS check VHT_IBSS flag */
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
if (ssid->mode == WPAS_MODE_IBSS &&
!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS))
return;
vht_freq = *freq;

View file

@ -734,6 +734,7 @@ struct wpa_supplicant {
int mesh_if_idx;
unsigned int mesh_if_created:1;
unsigned int mesh_ht_enabled:1;
unsigned int mesh_vht_enabled:1;
int mesh_auth_block_duration; /* sec */
#endif /* CONFIG_MESH */