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:
Sreeramya Soratkal 2021-07-22 18:11:00 +05:30 committed by Jouni Malinen
parent f725254cc1
commit e5173e8b12
7 changed files with 156 additions and 39 deletions

View file

@ -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);

View file

@ -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 },

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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);