P2P: Modify wpas_p2p_init_go_params()
authorIlan Peer <ilan.peer@intel.com>
Mon, 27 Jul 2015 19:24:23 +0000 (22:24 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 3 Aug 2015 21:38:54 +0000 (00:38 +0300)
Not all paths in wpas_p2p_init_go_params() verified that the candidate
frequency can be used for GO purposes. Fix this, and in addition
re-factor the code to put better emphasis on the frequency selection
priorities.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
wpa_supplicant/p2p_supplicant.c

index 214ea43..04d99bd 100644 (file)
@@ -5355,30 +5355,45 @@ static int wpas_p2p_select_go_freq(struct wpa_supplicant *wpa_s, int freq)
 }
 
 
-static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s,
-                                       struct p2p_go_neg_results *params,
-                                       const struct p2p_channels *channels)
+static int wpas_p2p_supported_freq_go(struct wpa_supplicant *wpa_s,
+                                     const struct p2p_channels *channels,
+                                     int freq)
+{
+       if (!wpas_p2p_disallowed_freq(wpa_s->global, freq) &&
+           p2p_supported_freq_go(wpa_s->global->p2p, freq) &&
+           freq_included(wpa_s, channels, freq))
+               return 1;
+       return 0;
+}
+
+
+static void wpas_p2p_select_go_freq_no_pref(struct wpa_supplicant *wpa_s,
+                                           struct p2p_go_neg_results *params,
+                                           const struct p2p_channels *channels)
 {
        unsigned int i, r;
 
        /* first try some random selection of the social channels */
        if (os_get_random((u8 *) &r, sizeof(r)) < 0)
-               return -1;
+               return;
 
        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(wpa_s, channels, params->freq) &&
-                   p2p_supported_freq(wpa_s->global->p2p, params->freq))
+               if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
                        goto out;
        }
 
-       /* try all channels in reg. class 81 */
+       /* try all other channels in operating class 81 */
        for (i = 0; i < 11; i++) {
                params->freq = 2412 + i * 5;
-               if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) &&
-                   freq_included(wpa_s, channels, params->freq) &&
-                   p2p_supported_freq(wpa_s->global->p2p, params->freq))
+
+               /* skip social channels; covered in the previous loop */
+               if (params->freq == 2412 ||
+                   params->freq == 2437 ||
+                   params->freq == 2462)
+                       continue;
+
+               if (wpas_p2p_supported_freq_go(wpa_s, channels, params->freq))
                        goto out;
        }
 
@@ -5416,12 +5431,12 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s,
                        goto out;
        }
 
+       params->freq = 0;
        wpa_printf(MSG_DEBUG, "P2P: No 2.4, 5, or 60 GHz channel allowed");
-       return -1;
+       return;
 out:
        wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference known)",
                   params->freq);
-       return 0;
 }
 
 
@@ -5431,7 +5446,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
                                   const struct p2p_channels *channels)
 {
        struct wpa_used_freq_data *freqs;
-       unsigned int pref_freq, cand_freq;
+       unsigned int cand;
        unsigned int num, i;
 
        os_memset(params, 0, sizeof(*params));
@@ -5443,124 +5458,174 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s,
                wpa_printf(MSG_DEBUG, "P2P: %s called for an active GO",
                           __func__);
 
+       freqs = os_calloc(wpa_s->num_multichan_concurrent,
+                         sizeof(struct wpa_used_freq_data));
+       if (!freqs)
+               return -1;
+
+       num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
+                                       wpa_s->num_multichan_concurrent);
+
+       /* try using the forced freq */
        if (freq) {
-               if (!freq_included(wpa_s, channels, freq)) {
-                       wpa_printf(MSG_DEBUG, "P2P: Forced GO freq %d MHz not "
-                                  "accepted", freq);
-                       return -1;
+               if (!wpas_p2p_supported_freq_go(wpa_s, channels, freq)) {
+                       wpa_printf(MSG_DEBUG,
+                                  "P2P: Forced GO freq %d MHz not accepted",
+                                  freq);
+                       goto fail;
+               }
+
+               for (i = 0; i < num; i++) {
+                       if (freqs[i].freq == freq) {
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: forced freq (%d MHz) is also shared",
+                                          freq);
+                               params->freq = freq;
+                               goto success;
+                       }
                }
-               wpa_printf(MSG_DEBUG, "P2P: Set GO freq based on forced "
-                          "frequency %d MHz", freq);
+
+               if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
+                       wpa_printf(MSG_DEBUG,
+                                  "P2P: Cannot force GO on freq (%d MHz) as all the channels are in use",
+                                  freq);
+                       goto fail;
+               }
+
+               wpa_printf(MSG_DEBUG,
+                          "P2P: force GO freq (%d MHz) on a free channel",
+                          freq);
                params->freq = freq;
