Change share_vif_oper_freq() to handle multiple freqs
authorIlan Peer <ilan.peer@intel.com>
Sun, 21 Jul 2013 17:03:53 +0000 (20:03 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 21 Jul 2013 17:03:53 +0000 (20:03 +0300)
There are devices that can operate several channels concurrently.
Change shared_vif_oper_freq() to get_shared_radio_freqs() that can
return an array of frequencies currently used by all the virtual
interfaces that share the same radio.

In addition, move it to wpa_supplicant.c, so it can be used by other
modules.

Signed-hostap: Ilan Peer <ilan.peer@intel.com>
Signed-hostap: David Spinadel <david.spinadel@intel.com>

wpa_supplicant/scan.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 75548e2..04e8fa6 100644 (file)
@@ -483,44 +483,6 @@ static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s)
 
 #endif /* CONFIG_P2P */
 
-/*
- * Find the operating frequency of any other virtual interface that is using
- * the same radio concurrently.
- */
-static int shared_vif_oper_freq(struct wpa_supplicant *wpa_s)
-{
-       const char *rn, *rn2;
-       struct wpa_supplicant *ifs;
-       u8 bssid[ETH_ALEN];
-
-       if (!wpa_s->driver->get_radio_name)
-               return -1;
-
-       rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
-       if (rn == NULL || rn[0] == '\0')
-               return -1;
-
-       for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
-               if (ifs == wpa_s || !ifs->driver->get_radio_name)
-                       continue;
-
-               rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
-               if (!rn2 || os_strcmp(rn, rn2) != 0)
-                       continue;
-
-               if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
-                       continue;
-
-               if (ifs->current_ssid->mode == WPAS_MODE_AP ||
-                   ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
-                       return ifs->current_ssid->frequency;
-               if (wpa_drv_get_bssid(ifs, bssid) == 0)
-                       return ifs->assoc_freq;
-       }
-
-       return 0;
-}
-
 
 static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
                                          u16 num_modes,
@@ -815,14 +777,19 @@ ssid_list_set:
 
        /* Use current associated channel? */
        if (wpa_s->conf->scan_cur_freq && !params.freqs) {
-               int freq = shared_vif_oper_freq(wpa_s);
-               if (freq > 0) {
-                       wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current "
-                               "operating channel (%d MHz) since "
-                               "scan_cur_freq is enabled", freq);
-                       params.freqs = os_zalloc(sizeof(int) * 2);
-                       if (params.freqs)
-                               params.freqs[0] = freq;
+               unsigned int num = wpa_s->num_multichan_concurrent;
+
+               params.freqs = os_calloc(num + 1, sizeof(int));
+               if (params.freqs) {
+                       num = get_shared_radio_freqs(wpa_s, params.freqs, num);
+                       if (num > 0) {
+                               wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the "
+                                       "current operating channels since "
+                                       "scan_cur_freq is enabled");
+                       } else {
+                               os_free(params.freqs);
+                               params.freqs = NULL;
+                       }
                }
        }
 
@@ -860,18 +827,19 @@ scan:
        if (wpa_s->scan_for_connection && scan_req == NORMAL_SCAN_REQ &&
            !scan_params->freqs && !params.freqs &&
            wpas_is_p2p_prioritized(wpa_s) &&
-           !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) &&
            wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE &&
            non_p2p_network_enabled(wpa_s)) {
-               int freq = shared_vif_oper_freq(wpa_s);
-               if (freq > 0) {
-                       wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only the current "
-                               "operating channel (%d MHz) since driver does "
-                               "not support multi-channel concurrency", freq);
-                       params.freqs = os_zalloc(sizeof(int) * 2);
-                       if (params.freqs)
-                               params.freqs[0] = freq;
-                       scan_params->freqs = params.freqs;
+               unsigned int num = wpa_s->num_multichan_concurrent;
+
+               params.freqs = os_calloc(num + 1, sizeof(int));
+               if (params.freqs) {
+                       num = get_shared_radio_freqs(wpa_s, params.freqs, num);
+                       if (num > 0 && num == wpa_s->num_multichan_concurrent) {
+                               wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used");
+                       } else {
+                               os_free(params.freqs);
+                               params.freqs = NULL;
+                       }
                }
        }
 #endif /* CONFIG_P2P */
index 13b6757..62417ac 100644 (file)
@@ -3942,3 +3942,67 @@ int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s)
 
        return 0;
 }
+
+
+/*
+ * Find the operating frequencies of any of the virtual interfaces that
+ * are using the same radio as the current interface.
+ */
+int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
+                          int *freq_array, unsigned int len)
+{
+       const char *rn, *rn2;
+       struct wpa_supplicant *ifs;
+       u8 bssid[ETH_ALEN];
+       int freq;
+       unsigned int idx = 0, i;
+
+       os_memset(freq_array, 0, sizeof(int) * len);
+
+       /* First add the frequency of the local interface */
+       if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
+               if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
+                   wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
+                       freq_array[idx++] = wpa_s->current_ssid->frequency;
+               else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
+                       freq_array[idx++] = wpa_s->assoc_freq;
+       }
+
+       /* If get_radio_name is not supported, use only the local freq */
+       if (!wpa_s->driver->get_radio_name)
+               return idx;
+
+       rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
+       if (rn == NULL || rn[0] == '\0')
+               return idx;
+
+       for (ifs = wpa_s->global->ifaces, idx = 0; ifs && idx < len;
+            ifs = ifs->next) {
+               if (wpa_s == ifs || !ifs->driver->get_radio_name)
+                       continue;
+
+               rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
+               if (!rn2 || os_strcmp(rn, rn2) != 0)
+                       continue;
+
+               if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
+                       continue;
+
+               if (ifs->current_ssid->mode == WPAS_MODE_AP ||
+                   ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
+                       freq = ifs->current_ssid->frequency;
+               else if (wpa_drv_get_bssid(ifs, bssid) == 0)
+                       freq = ifs->assoc_freq;
+               else
+                       continue;
+
+               /* Hold only distinct freqs */
+               for (i = 0; i < idx; i++)
+                       if (freq_array[i] == freq)
+                               break;
+
+               if (i == idx)
+                       freq_array[idx++] = freq;
+       }
+       return idx;
+}
index 7597908..0858bbc 100644 (file)
@@ -862,4 +862,7 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
 
 int wpas_init_ext_pw(struct wpa_supplicant *wpa_s);
 
+int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
+                          int *freq_array, unsigned int len);
+
 #endif /* WPA_SUPPLICANT_I_H */