[PATCH] supplicant: Enable sharing of scan results.

Ben Greear greearb
Tue Nov 16 15:39:16 PST 2010


When using multiple VIFs on the same physical radio,
we can share scan results with sibling interfaces.
This decreases time it takes to connect many VIFs.

This is currently only supported on Linux, in the WEXT
and NL drivers.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
:100644 100644 aef8554... 790b85a... M	src/drivers/driver.h
:100644 100644 51bf446... f4b1868... M	src/drivers/driver_nl80211.c
:100644 100644 f0de6aa... b6486a0... M	src/drivers/driver_wext.c
:100644 100644 6382bbb... 89c13eb... M	src/drivers/driver_wext.h
:100644 100644 39ac33b... 414b417... M	wpa_supplicant/events.c
:100644 100644 0a603af... 64f0ef5... M	wpa_supplicant/wpa_supplicant.c
 src/drivers/driver.h            |    7 ++++++
 src/drivers/driver_nl80211.c    |   34 ++++++++++++++++++++++++++++++
 src/drivers/driver_wext.c       |   32 ++++++++++++++++++++++++++++
 src/drivers/driver_wext.h       |    1 +
 wpa_supplicant/events.c         |   44 ++++++++++++++++++++++++++++++++++++--
 wpa_supplicant/wpa_supplicant.c |    4 +-
 6 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index aef8554..790b85a 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -718,6 +718,13 @@ struct wpa_driver_ops {
 	 */
 	int (*get_ssid)(void *priv, u8 *ssid);
 
+	/** Return the physical radio name for this device, if known.
+	 * The returned data must not be modified by the caller.
+	 * It is assumed that any interface that has the same radio
+	 * name as another is sharing the same physical radio.
+	 */
+	const char* (*get_radio_name)(void *priv);
+
 	/**
 	 * set_key - Configure encryption key
 	 * @ifname: Interface name (for multi-SSID/VLAN support)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 51bf446..f4b1868 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -18,6 +18,9 @@
 
 #include "includes.h"
 #include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <net/if.h>
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
@@ -104,6 +107,7 @@ struct i802_bss {
 	struct i802_bss *next;
 	int ifindex;
 	char ifname[IFNAMSIZ + 1];
+	char phyname[32];
 	unsigned int beacon_set:1;
 };
 
@@ -364,6 +368,12 @@ static int wpa_driver_nl80211_get_ssid(void *priv, u8 *ssid)
 	return drv->ssid_len;
 }
 
+static const char *wpa_driver_nl80211_get_radio_name(void *priv)
+{
+	struct i802_bss *bss = priv;
+	return bss->phyname;
+}
+
 
 static void wpa_driver_nl80211_event_link(struct wpa_driver_nl80211_data *drv,
 					  char *buf, size_t len, int del)
@@ -1673,6 +1683,29 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname)
 		return NULL;
 	}
 
+	/* Find phy (radio) to which this interface belongs. */
+	{
+		char buf[90];
+		int f;
+		int rv;
+
+		bss->phyname[0] = 0;
+		snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name", ifname);
+		f = open(buf, O_RDONLY);
+		if (f < 0)
+			wpa_printf(MSG_DEBUG, "Could not open file: %s, error: %s",
+				   buf, strerror(errno));
+		else {
+			rv = read(f, bss->phyname, sizeof(bss->phyname) - 1);
+			close(f);
+			if (rv < 0)
+				wpa_printf(MSG_DEBUG, "Could not read file: %s  error: %s",
+					   buf, strerror(errno));
+			else
+				bss->phyname[rv] = 0;
+		}
+	}
+
 	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
 	if (drv->ioctl_sock < 0) {
 		perror("socket(PF_INET,SOCK_DGRAM)");
@@ -5952,6 +5985,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.desc = "Linux nl80211/cfg80211",
 	.get_bssid = wpa_driver_nl80211_get_bssid,
 	.get_ssid = wpa_driver_nl80211_get_ssid,
+	.get_radio_name = wpa_driver_nl80211_get_radio_name,
 	.set_key = wpa_driver_nl80211_set_key,
 	.scan2 = wpa_driver_nl80211_scan,
 	.get_scan_results2 = wpa_driver_nl80211_get_scan_results,
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index f0de6aa..b6486a0 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -20,7 +20,9 @@
 
 #include "includes.h"
 #include <sys/ioctl.h>
+#include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #include <net/if_arp.h>
 
 #include "wireless_copy.h"
@@ -751,6 +753,29 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
 		drv->cfg80211 = 1;
 	}
 
+	/* Find phy (radio) to which this interface belongs. */
+	{
+		char buf[90];
+		int f;
+		int rv;
+
+		drv->phyname[0] = 0;
+		snprintf(buf, sizeof(buf) - 1, "/sys/class/net/%s/phy80211/name", ifname);
+		f = open(buf, O_RDONLY);
+		if (f < 0)
+			wpa_printf(MSG_DEBUG, "Could not open file: %s, error: %s",
+				   buf, strerror(errno));
+		else {
+			rv = read(f, drv->phyname, sizeof(drv->phyname) - 1);
+			close(f);
+			if (rv < 0)
+				wpa_printf(MSG_DEBUG, "Could not read file: %s  error: %s",
+					   buf, strerror(errno));
+			else
+				drv->phyname[rv] = 0;
+		}
+	}
+
 	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
 	if (drv->ioctl_sock < 0) {
 		perror("socket(PF_INET,SOCK_DGRAM)");
@@ -2248,6 +2273,12 @@ int wpa_driver_wext_set_operstate(void *priv, int state)
 				      state ? IF_OPER_UP : IF_OPER_DORMANT);
 }
 
