P2P: Add support for VHT 80+80 MHz and 160 MHz

The new max_oper_chwidth and freq2 arguments to P2P_CONNECT, P2P_INVITE,
and P2P_GROUP_ADD control interface commands can be used to request
larger VHT operating channel bandwidth to be used than the previously
used maximum 80 MHz.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Ahmad Kholaif 2015-10-28 14:14:10 -07:00 committed by Jouni Malinen
parent bee5d8e067
commit c27f4c9006
8 changed files with 185 additions and 47 deletions

View file

@ -99,6 +99,10 @@ struct p2p_go_neg_results {
int vht; int vht;
u8 max_oper_chwidth;
unsigned int vht_center_freq2;
/** /**
* ssid - SSID of the group * ssid - SSID of the group
*/ */

View file

@ -56,12 +56,32 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
if (!conf->secondary_channel) if (!conf->secondary_channel)
goto no_vht; goto no_vht;
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel); switch (conf->vht_oper_chwidth) {
case VHT_CHANWIDTH_80MHZ:
case VHT_CHANWIDTH_80P80MHZ:
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel);
break;
case VHT_CHANWIDTH_160MHZ:
center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
break;
default:
/*
* conf->vht_oper_chwidth might not be set for non-P2P GO cases,
* try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is
* not supported.
*/
conf->vht_oper_chwidth = VHT_CHANWIDTH_160MHZ;
center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel);
if (!center_chan) {
conf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
center_chan = wpas_p2p_get_vht80_center(wpa_s, mode,
channel);
}
break;
}
if (!center_chan) if (!center_chan)
goto no_vht; goto no_vht;
/* Use 80 MHz channel */
conf->vht_oper_chwidth = 1;
conf->vht_oper_centr_freq_seg0_idx = center_chan; conf->vht_oper_centr_freq_seg0_idx = center_chan;
return; return;
@ -635,6 +655,13 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
return -1; return -1;
} }
/* Use the maximum oper channel width if it's given. */
if (ssid->max_oper_chwidth)
conf->vht_oper_chwidth = ssid->max_oper_chwidth;
ieee80211_freq_to_chan(ssid->vht_center_freq2,
&conf->vht_oper_centr_freq_seg1_idx);
os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params, os_memcpy(wpa_s->ap_iface->conf->wmm_ac_params,
wpa_s->conf->wmm_ac_params, wpa_s->conf->wmm_ac_params,
sizeof(wpa_s->conf->wmm_ac_params)); sizeof(wpa_s->conf->wmm_ac_params));

View file

