[PATCH 5/6] wext: Use one global netlink socket instead of one per interface.

Ben Greear greearb at candelatech.com
Fri Dec 3 19:55:04 EST 2010


This saves a lot of work for the kernel and for wpa_supplicant
since each netlink message no longer has to be dupplicated for
each interface.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
:100644 100644 9f4edf8... 8166fdc... M	src/drivers/driver_wext.c
:100644 100644 89c13eb... 54b1702... M	src/drivers/driver_wext.h
 src/drivers/driver_wext.c |   99 +++++++++++++++++++++++++++++++++++----------
 src/drivers/driver_wext.h |    2 +-
 2 files changed, 78 insertions(+), 23 deletions(-)

diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 9f4edf8..8166fdc 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -45,6 +45,13 @@ static void wpa_driver_wext_disconnect(struct wpa_driver_wext_data *drv);
 static int wpa_driver_wext_set_auth_alg(void *priv, int auth_alg);
 
 
+/* One netlink instance per program, not per vif.
+ */
+static struct netlink_data *netlink = NULL;
+static int netlink_refcnt = 0;
+
+static struct wpa_driver_wext_data* all_driver_data = NULL;
+
 int wpa_driver_wext_set_auth_param(struct wpa_driver_wext_data *drv,
 				   int idx, u32 value)
 {
@@ -620,12 +627,18 @@ static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv,
 static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
 					      u8 *buf, size_t len)
 {
-	struct wpa_driver_wext_data *drv = ctx;
 	int attrlen, rta_len;
 	struct rtattr *attr;
+	struct wpa_driver_wext_data *drv = all_driver_data;
+	while (drv) {
+		if (wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) {
+			break;
+		}
+		drv = drv->next;
+	}
 
-	if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) {
-		wpa_msg(drv->ctx, MSG_DEBUG, "Ignore event for foreign ifindex %d",
+	if (!drv) {
+		wpa_msg(NULL, MSG_DEBUG, "Ignore event for foreign ifindex %d",
 			ifi->ifi_index);
 		return;
 	}
@@ -659,7 +672,7 @@ static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
 	if (drv->operstate == 1 &&
 	    (ifi->ifi_flags & (IFF_LOWER_UP | IFF_DORMANT)) == IFF_LOWER_UP &&
 	    !(ifi->ifi_flags & IFF_RUNNING))
-		netlink_send_oper_ifla(drv->netlink, drv->ifindex,
+		netlink_send_oper_ifla(netlink, drv->ifindex,
 				       -1, IF_OPER_UP);
 
 	attrlen = len;
@@ -684,9 +697,20 @@ static void wpa_driver_wext_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi,
 static void wpa_driver_wext_event_rtm_dellink(void *ctx, struct ifinfomsg *ifi,
 					      u8 *buf, size_t len)
 {
-	struct wpa_driver_wext_data *drv = ctx;
 	int attrlen, rta_len;
 	struct rtattr *attr;
+	struct wpa_driver_wext_data *drv = all_driver_data;
+	while (drv) {
+		if (wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, buf, len)) {
+			break;
+		}
+		drv = drv->next;
+	}
+	if (!drv) {
+		wpa_msg(NULL, MSG_DEBUG, "Ignore event for foreign ifindex %d",
+			ifi->ifi_index);
+		return;
+	}
 
 	attrlen = len;
 	attr = (struct rtattr *) buf;
@@ -770,7 +794,6 @@ static void wext_get_phy_name(struct wpa_driver_wext_data *drv)
 void * wpa_driver_wext_init(void *ctx, const char *ifname)
 {
 	struct wpa_driver_wext_data *drv;
-	struct netlink_config *cfg;
 	struct rfkill_config *rcfg;
 	char path[128];
 	struct stat buf;
@@ -794,16 +817,20 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
 		goto err1;
 	}
 
-	cfg = os_zalloc(sizeof(*cfg));
-	if (cfg == NULL)
-		goto err1;
-	cfg->ctx = drv;
-	cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink;
-	cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink;
-	drv->netlink = netlink_init(cfg);
-	if (drv->netlink == NULL) {
-		os_free(cfg);
-		goto err2;
+	if (netlink_refcnt == 0) {
+		struct netlink_config *cfg;
+		cfg = os_zalloc(sizeof(*cfg));
+		if (cfg == NULL)
+			goto err1;
+		cfg->ctx = NULL;
+		cfg->newlink_cb = wpa_driver_wext_event_rtm_newlink;
+		cfg->dellink_cb = wpa_driver_wext_event_rtm_dellink;
+		netlink = netlink_init(cfg);
+		if (netlink == NULL) {
+			os_free(cfg);
+			goto err2;
+		}
+		netlink_refcnt++;
 	}
 
 	rcfg = os_zalloc(sizeof(*rcfg));
@@ -826,11 +853,18 @@ void * wpa_driver_wext_init(void *ctx, const char *ifname)
 
 	wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 1);
 
+	drv->next = all_driver_data;
+	all_driver_data = drv;
+	
 	return drv;
 
 err3:
 	rfkill_deinit(drv->rfkill);
-	netlink_deinit(drv->netlink);
+	if (--netlink_refcnt <= 0) {
+		netlink_deinit(netlink);
+		netlink = NULL;
+		netlink_refcnt = 0;
+	}
 err2:
 	close(drv->ioctl_sock);
 err1:
@@ -900,7 +934,7 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
 		wpa_driver_wext_alternative_ifindex(drv, ifname2);
 	}
 
-	netlink_send_oper_ifla(drv->netlink, drv->ifindex,
+	netlink_send_oper_ifla(netlink, drv->ifindex,
 			       1, IF_OPER_DORMANT);
 
 	if (send_rfkill_event) {
@@ -922,7 +956,7 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
 void wpa_driver_wext_deinit(void *priv)
 {
 	struct wpa_driver_wext_data *drv = priv;
-
+	
 	wpa_driver_wext_set_auth_param(drv, IW_AUTH_WPA_ENABLED, 0);
 
 	eloop_cancel_timeout(wpa_driver_wext_scan_timeout, drv, drv->ctx);
@@ -933,8 +967,12 @@ void wpa_driver_wext_deinit(void *priv)
 	 */
 	wpa_driver_wext_disconnect(drv);
 
-	netlink_send_oper_ifla(drv->netlink, drv->ifindex, 0, IF_OPER_UP);
-	netlink_deinit(drv->netlink);
+	netlink_send_oper_ifla(netlink, drv->ifindex, 0, IF_OPER_UP);
+	if (--netlink_refcnt <= 0) {
+		netlink_deinit(netlink);
+		netlink = NULL;
+		netlink_refcnt = 0;
+	}
 	rfkill_deinit(drv->rfkill);
 
 	if (drv->mlme_sock >= 0)
@@ -947,6 +985,23 @@ void wpa_driver_wext_deinit(void *priv)
 		close(drv->mlme_sock);
 	os_free(drv->assoc_req_ies);
 	os_free(drv->assoc_resp_ies);
+
+	/* Unlink us from global driver data list. */
+	if (all_driver_data == drv)
+		all_driver_data = all_driver_data->next;
+	else {
+		struct wpa_driver_wext_data *prev = all_driver_data;
+		struct wpa_driver_wext_data *next = NULL;
+		if (prev)
+			next = prev->next;
+		while (next && (next != drv)) {
+			prev = next;
+			next = next->next;
+		}
+		if (next)
+			prev->next = next->next;
+	}
+	
 	os_free(drv);
 }
 
@@ -2284,7 +2339,7 @@ int wpa_driver_wext_set_operstate(void *priv, int state)
 	wpa_msg(drv->ctx, MSG_DEBUG, "%s: operstate %d->%d (%s)",
 		__func__, drv->operstate, state, state ? "UP" : "DORMANT");
 	drv->operstate = state;
-	return netlink_send_oper_ifla(drv->netlink, drv->ifindex, -1,
+	return netlink_send_oper_ifla(netlink, drv->ifindex, -1,
 				      state ? IF_OPER_UP : IF_OPER_DORMANT);
 }
 
diff --git a/src/drivers/driver_wext.h b/src/drivers/driver_wext.h
index 89c13eb..54b1702 100644
--- a/src/drivers/driver_wext.h
+++ b/src/drivers/driver_wext.h
@@ -19,7 +19,7 @@
 
 struct wpa_driver_wext_data {
 	void *ctx;
-	struct netlink_data *netlink;
+	struct wpa_driver_wext_data* next;
 	int ioctl_sock;
 	int mlme_sock;
 	char ifname[IFNAMSIZ + 1];
-- 
1.7.2.3



More information about the HostAP mailing list