P2P: Use preferred frequency list from the local driver
authorAhmad Kholaif <akholaif@qca.qualcomm.com>
Fri, 24 Jul 2015 00:39:45 +0000 (17:39 -0700)
committerJouni Malinen <j@w1.fi>
Thu, 30 Jul 2015 19:13:48 +0000 (22:13 +0300)
If the driver supports the preferred frequency list extension, use this
information from the driver when no explicitly configured preference
list (p2p_pref_chan) is present for P2P operating channel selection.
This commit adds this for GO Negotiation and Invitation use cases.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_i.h
wpa_supplicant/p2p_supplicant.c

index b106fcf..8cf0b9c 100644 (file)
@@ -5383,3 +5383,20 @@ void p2p_go_neg_wait_timeout(void *eloop_ctx, void *timeout_ctx)
                "Timeout on waiting peer to become ready for GO Negotiation");
        p2p_go_neg_failed(p2p, -1);
 }
+
+
+void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
+                               const unsigned int *pref_freq_list,
+                               unsigned int size)
+{
+       unsigned int i;
+
+       if (size > P2P_MAX_PREF_CHANNELS)
+               size = P2P_MAX_PREF_CHANNELS;
+       p2p->num_pref_freq = size;
+       for (i = 0; i < size; i++) {
+               p2p->pref_freq_list[i] = pref_freq_list[i];
+               p2p_dbg(p2p, "Own preferred frequency list[%u]=%u MHz",
+                       i, p2p->pref_freq_list[i]);
+       }
+}
index 4b1c1f1..15b093a 100644 (file)
 #define P2PS_FEATURE_CAPAB_CPT_MAX 2
 
 /**
+ * P2P_MAX_PREF_CHANNELS - Maximum number of preferred channels
+ */
+#define P2P_MAX_PREF_CHANNELS 100
+
+/**
  * P2P_MAX_REG_CLASSES - Maximum number of regulatory classes
  */
 #define P2P_MAX_REG_CLASSES 10
@@ -2302,4 +2307,8 @@ struct p2ps_advertisement * p2p_get_p2ps_adv_list(struct p2p_data *p2p);
  */
 void p2p_expire_peers(struct p2p_data *p2p);
 
+void p2p_set_own_pref_freq_list(struct p2p_data *p2p,
+                               const unsigned int *pref_freq_list,
+                               unsigned int size);
+
 #endif /* P2P_H */
index f4b2405..3d6bc70 100644 (file)
@@ -538,6 +538,9 @@ struct p2p_data {
        u16 authorized_oob_dev_pw_id;
 
        struct wpabuf **vendor_elem;
+
+       unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS];
+       unsigned int num_pref_freq;
 };
 
 /**
index 8f90e38..9c11b9a 100644 (file)
@@ -4792,11 +4792,16 @@ static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
 
 
 static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
-                               int *force_freq, int *pref_freq, int go)
+                               int *force_freq, int *pref_freq, int go,
+                               unsigned int *pref_freq_list,
+                               unsigned int *num_pref_freq)
 {
        struct wpa_used_freq_data *freqs;
        int res, best_freq, num_unused;
-       unsigned int freq_in_use = 0, num, i;
+       unsigned int freq_in_use = 0, num, i, max_pref_freq;
+
+       max_pref_freq = *num_pref_freq;
+       *num_pref_freq = 0;
 
        freqs = os_calloc(wpa_s->num_multichan_concurrent,
                          sizeof(struct wpa_used_freq_data));
@@ -4861,6 +4866,47 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
 
        best_freq = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num);
 
+       if (!wpa_s->conf->num_p2p_pref_chan && *pref_freq == 0) {
+               enum wpa_driver_if_type iface_type;
+
+               if (go)
+                       iface_type = WPA_IF_P2P_GO;
+               else
+                       iface_type = WPA_IF_P2P_CLIENT;
+
+               wpa_printf(MSG_DEBUG, "P2P: best_freq=%d, go=%d",
+                          best_freq, go);
+
+               res = wpa_drv_get_pref_freq_list(wpa_s, iface_type,
+                                                &max_pref_freq,
+                                                pref_freq_list);
+               if (!res && max_pref_freq > 0) {
+                       *num_pref_freq = max_pref_freq;
+                       i = 0;
+                       while (wpas_p2p_disallowed_freq(wpa_s->global,
+                                                       pref_freq_list[i]) &&
+                              i < *num_pref_freq) {
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: preferred_freq_list[%d]=%d is disallowed",
+                                          i, pref_freq_list[i]);
+                               i++;
+                       }
+                       if (i != *num_pref_freq) {
+                               best_freq = pref_freq_list[i];
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: Using preferred_freq_list[%d]=%d",
+                                          i, best_freq);
+                       } else {
+                               wpa_printf(MSG_DEBUG,
+                                          "P2P: All driver preferred frequencies are disallowed for P2P use");
+                               *num_pref_freq = 0;
+                       }
+               } else {
+                       wpa_printf(MSG_DEBUG,
+                                  "P2P: No preferred frequency list available");
+               }
+       }
+
        /* We have a candidate frequency to use */
        if (best_freq > 0) {
                if (*pref_freq == 0 && num_unused > 0) {
@@ -4925,6 +4971,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        enum wpa_driver_if_type iftype;
        const u8 *if_addr;
        struct wpa_ssid *ssid = NULL;
+       unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
 
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
                return -1;
@@ -5001,13 +5048,16 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                return ret;
        }
 
+       size = P2P_MAX_PREF_CHANNELS;
        res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
-                                  go_intent == 15);
+                                  go_intent == 15, pref_freq_list, &size);
        if (res)
                return res;
        wpas_p2p_set_own_freq_preference(wpa_s,
                                         force_freq ? force_freq : pref_freq);
 
+       p2p_set_own_pref_freq_list(wpa_s->global->p2p, pref_freq_list, size);
+
        wpa_s->create_p2p_iface = wpas_p2p_create_iface(wpa_s);
 
        if (wpa_s->create_p2p_iface) {
@@ -6190,6 +6240,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        int force_freq = 0;
        int res;
        int no_pref_freq_given = pref_freq == 0;
+       unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
 
        wpa_s->global->p2p_invite_group = NULL;
        if (peer_addr)
@@ -6223,8 +6274,10 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
        }
        wpa_s->pending_invite_ssid_id = ssid->id;
 
+       size = P2P_MAX_PREF_CHANNELS;
        res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
-                                  role == P2P_INVITE_ROLE_GO);
+                                  role == P2P_INVITE_ROLE_GO,
+                                  pref_freq_list, &size);
        if (res)
                return res;
 
@@ -6263,6 +6316,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
        int persistent;
        int freq = 0, force_freq = 0, pref_freq = 0;
        int res;
+       unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
 
        wpa_s->p2p_persistent_go_freq = 0;
        wpa_s->p2p_go_ht40 = 0;
@@ -6314,8 +6368,10 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
        if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
                return -1;
 
+       size = P2P_MAX_PREF_CHANNELS;
        res = wpas_p2p_setup_freqs(wpa_s, freq, &force_freq, &pref_freq,
-                                  role == P2P_INVITE_ROLE_ACTIVE_GO);
+                                  role == P2P_INVITE_ROLE_ACTIVE_GO,
+                                  pref_freq_list, &size);
        if (res)
                return res;
        wpas_p2p_set_own_freq_preference(wpa_s, force_freq);