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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2017-01-08 12:08:04 +02:00
parent fadaa7b613
commit 688556722c
3 changed files with 53 additions and 5 deletions

View File

@ -1,6 +1,6 @@
/*
* Driver interface definition
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
*
* 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;
/**

View File

@ -1,6 +1,6 @@
/*
* Common driver-related functions
* Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
*
* 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";

View File

@ -1,6 +1,6 @@
/*
* Driver interaction with Linux nl80211/cfg80211 - Event processing
* Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
* Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
* 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) {