From 202dec2a94695a696236ee5a2ad1be0905ccea14 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 24 Nov 2013 19:53:19 +0200 Subject: [PATCH] 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 --- wpa_supplicant/wpa_supplicant.c | 66 ++++++++++++++++++++++++++++++- wpa_supplicant/wpa_supplicant_i.h | 15 +++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index a291aeea0..354a00e10 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 fb635e45b..8cc813c8b 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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;