@ -449,6 +449,10 @@ struct wpa_ssid {
int vht; int vht;
u8 max_oper_chwidth;
unsigned int vht_center_freq2;
/** /**
* wpa_ptk_rekey - Maximum lifetime for PTK in seconds * wpa_ptk_rekey - Maximum lifetime for PTK in seconds
* *

View file

@ -4861,6 +4861,30 @@ static int p2p_ctrl_asp_provision(struct wpa_supplicant *wpa_s, char *cmd)
} }
static int parse_freq(int chwidth, int freq2)
{
if (freq2 < 0)
return -1;
if (freq2)
return VHT_CHANWIDTH_80P80MHZ;
switch (chwidth) {
case 0:
case 20:
case 40:
return VHT_CHANWIDTH_USE_HT;
case 80:
return VHT_CHANWIDTH_80MHZ;
case 160:
return VHT_CHANWIDTH_160MHZ;
default:
wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
chwidth);
return -1;
}
}
static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd, static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
char *buf, size_t buflen) char *buf, size_t buflen)
{ {
@ -4877,7 +4901,7 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
int go_intent = -1; int go_intent = -1;
int freq = 0; int freq = 0;
int pd; int pd;
int ht40, vht; int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
if (!wpa_s->global->p2p_init_wpa_s) if (!wpa_s->global->p2p_init_wpa_s)
return -1; return -1;
@ -4938,6 +4962,18 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
return -1; return -1;
} }
pos2 = os_strstr(pos, " freq2=");
if (pos2)
freq2 = atoi(pos2 + 7);
pos2 = os_strstr(pos, " max_oper_chwidth=");
if (pos2)
chwidth = atoi(pos2 + 18);
max_oper_chwidth = parse_freq(chwidth, freq2);
if (max_oper_chwidth < 0)
return -1;
if (os_strncmp(pos, "pin", 3) == 0) { if (os_strncmp(pos, "pin", 3) == 0) {
/* Request random PIN (to be displayed) and enable the PIN */ /* Request random PIN (to be displayed) and enable the PIN */
wps_method = WPS_PIN_DISPLAY; wps_method = WPS_PIN_DISPLAY;
@ -4962,8 +4998,8 @@ static int p2p_ctrl_connect(struct wpa_supplicant *wpa_s, char *cmd,
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, automatic, join, persistent_group, automatic, join,
auth, go_intent, freq, persistent_id, pd, auth, go_intent, freq, freq2, persistent_id,
ht40, vht); pd, ht40, vht, max_oper_chwidth);
if (new_pin == -2) { if (new_pin == -2) {
os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25); os_memcpy(buf, "FAIL-CHANNEL-UNAVAILABLE\n", 25);
return 25; return 25;
@ -5518,7 +5554,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
struct wpa_ssid *ssid; struct wpa_ssid *ssid;
u8 *_peer = NULL, peer[ETH_ALEN]; u8 *_peer = NULL, peer[ETH_ALEN];
int freq = 0, pref_freq = 0; int freq = 0, pref_freq = 0;
int ht40, vht; int ht40, vht, max_oper_chwidth, chwidth = 0, freq2 = 0;
id = atoi(cmd); id = atoi(cmd);
pos = os_strstr(cmd, " peer="); pos = os_strstr(cmd, " peer=");
@ -5556,8 +5592,20 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 || ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40 ||
vht; vht;
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, vht, pos = os_strstr(cmd, "freq2=");
pref_freq); if (pos)
freq2 = atoi(pos + 6);
pos = os_strstr(cmd, " max_oper_chwidth=");
if (pos)
chwidth = atoi(pos + 18);
max_oper_chwidth = parse_freq(chwidth, freq2);
if (max_oper_chwidth < 0)
return -1;
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, freq2, ht40, vht,
max_oper_chwidth, pref_freq);
} }
@ -5604,7 +5652,8 @@ static int p2p_ctrl_invite(struct wpa_supplicant *wpa_s, char *cmd)
static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s, static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
int id, int freq, int ht40, int vht) int id, int freq, int vht_center_freq2,
int ht40, int vht, int vht_chwidth)
{ {
struct wpa_ssid *ssid; struct wpa_ssid *ssid;
@ -5616,8 +5665,9 @@ static int p2p_ctrl_group_add_persistent(struct wpa_supplicant *wpa_s,
return -1; return -1;
} }
return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, ht40, vht, return wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq,
NULL, 0, 0); vht_center_freq2, 0, ht40, vht,
vht_chwidth, NULL, 0, 0);
} }
@ -5626,11 +5676,14 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
int freq = 0, persistent = 0, group_id = -1; int freq = 0, persistent = 0, group_id = -1;
int vht = wpa_s->conf->p2p_go_vht; int vht = wpa_s->conf->p2p_go_vht;
int ht40 = wpa_s->conf->p2p_go_ht40 || vht; int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
int max_oper_chwidth, chwidth = 0, freq2 = 0;
char *token, *context = NULL; char *token, *context = NULL;
while ((token = str_token(cmd, " ", &context))) { while ((token = str_token(cmd, " ", &context))) {
if (sscanf(token, "freq=%d", &freq) == 1 || if (sscanf(token, "freq=%d", &freq) == 1 ||
sscanf(token, "persistent=%d", &group_id) == 1) { sscanf(token, "freq2=%d", &freq2) == 1 ||
sscanf(token, "persistent=%d", &group_id) == 1 ||
sscanf(token, "max_oper_chwidth=%d", &chwidth) == 1) {
continue; continue;
} else if (os_strcmp(token, "ht40") == 0) { } else if (os_strcmp(token, "ht40") == 0) {
ht40 = 1; ht40 = 1;
@ -5647,11 +5700,17 @@ static int p2p_ctrl_group_add(struct wpa_supplicant *wpa_s, char *cmd)
} }
} }
max_oper_chwidth = parse_freq(chwidth, freq2);
if (max_oper_chwidth < 0)
return -1;
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, ht40, vht); freq, freq2, ht40, vht,
max_oper_chwidth);
return wpas_p2p_group_add(wpa_s, persistent, freq, ht40, vht); return wpas_p2p_group_add(wpa_s, persistent, freq, freq2, ht40, vht,
max_oper_chwidth);
} }

View file

@ -364,13 +364,14 @@ DBusMessage * wpas_dbus_handler_p2p_group_add(DBusMessage *message,
goto inv_args; goto inv_args;
if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0, if (wpas_p2p_group_add_persistent(wpa_s, ssid, 0, freq, 0, 0, 0,
NULL, 0, 0)) { 0, 0, NULL, 0, 0)) {
reply = wpas_dbus_error_unknown_error( reply = wpas_dbus_error_unknown_error(
message, message,
"Failed to reinvoke a persistent group"); "Failed to reinvoke a persistent group");
goto out; goto out;
} }
} else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0)) } else if (wpas_p2p_group_add(wpa_s, persistent_group, freq, 0, 0, 0,
0))
goto inv_args; goto inv_args;
out: out:
@ -582,7 +583,7 @@ DBusMessage * wpas_dbus_handler_p2p_connect(DBusMessage *message,
new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method, new_pin = wpas_p2p_connect(wpa_s, addr, pin, wps_method,
persistent_group, 0, join, authorize_only, persistent_group, 0, join, authorize_only,
go_intent, freq, -1, 0, 0, 0); go_intent, freq, 0, -1, 0, 0, 0, 0);
if (new_pin >= 0) { if (new_pin >= 0) {
char npin[9]; char npin[9];
@ -733,8 +734,8 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
if (ssid == NULL || ssid->disabled != 2) if (ssid == NULL || ssid->disabled != 2)
goto err; goto err;
if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0) < if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0, 0, 0,
0) { 0) < 0) {
reply = wpas_dbus_error_unknown_error( reply = wpas_dbus_error_unknown_error(
message, message,
"Failed to reinvoke a persistent group"); "Failed to reinvoke a persistent group");

View file

@ -1877,6 +1877,8 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s,
ssid->frequency = params->freq; ssid->frequency = params->freq;
ssid->ht40 = params->ht40; ssid->ht40 = params->ht40;
ssid->vht = params->vht; ssid->vht = params->vht;
ssid->max_oper_chwidth = params->max_oper_chwidth;
ssid->vht_center_freq2 = params->vht_center_freq2;
ssid->ssid = os_zalloc(params->ssid_len + 1); ssid->ssid = os_zalloc(params->ssid_len + 1);
if (ssid->ssid) { if (ssid->ssid) {
os_memcpy(ssid->ssid, params->ssid, params->ssid_len); os_memcpy(ssid->ssid, params->ssid, params->ssid_len);
@ -2178,6 +2180,8 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res)
res->ht40 = 1; res->ht40 = 1;
if (wpa_s->p2p_go_vht) if (wpa_s->p2p_go_vht)
res->vht = 1; res->vht = 1;
res->max_oper_chwidth = wpa_s->p2p_go_max_oper_chwidth;
res->vht_center_freq2 = wpa_s->p2p_go_vht_center_freq2;
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS "role=%s " wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_GO_NEG_SUCCESS "role=%s "
"freq=%d ht40=%d peer_dev=" MACSTR " peer_iface=" MACSTR "freq=%d ht40=%d peer_dev=" MACSTR " peer_iface=" MACSTR
@ -2966,7 +2970,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
if (s) { if (s) {
int go = s->mode == WPAS_MODE_P2P_GO; int go = s->mode == WPAS_MODE_P2P_GO;
wpas_p2p_group_add_persistent( wpas_p2p_group_add_persistent(
wpa_s, s, go, 0, op_freq, 0, 0, NULL, wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0,
1); 1);
} else if (bssid) { } else if (bssid) {
@ -3183,7 +3187,9 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
ssid->mode == WPAS_MODE_P2P_GO, ssid->mode == WPAS_MODE_P2P_GO,
wpa_s->p2p_persistent_go_freq, wpa_s->p2p_persistent_go_freq,
freq, freq,
wpa_s->p2p_go_vht_center_freq2,
wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht, wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
wpa_s->p2p_go_max_oper_chwidth,
channels, channels,
ssid->mode == WPAS_MODE_P2P_GO ? ssid->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
@ -4124,13 +4130,13 @@ static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
if (response_done && persistent_go) { if (response_done && persistent_go) {
wpas_p2p_group_add_persistent( wpas_p2p_group_add_persistent(
wpa_s, persistent_go, wpa_s, persistent_go,
0, 0, freq, 0, 0, NULL, 0, 0, freq, 0, 0, 0, 0, NULL,
persistent_go->mode == persistent_go->mode ==
WPAS_MODE_P2P_GO ? WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
0, 0); 0, 0);
} else if (response_done) { } else if (response_done) {
wpas_p2p_group_add(wpa_s, 1, freq, 0, 0); wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
} }
if (passwd_id == DEV_PW_P2PS_DEFAULT) { if (passwd_id == DEV_PW_P2PS_DEFAULT) {
@ -4234,11 +4240,11 @@ static int wpas_prov_disc_resp_cb(void *ctx)
if (persistent_go) { if (persistent_go) {
wpas_p2p_group_add_persistent( wpas_p2p_group_add_persistent(
wpa_s, persistent_go, 0, 0, 0, 0, 0, NULL, wpa_s, persistent_go, 0, 0, 0, 0, 0, 0, 0, NULL,
persistent_go->mode == WPAS_MODE_P2P_GO ? persistent_go->mode == WPAS_MODE_P2P_GO ?
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0); P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 0);
} else { } else {
wpas_p2p_group_add(wpa_s, 1, freq, 0, 0); wpas_p2p_group_add(wpa_s, 1, freq, 0, 0, 0, 0);
} }
return 1; return 1;
@ -4756,10 +4762,12 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s,
wpa_s->p2p_persistent_group, 0, 0, 0, wpa_s->p2p_persistent_group, 0, 0, 0,
wpa_s->p2p_go_intent, wpa_s->p2p_go_intent,
wpa_s->p2p_connect_freq, wpa_s->p2p_connect_freq,
wpa_s->p2p_go_vht_center_freq2,
wpa_s->p2p_persistent_id, wpa_s->p2p_persistent_id,
wpa_s->p2p_pd_before_go_neg, wpa_s->p2p_pd_before_go_neg,
wpa_s->p2p_go_ht40, wpa_s->p2p_go_ht40,
wpa_s->p2p_go_vht); wpa_s->p2p_go_vht,
wpa_s->p2p_go_max_oper_chwidth);
return; return;
} }
@ -5264,12 +5272,15 @@ exit_free:
* initiating Group Owner negotiation * initiating Group Owner negotiation
* @go_intent: GO Intent or -1 to use default * @go_intent: GO Intent or -1 to use default
* @freq: Frequency for the group or 0 for auto-selection * @freq: Frequency for the group or 0 for auto-selection
* @freq2: Center frequency of segment 1 for the GO operating in VHT 80P80 mode
* @persistent_id: Persistent group credentials to use for forcing GO * @persistent_id: Persistent group credentials to use for forcing GO
* parameters or -1 to generate new values (SSID/passphrase) * parameters or -1 to generate new values (SSID/passphrase)
* @pd: Whether to send Provision Discovery prior to GO Negotiation as an * @pd: Whether to send Provision Discovery prior to GO Negotiation as an
* interoperability workaround when initiating group formation * interoperability workaround when initiating group formation
* @ht40: Start GO with 40 MHz channel width * @ht40: Start GO with 40 MHz channel width
* @vht: Start GO with VHT support * @vht: Start GO with VHT support
* @vht_chwidth: Channel width supported by GO operating with VHT support
* (VHT_CHANWIDTH_*).
* Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified * Returns: 0 or new PIN (if pin was %NULL) on success, -1 on unspecified
* failure, -2 on failure due to channel not currently available, * failure, -2 on failure due to channel not currently available,
* -3 if forced channel is not supported * -3 if forced channel is not supported
@ -5277,8 +5288,9 @@ exit_free:
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
const char *pin, enum p2p_wps_method wps_method, const char *pin, enum p2p_wps_method wps_method,
int persistent_group, int auto_join, int join, int auth, int persistent_group, int auto_join, int join, int auth,
int go_intent, int freq, int persistent_id, int pd, int go_intent, int freq, unsigned int vht_center_freq2,
int ht40, int vht) int persistent_id, int pd, int ht40, int vht,
unsigned int vht_chwidth)
{ {
int force_freq = 0, pref_freq = 0; int force_freq = 0, pref_freq = 0;
int ret = 0, res; int ret = 0, res;
@ -5320,6 +5332,8 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
wpa_s->p2p_pd_before_go_neg = !!pd; wpa_s->p2p_pd_before_go_neg = !!pd;
wpa_s->p2p_go_ht40 = !!ht40; wpa_s->p2p_go_ht40 = !!ht40;
wpa_s->p2p_go_vht = !!vht; wpa_s->p2p_go_vht = !!vht;
wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
wpa_s->p2p_go_max_oper_chwidth = vht_chwidth;
if (pin) if (pin)
os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin)); os_strlcpy(wpa_s->p2p_pin, pin, sizeof(wpa_s->p2p_pin));
@ -5718,7 +5732,8 @@ out:
static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
struct p2p_go_neg_results *params, struct p2p_go_neg_results *params,
int freq, int ht40, int vht, int freq, int vht_center_freq2, int ht40,
int vht, int max_oper_chwidth,
const struct p2p_channels *channels) const struct p2p_channels *channels)
{ {
struct wpa_used_freq_data *freqs; struct wpa_used_freq_data *freqs;
@ -5730,6 +5745,8 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
params->role_go = 1; params->role_go = 1;
params->ht40 = ht40; params->ht40 = ht40;
params->vht = vht; params->vht = vht;
params->max_oper_chwidth = max_oper_chwidth;
params->vht_center_freq2 = vht_center_freq2;
freqs = os_calloc(wpa_s->num_multichan_concurrent, freqs = os_calloc(wpa_s->num_multichan_concurrent,
sizeof(struct wpa_used_freq_data)); sizeof(struct wpa_used_freq_data));
@ -5964,15 +5981,18 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
* @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface() * @wpa_s: Pointer to wpa_supplicant data from wpa_supplicant_add_iface()
* @persistent_group: Whether to create a persistent group * @persistent_group: Whether to create a persistent group
* @freq: Frequency for the group or 0 to indicate no hardcoding * @freq: Frequency for the group or 0 to indicate no hardcoding
* @vht_center_freq2: segment_1 center frequency for GO operating in VHT 80P80
* @ht40: Start GO with 40 MHz channel width * @ht40: Start GO with 40 MHz channel width
* @vht: Start GO with VHT support * @vht: Start GO with VHT support
* @vht_chwidth: channel bandwidth for GO operating with VHT support
* Returns: 0 on success, -1 on failure * Returns: 0 on success, -1 on failure
* *
* This function creates a new P2P group with the local end as the Group Owner, * This function creates a new P2P group with the local end as the Group Owner,
* i.e., without using Group Owner Negotiation. * i.e., without using Group Owner Negotiation.
*/ */
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int ht40, int vht) int freq, int vht_center_freq2, int ht40, int vht,
int max_oper_chwidth)
{ {
struct p2p_go_neg_results params; struct p2p_go_neg_results params;
@ -5990,7 +6010,8 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
if (freq < 0) if (freq < 0)
return -1; return -1;
if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40, vht, NULL)) if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
ht40, vht, max_oper_chwidth, NULL))
return -1; return -1;
if (params.freq && if (params.freq &&
!p2p_supported_freq_go(wpa_s->global->p2p, params.freq)) { !p2p_supported_freq_go(wpa_s->global->p2p, params.freq)) {
@ -6080,8 +6101,10 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated, struct wpa_ssid *ssid, int addr_allocated,
int force_freq, int neg_freq, int ht40, int force_freq, int neg_freq,
int vht, const struct p2p_channels *channels, int vht_center_freq2, int ht40,
int vht, int max_oper_chwidth,
const struct p2p_channels *channels,
int connection_timeout, int force_scan) int connection_timeout, int force_scan)
{ {
struct p2p_go_neg_results params; struct p2p_go_neg_results params;
@ -6155,7 +6178,8 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
return -1; return -1;
} }
if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40, vht, channels)) if (wpas_p2p_init_go_params(wpa_s, &params, freq, vht_center_freq2,
ht40, vht, max_oper_chwidth, channels))
return -1; return -1;
params.role_go = 1; params.role_go = 1;
@ -6682,7 +6706,8 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
/* Invite to reinvoke a persistent group */ /* Invite to reinvoke a persistent group */
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq, struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int ht40, int vht, int pref_freq) int vht_center_freq2, int ht40, int vht, int max_chwidth,
int pref_freq)
{ {
enum p2p_invite_role role; enum p2p_invite_role role;
u8 *bssid = NULL; u8 *bssid = NULL;
@ -6699,6 +6724,9 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
wpa_s->p2p_persistent_go_freq = freq; wpa_s->p2p_persistent_go_freq = freq;
wpa_s->p2p_go_ht40 = !!ht40; wpa_s->p2p_go_ht40 = !!ht40;
wpa_s->p2p_go_vht = !!vht;
wpa_s->p2p_go_max_oper_chwidth = max_chwidth;
wpa_s->p2p_go_vht_center_freq2 = vht_center_freq2;
if (ssid->mode == WPAS_MODE_P2P_GO) { if (ssid->mode == WPAS_MODE_P2P_GO) {
role = P2P_INVITE_ROLE_GO; role = P2P_INVITE_ROLE_GO;
if (peer_addr == NULL) { if (peer_addr == NULL) {
@ -6771,6 +6799,8 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
wpa_s->p2p_persistent_go_freq = 0; wpa_s->p2p_persistent_go_freq = 0;
wpa_s->p2p_go_ht40 = 0; wpa_s->p2p_go_ht40 = 0;
wpa_s->p2p_go_vht = 0; wpa_s->p2p_go_vht = 0;
wpa_s->p2p_go_vht_center_freq2 = 0;
wpa_s->p2p_go_max_oper_chwidth = 0;
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
if (os_strcmp(wpa_s->ifname, ifname) == 0) if (os_strcmp(wpa_s->ifname, ifname) == 0)
@ -7701,10 +7731,12 @@ static int wpas_p2p_fallback_to_go_neg(struct wpa_supplicant *wpa_s,
wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin, wpas_p2p_connect(wpa_s, wpa_s->pending_join_dev_addr, wpa_s->p2p_pin,
wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0, wpa_s->p2p_wps_method, wpa_s->p2p_persistent_group, 0,
0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq, 0, 0, wpa_s->p2p_go_intent, wpa_s->p2p_connect_freq,
wpa_s->p2p_go_vht_center_freq2,
wpa_s->p2p_persistent_id, wpa_s->p2p_persistent_id,
wpa_s->p2p_pd_before_go_neg, wpa_s->p2p_pd_before_go_neg,
wpa_s->p2p_go_ht40, wpa_s->p2p_go_ht40,
wpa_s->p2p_go_vht); wpa_s->p2p_go_vht,
wpa_s->p2p_go_max_oper_chwidth);
return ret; return ret;
} }
@ -8238,7 +8270,8 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s,
return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL, return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent, WPS_NFC, 0, 0, 1, 0, wpa_s->conf->p2p_go_intent,
params->go_freq, -1, 0, 1, 1); params->go_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth);
} }
@ -8314,7 +8347,8 @@ static int wpas_p2p_nfc_init_go_neg(struct wpa_supplicant *wpa_s,
"connection handover"); "connection handover");
return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL, return wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent, WPS_NFC, 0, 0, 0, 0, wpa_s->conf->p2p_go_intent,
forced_freq, -1, 0, 1, 1); forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth);
} }
@ -8328,7 +8362,8 @@ static int wpas_p2p_nfc_resp_go_neg(struct wpa_supplicant *wpa_s,
"connection handover"); "connection handover");
res = wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL, res = wpas_p2p_connect(wpa_s, params->peer->p2p_device_addr, NULL,
WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent, WPS_NFC, 0, 0, 0, 1, wpa_s->conf->p2p_go_intent,
forced_freq, -1, 0, 1, 1); forced_freq, wpa_s->p2p_go_vht_center_freq2,
-1, 0, 1, 1, wpa_s->p2p_go_max_oper_chwidth);
if (res) if (res)
return res; return res;
@ -8711,7 +8746,7 @@ static int wpas_p2p_move_go_csa(struct wpa_supplicant *wpa_s)
* TODO: This function may not always work correctly. For example, * TODO: This function may not always work correctly. For example,
* when we have a running GO and a BSS on a DFS channel. * when we have a running GO and a BSS on a DFS channel.
*/ */
if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, NULL)) { if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, NULL)) {
wpa_dbg(wpa_s, MSG_DEBUG, wpa_dbg(wpa_s, MSG_DEBUG,
"P2P CSA: Failed to select new frequency for GO"); "P2P CSA: Failed to select new frequency for GO");
return -1; return -1;
@ -8823,7 +8858,7 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s)
wpa_supplicant_ap_deinit(wpa_s); wpa_supplicant_ap_deinit(wpa_s);
/* Reselect the GO frequency */ /* Reselect the GO frequency */
if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, NULL)) { if (wpas_p2p_init_go_params(wpa_s, &params, 0, 0, 0, 0, 0, NULL)) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq"); wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Failed to reselect freq");
wpas_p2p_group_delete(wpa_s, wpas_p2p_group_delete(wpa_s,
P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL); P2P_GROUP_REMOVAL_GO_LEAVE_CHANNEL);