-       } 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(wpa_s, channels,
-                                2407 + 5 * wpa_s->conf->p2p_oper_channel)) {
+               goto success;
+       }
+
+       /* consider using one of the shared frequencies */
+       if (num) {
+               cand = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
+               if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+                       wpa_printf(MSG_DEBUG,
+                                  "P2P: Use shared freq (%d MHz) for GO",
+                                  freq);
+                       params->freq = cand;
+                       goto success;
+               }
+
+               /* try using one of the shared freqs */
+               for (i = 0; i < num; i++) {
+                       if (wpas_p2p_supported_freq_go(wpa_s, channels,
+                                                      freqs[i].freq)) {
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: Use shared freq (%d MHz) for GO",
+                                          freq);
+                               params->freq = freqs[i].freq;
+                               goto success;
+                       }
+               }
+       }
+
+       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");
+               goto fail;
+       }
+
+       /* try using the setting from the configuration file */
+       if (wpa_s->conf->p2p_oper_reg_class == 81 &&
+           wpa_s->conf->p2p_oper_channel >= 1 &&
+           wpa_s->conf->p2p_oper_channel <= 11 &&
+           wpas_p2p_supported_freq_go(
+                   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 "
                           "frequency %d MHz", params->freq);
-       } else if ((wpa_s->conf->p2p_oper_reg_class == 115 ||
-                   wpa_s->conf->p2p_oper_reg_class == 116 ||
-                   wpa_s->conf->p2p_oper_reg_class == 117 ||
-                   wpa_s->conf->p2p_oper_reg_class == 124 ||
-                   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(wpa_s, channels,
-                                5000 + 5 * wpa_s->conf->p2p_oper_channel)) {
+               goto success;
+       }
+
+       if ((wpa_s->conf->p2p_oper_reg_class == 115 ||
+            wpa_s->conf->p2p_oper_reg_class == 116 ||
+            wpa_s->conf->p2p_oper_reg_class == 117 ||
+            wpa_s->conf->p2p_oper_reg_class == 124 ||
+            wpa_s->conf->p2p_oper_reg_class == 125 ||
+            wpa_s->conf->p2p_oper_reg_class == 126 ||
+            wpa_s->conf->p2p_oper_reg_class == 127) &&
+           wpas_p2p_supported_freq_go(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 "
                           "frequency %d MHz", params->freq);
-       } else if (wpa_s->conf->p2p_oper_channel == 0 &&
-                  wpa_s->best_overall_freq > 0 &&
-                  p2p_supported_freq_go(wpa_s->global->p2p,
-                                        wpa_s->best_overall_freq) &&
-                  freq_included(wpa_s, channels, wpa_s->best_overall_freq)) {
+               goto success;
+       }
+
+       /* Try using best channels */
+       if (wpa_s->conf->p2p_oper_channel == 0 &&
+           wpa_s->best_overall_freq > 0 &&
+           wpas_p2p_supported_freq_go(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);
-       } else if (wpa_s->conf->p2p_oper_channel == 0 &&
-                  wpa_s->best_24_freq > 0 &&
-                  p2p_supported_freq_go(wpa_s->global->p2p,
-                                        wpa_s->best_24_freq) &&
-                  freq_included(wpa_s, channels, wpa_s->best_24_freq)) {
+               goto success;
+       }
+
+       if (wpa_s->conf->p2p_oper_channel == 0 &&
+           wpa_s->best_24_freq > 0 &&
+           wpas_p2p_supported_freq_go(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);
-       } else if (wpa_s->conf->p2p_oper_channel == 0 &&
-                  wpa_s->best_5_freq > 0 &&
-                  p2p_supported_freq_go(wpa_s->global->p2p,
-                                        wpa_s->best_5_freq) &&
-                  freq_included(wpa_s, channels, wpa_s->best_5_freq)) {
+               goto success;
+       }
+
+       if (wpa_s->conf->p2p_oper_channel == 0 &&
+           wpa_s->best_5_freq > 0 &&
+           wpas_p2p_supported_freq_go(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);
-       } else if ((pref_freq = p2p_get_pref_freq(wpa_s->global->p2p,
-                                                 channels))) {
-               params->freq = pref_freq;
+               goto success;
+       }
+
+       /* try using preferred channels */
+       cand = p2p_get_pref_freq(wpa_s->global->p2p, channels);
+       if (cand && wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+               params->freq = cand;
                wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz from preferred "
                           "channels", params->freq);
-       } else if (wpa_s->p2p_group_common_freqs) {
+               goto success;
+       }
+
+       /* Try using one of the group common freqs */
+       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];
+                       cand = wpa_s->p2p_group_common_freqs[i];
+                       if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
+                               params->freq = cand;
                                wpa_printf(MSG_DEBUG,
                                           "P2P: Use freq %d MHz common with the peer",
                                           params->freq);
-                               break;
+                               goto success;
                        }
                }
-       } else {
-               /* no preference, select some channel */
-               if (wpas_p2p_select_freq_no_pref(wpa_s, params, channels) < 0)
-                       return -1;
        }
 
-       freqs = os_calloc(wpa_s->num_multichan_concurrent,
-                         sizeof(struct wpa_used_freq_data));
-       if (!freqs)
-               return -1;
-
-       num = wpas_p2p_valid_oper_freqs(wpa_s, freqs,
-                                       wpa_s->num_multichan_concurrent);
-
-       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) {
-               params->freq = cand_freq;
-       } else if (!freq) {
-               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++) {
-                       if (freqs[i].freq == freq)
-                               break;
-               }
+       /* no preference, select some channel */
+       wpas_p2p_select_go_freq_no_pref(wpa_s, params, channels);
 
-               if (i == num) {
-                       if (wpas_p2p_num_unused_channels(wpa_s) <= 0) {
-                               if (freq)
-                                       wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on freq (%u MHz) as all the channels are in use", freq);
-                               os_free(freqs);
-                               return -1;
-                       } else {
-                               wpa_printf(MSG_DEBUG, "P2P: Use one of the free channels");
-                       }
-               }
+       if (params->freq == 0) {
+               wpa_printf(MSG_DEBUG, "P2P: did not find a freq for GO use");
+               goto fail;
        }
 
+success:
        os_free(freqs);
        return 0;
+fail:
+       os_free(freqs);
+       return -1;
 }