def run_multi_ap_backhaul_roam_with_bridge(dev, apdev): br_ifname = 'sta-br0' ifname = 'wlan5' wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') subprocess.call(['brctl', 'addbr', br_ifname]) subprocess.call(['brctl', 'setfd', br_ifname, '0']) subprocess.call(['ip', 'link', 'set', 'dev', br_ifname, 'up']) subprocess.call(['iw', ifname, 'set', '4addr', 'on']) subprocess.check_call(['brctl', 'addif', br_ifname, ifname]) wpas.interface_add(ifname, br_ifname=br_ifname) wpas.flush_scan_cache() params = hostapd.wpa2_params(ssid="multi-ap", passphrase="12345678") params["multi_ap"] = "1" hapd = hostapd.add_ap(apdev[0], params) wpas.connect("multi-ap", psk="12345678", scan_freq="2412", multi_ap_backhaul_sta="1") hapd2 = hostapd.add_ap(apdev[1], params) bssid2 = hapd2.own_addr() wpas.scan_for_bss(bssid2, freq="2412", force_scan=True) wpas.roam(bssid2)
def test_connect_cmd_disconnect_event(dev, apdev): """Connection using cfg80211 connect command getting disconnected by the AP""" params = {"ssid": "sta-connect"} hapd = hostapd.add_ap(apdev[0], params) wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") wpas.connect("sta-connect", key_mgmt="NONE", scan_freq="2412") if "OK" not in hapd.request("DEAUTHENTICATE " + wpas.p2p_interface_addr()): raise Exception("DEAUTHENTICATE command failed") ev = wpas.wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5) if ev is None: raise Exception("Disconnection event timed out") # This event was actually based on deauthenticate event since we force # connect command to be used with a driver that supports auth+assoc for # testing purposes. Anyway, wait some time to allow the debug log to capture # the following NL80211_CMD_DISCONNECT event. time.sleep(0.1) wpas.dump_monitor() # Clean up to avoid causing issue for following test cases wpas.request("REMOVE_NETWORK all") wpas.wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=2) wpas.flush_scan_cache() wpas.dump_monitor() wpas.interface_remove("wlan5") del wpas
def test_pmksa_cache_opportunistic_multiple_sta(dev, apdev): """Opportunistic PMKSA caching with multiple stations""" params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache") params['okc'] = "1" hostapd.add_ap(apdev[0], params) bssid = apdev[0]['bssid'] for d in dev: d.flush_scan_cache() wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5") wpas.flush_scan_cache() for sta in [dev[0], dev[1], dev[2], wpas]: sta.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP", eap="GPSK", identity="gpsk user", password="******", okc=True, scan_freq="2412") hostapd.add_ap(apdev[1], params) bssid2 = apdev[1]['bssid'] logger.info("Roam to AP2") for sta in [dev[2], dev[0], wpas, dev[1]]: sta.dump_monitor() sta.scan_for_bss(bssid2, freq="2412") if "OK" not in sta.request("ROAM " + bssid2): raise Exception("ROAM command failed") ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED", "CTRL-EVENT-CONNECTED"], timeout=10) if ev is None: raise Exception("Roaming with the AP timed out") if "CTRL-EVENT-EAP-STARTED" in ev: raise Exception("Unexpected EAP exchange") pmksa2 = sta.get_pmksa(bssid2) if pmksa2 is None: raise Exception("No PMKSA cache entry created") sta.dump_monitor() logger.info("Roam back to AP1") for sta in [dev[0], dev[1], dev[2], wpas]: sta.dump_monitor() sta.scan_for_bss(bssid, freq="2412") sta.request("ROAM " + bssid) ev = sta.wait_event(["CTRL-EVENT-EAP-STARTED", "CTRL-EVENT-CONNECTED"], timeout=10) if ev is None: raise Exception("Roaming with the AP timed out") if "CTRL-EVENT-EAP-STARTED" in ev: raise Exception("Unexpected EAP exchange")
def test_go_neg_forced_freq_diff_than_bss_freq(dev, apdev): """P2P channel selection: GO negotiation with forced freq different than station interface""" with HWSimRadio(n_channels=2) as (radio, iface): wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add(iface) if wpas.get_mcc() < 2: raise Exception("New radio does not support MCC") # Clear possible PBC session overlap from previous test case dev[1].flush_scan_cache() wpas.global_request("SET p2p_no_group_iface 0") hapd = hostapd.add_ap(apdev[0], { "country_code": 'US', "ssid": 'bss-5ghz', "hw_mode": 'a', "channel": '40' }) wpas.connect("bss-5ghz", key_mgmt="NONE", scan_freq="5200") # GO and peer force the same freq, different than BSS freq, # wpas to become GO [i_res, r_res] = go_neg_pbc(i_dev=dev[1], i_intent=1, i_freq=5180, r_dev=wpas, r_intent=14, r_freq=5180) check_grpform_results(i_res, r_res) if i_res['freq'] != "5180": raise Exception("P2P group formed on unexpected frequency: " + i_res['freq']) if r_res['role'] != "GO": raise Exception("GO not selected according to go_intent") hwsim_utils.test_connectivity(wpas, hapd) wpas.remove_group(r_res['ifname']) dev[1].wait_go_ending_session() dev[1].flush_scan_cache() # GO and peer force the same freq, different than BSS freq, wpas to # become client [i_res2, r_res2] = go_neg_pbc(i_dev=dev[1], i_intent=14, i_freq=2422, r_dev=wpas, r_intent=1, r_freq=2422) check_grpform_results(i_res2, r_res2) if i_res2['freq'] != "2422": raise Exception("P2P group formed on unexpected frequency: " + i_res2['freq']) if r_res2['role'] != "client": raise Exception("GO not selected according to go_intent") hwsim_utils.test_connectivity(wpas, hapd) wpas.request("DISCONNECT") hapd.request("DISABLE") subprocess.call(['iw', 'reg', 'set', '00']) wpas.flush_scan_cache()
def test_go_neg_forced_freq_diff_than_bss_freq(dev, apdev): """P2P channel selection: GO negotiation with forced freq different than station interface""" with HWSimRadio(n_channels=2) as (radio, iface): wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add(iface) if wpas.get_mcc() < 2: raise Exception("New radio does not support MCC") # Clear possible PBC session overlap from previous test case dev[1].flush_scan_cache() wpas.request("SET p2p_no_group_iface 0") hapd = hostapd.add_ap(apdev[0]['ifname'], { "country_code": 'US', "ssid": 'bss-5ghz', "hw_mode": 'a', "channel": '40' }) wpas.connect("bss-5ghz", key_mgmt="NONE", scan_freq="5200") # GO and peer force the same freq, different than BSS freq, # wpas to become GO [i_res, r_res] = go_neg_pbc(i_dev=dev[1], i_intent=1, i_freq=5180, r_dev=wpas, r_intent=14, r_freq=5180) check_grpform_results(i_res, r_res) if i_res['freq'] != "5180": raise Exception("P2P group formed on unexpected frequency: " + i_res['freq']) if r_res['role'] != "GO": raise Exception("GO not selected according to go_intent") hwsim_utils.test_connectivity(wpas, hapd) wpas.remove_group(r_res['ifname']) dev[1].wait_go_ending_session() dev[1].flush_scan_cache() # GO and peer force the same freq, different than BSS freq, wpas to # become client [i_res2, r_res2] = go_neg_pbc(i_dev=dev[1], i_intent=14, i_freq=2422, r_dev=wpas, r_intent=1, r_freq=2422) check_grpform_results(i_res2, r_res2) if i_res2['freq'] != "2422": raise Exception("P2P group formed on unexpected frequency: " + i_res2['freq']) if r_res2['role'] != "client": raise Exception("GO not selected according to go_intent") hwsim_utils.test_connectivity(wpas, hapd) wpas.request("DISCONNECT") hapd.request("DISABLE") subprocess.call(['iw', 'reg', 'set', '00']) wpas.flush_scan_cache()
def test_offchannel_tx_roc_gas(dev, apdev): """GAS using cfg80211 remain-on-channel for offchannel TX""" start_ap(apdev[0]) bssid = apdev[0]['bssid'] wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="no_offchannel_tx=1") wpas.flush_scan_cache() wpas.scan_for_bss(bssid, freq=2412) anqp_get(wpas, bssid, 263) ev = wpas.wait_event(["GAS-QUERY-DONE"], timeout=10) if ev is None: raise Exception("GAS query timed out") if "result=SUCCESS" not in ev: raise Exception("Unexpected GAS query result")
def test_connect_cmd_bssid_hint(dev, apdev): """cfg80211 connect command with bssid_hint""" params = {"ssid": "sta-connect"} hostapd.add_ap(apdev[0], params) hostapd.add_ap(apdev[1], params) # This does not really give full coverage with mac80211_hwsim since the # driver does not end up claiming support for driver-based BSS selection. # Anyway, some test coverage can be achieved for setting the parameter and # checking that it does not prevent connection with another BSSID. wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") wpas.connect("sta-connect", key_mgmt="NONE", scan_freq="2412", bssid_hint=apdev[0]['bssid']) wpas.request("REMOVE_NETWORK all") wpas.wait_disconnected() wpas.dump_monitor() wpas.request("BSS_FLUSH 0") wpas.connect("sta-connect", key_mgmt="NONE", scan_freq="2412", bssid_hint='22:33:44:55:66:77') wpas.request("REMOVE_NETWORK all") wpas.wait_disconnected() wpas.dump_monitor() # Additional coverage using ap_scan=2 to prevent scan entry -based selection # within wpa_supplicant from overriding bssid_hint. try: if "OK" not in wpas.request("AP_SCAN 2"): raise Exception("Failed to set AP_SCAN 2") wpas.request("BSS_FLUSH 0") wpas.connect("sta-connect", key_mgmt="NONE", scan_freq="2412", bssid_hint='22:33:44:55:66:77') wpas.request("REMOVE_NETWORK all") wpas.wait_disconnected() wpas.dump_monitor() finally: wpas.request("AP_SCAN 1") wpas.flush_scan_cache()
def test_ap_reconnect_auth_timeout(dev, apdev, params): """Reconnect to 2nd AP and authentication times out""" wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1,force_bss_selection=1") wpas.flush_scan_cache() params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") hapd0 = hostapd.add_ap(apdev[0], params) bssid0 = hapd0.own_addr() wpas.scan_for_bss(bssid0, freq=2412) id = wpas.connect("test-wpa2-psk", psk="12345678", scan_freq="2412") hapd0.wait_sta() hwsim_utils.test_connectivity(wpas, hapd0) hapd1 = hostapd.add_ap(apdev[1], params) bssid1 = hapd1.own_addr() wpas.request("BSSID_IGNORE " + bssid0) wpas.scan_for_bss(bssid1, freq=2412) wpas.request("DISCONNECT") if "OK" not in wpas.request("SET ignore_auth_resp 1"): raise Exception("SET ignore_auth_resp failed") if "OK" not in wpas.request("ENABLE_NETWORK " + str(id)): raise Exception("ENABLE_NETWORK failed") if "OK" not in wpas.request("SELECT_NETWORK " + str(id)): raise Exception("SELECT_NETWORK failed") logger.info("Wait ~10s for auth timeout...") time.sleep(10) ev = wpas.wait_event(["CTRL-EVENT-SCAN-STARTED"], 12) if not ev: raise Exception("CTRL-EVENT-SCAN-STARTED not seen") b = get_bssid_ignore_list(wpas) if '00:00:00:00:00:00' in b: raise Exception("Unexpected ignore list contents: " + str(b)) if bssid1 not in b: raise Exception("Unexpected ignore list contents: " + str(b))
def test_scan_and_bss_entry_removed(dev, apdev): """Last scan result and connect work processing on BSS entry update""" hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open", "eap_server": "1", "wps_state": "2" }) bssid = apdev[0]['bssid'] wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") # Add a BSS entry dev[0].scan_for_bss(bssid, freq="2412") wpas.scan_for_bss(bssid, freq="2412") # Start a connect radio work with a blocking entry preventing this from # proceeding; this stores a pointer to the selected BSS entry. id = dev[0].request("RADIO_WORK add block-work") w_id = wpas.request("RADIO_WORK add block-work") dev[0].wait_event(["EXT-RADIO-WORK-START"], timeout=1) wpas.wait_event(["EXT-RADIO-WORK-START"], timeout=1) nid = dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", wait_connect=False) w_nid = wpas.connect("open", key_mgmt="NONE", scan_freq="2412", wait_connect=False) time.sleep(0.1) # Remove the BSS entry dev[0].request("BSS_FLUSH 0") wpas.request("BSS_FLUSH 0") # Allow the connect radio work to continue. The bss entry stored in the # pending connect work is now stale. This will result in the connection # attempt failing since the BSS entry does not exist. dev[0].request("RADIO_WORK done " + id) wpas.request("RADIO_WORK done " + w_id) ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected connection") dev[0].remove_network(nid) ev = wpas.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected connection") wpas.remove_network(w_nid) time.sleep(0.5) dev[0].request("BSS_FLUSH 0") wpas.request("BSS_FLUSH 0") # Add a BSS entry dev[0].scan_for_bss(bssid, freq="2412") wpas.scan_for_bss(bssid, freq="2412") # Start a connect radio work with a blocking entry preventing this from # proceeding; this stores a pointer to the selected BSS entry. id = dev[0].request("RADIO_WORK add block-work") w_id = wpas.request("RADIO_WORK add block-work") dev[0].wait_event(["EXT-RADIO-WORK-START"], timeout=1) wpas.wait_event(["EXT-RADIO-WORK-START"], timeout=1) # Schedule a connection based on the current BSS entry. dev[0].connect("open", key_mgmt="NONE", scan_freq="2412", wait_connect=False) wpas.connect("open", key_mgmt="NONE", scan_freq="2412", wait_connect=False) # Update scan results with results that have longer set of IEs so that new # memory needs to be allocated for the BSS entry. hapd.request("WPS_PBC") time.sleep(0.1) subprocess.call(['iw', dev[0].ifname, 'scan', 'trigger', 'freq', '2412']) subprocess.call(['iw', wpas.ifname, 'scan', 'trigger', 'freq', '2412']) time.sleep(0.1) # Allow the connect radio work to continue. The bss entry stored in the # pending connect work becomes stale during the scan and it must have been # updated for the connection to work. dev[0].request("RADIO_WORK done " + id) wpas.request("RADIO_WORK done " + w_id) dev[0].wait_connected(timeout=15, error="No connection (sme-connect)") wpas.wait_connected(timeout=15, error="No connection (connect)") dev[0].request("DISCONNECT") wpas.request("DISCONNECT") dev[0].flush_scan_cache() wpas.flush_scan_cache()
def test_pmksa_cache_multiple_sta(dev, apdev): """PMKSA cache with multiple stations""" params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache") hostapd.add_ap(apdev[0], params) bssid = apdev[0]['bssid'] for d in dev: d.flush_scan_cache() dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP", eap="GPSK", identity="gpsk-user-session-timeout", password="******", scan_freq="2412") dev[1].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP", eap="GPSK", identity="gpsk user", password="******", scan_freq="2412") dev[2].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP", eap="GPSK", identity="gpsk-user-session-timeout", password="******", scan_freq="2412") wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5") wpas.flush_scan_cache() wpas.connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP", eap="GPSK", identity="gpsk user", password="******", scan_freq="2412") hostapd.add_ap(apdev[1], params) bssid2 = apdev[1]['bssid'] logger.info("Roam to AP2") for sta in [dev[1], dev[0], dev[2], wpas]: sta.dump_monitor() sta.scan_for_bss(bssid2, freq="2412") if "OK" not in sta.request("ROAM " + bssid2): raise Exception("ROAM command failed (" + sta.ifname + ")") ev = sta.wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=10) if ev is None: raise Exception("EAP success timed out") sta.wait_connected(timeout=10, error="Roaming timed out") sta.dump_monitor() logger.info("Roam back to AP1") for sta in [dev[1], wpas, dev[0], dev[2]]: sta.dump_monitor() sta.scan(freq="2412") sta.dump_monitor() sta.request("ROAM " + bssid) sta.wait_connected(timeout=10, error="Roaming timed out") sta.dump_monitor() time.sleep(4) logger.info("Roam back to AP2") for sta in [dev[1], wpas, dev[0], dev[2]]: sta.dump_monitor() sta.scan(freq="2412") sta.dump_monitor() sta.request("ROAM " + bssid2) sta.wait_connected(timeout=10, error="Roaming timed out") sta.dump_monitor()