View file

@ -35,16 +35,20 @@ struct wpa_supplicant * wpas_get_p2p_client_iface(struct wpa_supplicant *wpa_s,
int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
const char *pin, enum p2p_wps_method wps_method, const char *pin, enum p2p_wps_method wps_method,
int persistent_group, int auto_join, int join, int persistent_group, int auto_join, int join,
int auth, int go_intent, int freq, int persistent_id, int auth, int go_intent, int freq,
int pd, int ht40, int vht); unsigned int vht_center_freq2, int persistent_id,
int pd, int ht40, int vht, unsigned int max_oper_chwidth);
int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s,
int freq, struct wpa_ssid *ssid); int freq, struct wpa_ssid *ssid);
int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
int freq, int ht40, int vht); int freq, int vht_center_freq2, int ht40, int vht,
int max_oper_chwidth);
int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid, int addr_allocated, struct wpa_ssid *ssid, int addr_allocated,
int force_freq, int neg_freq, int ht40, int force_freq, int neg_freq,
int vht, const struct p2p_channels *channels, int vht_center_freq2, int ht40,
int vht, int max_oper_chwidth,
const struct p2p_channels *channels,
int connection_timeout, int force_scan); int connection_timeout, int force_scan);
struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid); struct wpa_ssid *ssid);
@ -111,7 +115,8 @@ void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic,
int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr); int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq, struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
int ht40, int vht, int pref_freq); int vht_center_freq2, int ht40, int vht,
int max_oper_chwidth, int pref_freq);
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
const u8 *peer_addr, const u8 *go_dev_addr); const u8 *peer_addr, const u8 *go_dev_addr);
int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1, int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1,

View file

@ -857,6 +857,9 @@ struct wpa_supplicant {
int *p2p_group_common_freqs; int *p2p_group_common_freqs;
unsigned int p2p_group_common_freqs_num; unsigned int p2p_group_common_freqs_num;
u8 p2ps_join_addr[ETH_ALEN]; u8 p2ps_join_addr[ETH_ALEN];
unsigned int p2p_go_max_oper_chwidth;
unsigned int p2p_go_vht_center_freq2;
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
struct wpa_ssid *bgscan_ssid; struct wpa_ssid *bgscan_ssid;