From 688556722c8b134d74b5041e74677e72237126c9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 8 Jan 2017 12:08:04 +0200 Subject: [PATCH] nl80211: More complete processing of connection quality monitor events This adds processing of beacon loss events and generation of an internal EVENT_BEACON_LOSS event based on them for wpa_supplicant processing. In addition, number of consecutively lost (not acknowledged) packets is now reported and TXE events are noted in the debug log. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 14 +++++++++- src/drivers/driver_common.c | 3 ++- src/drivers/driver_nl80211_event.c | 41 +++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 291d4d6ef..92688a35d 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1,6 +1,6 @@ /* * Driver interface definition - * Copyright (c) 2003-2015, Jouni Malinen + * Copyright (c) 2003-2017, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -4228,6 +4228,15 @@ enum wpa_event_type { * EVENT_P2P_LO_STOP - Notify that P2P listen offload is stopped */ EVENT_P2P_LO_STOP, + + /** + * EVENT_BEACON_LOSS - Beacon loss detected + * + * This event indicates that no Beacon frames has been received from + * the current AP. This may indicate that the AP is not anymore in + * range. + */ + EVENT_BEACON_LOSS, }; @@ -4817,9 +4826,12 @@ union wpa_event_data { /** * struct low_ack - Data for EVENT_STATION_LOW_ACK events * @addr: station address + * @num_packets: Number of packets lost (consecutive packets not + * acknowledged) */ struct low_ack { u8 addr[ETH_ALEN]; + u32 num_packets; } low_ack; /** diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index c7107ba89..b6bcbcad2 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -1,6 +1,6 @@ /* * Common driver-related functions - * Copyright (c) 2003-2011, Jouni Malinen + * Copyright (c) 2003-2017, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -81,6 +81,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(ACS_CHANNEL_SELECTED); E2S(DFS_CAC_STARTED); E2S(P2P_LO_STOP); + E2S(BEACON_LOSS); } return "UNKNOWN"; diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index de539b1c5..c18fc223f 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -1,6 +1,6 @@ /* * Driver interaction with Linux nl80211/cfg80211 - Event processing - * Copyright (c) 2002-2014, Jouni Malinen + * Copyright (c) 2002-2017, Jouni Malinen * Copyright (c) 2007, Johannes Berg * Copyright (c) 2009-2010, Atheros Communications * @@ -1132,6 +1132,10 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, [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 }, + [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 }, + [NL80211_ATTR_CQM_TXE_PKTS] = { .type = NLA_U32 }, + [NL80211_ATTR_CQM_TXE_INTVL] = { .type = NLA_U32 }, + [NL80211_ATTR_CQM_BEACON_LOSS_EVENT] = { .type = NLA_FLAG }, }; struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; enum nl80211_cqm_rssi_threshold_event event; @@ -1153,12 +1157,39 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, return; os_memcpy(ed.low_ack.addr, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN); + ed.low_ack.num_packets = + nla_get_u32(cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]); + wpa_printf(MSG_DEBUG, "nl80211: Packet loss event for " MACSTR + " (num_packets %u)", + MAC2STR(ed.low_ack.addr), ed.low_ack.num_packets); wpa_supplicant_event(drv->ctx, EVENT_STATION_LOW_ACK, &ed); return; } - if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL) + if (cqm[NL80211_ATTR_CQM_BEACON_LOSS_EVENT]) { + wpa_printf(MSG_DEBUG, "nl80211: Beacon loss event"); + wpa_supplicant_event(drv->ctx, EVENT_BEACON_LOSS, NULL); return; + } + + if (cqm[NL80211_ATTR_CQM_TXE_RATE] && + cqm[NL80211_ATTR_CQM_TXE_PKTS] && + cqm[NL80211_ATTR_CQM_TXE_INTVL] && + cqm[NL80211_ATTR_MAC]) { + wpa_printf(MSG_DEBUG, "nl80211: CQM TXE event for " MACSTR + " (rate: %u pkts: %u interval: %u)", + MAC2STR((u8 *) nla_data(cqm[NL80211_ATTR_MAC])), + nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_RATE]), + nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_PKTS]), + nla_get_u32(cqm[NL80211_ATTR_CQM_TXE_INTVL])); + return; + } + + if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] == NULL) { + wpa_printf(MSG_DEBUG, + "nl80211: Not a CQM RSSI threshold event"); + return; + } event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]); if (event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH) { @@ -1169,8 +1200,12 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, wpa_printf(MSG_DEBUG, "nl80211: Connection quality monitor " "event: RSSI low"); ed.signal_change.above_threshold = 0; - } else + } else { + wpa_printf(MSG_DEBUG, + "nl80211: Unknown CQM RSSI threshold event: %d", + event); return; + } res = nl80211_get_link_signal(drv, &sig); if (res == 0) {