[RFC] wpa_s/hostapd/nl80211: disassociate stations with low ACK
Johannes Berg
johannes
Mon Nov 29 03:40:47 PST 2010
From: Johannes Berg <johannes.berg at intel.com>
The nl80211 driver can report low ACK condition
(in fact it reports complete loss right now only).
Use that, along with a config option, to disassoc
stations.
Signed-off-by: Johannes Berg <johannes.berg at intel.com>
---
Needs an update to nl80211_copy.h!
hostapd/config_file.c | 2 ++
src/ap/ap_config.h | 2 ++
src/ap/drv_callbacks.c | 19 +++++++++++++++++++
src/ap/hostapd.h | 1 +
src/common/ieee802_11_defs.h | 2 ++
src/drivers/driver.h | 19 ++++++++++++++++++-
src/drivers/driver_nl80211.c | 14 ++++++++++++--
wpa_supplicant/ap.c | 2 ++
wpa_supplicant/config.c | 3 ++-
wpa_supplicant/config.h | 5 +++++
wpa_supplicant/events.c | 7 +++++++
11 files changed, 72 insertions(+), 4 deletions(-)
--- hostap.orig/src/drivers/driver.h 2010-11-29 12:20:53.000000000 +0100
+++ hostap/src/drivers/driver.h 2010-11-29 12:21:23.000000000 +0100
@@ -2266,7 +2266,16 @@ enum wpa_event_type {
* (e.g., based on RSSI or channel use). This information can be used
* to improve channel selection for a new AP/P2P group.
*/
- EVENT_BEST_CHANNEL
+ EVENT_BEST_CHANNEL,
+
+ /**
+ * EVENT_STATION_LOW_ACK
+ *
+ * Driver generates this event whenever it detected that a particular
+ * station was lost. Detection can be through massive transmission
+ * failures for example.
+ */
+ EVENT_STATION_LOW_ACK
};
@@ -2700,6 +2709,14 @@ union wpa_event_data {
int freq_5;
int freq_overall;
} best_chan;
+
+ /**
+ * struct low_ack - Data for EVENT_STATION_LOW_ACK events
+ * @addr: station address
+ */
+ struct low_ack {
+ u8 addr[ETH_ALEN];
+ } low_ack;
};
/**
--- hostap.orig/src/drivers/driver_nl80211.c 2010-11-29 12:20:53.000000000 +0100
+++ hostap/src/drivers/driver_nl80211.c 2010-11-29 12:21:23.000000000 +0100
@@ -1170,6 +1170,7 @@ static void nl80211_cqm_event(struct wpa
[NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
[NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U8 },
[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
+ [NL80211_ATTR_CQM_PKT_LOSS_EVENT] = { .type = NLA_U32 },
};
struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
enum nl80211_cqm_rssi_threshold_event event;
@@ -1184,12 +1185,21 @@ static void nl80211_cqm_event(struct wpa
return;
}
+ os_memset(&ed, 0, sizeof(ed));
+
+ if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {
+ if (!tb[NL80211_ATTR_MAC])
+ return;
+ memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]),
+ ETH_ALEN);
+ wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed);
+ return;
+ }
+
if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL)
return;
event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
- os_memset(&ed, 0, sizeof(ed));
-
if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) {
wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor "
"event: RSSI high");
--- hostap.orig/hostapd/config_file.c 2010-11-29 12:20:52.000000000 +0100
+++ hostap/hostapd/config_file.c 2010-11-29 12:21:23.000000000 +0100
@@ -2032,6 +2032,8 @@ struct hostapd_config * hostapd_config_r
else
bss->p2p &= ~P2P_ALLOW_CROSS_CONNECTION;
#endif /* CONFIG_P2P_MANAGER */
+ } else if (os_strcmp(buf, "disassoc_low_ack")) {
+ bss->disassoc_low_ack = atoi(pos);
} else {
wpa_printf(MSG_ERROR, "Line %d: unknown configuration "
"item '%s'", line, buf);
--- hostap.orig/src/ap/ap_config.h 2010-11-29 12:20:52.000000000 +0100
+++ hostap/src/ap/ap_config.h 2010-11-29 12:21:23.000000000 +0100
@@ -323,6 +323,8 @@ struct hostapd_bss_config {
#define P2P_MANAGE BIT(3)
#define P2P_ALLOW_CROSS_CONNECTION BIT(4)
int p2p;
+
+ int disassoc_low_ack;
};
--- hostap.orig/src/ap/drv_callbacks.c 2010-11-29 12:20:52.000000000 +0100
+++ hostap/src/ap/drv_callbacks.c 2010-11-29 12:27:35.000000000 +0100
@@ -231,6 +231,20 @@ void hostapd_notif_disassoc(struct hosta
}
+void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
+{
+ struct sta_info *sta = ap_get_sta(hapd, addr);
+
+ if (!sta)
+ return;
+
+ hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
+ if (sta)
+ ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
+
+}
+
+
#ifdef HOSTAPD
#ifdef NEED_AP_MLME
@@ -500,6 +514,11 @@ void wpa_supplicant_event(void *ctx, enu
if (data)
hostapd_notif_disassoc(hapd, data->deauth_info.addr);
break;
+ case EVENT_STATION_LOW_ACK:
+ if (!data)
+ break;
+ hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
+ break;
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;
--- hostap.orig/wpa_supplicant/ap.c 2010-11-29 12:20:53.000000000 +0100
+++ hostap/wpa_supplicant/ap.c 2010-11-29 12:21:23.000000000 +0100
@@ -191,6 +191,8 @@ static int wpa_supplicant_conf_ap(struct
else
bss->max_num_sta = wpa_s->conf->max_num_sta;
+ bss->disassoc_low_ack = wpa_s->conf->disassoc_low_ack;
+
return 0;
}
--- hostap.orig/wpa_supplicant/config.c 2010-11-29 12:20:53.000000000 +0100
+++ hostap/wpa_supplicant/config.c 2010-11-29 12:21:23.000000000 +0100
@@ -2408,7 +2408,8 @@ static const struct global_parse_data gl
{ FUNC(country), CFG_CHANGED_COUNTRY },
{ INT(bss_max_count), 0 },
{ INT_RANGE(filter_ssids, 0, 1), 0 },
- { INT(max_num_sta), 0 }
+ { INT(max_num_sta), 0 },
+ { INT_RANGE(disassoc_low_ack, 0, 1), 0 }
};
#undef FUNC
--- hostap.orig/wpa_supplicant/config.h 2010-11-29 12:20:53.000000000 +0100
+++ hostap/wpa_supplicant/config.h 2010-11-29 12:21:23.000000000 +0100
@@ -400,6 +400,11 @@ struct wpa_config {
* changed_parameters - Bitmap of changed parameters since last update
*/
unsigned int changed_parameters;
+
+ /**
+ * disassoc_low_ack - disassocenticate stations with massive packet loss
+ */
+ int disassoc_low_ack;
};
--- hostap.orig/src/common/ieee802_11_defs.h 2010-11-29 12:20:53.000000000 +0100
+++ hostap/src/common/ieee802_11_defs.h 2010-11-29 12:21:23.000000000 +0100
@@ -174,6 +174,8 @@
#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24
+/* IEEE 802.11e */
+#define WLAN_REASON_DISASSOC_LOW_ACK 34
/* Information Element IDs */
--- hostap.orig/src/ap/hostapd.h 2010-11-29 12:27:09.000000000 +0100
+++ hostap/src/ap/hostapd.h 2010-11-29 12:27:34.000000000 +0100
@@ -247,5 +247,6 @@ void hostapd_prune_associations(struct h
int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
const u8 *ie, size_t ielen);
void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr);
+void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr);
#endif /* HOSTAPD_H */
--- hostap.orig/wpa_supplicant/events.c 2010-11-29 12:25:02.000000000 +0100
+++ hostap/wpa_supplicant/events.c 2010-11-29 12:28:35.000000000 +0100
@@ -1970,6 +1970,13 @@ void wpa_supplicant_event(void *ctx, enu
data->best_chan.freq_overall);
#endif /* CONFIG_P2P */
break;
+ case EVENT_STATION_LOW_ACK:
+#ifdef CONFIG_AP
+ if (wpa_s->ap_iface && data)
+ hostapd_event_sta_low_ack(wpa_s->ap_iface->bss[0],
+ data->low_ack.addr);
+#endif /* CONFIG_AP */
+ break;
default:
wpa_printf(MSG_INFO, "Unknown event %d", event);
break;
More information about the Hostap
mailing list