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 <seckelmann@datto.com>
This commit is contained in:
parent
29d8bd1dec
commit
3459c54ac7
6 changed files with 69 additions and 3 deletions
|
@ -185,6 +185,7 @@ struct hostapd_channel_data {
|
||||||
#define HE_MAX_MAC_CAPAB_SIZE 6
|
#define HE_MAX_MAC_CAPAB_SIZE 6
|
||||||
#define HE_MAX_PHY_CAPAB_SIZE 11
|
#define HE_MAX_PHY_CAPAB_SIZE 11
|
||||||
#define HE_MAX_MCS_CAPAB_SIZE 12
|
#define HE_MAX_MCS_CAPAB_SIZE 12
|
||||||
|
#define HE_MAX_PPET_CAPAB_SIZE 25
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct he_capabilities - IEEE 802.11ax HE capabilities
|
* struct he_capabilities - IEEE 802.11ax HE capabilities
|
||||||
|
@ -194,7 +195,7 @@ struct he_capabilities {
|
||||||
u8 phy_cap[HE_MAX_PHY_CAPAB_SIZE];
|
u8 phy_cap[HE_MAX_PHY_CAPAB_SIZE];
|
||||||
u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE];
|
u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE];
|
||||||
u8 mcs[HE_MAX_MCS_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)
|
#define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0)
|
||||||
|
|
|
@ -239,6 +239,11 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
|
||||||
conf->vht_capab |= mode->vht_capab;
|
conf->vht_capab |= mode->vht_capab;
|
||||||
wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -456,6 +456,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
|
||||||
ibss_mesh_setup_freq(wpa_s, ssid, ¶ms->freq);
|
ibss_mesh_setup_freq(wpa_s, ssid, ¶ms->freq);
|
||||||
wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
|
wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
|
||||||
wpa_s->mesh_vht_enabled = !!params->freq.vht_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)
|
if (params->freq.ht_enabled && params->freq.sec_channel_offset)
|
||||||
ssid->ht40 = 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (wpa_s->mesh_he_enabled)
|
||||||
|
ssid->he = 1;
|
||||||
if (ssid->beacon_int > 0)
|
if (ssid->beacon_int > 0)
|
||||||
params->beacon_int = ssid->beacon_int;
|
params->beacon_int = ssid->beacon_int;
|
||||||
else if (wpa_s->conf->beacon_int > 0)
|
else if (wpa_s->conf->beacon_int > 0)
|
||||||
|
|
|
@ -245,6 +245,16 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
|
||||||
2 + 5; /* VHT Operation */
|
2 + 5; /* VHT Operation */
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#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)
|
if (type != PLINK_CLOSE)
|
||||||
buf_len += conf->rsn_ie_len; /* RSN IE */
|
buf_len += conf->rsn_ie_len; /* RSN IE */
|
||||||
#ifdef CONFIG_OCV
|
#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);
|
wpabuf_put_data(buf, vht_capa_oper, pos - vht_capa_oper);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#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
|
#ifdef CONFIG_OCV
|
||||||
if (type != PLINK_CLOSE && conf->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);
|
set_sta_vht_opmode(data, sta, elems->vht_opmode_notif);
|
||||||
#endif /* CONFIG_IEEE80211AC */
|
#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) {
|
if (hostapd_get_aid(data, sta) < 0) {
|
||||||
wpa_msg(wpa_s, MSG_ERROR, "No AIDs available");
|
wpa_msg(wpa_s, MSG_ERROR, "No AIDs available");
|
||||||
ap_free_sta(data, sta);
|
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.listen_interval = 100;
|
||||||
params.ht_capabilities = sta->ht_capabilities;
|
params.ht_capabilities = sta->ht_capabilities;
|
||||||
params.vht_capabilities = sta->vht_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 |= WPA_STA_WMM;
|
||||||
params.flags_mask |= WPA_STA_AUTHENTICATED;
|
params.flags_mask |= WPA_STA_AUTHENTICATED;
|
||||||
if (conf->security == MESH_CONF_SEC_NONE) {
|
if (conf->security == MESH_CONF_SEC_NONE) {
|
||||||
|
|
|
@ -2140,6 +2140,7 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
|
||||||
const struct wpa_ssid *ssid,
|
const struct wpa_ssid *ssid,
|
||||||
struct hostapd_freq_params *freq)
|
struct hostapd_freq_params *freq)
|
||||||
{
|
{
|
||||||
|
int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
|
||||||
enum hostapd_hw_mode hw_mode;
|
enum hostapd_hw_mode hw_mode;
|
||||||
struct hostapd_hw_modes *mode = NULL;
|
struct hostapd_hw_modes *mode = NULL;
|
||||||
int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
|
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)
|
if (!mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* HE can work without HT + VHT */
|
||||||
|
freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported;
|
||||||
|
|
||||||
#ifdef CONFIG_HT_OVERRIDES
|
#ifdef CONFIG_HT_OVERRIDES
|
||||||
if (ssid->disable_ht) {
|
if (ssid->disable_ht) {
|
||||||
freq->ht_enabled = 0;
|
freq->ht_enabled = 0;
|
||||||
|
@ -2409,9 +2413,10 @@ skip_ht40:
|
||||||
|
|
||||||
if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
|
if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq,
|
||||||
freq->channel, freq->ht_enabled,
|
freq->channel, freq->ht_enabled,
|
||||||
vht_freq.vht_enabled, 0,
|
vht_freq.vht_enabled, freq->he_enabled,
|
||||||
freq->sec_channel_offset,
|
freq->sec_channel_offset,
|
||||||
chwidth, seg0, seg1, vht_caps, NULL) != 0)
|
chwidth, seg0, seg1, vht_caps,
|
||||||
|
&mode->he_capab[ieee80211_mode]) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
*freq = vht_freq;
|
*freq = vht_freq;
|
||||||
|
|
|
@ -823,6 +823,7 @@ struct wpa_supplicant {
|
||||||
unsigned int mesh_if_created:1;
|
unsigned int mesh_if_created:1;
|
||||||
unsigned int mesh_ht_enabled:1;
|
unsigned int mesh_ht_enabled:1;
|
||||||
unsigned int mesh_vht_enabled:1;
|
unsigned int mesh_vht_enabled:1;
|
||||||
|
unsigned int mesh_he_enabled:1;
|
||||||
struct wpa_driver_mesh_join_params *mesh_params;
|
struct wpa_driver_mesh_join_params *mesh_params;
|
||||||
#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
|
#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
|
||||||
/* struct external_pmksa_cache::list */
|
/* 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;
|
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_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);
|
int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue