P2P: Optimize scan for GO during persistent group invocation

Scan for GO on the negotiated operating channel for few iterations
before searching on all the supported channels during persistent group
reinvocation. In addition, use the already known SSID of the group in
the scans. These optimizations reduce group formation time.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Rashmi Ramanna 2014-03-21 18:26:02 +05:30 committed by Jouni Malinen
parent 406739c499
commit 41d5ce9e0b
7 changed files with 90 additions and 16 deletions

View file

@ -3310,7 +3310,7 @@ static void p2p_timeout_invite_listen(struct p2p_data *p2p)
p2p->cfg->invitation_result(
p2p->cfg->cb_ctx, -1, NULL, NULL,
p2p->invite_peer->info.p2p_device_addr,
0);
0, 0);
}
p2p_set_state(p2p, P2P_IDLE);
}

View file

@ -764,6 +764,8 @@ struct p2p_config {
* @channels: Available operating channels for the group
* @addr: Peer address
* @freq: Frequency (in MHz) indicated during invitation or 0
* @peer_oper_freq: Operating frequency (in MHz) advertized by the peer
* during invitation or 0
*
* This callback is used to indicate result of an Invitation procedure
* started with a call to p2p_invite(). The indicated status code is
@ -773,7 +775,7 @@ struct p2p_config {
*/
void (*invitation_result)(void *ctx, int status, const u8 *bssid,
const struct p2p_channels *channels,
const u8 *addr, int freq);
const u8 *addr, int freq, int peer_oper_freq);
/**
* go_connected - Check whether we are connected to a GO

View file

@ -288,7 +288,9 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
}
}
if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
/* Reselect the channel only for the case of the GO */
if (go &&
!p2p_channels_includes(&intersection, p2p->op_reg_class,
p2p->op_channel)) {
p2p_dbg(p2p, "Initially selected channel (op_class %d channel %d) not in channel intersection - try to reselect",
p2p->op_reg_class, p2p->op_channel);
@ -303,7 +305,7 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
} else if (!(dev->flags & P2P_DEV_FORCE_FREQ) &&
} else if (go && !(dev->flags & P2P_DEV_FORCE_FREQ) &&
!p2p->cfg->cfg_op_channel) {
p2p_dbg(p2p, "Try to reselect channel selection with peer information received; previously selected op_class %u channel %u",
p2p->op_reg_class, p2p->op_channel);
@ -444,13 +446,23 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
}
if (p2p->cfg->invitation_result) {
int peer_oper_freq = 0;
int freq = p2p_channel_to_freq(p2p->op_reg_class,
p2p->op_channel);
if (freq < 0)
freq = 0;
if (msg.operating_channel) {
peer_oper_freq = p2p_channel_to_freq(
msg.operating_channel[3],
msg.operating_channel[4]);
if (peer_oper_freq < 0)
peer_oper_freq = 0;
}
p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
msg.group_bssid, channels, sa,
freq);
freq, peer_oper_freq);
}
p2p_parse_free(&msg);

View file

