2020-01-03 10:37:12

by Nicolas Cavallari

[permalink] [raw]
Subject: [PATCH v2 0/2] Allow userspace to reset IBSS stations to fix aggregation issue

I encountered the same issue in an IBSS-RSN network, where quick reboot
of a station would cause issues with aggregation because the kernel is
not aware of the reboot.

I figured out that since wpa_supplicant already detect reboots, the
simplest way to fix it would be for wpa_supplicant to reset the entire
state of the station in the kernel, instead of just resetting keys and
port.

This means extending NL80211_CMD_DEL_STATION to work in IBSS mode too,
just like it does in mesh point mode.

Changes:
v2: Use a nl80211 feature flag instead of patching every driver.



2020-01-03 10:37:12

by Nicolas Cavallari

[permalink] [raw]
Subject: [PATCH v2 2/2] mac80211: Allow deleting stations in ibss mode to reset their state.

Set the NL80211_EXT_FEATURE_DEL_IBSS_STA if the interface support IBSS
mode, so that stations can be resetted from user space.

mac80211 already deletes stations by itself, so mac80211 drivers must
already support this.

This has been successfuly tested with ath9k.

Signed-off-by: Nicolas Cavallari <[email protected]>
---
net/mac80211/main.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 4c2b5ba3ac09..02f36590c01d 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1065,6 +1065,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
NL80211_EXT_FEATURE_EXT_KEY_ID);
}

+ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_ADHOC))
+ wiphy_ext_feature_set(local->hw.wiphy,
+ NL80211_EXT_FEATURE_DEL_IBSS_STA);
+
/*
* Calculate scan IE length -- we need this to alloc
* memory and to subtract from the driver limit. It
--
2.25.0.rc0

2020-01-13 11:47:47

by Koen Vandeputte

[permalink] [raw]
Subject: Re: [PATCH v2 0/2] Allow userspace to reset IBSS stations to fix aggregation issue


On 03.01.20 11:34, Nicolas Cavallari wrote:
> I encountered the same issue in an IBSS-RSN network, where quick reboot
> of a station would cause issues with aggregation because the kernel is
> not aware of the reboot.
>
> I figured out that since wpa_supplicant already detect reboots, the
> simplest way to fix it would be for wpa_supplicant to reset the entire
> state of the station in the kernel, instead of just resetting keys and
> port.
>
> This means extending NL80211_CMD_DEL_STATION to work in IBSS mode too,
> just like it does in mesh point mode.
>
> Changes:
> v2: Use a nl80211 feature flag instead of patching every driver.
>
>
I'm more than happy to give this a thorough test on dozens of devices
offshore

which I suspect are suffering from this issue as they sail in-out of range,

but as a new flag is defined in nl80211.h, is anything additional
required at wpa_sup side to use this?

If yes, please also provide a patch for that to me directly. (based on
>= v2.9)

Thanks,

Koen

2020-01-14 09:28:18

by Nicolas Cavallari

[permalink] [raw]
Subject: Re: [PATCH v2 0/2] Allow userspace to reset IBSS stations to fix aggregation issue

On 13/01/2020 12:45, Koen Vandeputte wrote:
> I'm more than happy to give this a thorough test on dozens of devices offshore
>
> which I suspect are suffering from this issue as they sail in-out of range,
>
> but as a new flag is defined in nl80211.h, is anything additional required at wpa_sup side to use this?

I use this blunt patch for now, until this issue settles.

Note that it only work in IBSS RSN case, because that's the only mode
where wpa_supplicant registers for auth frames (and thus the kernel doesn't
handle them) and does reboot detection.

diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 37368c4cb..026750161 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -353,7 +353,11 @@ static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
static void ibss_rsn_disconnect(void *ctx, const u8 *addr, u16 reason)
{
struct ibss_rsn *ibss_rsn = ctx;
- wpa_drv_sta_deauth(ibss_rsn->wpa_s, addr, reason);
+ struct ibss_rsn_peer *peer = ibss_rsn_get_peer(ibss_rsn, addr);
+ if (peer && wpa_drv_sta_remove(ibss_rsn->wpa_s, addr) == 0)
+ peer->authentication_status |= IBSS_RSN_PENDING_DELETION;
+ else
+ wpa_drv_sta_deauth(ibss_rsn->wpa_s, addr, reason);
}


@@ -810,6 +814,13 @@ int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr,
return -1;

peer = ibss_rsn_get_peer(ibss_rsn, src_addr);
+ if (peer->authentication_status & IBSS_RSN_PENDING_DELETION) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: Ignoring RX EAPOL from removed peer " MACSTR,
+ MAC2STR(src_addr));
+ return -1;
+ }
+
if (peer)
return ibss_rsn_process_rx_eapol(ibss_rsn, peer, buf, len);

@@ -849,6 +860,10 @@ static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
{
wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR,
MAC2STR(addr));
+ if (peer && peer->authentication_status & IBSS_RSN_PENDING_DELETION) {
+ wpa_printf(MSG_DEBUG, "RSN: Ignoring auth from removed sta");
+ return;
+ }

if (peer &&
peer->authentication_status & (IBSS_RSN_SET_PTK_SUPP |
@@ -883,8 +898,16 @@ static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn,
wpa_printf(MSG_DEBUG, "RSN: IBSS Reinitializing station "
MACSTR, MAC2STR(addr));

- ibss_rsn_stop(ibss_rsn, addr);
- peer = NULL;
+ if (wpa_drv_sta_remove(ibss_rsn->wpa_s, addr) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: IBSS sta deletion requested.");
+ peer->authentication_status
+ |= IBSS_RSN_PENDING_DELETION;
+ return;
+ } else {
+ ibss_rsn_stop(ibss_rsn, addr);
+ peer = NULL;
+ }
}

if (!peer) {
@@ -935,6 +958,11 @@ void ibss_rsn_handle_auth(struct ibss_rsn *ibss_rsn, const u8 *auth_frame,
"unknown STA " MACSTR, MAC2STR(header->sa));
break;
}
+ if (peer->authentication_status & IBSS_RSN_PENDING_DELETION) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: Ignoring auth from removed sta");
+ break;
+ }

/* authentication has been completed */
eloop_cancel_timeout(ibss_rsn_auth_timeout, peer, NULL);
diff --git a/wpa_supplicant/ibss_rsn.h b/wpa_supplicant/ibss_rsn.h
index 626c54354..17f5ca0ee 100644
--- a/wpa_supplicant/ibss_rsn.h
+++ b/wpa_supplicant/ibss_rsn.h
@@ -25,6 +25,8 @@ struct ibss_rsn;
#define IBSS_RSN_SET_PTK_AUTH 0x10
/* PTK completion reported */
#define IBSS_RSN_REPORTED_PTK 0x20
+/* requested STA deletion to kernel */
+#define IBSS_RSN_PENDING_DELETION 0x40

struct ibss_rsn_peer {
struct ibss_rsn_peer *next;