aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <j@w1.fi>2013-11-24 17:53:19 (GMT)
committerJouni Malinen <j@w1.fi>2013-11-24 19:20:14 (GMT)
commit202dec2a94695a696236ee5a2ad1be0905ccea14 (patch)
tree703ce919d9d95947a45b45cb07d6b191201657ed
parent73c00fd794630e150a8797ccfd5aea82f0a120d9 (diff)
downloadhostap-202dec2a94695a696236ee5a2ad1be0905ccea14.zip
hostap-202dec2a94695a696236ee5a2ad1be0905ccea14.tar.gz
hostap-202dec2a94695a696236ee5a2ad1be0905ccea14.tar.bz2
Add shared per-radio structure for wpa_supplicant
struct wpa_radio is used as a shared data structure between all struct wpa_supplicant instances that share the same physical radio. Signed-hostap: Jouni Malinen <j@w1.fi>
-rw-r--r--wpa_supplicant/wpa_supplicant.c66
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h15
2 files changed, 80 insertions, 1 deletions
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index a291aee..354a00e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2872,10 +2872,61 @@ int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
}
+static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
+ const char *rn)
+{
+ struct wpa_supplicant *iface = wpa_s->global->ifaces;
+ struct wpa_radio *radio;
+
+ while (rn && iface) {
+ radio = iface->radio;
+ if (radio && os_strcmp(rn, radio->name) == 0) {
+ wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
+ wpa_s->ifname, rn);
+ dl_list_add(&radio->ifaces, &wpa_s->radio_list);
+ return radio;
+ }
+ }
+
+ wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
+ wpa_s->ifname, rn ? rn : "N/A");
+ radio = os_zalloc(sizeof(*radio));
+ if (radio == NULL)
+ return NULL;
+
+ if (rn)
+ os_strlcpy(radio->name, rn, sizeof(radio->name));
+ dl_list_init(&radio->ifaces);
+ dl_list_add(&radio->ifaces, &wpa_s->radio_list);
+
+ return radio;
+}
+
+
+static void radio_remove_interface(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_radio *radio = wpa_s->radio;
+
+ if (!radio)
+ return;
+
+ wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
+ wpa_s->ifname, radio->name);
+ dl_list_del(&wpa_s->radio_list);
+ wpa_s->radio = NULL;
+
+ if (!dl_list_empty(&radio->ifaces))
+ return; /* Interfaces remain for this radio */
+
+ wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
+ os_free(radio);
+}
+
+
static int wpas_init_driver(struct wpa_supplicant *wpa_s,
struct wpa_interface *iface)
{
- const char *ifname, *driver;
+ const char *ifname, *driver, *rn;
driver = iface->driver;
next_driver:
@@ -2909,6 +2960,17 @@ next_driver:
os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
}
+ if (wpa_s->driver->get_radio_name)
+ rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
+ else
+ rn = NULL;
+ if (rn && rn[0] == '\0')
+ rn = NULL;
+
+ wpa_s->radio = radio_add_interface(wpa_s, rn);
+ if (wpa_s->radio == NULL)
+ return -1;
+
return 0;
}
@@ -3180,6 +3242,8 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_P2P */
+ radio_remove_interface(wpa_s);
+
if (wpa_s->drv_priv)
wpa_drv_deinit(wpa_s);
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index fb635e4..8cc813c 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -271,6 +271,19 @@ struct wpa_global {
/**
+ * struct wpa_radio - Internal data for per-radio information
+ *
+ * This structure is used to share data about configured interfaces
+ * (struct wpa_supplicant) that share the same physical radio, e.g., to allow
+ * better coordination of offchannel operations.
+ */
+struct wpa_radio {
+ char name[16]; /* from driver_ops get_radio_name() or empty if not
+ * available */
+ struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
+};
+
+/**
* offchannel_send_action_result - Result of offchannel send Action frame
*/
enum offchannel_send_action_result {
@@ -307,6 +320,8 @@ struct wpa_ssid_value {
*/
struct wpa_supplicant {
struct wpa_global *global;
+ struct wpa_radio *radio; /* shared radio context */
+ struct dl_list radio_list; /* list head: struct wpa_radio::ifaces */
struct wpa_supplicant *parent;
struct wpa_supplicant *next;
struct l2_packet_data *l2;