+static const char *wpa_driver_wext_get_radio_name(void *priv)
+{
+	struct wpa_driver_wext_data *drv = priv;
+	return drv->phyname;
+}
+
 
 int wpa_driver_wext_get_version(struct wpa_driver_wext_data *drv)
 {
@@ -2260,6 +2291,7 @@ const struct wpa_driver_ops wpa_driver_wext_ops = {
 	.desc = "Linux wireless extensions (generic)",
 	.get_bssid = wpa_driver_wext_get_bssid,
 	.get_ssid = wpa_driver_wext_get_ssid,
+	.get_radio_name = wpa_driver_wext_get_radio_name,
 	.set_key = wpa_driver_wext_set_key,
 	.set_countermeasures = wpa_driver_wext_set_countermeasures,
 	.scan2 = wpa_driver_wext_scan,
diff --git a/src/drivers/driver_wext.h b/src/drivers/driver_wext.h
index 6382bbb..89c13eb 100644
--- a/src/drivers/driver_wext.h
+++ b/src/drivers/driver_wext.h
@@ -23,6 +23,7 @@ struct wpa_driver_wext_data {
 	int ioctl_sock;
 	int mlme_sock;
 	char ifname[IFNAMSIZ + 1];
+	char phyname[32];
 	int ifindex;
 	int ifindex2;
 	int if_removed;
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 39ac33b..414b417 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -810,8 +810,7 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
 	return 1;
 }
 
-
-static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
+static void _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
 					      union wpa_event_data *data)
 {
 	struct wpa_bss *selected;
@@ -851,7 +850,7 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
 		return;
 	}
 
-	wpa_printf(MSG_DEBUG, "New scan results available");
+	wpa_printf(MSG_DEBUG, "%s: New scan results available", wpa_s->ifname);
 	wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
 	wpas_notify_scan_results(wpa_s);
 
@@ -910,6 +909,45 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
 		}
 	}
 }
+
+static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
+					      union wpa_event_data *data)
+{
+	const char* rn = NULL;
+	_wpa_supplicant_event_scan_results(wpa_s, data);
+	
+	if (wpa_s->driver->get_radio_name)
+		rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
+
+	if (rn && rn[0]) {
+		struct wpa_supplicant *ifs;
+		wpa_printf(MSG_DEBUG, "%s: Checking for peer VIFS in event_scan_results.",
+			   wpa_s->ifname);
+
+		/* Check other interfaces to see if they have the same
+		 * radio-name.  If so, they get updated with this same scan info.
+		 */
+		ifs = wpa_s->global->ifaces;
+		while (ifs) {
+			if ((ifs == wpa_s) ||
+			    !ifs->driver->get_radio_name)
+				ifs = ifs->next;
+			else {
+				const char* rn2;
+				rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
+				if (rn2 && (strcmp(rn, rn2) == 0)) {
+					wpa_printf(MSG_DEBUG,
+						   "%s: Updating scan results from sibling.",
+						   ifs->ifname);
+					/* Got a winner! */
+					_wpa_supplicant_event_scan_results(ifs, data);
+				}
+				ifs = ifs->next;
+			}
+		}
+	}
+}
+
 #endif /* CONFIG_NO_SCAN_PROCESSING */
 
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 0a603af..64f0ef5 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -530,8 +530,8 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
 {
 	enum wpa_states old_state = wpa_s->wpa_state;
 
-	wpa_printf(MSG_DEBUG, "State: %s -> %s",
-		   wpa_supplicant_state_txt(wpa_s->wpa_state),
+	wpa_printf(MSG_DEBUG, "%s: State: %s -> %s",
+		   wpa_s->ifname, wpa_supplicant_state_txt(wpa_s->wpa_state),
 		   wpa_supplicant_state_txt(state));
 
 	if (state != WPA_SCANNING)
-- 
1.7.2.3




More information about the Hostap mailing list