@@ -149,3 +149,11 @@ def test_connectivity_p2p_sta(dev1, dev2, dscp=None, tos=None):
def test_connectivity_sta(dev1, dev2, dscp=None, tos=None):
test_connectivity(dev1, dev2, dscp, tos)
+
+(PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL) = range(4)
+
+def set_powersave(dev, val):
+ phy = dev.get_driver_status_field("phyname")
+ psf = open('/sys/kernel/debug/ieee80211/%s/hwsim/ps' % phy, 'w')
+ psf.write('%d\n' % val)
+ psf.close()
@@ -9,6 +9,7 @@ logger = logging.getLogger()
import struct
import subprocess
import time
+import os
import hostapd
import hwsim_utils
@@ -201,3 +202,62 @@ def test_ap_open_out_of_memory(dev, apdev):
# verify that a new interface can still be added when memory allocation does
# not fail
hostapd.add_ap(apdev[1]['ifname'], { "ssid": "open" })
+
+def test_ap_open_disconnect_in_ps(dev, apdev, params):
+ """disconnect with the client in PS to regression-test a kernel bug"""
+ hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" })
+ dev[0].connect("open", key_mgmt="NONE", scan_freq="2412",
+ bg_scan_period="0")
+ ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
+ if ev is None:
+ raise Exception("No connection event received from hostapd")
+
+ hwsim_utils.set_powersave(dev[0], hwsim_utils.PS_MANUAL_POLL)
+ try:
+ # inject some traffic
+ sa = hapd.own_addr()
+ da = dev[0].own_addr()
+ hapd.request('DATA_TEST_TX {} {} 0'.format(da, sa))
+
+ # let the AP send two beacons
+ time.sleep(0.2)
+
+ # disconnect - with traffic pending - shouldn't cause kernel warnings
+ dev[0].request("DISCONNECT")
+ finally:
+ hwsim_utils.set_powersave(dev[0], hwsim_utils.PS_DISABLED)
+
+ # wait a bit to make it more likely for wlantest sniffer to have captured
+ # and written the results into a file that we can process here
+ time.sleep(1)
+
+ try:
+ arg = [ "tshark",
+ "-r", os.path.join(params['logdir'], "hwsim0.pcapng"),
+ "-Y", "wlan_mgt.tim.partial_virtual_bitmap",
+ "-Tfields", "-e", "wlan_mgt.tim.partial_virtual_bitmap" ]
+ cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
+ stderr=open('/dev/null', 'w'))
+ except Exception, e:
+ logger.info("Could run run tshark check: " + str(e))
+ cmd = None
+
+ if cmd:
+ (out,err) = cmd.communicate()
+ res = cmd.wait()
+ if res == 1:
+ arg[3] = '-R'
+ cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
+ stderr=open('/dev/null', 'w'))
+ (out,err) = cmd.communicate()
+ res = cmd.wait()
+
+ state = 0
+ for l in out.splitlines():
+ pvb = int(l, 16)
+ if pvb > 0 and state == 0:
+ state = 1
+ elif pvb == 0 and state == 1:
+ state = 2
+ if state != 2:
+ raise Exception("didn't observe TIM bit getting set and unset")