]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add shared per-radio structure for wpa_supplicant
authorJouni Malinen <j@w1.fi>
Sun, 24 Nov 2013 17:53:19 +0000 (19:53 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 24 Nov 2013 19:20:14 +0000 (21:20 +0200)
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>

wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index a291aeea0a148a464b997cdb9cf205b4df82ddc2..354a00e10bee676543aebda1296ffbfddd42cc66 100644 (file)
@@ -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);
 
index fb635e45bfd948eaff0226ef049a85c1dc8b5d71..8cc813c8bfd6e9c1e8dbd340c7fb6ad57468da9a 100644 (file)
@@ -270,6 +270,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
  */
@@ -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;