diff --git a/tests/hwsim/bss-1.conf b/tests/hwsim/bss-1.conf new file mode 100644 index 000000000..b465dcbbd --- /dev/null +++ b/tests/hwsim/bss-1.conf @@ -0,0 +1,11 @@ +driver=nl80211 + +hw_mode=g +channel=1 +ieee80211n=1 + +interface=wlan3 +bssid=02:00:00:00:03:00 +ctrl_interface=/var/run/hostapd + +ssid=bss-1 diff --git a/tests/hwsim/bss-2.conf b/tests/hwsim/bss-2.conf new file mode 100644 index 000000000..7a8c64c15 --- /dev/null +++ b/tests/hwsim/bss-2.conf @@ -0,0 +1,11 @@ +driver=nl80211 + +hw_mode=g +channel=1 +ieee80211n=1 + +interface=wlan3-2 +bssid=02:00:00:00:03:01 +ctrl_interface=/var/run/hostapd + +ssid=bss-2 diff --git a/tests/hwsim/bss-3.conf b/tests/hwsim/bss-3.conf new file mode 100644 index 000000000..fe671def4 --- /dev/null +++ b/tests/hwsim/bss-3.conf @@ -0,0 +1,11 @@ +driver=nl80211 + +hw_mode=g +channel=1 +ieee80211n=1 + +interface=wlan3-3 +bssid=02:00:00:00:03:02 +ctrl_interface=/var/run/hostapd + +ssid=bss-3 diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index 161a34c36..10f2206c0 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -24,6 +24,12 @@ class HostapdGlobal: if not "OK" in res: raise Exception("Could not add hostapd interface " + ifname) + def add_bss(self, phy, confname, ignore_error=False): + res = self.ctrl.request("ADD bss_config=" + phy + ":" + confname) + if not "OK" in res: + if not ignore_error: + raise Exception("Could not add hostapd BSS") + def remove(self, ifname): self.ctrl.request("REMOVE " + ifname) @@ -120,6 +126,19 @@ def add_ap(ifname, params): hapd.set(f, v) hapd.enable() +def add_bss(phy, ifname, confname, ignore_error=False): + logger.info("Starting BSS phy=" + phy + " ifname=" + ifname) + hapd_global = HostapdGlobal() + hapd_global.add_bss(phy, confname, ignore_error) + hapd = Hostapd(ifname) + if not hapd.ping(): + raise Exception("Could not ping hostapd") + +def remove_bss(ifname): + logger.info("Removing BSS " + ifname) + hapd_global = HostapdGlobal() + hapd_global.remove(ifname) + def wpa2_params(ssid=None, passphrase=None): params = { "wpa": "2", "wpa_key_mgmt": "WPA-PSK", diff --git a/tests/hwsim/run-tests.py b/tests/hwsim/run-tests.py index 5b2f884bf..16b5e19b7 100755 --- a/tests/hwsim/run-tests.py +++ b/tests/hwsim/run-tests.py @@ -30,6 +30,8 @@ def reset_devs(dev, apdev): except Exception, e: logger.info("Failed to reset device " + d.ifname) print str(e) + hapd.remove('wlan3-3') + hapd.remove('wlan3-2') for ap in apdev: hapd.remove(ap['ifname']) diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index 515aae05c..b1987dffa 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -33,3 +33,130 @@ def test_ap_change_ssid(dev, apdev): dev[0].set_network_quoted(id, "ssid", "test-wpa2-psk-new") dev[0].connect_network(id) + +def multi_check(dev, check0, check1, check2): + for d in dev: + d.request("BSS_FLUSH 0") + d.dump_monitor() + + id0 = dev[0].connect("bss-1", key_mgmt="NONE", scan_freq="2412", + wait_connect=check0) + id1 = dev[1].connect("bss-2", key_mgmt="NONE", scan_freq="2412", + wait_connect=check1) + id2 = dev[2].connect("bss-3", key_mgmt="NONE", scan_freq="2412", + wait_connect=check2) + if not check0: + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.2) + if ev: + raise Exception("Unexpected connection") + if not check1: + ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.2) + if ev: + raise Exception("Unexpected connection") + if not check2: + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=0.2) + if ev: + raise Exception("Unexpected connection") + + dev[0].remove_network(id0) + dev[1].remove_network(id1) + dev[2].remove_network(id2) + + time.sleep(0.3) + + res0 = dev[0].request("BSS RANGE=ALL MASK=0x2") + res1 = dev[1].request("BSS RANGE=ALL MASK=0x2") + res2 = dev[2].request("BSS RANGE=ALL MASK=0x2") + + if not check0: + if ('02:00:00:00:03:00' in res0 or + '02:00:00:00:03:00' in res1 or + '02:00:00:00:03:00' in res2): + raise Exception("Unexpected BSS0 in scan results") + + if not check1: + if ('02:00:00:00:03:01' in res0 or + '02:00:00:00:03:01' in res1 or + '02:00:00:00:03:01' in res2): + raise Exception("Unexpected BSS1 in scan results") + + if not check2: + if ('02:00:00:00:03:02' in res0 or + '02:00:00:00:03:02' in res1 or + '02:00:00:00:03:02' in res2): + raise Exception("Unexpected BSS2 in scan results") + +def test_ap_bss_add_remove(dev, apdev): + """Dynamic BSS add/remove operations with hostapd""" + for d in dev: + d.request("SET ignore_old_scan_res 1") + ifname1 = apdev[0]['ifname'] + ifname2 = apdev[0]['ifname'] + '-2' + ifname3 = apdev[0]['ifname'] + '-3' + logger.info("Set up three BSSes one by one") + hostapd.add_bss('phy3', ifname1, 'bss-1.conf') + multi_check(dev, True, False, False) + hostapd.add_bss('phy3', ifname2, 'bss-2.conf') + multi_check(dev, True, True, False) + hostapd.add_bss('phy3', ifname3, 'bss-3.conf') + multi_check(dev, True, True, True) + + logger.info("Remove the last BSS and re-add it") + hostapd.remove_bss(ifname3) + multi_check(dev, True, True, False) + hostapd.add_bss('phy3', ifname3, 'bss-3.conf') + multi_check(dev, True, True, True) + + logger.info("Remove the middle BSS and re-add it") + hostapd.remove_bss(ifname2) + multi_check(dev, True, False, True) + hostapd.add_bss('phy3', ifname2, 'bss-2.conf') + multi_check(dev, True, True, True) + + logger.info("Remove the first BSS and re-add it") + hostapd.remove_bss(ifname1) + multi_check(dev, False, True, True) + hostapd.add_bss('phy3', ifname1, 'bss-1.conf') + multi_check(dev, True, True, True) + + logger.info("Remove two BSSes and re-add them") + hostapd.remove_bss(ifname2) + multi_check(dev, True, False, True) + hostapd.remove_bss(ifname3) + multi_check(dev, True, False, False) + dev[0].request("NOTE failure-done") + hostapd.add_bss('phy3', ifname2, 'bss-2.conf') + multi_check(dev, True, True, False) + hostapd.add_bss('phy3', ifname3, 'bss-3.conf') + multi_check(dev, True, True, True) + + logger.info("Remove three BSSes and re-add them") + hostapd.remove_bss(ifname1) + multi_check(dev, False, True, True) + hostapd.remove_bss(ifname2) + multi_check(dev, False, False, True) + hostapd.remove_bss(ifname3) + multi_check(dev, False, False, False) + hostapd.add_bss('phy3', ifname1, 'bss-1.conf') + multi_check(dev, True, False, False) + hostapd.add_bss('phy3', ifname2, 'bss-2.conf') + multi_check(dev, True, True, False) + hostapd.add_bss('phy3', ifname3, 'bss-3.conf') + multi_check(dev, True, True, True) + + logger.info("Remove three BSSes in reverse order and re-add them") + hostapd.remove_bss(ifname3) + multi_check(dev, True, True, False) + hostapd.remove_bss(ifname2) + multi_check(dev, True, False, False) + hostapd.remove_bss(ifname1) + hostapd.add_bss('phy3', ifname1, 'bss-1.conf') + multi_check(dev, True, False, False) + hostapd.add_bss('phy3', ifname2, 'bss-2.conf') + multi_check(dev, True, True, False) + hostapd.add_bss('phy3', ifname3, 'bss-3.conf') + multi_check(dev, True, True, True) + + logger.info("Test error handling if a duplicate ifname is tried") + hostapd.add_bss('phy3', ifname3, 'bss-3.conf', ignore_error=True) + multi_check(dev, True, True, True)