From e280110d1782a12bf08e97034d418d2559375c7d Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 27 Jul 2015 22:24:21 +0300 Subject: [PATCH] P2P: Move a GO to a frequency that is also supported by the client A P2P GO interface that was instantiated after a GO Negotiation or Invitation holds the intersection of frequencies between the GO and the client. In case the GO is going to move to another frequency, allow it to move only to a frequency that is also supported by the client. Signed-off-by: Ilan Peer --- wpa_supplicant/p2p_supplicant.c | 95 ++++++++++++++++++--------------- 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 88798e303..214ea439b 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -136,6 +136,7 @@ static int wpas_p2p_add_group_interface(struct wpa_supplicant *wpa_s, static void wpas_p2p_group_formation_failed(struct wpa_supplicant *wpa_s, int already_deleted); static void wpas_p2p_move_go(void *eloop_ctx, void *timeout_ctx); +static int wpas_p2p_go_is_peer_freq(struct wpa_supplicant *wpa_s, int freq); /* @@ -2597,12 +2598,14 @@ static void wpas_prov_disc_fail(void *ctx, const u8 *peer, } -static int freq_included(const struct p2p_channels *channels, unsigned int freq) +static int freq_included(struct wpa_supplicant *wpa_s, + const struct p2p_channels *channels, + unsigned int freq) { - if (channels == NULL) - return 1; /* Assume no restrictions */ - return p2p_channels_includes_freq(channels, freq); - + if ((channels == NULL || p2p_channels_includes_freq(channels, freq)) && + wpas_p2p_go_is_peer_freq(wpa_s, freq)) + return 1; + return 0; } @@ -2826,7 +2829,7 @@ accept_inv: "running a GO but we are capable of MCC, " "figure out the best channel to use"); *force_freq = 0; - } else if (!freq_included(channels, *force_freq)) { + } else if (!freq_included(wpa_s, channels, *force_freq)) { /* We are the GO, and *force_freq is not in the * intersection */ wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not " @@ -3033,10 +3036,10 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid, os_sleep(0, 50000); if (neg_freq > 0 && ssid->mode == WPAS_MODE_P2P_GO && - freq_included(channels, neg_freq)) + freq_included(wpa_s, 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_included(wpa_s, channels, peer_oper_freq)) freq = peer_oper_freq; else freq = 0; @@ -5365,7 +5368,7 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, for (i = 0; i < 3; i++) { params->freq = 2412 + ((r + i) % 3) * 25; if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && - freq_included(channels, params->freq) && + freq_included(wpa_s, channels, params->freq) && p2p_supported_freq(wpa_s->global->p2p, params->freq)) goto out; } @@ -5374,7 +5377,7 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, for (i = 0; i < 11; i++) { params->freq = 2412 + i * 5; if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && - freq_included(channels, params->freq) && + freq_included(wpa_s, channels, params->freq) && p2p_supported_freq(wpa_s->global->p2p, params->freq)) goto out; } @@ -5383,7 +5386,7 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, for (i = 0; i < 4; i++) { params->freq = 5180 + i * 20; if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && - freq_included(channels, params->freq) && + freq_included(wpa_s, channels, params->freq) && p2p_supported_freq(wpa_s->global->p2p, params->freq)) goto out; } @@ -5392,7 +5395,7 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, for (i = 0; i < 4; i++) { params->freq = 5745 + i * 20; if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && - freq_included(channels, params->freq) && + freq_included(wpa_s, channels, params->freq) && p2p_supported_freq(wpa_s->global->p2p, params->freq)) goto out; } @@ -5400,7 +5403,7 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, /* try social channel class 180 channel 2 */ params->freq = 58320 + 1 * 2160; if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && - freq_included(channels, params->freq) && + freq_included(wpa_s, channels, params->freq) && p2p_supported_freq(wpa_s->global->p2p, params->freq)) goto out; @@ -5408,7 +5411,7 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, for (i = 0; i < 4; i++) { params->freq = 58320 + i * 2160; if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && - freq_included(channels, params->freq) && + freq_included(wpa_s, channels, params->freq) && p2p_supported_freq(wpa_s->global->p2p, params->freq)) goto out; } @@ -5435,8 +5438,13 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, params->role_go = 1; params->ht40 = ht40; params->vht = vht; + + if (wpa_s->p2p_group_common_freqs_num) + wpa_printf(MSG_DEBUG, "P2P: %s called for an active GO", + __func__); + if (freq) { - if (!freq_included(channels, freq)) { + if (!freq_included(wpa_s, channels, freq)) { wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not " "accepted", freq); return -1; @@ -5447,7 +5455,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, } else if (wpa_s->conf->p2p_oper_reg_class == 81 && wpa_s->conf->p2p_oper_channel >= 1 && wpa_s->conf->p2p_oper_channel <= 11 && - freq_included(channels, + freq_included(wpa_s, channels, 2407 + 5 * wpa_s->conf->p2p_oper_channel)) { params->freq = 2407 + 5 * wpa_s->conf->p2p_oper_channel; wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured " @@ -5459,7 +5467,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, wpa_s->conf->p2p_oper_reg_class == 125 || wpa_s->conf->p2p_oper_reg_class == 126 || wpa_s->conf->p2p_oper_reg_class == 127) && - freq_included(channels, + freq_included(wpa_s, channels, 5000 + 5 * wpa_s->conf->p2p_oper_channel)) { params->freq = 5000 + 5 * wpa_s->conf->p2p_oper_channel; wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on configured " @@ -5468,7 +5476,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, wpa_s->best_overall_freq > 0 && p2p_supported_freq_go(wpa_s->global->p2p, wpa_s->best_overall_freq) && - freq_included(channels, wpa_s->best_overall_freq)) { + freq_included(wpa_s, channels, wpa_s->best_overall_freq)) { params->freq = wpa_s->best_overall_freq; wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best overall " "channel %d MHz", params->freq); @@ -5476,7 +5484,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, wpa_s->best_24_freq > 0 && p2p_supported_freq_go(wpa_s->global->p2p, wpa_s->best_24_freq) && - freq_included(channels, wpa_s->best_24_freq)) { + freq_included(wpa_s, channels, wpa_s->best_24_freq)) { params->freq = wpa_s->best_24_freq; wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 2.4 GHz " "channel %d MHz", params->freq); @@ -5484,7 +5492,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, wpa_s->best_5_freq > 0 && p2p_supported_freq_go(wpa_s->global->p2p, wpa_s->best_5_freq) && - freq_included(channels, wpa_s->best_5_freq)) { + freq_included(wpa_s, channels, wpa_s->best_5_freq)) { params->freq = wpa_s->best_5_freq; wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on best 5 GHz " "channel %d MHz", params->freq); @@ -5493,6 +5501,17 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, params->freq = pref_freq; wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred " "channels", params->freq); + } else if (wpa_s->p2p_group_common_freqs) { + for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) { + if (freq_included(wpa_s, channels, + wpa_s->p2p_group_common_freqs[i])) { + params->freq = wpa_s->p2p_group_common_freqs[i]; + wpa_printf(MSG_DEBUG, + "P2P: Use freq %d MHz common with the peer", + params->freq); + break; + } + } } else { /* no preference, select some channel */ if (wpas_p2p_select_freq_no_pref(wpa_s, params, channels) < 0) @@ -5510,27 +5529,17 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, cand_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num); /* First try the best used frequency if possible */ - if (!freq && cand_freq > 0 && freq_included(channels, cand_freq)) { + if (!freq && cand_freq > 0) { params->freq = cand_freq; } else if (!freq) { - /* Try any of the used frequencies */ - for (i = 0; i < num; i++) { - if (freq_included(channels, freqs[i].freq)) { - wpa_printf(MSG_DEBUG, "P2P: Force GO on a channel we are already using (%u MHz)", - freqs[i].freq); - params->freq = freqs[i].freq; - break; - } - } - - if (i == num) { - if (wpas_p2p_num_unused_channels(wpa_s) <= 0) { - wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using"); - os_free(freqs); - return -1; - } else { - wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels"); - } + if (wpas_p2p_num_unused_channels(wpa_s) <= 0) { + wpa_printf(MSG_DEBUG, + "P2P: Cannot force GO on any of the channels we are already using"); + os_free(freqs); + return -1; + } else { + wpa_printf(MSG_DEBUG, + "P2P: Cannot force GO on any of the channels we are already using. Use one of the free channels"); } } else { for (i = 0; i < num; i++) { @@ -5758,12 +5767,12 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, } else { freq = wpas_p2p_select_go_freq(wpa_s, neg_freq); if (freq < 0 || - (freq > 0 && !freq_included(channels, freq))) + (freq > 0 && !freq_included(wpa_s, channels, freq))) freq = 0; } } else if (ssid->mode == WPAS_MODE_INFRA) { freq = neg_freq; - if (freq <= 0 || !freq_included(channels, freq)) { + if (freq <= 0 || !freq_included(wpa_s, channels, freq)) { struct os_reltime now; struct wpa_bss *bss = wpa_bss_get_p2p_dev_addr(wpa_s, ssid->bssid); @@ -5771,7 +5780,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, os_get_reltime(&now); if (bss && !os_reltime_expired(&now, &bss->last_update, 5) && - freq_included(channels, bss->freq)) + freq_included(wpa_s, channels, bss->freq)) freq = bss->freq; else freq = 0; @@ -7014,7 +7023,7 @@ void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s) ifs->current_ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION)) continue; freq = ifs->current_ssid->frequency; - if (freq_included(&chan, freq)) { + if (freq_included(ifs, &chan, freq)) { wpa_dbg(ifs, MSG_DEBUG, "P2P GO operating frequency %d MHz in valid range", freq);