P2P: Enable multiple channel widths for P2P in 6 GHz band
Enable support for P2P connection in 6 GHz with the channel width of 40 MHz, 80 MHz, and 160 MHz. The flag max_oper_chwidth is used to configure the maximum channel width for P2P connection in 6 GHz with the commands P2P_CONNECT, P2P_INVITE, and P2P_GROUP_ADD. Signed-off-by: Sreeramya Soratkal <ssramya@codeaurora.org>
This commit is contained in:
parent
f725254cc1
commit
e5173e8b12
7 changed files with 156 additions and 39 deletions
|
@ -417,7 +417,16 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
||||||
data->sec_channel_offset = sec_channel_offset;
|
data->sec_channel_offset = sec_channel_offset;
|
||||||
data->center_freq1 = freq + sec_channel_offset * 10;
|
data->center_freq1 = freq + sec_channel_offset * 10;
|
||||||
data->center_freq2 = 0;
|
data->center_freq2 = 0;
|
||||||
data->bandwidth = sec_channel_offset ? 40 : 20;
|
if (oper_chwidth == CHANWIDTH_80MHZ)
|
||||||
|
data->bandwidth = 80;
|
||||||
|
else if (oper_chwidth == CHANWIDTH_160MHZ ||
|
||||||
|
oper_chwidth == CHANWIDTH_80P80MHZ)
|
||||||
|
data->bandwidth = 160;
|
||||||
|
else if (sec_channel_offset)
|
||||||
|
data->bandwidth = 40;
|
||||||
|
else
|
||||||
|
data->bandwidth = 20;
|
||||||
|
|
||||||
|
|
||||||
hostapd_encode_edmg_chan(enable_edmg, edmg_channel, channel,
|
hostapd_encode_edmg_chan(enable_edmg, edmg_channel, channel,
|
||||||
&data->edmg);
|
&data->edmg);
|
||||||
|
@ -441,9 +450,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
||||||
"Segment 0 center frequency isn't set");
|
"Segment 0 center frequency isn't set");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (!sec_channel_offset)
|
||||||
data->center_freq1 = data->freq;
|
data->center_freq1 = data->freq;
|
||||||
data->bandwidth = 20;
|
|
||||||
} else {
|
} else {
|
||||||
int freq1, freq2 = 0;
|
int freq1, freq2 = 0;
|
||||||
int bw = center_idx_to_bw_6ghz(center_segment0);
|
int bw = center_idx_to_bw_6ghz(center_segment0);
|
||||||
|
|
|
@ -1895,9 +1895,9 @@ const struct oper_class_map global_op_class[] = {
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 128, 36, 177, 4, BW80, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 129, 36, 177, 4, BW160, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP },
|
||||||
{ HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
|
{ HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP },
|
||||||
|
|
||||||
|
|
|
@ -1337,6 +1337,7 @@ struct ieee80211_ampe_ie {
|
||||||
#define CHANWIDTH_4320MHZ 5
|
#define CHANWIDTH_4320MHZ 5
|
||||||
#define CHANWIDTH_6480MHZ 6
|
#define CHANWIDTH_6480MHZ 6
|
||||||
#define CHANWIDTH_8640MHZ 7
|
#define CHANWIDTH_8640MHZ 7
|
||||||
|
#define CHANWIDTH_40MHZ_6GHZ 8
|
||||||
|
|
||||||
#define HE_NSS_MAX_STREAMS 8
|
#define HE_NSS_MAX_STREAMS 8
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,11 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
|
||||||
/* Use the maximum oper channel width if it's given. */
|
/* Use the maximum oper channel width if it's given. */
|
||||||
if (ssid->max_oper_chwidth)
|
if (ssid->max_oper_chwidth)
|
||||||
hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth);
|
hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth);
|
||||||
|
if (hostapd_get_oper_chwidth(conf))
|
||||||
|
ieee80211_freq_to_channel_ext(ssid->frequency, 0,
|
||||||
|
hostapd_get_oper_chwidth(conf),
|
||||||
|
&conf->op_class,
|
||||||
|
&conf->channel);
|
||||||
|
|
||||||
if (hostapd_get_oper_chwidth(conf) == CHANWIDTH_80P80MHZ) {
|
if (hostapd_get_oper_chwidth(conf) == CHANWIDTH_80P80MHZ) {
|
||||||
ieee80211_freq_to_chan(ssid->vht_center_freq2,
|
ieee80211_freq_to_chan(ssid->vht_center_freq2,
|
||||||
|
@ -191,19 +196,75 @@ wpa_supplicant_find_hw_mode(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int get_max_oper_chwidth_6ghz(int chwidth)
|
||||||
|
{
|
||||||
|
switch (chwidth) {
|
||||||
|
case CHANWIDTH_USE_HT:
|
||||||
|
return 20;
|
||||||
|
case CHANWIDTH_40MHZ_6GHZ:
|
||||||
|
return 40;
|
||||||
|
case CHANWIDTH_80MHZ:
|
||||||
|
return 80;
|
||||||
|
case CHANWIDTH_80P80MHZ:
|
||||||
|
case CHANWIDTH_160MHZ:
|
||||||
|
return 160;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_conf_ap_he_6ghz(struct wpa_supplicant *wpa_s,
|
||||||
|
struct hostapd_hw_modes *mode,
|
||||||
|
struct wpa_ssid *ssid,
|
||||||
|
struct hostapd_config *conf)
|
||||||
|
{
|
||||||
|
bool is_chanwidth_40_80, is_chanwidth_160;
|
||||||
|
int he_chanwidth;
|
||||||
|
|
||||||
|
he_chanwidth =
|
||||||
|
mode->he_capab[wpas_mode_to_ieee80211_mode(
|
||||||
|
ssid->mode)].phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
|
||||||
|
is_chanwidth_40_80 = he_chanwidth &
|
||||||
|
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G;
|
||||||
|
is_chanwidth_160 = he_chanwidth &
|
||||||
|
HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Enable HE support (p2p_group=%d he_chwidth_cap=%d)",
|
||||||
|
ssid->p2p_group, he_chanwidth);
|
||||||
|
|
||||||
|
if (mode->he_capab[wpas_mode_to_ieee80211_mode(
|
||||||
|
ssid->mode)].he_supported &&
|
||||||
|
ssid->he)
|
||||||
|
conf->ieee80211ax = 1;
|
||||||
|
|
||||||
|
if (is_chanwidth_40_80 && ssid->p2p_group &&
|
||||||
|
get_max_oper_chwidth_6ghz(ssid->max_oper_chwidth) >= 40) {
|
||||||
|
conf->secondary_channel =
|
||||||
|
wpas_p2p_get_sec_channel_offset_40mhz(
|
||||||
|
wpa_s, mode, conf->channel);
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"Secondary channel offset %d for P2P group",
|
||||||
|
conf->secondary_channel);
|
||||||
|
if (ssid->max_oper_chwidth == CHANWIDTH_40MHZ_6GHZ)
|
||||||
|
ssid->max_oper_chwidth = CHANWIDTH_USE_HT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((is_chanwidth_40_80 || is_chanwidth_160) && ssid->p2p_group &&
|
||||||
|
get_max_oper_chwidth_6ghz(ssid->max_oper_chwidth) >= 80)
|
||||||
|
wpas_conf_ap_vht(wpa_s, ssid, conf, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
|
int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
|
||||||
struct wpa_ssid *ssid,
|
struct wpa_ssid *ssid,
|
||||||
struct hostapd_config *conf)
|
struct hostapd_config *conf)
|
||||||
{
|
{
|
||||||
conf->hw_mode = ieee80211_freq_to_channel_ext(ssid->frequency, 0,
|
conf->hw_mode = ieee80211_freq_to_channel_ext(ssid->frequency, 0,
|
||||||
ssid->max_oper_chwidth,
|
CHANWIDTH_USE_HT,
|
||||||
&conf->op_class,
|
&conf->op_class,
|
||||||
&conf->channel);
|
&conf->channel);
|
||||||
/* ssid->max_oper_chwidth is not valid in all cases, so fall back to the
|
|
||||||
* less specific mechanism, if needed, at least for now */
|
|
||||||
if (conf->hw_mode == NUM_HOSTAPD_MODES)
|
|
||||||
conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
|
|
||||||
&conf->channel);
|
|
||||||
if (conf->hw_mode == NUM_HOSTAPD_MODES) {
|
if (conf->hw_mode == NUM_HOSTAPD_MODES) {
|
||||||
wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
|
wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
|
||||||
ssid->frequency);
|
ssid->frequency);
|
||||||
|
@ -256,7 +317,10 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
|
||||||
no_ht = 1;
|
no_ht = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!no_ht && mode && mode->ht_capab) {
|
if (mode && is_6ghz_freq(ssid->frequency) &&
|
||||||
|
conf->hw_mode == HOSTAPD_MODE_IEEE80211A) {
|
||||||
|
wpas_conf_ap_he_6ghz(wpa_s, mode, ssid, conf);
|
||||||
|
} else if (!no_ht && mode && mode->ht_capab) {
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"Enable HT support (p2p_group=%d 11a=%d ht40_hw_capab=%d ssid->ht40=%d)",
|
"Enable HT support (p2p_group=%d 11a=%d ht40_hw_capab=%d ssid->ht40=%d)",
|
||||||
ssid->p2p_group,
|
ssid->p2p_group,
|
||||||
|
|
|
@ -6126,6 +6126,9 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
|
||||||
if (max_oper_chwidth < 0)
|
if (max_oper_chwidth < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (allow_6ghz && chwidth == 40)
|
||||||
|
max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
|
||||||
|
|
||||||
pos2 = os_strstr(pos, " ssid=");
|
pos2 = os_strstr(pos, " ssid=");
|
||||||
if (pos2) {
|
if (pos2) {
|
||||||
char *end;
|
char *end;
|
||||||
|
@ -6779,6 +6782,9 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
|
|
||||||
allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
|
allow_6ghz = os_strstr(cmd, " allow_6ghz") != NULL;
|
||||||
|
|
||||||
|
if (allow_6ghz && chwidth == 40)
|
||||||
|
max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
|
||||||
|
|
||||||
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
|
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
|
||||||
max_oper_chwidth, pref_freq, he, edmg,
|
max_oper_chwidth, pref_freq, he, edmg,
|
||||||
allow_6ghz);
|
allow_6ghz);
|
||||||
|
@ -6922,6 +6928,9 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
if (max_oper_chwidth < 0)
|
if (max_oper_chwidth < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (allow_6ghz && chwidth == 40)
|
||||||
|
max_oper_chwidth = CHANWIDTH_40MHZ_6GHZ;
|
||||||
|
|
||||||
if (group_id >= 0)
|
if (group_id >= 0)
|
||||||
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
|
return p2p_ctrl_group_add_persistent(wpa_s, group_id,
|
||||||
freq, freq2, ht40, vht,
|
freq, freq2, ht40, vht,
|
||||||
|
|
|
@ -207,11 +207,15 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
|
||||||
if (!(flag & HOSTAPD_CHAN_HT40MINUS))
|
if (!(flag & HOSTAPD_CHAN_HT40MINUS))
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
res2 = allow_channel(mode, op_class, channel - 4, NULL);
|
res2 = allow_channel(mode, op_class, channel - 4, NULL);
|
||||||
} else if (bw == BW40PLUS ||
|
} else if (bw == BW40PLUS) {
|
||||||
(bw == BW40 && !(((channel - 1) / 4) % 2))) {
|
|
||||||
if (!(flag & HOSTAPD_CHAN_HT40PLUS))
|
if (!(flag & HOSTAPD_CHAN_HT40PLUS))
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
res2 = allow_channel(mode, op_class, channel + 4, NULL);
|
res2 = allow_channel(mode, op_class, channel + 4, NULL);
|
||||||
|
} else if (is_6ghz_op_class(op_class) && bw == BW40) {
|
||||||
|
if (get_6ghz_sec_channel(channel) < 0)
|
||||||
|
res2 = allow_channel(mode, op_class, channel - 4, NULL);
|
||||||
|
else
|
||||||
|
res2 = allow_channel(mode, op_class, channel + 4, NULL);
|
||||||
} else if (bw == BW80) {
|
} else if (bw == BW80) {
|
||||||
/*
|
/*
|
||||||
* channel is a center channel and as such, not necessarily a
|
* channel is a center channel and as such, not necessarily a
|
||||||
|
|
|
@ -164,6 +164,17 @@ wpas_p2p_consider_moving_gos(struct wpa_supplicant *wpa_s,
|
||||||
static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx);
|
static void wpas_p2p_reconsider_moving_go(void *eloop_ctx, void *timeout_ctx);
|
||||||
|
|
||||||
|
|
||||||
|
static int wpas_get_6ghz_he_chwidth_capab(struct hostapd_hw_modes *mode)
|
||||||
|
{
|
||||||
|
int he_capab = 0;
|
||||||
|
|
||||||
|
if (mode)
|
||||||
|
he_capab = mode->he_capab[WPAS_MODE_INFRA].phy_cap[
|
||||||
|
HE_PHYCAP_CHANNEL_WIDTH_SET_IDX];
|
||||||
|
return he_capab;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the number of concurrent channels that the HW can operate, but that are
|
* Get the number of concurrent channels that the HW can operate, but that are
|
||||||
* currently not in use by any of the wpa_supplicant interfaces.
|
* currently not in use by any of the wpa_supplicant interfaces.
|
||||||
|
@ -3652,7 +3663,7 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
if (res == NO_IR)
|
if (res == NO_IR)
|
||||||
ret = NO_IR;
|
ret = NO_IR;
|
||||||
|
if (!is_6ghz) {
|
||||||
if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
|
if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_70))
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
|
if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_50))
|
||||||
|
@ -3661,6 +3672,11 @@ static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
|
if (i == 3 && !(flags & HOSTAPD_CHAN_VHT_70_10))
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
|
} else if (is_6ghz &&
|
||||||
|
(!(wpas_get_6ghz_he_chwidth_capab(mode) &
|
||||||
|
HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G))) {
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -3729,6 +3745,7 @@ static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
|
||||||
if (res == NO_IR)
|
if (res == NO_IR)
|
||||||
ret = NO_IR;
|
ret = NO_IR;
|
||||||
|
|
||||||
|
if (!is_6ghz_op_class(op_class)) {
|
||||||
if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
|
if (i == 0 && !(flags & HOSTAPD_CHAN_VHT_10_150))
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
|
if (i == 1 && !(flags & HOSTAPD_CHAN_VHT_30_130))
|
||||||
|
@ -3745,6 +3762,11 @@ static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
|
if (i == 7 && !(flags & HOSTAPD_CHAN_VHT_150_10))
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
|
} else if (is_6ghz_op_class(op_class) &&
|
||||||
|
(!(wpas_get_6ghz_he_chwidth_capab(mode) &
|
||||||
|
HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G))) {
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -3783,6 +3805,15 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
|
||||||
return NOT_ALLOWED;
|
return NOT_ALLOWED;
|
||||||
res2 = has_channel(wpa_s->global, mode, op_class, channel + 4,
|
res2 = has_channel(wpa_s->global, mode, op_class, channel + 4,
|
||||||
NULL);
|
NULL);
|
||||||
|
} else if (is_6ghz_op_class(op_class) && bw == BW40) {
|
||||||
|
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
|
||||||
|
return NOT_ALLOWED;
|
||||||
|
if (get_6ghz_sec_channel(channel) < 0)
|
||||||
|
res2 = has_channel(wpa_s->global, mode, op_class,
|
||||||
|
channel - 4, NULL);
|
||||||
|
else
|
||||||
|
res2 = has_channel(wpa_s->global, mode, op_class,
|
||||||
|
channel + 4, NULL);
|
||||||
} else if (bw == BW80) {
|
} else if (bw == BW80) {
|
||||||
res2 = wpas_p2p_verify_80mhz(wpa_s, mode, op_class, channel,
|
res2 = wpas_p2p_verify_80mhz(wpa_s, mode, op_class, channel,
|
||||||
bw);
|
bw);
|
||||||
|
|
Loading…
Reference in a new issue