[PATCH] hostapd: Process management frames only once per BSS

Simon Wunderlich sw at simonwunderlich.de
Mon Feb 10 10:04:17 EST 2014


From: Simon Wunderlich <simon at open-mesh.com>

At least in nl80211, management frames for broadcast, like probe
requests, are processed multiple times per BSS if multi-BSS is active.
In the case of probe requests, hostap will create multiple redundant
probe responses which are problematic when many BSS are on one channel.

This problem is caused by driver_nl80211 generating an event for
wpa_supplicant_event() for each BSS, and hostapd_mgmt_rx() calls
ieee802_11_mgmt() for each BSS too.

Fix this by processing broadcast events only for the BSS the driver
intended to. The behaviour is not changed for drivers not setting a BSS.

Signed-hostap: Simon Wunderlich <simon at open-mesh.com>
---
 src/ap/drv_callbacks.c       |    6 ++++++
 src/drivers/driver.h         |    6 ++++++
 src/drivers/driver_nl80211.c |    6 ++++--
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 9af9646..f62709a 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -678,6 +678,12 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
 		size_t i;
 		ret = 0;
 		for (i = 0; i < iface->num_bss; i++) {
+			/* if bss is set, driver will call this function for
+			 * each bss individually. */
+			if (rx_mgmt->drv_priv &&
+			    (iface->bss[i]->drv_priv != rx_mgmt->drv_priv))
+				continue;
+
 			if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame,
 					    rx_mgmt->frame_len, &fi) > 0)
 				ret = 1;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 7ad8576..24fdda2 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -3525,6 +3525,12 @@ union wpa_event_data {
 		const u8 *frame;
 		size_t frame_len;
 		u32 datarate;
+		/**
+		 * drv_priv - pointer to store driver private bss information,
+		 * 	used for comparison with struct hostapd_data->drv_priv
+		 * 	if not set to NULL.
+		 */
+		void *drv_priv;
 
 		/**
 		 * freq - Frequency (in MHz) on which the frame was received
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5978568..cfddf42 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1670,10 +1670,11 @@ static void mlme_timeout_event(struct wpa_driver_nl80211_data *drv,
 }
 
 
-static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
+static void mlme_event_mgmt(struct i802_bss *bss,
 			    struct nlattr *freq, struct nlattr *sig,
 			    const u8 *frame, size_t len)
 {
+	struct wpa_driver_nl80211_data *drv = bss->drv;
 	const struct ieee80211_mgmt *mgmt;
 	union wpa_event_data event;
 	u16 fc, stype;
@@ -1704,6 +1705,7 @@ static void mlme_event_mgmt(struct wpa_driver_nl80211_data *drv,
 	event.rx_mgmt.frame = frame;
 	event.rx_mgmt.frame_len = len;
 	event.rx_mgmt.ssi_signal = ssi_signal;
+	event.rx_mgmt.drv_priv = bss;
 	wpa_supplicant_event(drv->ctx, EVENT_RX_MGMT, &event);
 }
 
@@ -1928,7 +1930,7 @@ static void mlme_event(struct i802_bss *bss,
 					   nla_data(frame), nla_len(frame));
 		break;
 	case NL80211_CMD_FRAME:
-		mlme_event_mgmt(drv, freq, sig, nla_data(frame),
+		mlme_event_mgmt(bss, freq, sig, nla_data(frame),
 				nla_len(frame));
 		break;
 	case NL80211_CMD_FRAME_TX_STATUS:
-- 
1.7.10.4



More information about the HostAP mailing list