@ -1430,7 +1430,8 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
return 0;
if (wpa_s->p2p_in_provisioning ||
wpa_s->show_group_started) {
wpa_s->show_group_started ||
wpa_s->p2p_in_invitation) {
/*
* Use shorter wait during P2P Provisioning
* state and during P2P join-a-group operation

View file

@ -501,6 +501,8 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s,
wpa_s->p2p_in_provisioning = 0;
}
wpa_s->p2p_in_invitation = 0;
/*
* Make sure wait for the first client does not remain active after the
* group has been removed.
@ -3070,7 +3072,7 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid,
if (s) {
int go = s->mode == WPAS_MODE_P2P_GO;
wpas_p2p_group_add_persistent(
wpa_s, s, go, 0, go ? op_freq : 0, 0, 0, NULL,
wpa_s, s, go, 0, op_freq, 0, 0, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
@ -3177,10 +3179,12 @@ static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s,
static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
const struct p2p_channels *channels,
const u8 *peer, int neg_freq)
const u8 *peer, int neg_freq,
int peer_oper_freq)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid;
int freq;
if (bssid) {
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
@ -3236,10 +3240,21 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
"starting persistent group");
os_sleep(0, 50000);
if (neg_freq > 0 && ssid->mode == WPAS_MODE_P2P_GO &&
freq_included(channels, neg_freq))
freq = neg_freq;
else if (peer_oper_freq > 0 && ssid->mode != WPAS_MODE_P2P_GO &&
freq_included(channels, peer_oper_freq))
freq = peer_oper_freq;
else
freq = 0;
wpa_printf(MSG_DEBUG, "P2P: Persistent group invitation success - op_freq=%d MHz SSID=%s",
freq, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
wpas_p2p_group_add_persistent(wpa_s, ssid,
ssid->mode == WPAS_MODE_P2P_GO,
wpa_s->p2p_persistent_go_freq,
neg_freq,
freq,
wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
channels,
ssid->mode == WPAS_MODE_P2P_GO ?
@ -5150,7 +5165,8 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
struct wpa_ssid *params, int addr_allocated)
struct wpa_ssid *params, int addr_allocated,
int freq)
{
struct wpa_ssid *ssid;
@ -5187,6 +5203,8 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
ssid->passphrase = os_strdup(params->passphrase);
wpa_s->show_group_started = 1;
wpa_s->p2p_in_invitation = 1;
wpa_s->p2p_invite_go_freq = freq;
wpa_supplicant_select_network(wpa_s, ssid);
@ -5221,12 +5239,6 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
wpa_s->p2p_fallback_to_go_neg = 0;
if (ssid->mode == WPAS_MODE_INFRA)
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated);
if (ssid->mode != WPAS_MODE_P2P_GO)
return -1;
if (force_freq > 0) {
freq = wpas_p2p_select_go_freq(wpa_s, force_freq);
if (freq < 0)
@ -5237,6 +5249,12 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s,
freq = 0;
}
if (ssid->mode == WPAS_MODE_INFRA)
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq);
if (ssid->mode != WPAS_MODE_P2P_GO)
return -1;
if (wpas_p2p_init_go_params(wpa_s, &params, freq, ht40, vht, channels))
return -1;

View file

@ -326,6 +326,32 @@ static void wpa_supplicant_optimize_freqs(
}
wpa_s->p2p_in_provisioning++;
}
if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
/*
* Optimize scan based on GO information during persistent
* group reinvocation
*/
if (wpa_s->p2p_in_invitation < 5 ||
wpa_s->p2p_invite_go_freq > 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
wpa_s->p2p_invite_go_freq);
params->freqs = os_zalloc(2 * sizeof(int));
if (params->freqs)
params->freqs[0] = wpa_s->p2p_invite_go_freq;
}
wpa_s->p2p_in_invitation++;
if (wpa_s->p2p_in_invitation > 20) {
/*
* This should not really happen since the variable is
* cleared on group removal, but if it does happen, make
* sure we do not get stuck in special invitation scan
* mode.
*/
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation");
wpa_s->p2p_in_invitation = 0;
}
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_WPS
@ -639,6 +665,19 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
params.num_ssids = 1;
goto ssid_list_set;
}
if (wpa_s->p2p_in_invitation) {
if (wpa_s->current_ssid) {
wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation");
params.ssids[0].ssid = wpa_s->current_ssid->ssid;
params.ssids[0].ssid_len =
wpa_s->current_ssid->ssid_len;
params.num_ssids = 1;
} else {
wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation");
}
goto ssid_list_set;
}
#endif /* CONFIG_P2P */
/* Find the starting point from which to continue scanning */

View file

@ -687,6 +687,8 @@ struct wpa_supplicant {
u8 p2p_auth_invite[ETH_ALEN];
int p2p_sd_over_ctrl_iface;
int p2p_in_provisioning;
int p2p_in_invitation;
int p2p_invite_go_freq;
int pending_invite_ssid_id;
int show_group_started;
u8 go_dev_addr[ETH_ALEN];