zeus_masta_funk zeus_masta_funk - 6 months ago 12
Linux Question

Linux Kernel 3.3 not registering missed beacons with connected Access Point

I'm using linux kernel 3.3 (I cannot upgrade my kernel, sorry!) and am trying to use the

wpa_cli
utility to monitor the status of my WiFi connection. I'm using an Edimax WiFi dongle to connect to a wireless access point.

I expect to see something like this:

# wpa_cli status
Selected interface 'wlan0'
wpa_state=SCANNING
ip_address=XXX.XXX.XXX.XXX
address=XX:XX:XX:XX:XX:XX


Or the same thing but with
wpa_state=COMPLETED
, depending upon my connection status.

Parsing the this text output allows me to see if my wireless connection is active or scanning. However, I have noticed that after powering off my access point
wpa_state=COMPLETED
is still being returned. Using the command:

# iwlist wlan0 scanning


Forces a scan and
wpa_state
will occasionally be correct, but usually (99%) not.

Here is my
/etc/wpa_supplicant.conf
:

ctrl_interface=/var/run/wpa_supplicant
ap_scan=1
country=US


network={
ssid="myssid"
psk="mypsk"
key_mgmt=WPA-PSK
eap=
}


After some investigation, I believe something weird is happening causing the kernel to return a cached version of the AP list. I am using the
RTL8192cu
driver. I've already looked at this issue, and it is not the same as mine.

My belief is that the issue may be somewhere in the kernel. In the file
net/mac80211/scan.c
, at line 214 in function
ieee80211_scan_rx
, I see a
bssid
from the
BSS
of my AP appear (when AP has power) and get put via
ieee80211_rx_bss_put
(here). At this point, it is returned in scan results and
wpa_supplicant
causes the
MLME
layer in the kernel to authenticate and connect with that AP. However, after disconnecting AP power, I never see the
MLME
layer relinquish it's
atomic_t
hold on that
BSS
. This causes the
BSS
to never to unlinked in the function
cfg80211_bss_expire
at the end of a scan (
cfg80211_wext_giwscan
), in file
net/wireless/scan.c
, line 205 (here).

Specifically, I would like to know why the atomic used to "hold" a
BSS
is not decremented on power removal from the AP - causing linux to miss sufficient beacons for a disconnect? Or, is there some configuration with wpa_supplicant I need to add to have the
MLME
kernel layer decrement it's hold on the
BSS
, or is this clearly a kernel bug?

I've already tried:

# wpa_cli bss_expire_age 10
# wpa_cli bss_expire_count 2


and have not resolved my issue.

Answer

So after a lot of digging, I found that the issue was because of the kernel's rtlwifi driver. To me, it looks like the rtl8192cu driver was suppose to be responsible for handling missed beacons, by calling the function ieee80211_beacon_loss, but that call is nowhere to be found. I removed support for IEEE80211_HW_BEACON_FILTER in the rtlwifi driver and the issue has been fixed.

This patch is essentially the same changes that I made, and the comments in this file are part of what led to me this answer.