P2P: Add VHT support
Start GO with VHT support if VHT option was requested and the appropriate channels are available. Signed-hostap: Eliad Peller <eliadx.peller@intel.com>
This commit is contained in:
parent
20ea1ca406
commit
ca9bc5b566
5 changed files with 132 additions and 1 deletions
|
@ -412,6 +412,18 @@ void p2p_reselect_channel(struct p2p_data *p2p,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try a channel where we might be able to use VHT */
|
||||||
|
for (i = 0; i < intersection->reg_classes; i++) {
|
||||||
|
struct p2p_reg_class *c = &intersection->reg_class[i];
|
||||||
|
if (c->reg_class == 128) {
|
||||||
|
p2p_dbg(p2p, "Pick possible VHT channel (reg_class %u channel %u) from intersection",
|
||||||
|
c->reg_class, c->channel[0]);
|
||||||
|
p2p->op_reg_class = c->reg_class;
|
||||||
|
p2p->op_channel = c->channel[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Try a channel where we might be able to use HT40 */
|
/* Try a channel where we might be able to use HT40 */
|
||||||
for (i = 0; i < intersection->reg_classes; i++) {
|
for (i = 0; i < intersection->reg_classes; i++) {
|
||||||
struct p2p_reg_class *c = &intersection->reg_class[i];
|
struct p2p_reg_class *c = &intersection->reg_class[i];
|
||||||
|
|
|
@ -94,6 +94,10 @@ int p2p_channel_to_freq(int op_class, int channel)
|
||||||
if (channel < 149 || channel > 161)
|
if (channel < 149 || channel > 161)
|
||||||
return -1;
|
return -1;
|
||||||
return 5000 + 5 * channel;
|
return 5000 + 5 * channel;
|
||||||
|
case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
|
||||||
|
if (channel < 36 || channel > 161)
|
||||||
|
return -1;
|
||||||
|
return 5000 + 5 * channel;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,31 @@ static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
|
||||||
#endif /* CONFIG_WPS */
|
#endif /* CONFIG_WPS */
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
|
||||||
|
struct hostapd_config *conf,
|
||||||
|
struct hostapd_hw_modes *mode)
|
||||||
|
{
|
||||||
|
u8 center_chan = 0;
|
||||||
|
u8 channel = conf->channel;
|
||||||
|
|
||||||
|
if (!conf->secondary_channel)
|
||||||
|
goto no_vht;
|
||||||
|
|
||||||
|
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
|
||||||
|
if (!center_chan)
|
||||||
|
goto no_vht;
|
||||||
|
|
||||||
|
/* Use 80 MHz channel */
|
||||||
|
conf->vht_oper_chwidth = 1;
|
||||||
|
conf->vht_oper_centr_freq_seg0_idx = center_chan;
|
||||||
|
return;
|
||||||
|
|
||||||
|
no_vht:
|
||||||
|
conf->vht_oper_centr_freq_seg0_idx =
|
||||||
|
channel + conf->secondary_channel * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
|
static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_ssid *ssid,
|
struct wpa_ssid *ssid,
|
||||||
struct hostapd_config *conf)
|
struct hostapd_config *conf)
|
||||||
|
@ -114,6 +139,11 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
|
||||||
HT_CAP_INFO_SHORT_GI40MHZ |
|
HT_CAP_INFO_SHORT_GI40MHZ |
|
||||||
HT_CAP_INFO_RX_STBC_MASK |
|
HT_CAP_INFO_RX_STBC_MASK |
|
||||||
HT_CAP_INFO_MAX_AMSDU_SIZE);
|
HT_CAP_INFO_MAX_AMSDU_SIZE);
|
||||||
|
|
||||||
|
if (mode->vht_capab && ssid->vht) {
|
||||||
|
conf->ieee80211ac = 1;
|
||||||
|
wpas_conf_ap_vht(wpa_s, conf, mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211N */
|
#endif /* CONFIG_IEEE80211N */
|
||||||
|
|
|
@ -3038,7 +3038,7 @@ struct p2p_oper_class_map {
|
||||||
u8 min_chan;
|
u8 min_chan;
|
||||||
u8 max_chan;
|
u8 max_chan;
|
||||||
u8 inc;
|
u8 inc;
|
||||||
enum { BW20, BW40PLUS, BW40MINUS } bw;
|
enum { BW20, BW40PLUS, BW40MINUS, BW80 } bw;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct p2p_oper_class_map op_class[] = {
|
static struct p2p_oper_class_map op_class[] = {
|
||||||
|
@ -3053,10 +3053,81 @@ static struct p2p_oper_class_map op_class[] = {
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS },
|
{ HOSTAPD_MODE_IEEE80211A, 117, 40, 48, 8, BW40MINUS },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS },
|
{ HOSTAPD_MODE_IEEE80211A, 126, 149, 157, 8, BW40PLUS },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS },
|
{ HOSTAPD_MODE_IEEE80211A, 127, 153, 161, 8, BW40MINUS },
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IEEE P802.11ac/D7.0 Table E-4 actually talks about channel center
|
||||||
|
* frequency index 42, 58, 106, 122, 138, 155 with channel spacing of
|
||||||
|
* 80 MHz, but currently use the following definition for simplicity
|
||||||
|
* (these center frequencies are not actual channels, which makes
|
||||||
|
* has_channel() fail). wpas_p2p_verify_80mhz() should take care of
|
||||||
|
* removing invalid channels.
|
||||||
|
*/
|
||||||
|
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80 },
|
||||||
{ -1, 0, 0, 0, 0, BW20 }
|
{ -1, 0, 0, 0, 0, BW20 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
|
||||||
|
struct hostapd_hw_modes *mode,
|
||||||
|
u8 channel)
|
||||||
|
{
|
||||||
|
u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(center_channels); i++)
|
||||||
|
/*
|
||||||
|
* In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
|
||||||
|
* so the center channel is 6 channels away from the start/end.
|
||||||
|
*/
|
||||||
|
if (channel >= center_channels[i] - 6 &&
|
||||||
|
channel <= center_channels[i] + 6)
|
||||||
|
return center_channels[i];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
|
||||||
|
struct hostapd_hw_modes *mode,
|
||||||
|
u8 channel, u8 bw)
|
||||||
|
{
|
||||||
|
u8 center_chan;
|
||||||
|
int i, flags;
|
||||||
|
enum chan_allowed res, ret = ALLOWED;
|
||||||
|
|
||||||
|
center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
|
||||||
|
if (!center_chan)
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
if (center_chan >= 58 && center_chan <= 138)
|
||||||
|
return NOT_ALLOWED; /* Do not allow DFS channels for P2P */
|
||||||
|
|
||||||
|
/* check all the channels are available */
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
int adj_chan = center_chan - 6 + i * 4;
|
||||||
|
|
||||||
|
res = has_channel(wpa_s->global, mode, adj_chan, &flags);
|
||||||
|
if (res == NOT_ALLOWED)
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
if (res == PASSIVE_ONLY)
|
||||||
|
ret = PASSIVE_ONLY;
|
||||||
|
|
||||||
|
if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
if (i == 2 && !(flags & HOSTAPD_CHAN_VHT_50_30))
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
|
static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
|
||||||
struct hostapd_hw_modes *mode,
|
struct hostapd_hw_modes *mode,
|
||||||
u8 channel, u8 bw)
|
u8 channel, u8 bw)
|
||||||
|
@ -3073,6 +3144,8 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
|
||||||
if (!(flag & HOSTAPD_CHAN_HT40PLUS))
|
if (!(flag & HOSTAPD_CHAN_HT40PLUS))
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
res2 = has_channel(wpa_s->global, mode, channel + 4, NULL);
|
res2 = has_channel(wpa_s->global, mode, channel + 4, NULL);
|
||||||
|
} else if (bw == BW80) {
|
||||||
|
res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
|
if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
|
||||||
|
@ -3173,6 +3246,16 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
|
||||||
|
struct hostapd_hw_modes *mode, u8 channel)
|
||||||
|
{
|
||||||
|
if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW80))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf,
|
static int wpas_get_noa(void *ctx, const u8 *interface_addr, u8 *buf,
|
||||||
size_t buf_len)
|
size_t buf_len)
|
||||||
{
|
{
|
||||||
|
|
|
@ -152,6 +152,8 @@ void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s,
|
||||||
int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s);
|
int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s);
|
||||||
int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
|
int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
|
||||||
struct hostapd_hw_modes *mode, u8 channel);
|
struct hostapd_hw_modes *mode, u8 channel);
|
||||||
|
int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
|
||||||
|
struct hostapd_hw_modes *mode, u8 channel);
|
||||||
unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s);
|
unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s);
|
||||||
void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
|
void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
|
||||||
const u8 *p2p_dev_addr,
|
const u8 *p2p_dev_addr,
|
||||||
|
|
Loading…
Reference in a new issue