test_ap_ht.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. # Test cases for HT operations with hostapd
  2. # Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
  3. #
  4. # This software may be distributed under the terms of the BSD license.
  5. # See README for more details.
  6. import time
  7. import logging
  8. logger = logging.getLogger()
  9. import struct
  10. import subprocess
  11. import hostapd
  12. def clear_scan_cache(ifname):
  13. subprocess.call(['sudo', 'ifconfig', ifname, 'up'])
  14. subprocess.call(['sudo', 'iw', ifname, 'scan', 'freq', '2412', 'flush'])
  15. time.sleep(0.1)
  16. subprocess.call(['sudo', 'ifconfig', ifname, 'down'])
  17. def test_ap_ht40_scan(dev, apdev):
  18. """HT40 co-ex scan"""
  19. clear_scan_cache(apdev[0]['ifname'])
  20. params = { "ssid": "test-ht40",
  21. "channel": "5",
  22. "ht_capab": "[HT40-]"}
  23. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  24. state = hapd.get_status_field("state")
  25. if state != "HT_SCAN":
  26. time.sleep(0.1)
  27. state = hapd.get_status_field("state")
  28. if state != "HT_SCAN":
  29. raise Exception("Unexpected interface state - expected HT_SCAN")
  30. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  31. if not ev:
  32. raise Exception("AP setup timed out")
  33. state = hapd.get_status_field("state")
  34. if state != "ENABLED":
  35. raise Exception("Unexpected interface state - expected ENABLED")
  36. freq = hapd.get_status_field("freq")
  37. if freq != "2432":
  38. raise Exception("Unexpected frequency")
  39. pri = hapd.get_status_field("channel")
  40. if pri != "5":
  41. raise Exception("Unexpected primary channel")
  42. sec = hapd.get_status_field("secondary_channel")
  43. if sec != "-1":
  44. raise Exception("Unexpected secondary channel")
  45. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  46. def test_ap_ht40_scan_conflict(dev, apdev):
  47. """HT40 co-ex scan conflict"""
  48. clear_scan_cache(apdev[0]['ifname'])
  49. params = { "ssid": "test-ht40",
  50. "channel": "6",
  51. "ht_capab": "[HT40+]"}
  52. hostapd.add_ap(apdev[1]['ifname'], params)
  53. params = { "ssid": "test-ht40",
  54. "channel": "5",
  55. "ht_capab": "[HT40-]"}
  56. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  57. state = hapd.get_status_field("state")
  58. if state != "HT_SCAN":
  59. time.sleep(0.1)
  60. state = hapd.get_status_field("state")
  61. if state != "HT_SCAN":
  62. raise Exception("Unexpected interface state - expected HT_SCAN")
  63. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  64. if not ev:
  65. raise Exception("AP setup timed out")
  66. state = hapd.get_status_field("state")
  67. if state != "ENABLED":
  68. raise Exception("Unexpected interface state - expected ENABLED")
  69. freq = hapd.get_status_field("freq")
  70. if freq != "2432":
  71. raise Exception("Unexpected frequency")
  72. pri = hapd.get_status_field("channel")
  73. if pri != "5":
  74. raise Exception("Unexpected primary channel")
  75. sec = hapd.get_status_field("secondary_channel")
  76. if sec != "0":
  77. raise Exception("Unexpected secondary channel: " + sec)
  78. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  79. def test_ap_ht40_scan_match(dev, apdev):
  80. """HT40 co-ex scan matching configuration"""
  81. clear_scan_cache(apdev[0]['ifname'])
  82. params = { "ssid": "test-ht40",
  83. "channel": "5",
  84. "ht_capab": "[HT40-]"}
  85. hostapd.add_ap(apdev[1]['ifname'], params)
  86. params = { "ssid": "test-ht40",
  87. "channel": "5",
  88. "ht_capab": "[HT40-]"}
  89. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  90. state = hapd.get_status_field("state")
  91. if state != "HT_SCAN":
  92. time.sleep(0.1)
  93. state = hapd.get_status_field("state")
  94. if state != "HT_SCAN":
  95. raise Exception("Unexpected interface state - expected HT_SCAN")
  96. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  97. if not ev:
  98. raise Exception("AP setup timed out")
  99. state = hapd.get_status_field("state")
  100. if state != "ENABLED":
  101. raise Exception("Unexpected interface state - expected ENABLED")
  102. freq = hapd.get_status_field("freq")
  103. if freq != "2432":
  104. raise Exception("Unexpected frequency")
  105. pri = hapd.get_status_field("channel")
  106. if pri != "5":
  107. raise Exception("Unexpected primary channel")
  108. sec = hapd.get_status_field("secondary_channel")
  109. if sec != "-1":
  110. raise Exception("Unexpected secondary channel: " + sec)
  111. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  112. def test_ap_ht40_5ghz_match(dev, apdev):
  113. """HT40 co-ex scan on 5 GHz with matching pri/sec channel"""
  114. clear_scan_cache(apdev[0]['ifname'])
  115. try:
  116. params = { "ssid": "test-ht40",
  117. "hw_mode": "a",
  118. "channel": "36",
  119. "country_code": "US",
  120. "ht_capab": "[HT40+]"}
  121. hostapd.add_ap(apdev[1]['ifname'], params)
  122. params = { "ssid": "test-ht40",
  123. "hw_mode": "a",
  124. "channel": "36",
  125. "ht_capab": "[HT40+]"}
  126. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  127. state = hapd.get_status_field("state")
  128. if state != "HT_SCAN":
  129. time.sleep(0.1)
  130. state = hapd.get_status_field("state")
  131. if state != "HT_SCAN":
  132. raise Exception("Unexpected interface state - expected HT_SCAN")
  133. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  134. if not ev:
  135. raise Exception("AP setup timed out")
  136. state = hapd.get_status_field("state")
  137. if state != "ENABLED":
  138. raise Exception("Unexpected interface state - expected ENABLED")
  139. freq = hapd.get_status_field("freq")
  140. if freq != "5180":
  141. raise Exception("Unexpected frequency")
  142. pri = hapd.get_status_field("channel")
  143. if pri != "36":
  144. raise Exception("Unexpected primary channel")
  145. sec = hapd.get_status_field("secondary_channel")
  146. if sec != "1":
  147. raise Exception("Unexpected secondary channel: " + sec)
  148. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  149. finally:
  150. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  151. def test_ap_ht40_5ghz_switch(dev, apdev):
  152. """HT40 co-ex scan on 5 GHz switching pri/sec channel"""
  153. clear_scan_cache(apdev[0]['ifname'])
  154. try:
  155. params = { "ssid": "test-ht40",
  156. "hw_mode": "a",
  157. "channel": "36",
  158. "country_code": "US",
  159. "ht_capab": "[HT40+]"}
  160. hostapd.add_ap(apdev[1]['ifname'], params)
  161. params = { "ssid": "test-ht40",
  162. "hw_mode": "a",
  163. "channel": "40",
  164. "ht_capab": "[HT40-]"}
  165. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  166. state = hapd.get_status_field("state")
  167. if state != "HT_SCAN":
  168. time.sleep(0.1)
  169. state = hapd.get_status_field("state")
  170. if state != "HT_SCAN":
  171. raise Exception("Unexpected interface state - expected HT_SCAN")
  172. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  173. if not ev:
  174. raise Exception("AP setup timed out")
  175. state = hapd.get_status_field("state")
  176. if state != "ENABLED":
  177. raise Exception("Unexpected interface state - expected ENABLED")
  178. freq = hapd.get_status_field("freq")
  179. if freq != "5180":
  180. raise Exception("Unexpected frequency: " + freq)
  181. pri = hapd.get_status_field("channel")
  182. if pri != "36":
  183. raise Exception("Unexpected primary channel: " + pri)
  184. sec = hapd.get_status_field("secondary_channel")
  185. if sec != "1":
  186. raise Exception("Unexpected secondary channel: " + sec)
  187. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  188. finally:
  189. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  190. def test_ap_ht40_5ghz_switch2(dev, apdev):
  191. """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
  192. clear_scan_cache(apdev[0]['ifname'])
  193. try:
  194. params = { "ssid": "test-ht40",
  195. "hw_mode": "a",
  196. "channel": "36",
  197. "country_code": "US",
  198. "ht_capab": "[HT40+]"}
  199. hostapd.add_ap(apdev[1]['ifname'], params)
  200. id = dev[0].add_network()
  201. dev[0].set_network(id, "mode", "2")
  202. dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
  203. dev[0].set_network(id, "key_mgmt", "NONE")
  204. dev[0].set_network(id, "frequency", "5200")
  205. dev[0].set_network(id, "scan_freq", "5200")
  206. dev[0].select_network(id)
  207. time.sleep(1)
  208. params = { "ssid": "test-ht40",
  209. "hw_mode": "a",
  210. "channel": "40",
  211. "ht_capab": "[HT40-]"}
  212. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  213. state = hapd.get_status_field("state")
  214. if state != "HT_SCAN":
  215. time.sleep(0.1)
  216. state = hapd.get_status_field("state")
  217. if state != "HT_SCAN":
  218. raise Exception("Unexpected interface state - expected HT_SCAN")
  219. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  220. if not ev:
  221. raise Exception("AP setup timed out")
  222. state = hapd.get_status_field("state")
  223. if state != "ENABLED":
  224. raise Exception("Unexpected interface state - expected ENABLED")
  225. freq = hapd.get_status_field("freq")
  226. if freq != "5180":
  227. raise Exception("Unexpected frequency: " + freq)
  228. pri = hapd.get_status_field("channel")
  229. if pri != "36":
  230. raise Exception("Unexpected primary channel: " + pri)
  231. sec = hapd.get_status_field("secondary_channel")
  232. if sec != "1":
  233. raise Exception("Unexpected secondary channel: " + sec)
  234. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  235. finally:
  236. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  237. def test_obss_scan(dev, apdev):
  238. """Overlapping BSS scan request"""
  239. params = { "ssid": "obss-scan",
  240. "channel": "6",
  241. "ht_capab": "[HT40-]",
  242. "obss_interval": "10" }
  243. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  244. params = { "ssid": "another-bss",
  245. "channel": "9",
  246. "ieee80211n": "0" }
  247. hostapd.add_ap(apdev[1]['ifname'], params)
  248. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  249. hapd.set("ext_mgmt_frame_handling", "1")
  250. logger.info("Waiting for OBSS scan to occur")
  251. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  252. if ev is None:
  253. raise Exception("Timed out while waiting for OBSS scan to start")
  254. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  255. if ev is None:
  256. raise Exception("Timed out while waiting for OBSS scan results")
  257. received = False
  258. for i in range(0, 4):
  259. frame = hapd.mgmt_rx(timeout=5)
  260. if frame is None:
  261. raise Exception("MGMT RX wait timed out")
  262. if frame['subtype'] != 13:
  263. continue
  264. payload = frame['payload']
  265. if len(payload) < 3:
  266. continue
  267. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  268. if category != 4:
  269. continue
  270. if action != 0:
  271. continue
  272. if ie == 72:
  273. logger.info("20/40 BSS Coexistence report received")
  274. received = True
  275. break
  276. if not received:
  277. raise Exception("20/40 BSS Coexistence report not seen")
  278. def test_obss_scan_40_intolerant(dev, apdev):
  279. """Overlapping BSS scan request with 40 MHz intolerant AP"""
  280. params = { "ssid": "obss-scan",
  281. "channel": "6",
  282. "ht_capab": "[HT40-]",
  283. "obss_interval": "10" }
  284. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  285. params = { "ssid": "another-bss",
  286. "channel": "7",
  287. "ht_capab": "[40-INTOLERANT]" }
  288. hostapd.add_ap(apdev[1]['ifname'], params)
  289. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  290. hapd.set("ext_mgmt_frame_handling", "1")
  291. logger.info("Waiting for OBSS scan to occur")
  292. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  293. if ev is None:
  294. raise Exception("Timed out while waiting for OBSS scan to start")
  295. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  296. if ev is None:
  297. raise Exception("Timed out while waiting for OBSS scan results")
  298. received = False
  299. for i in range(0, 4):
  300. frame = hapd.mgmt_rx(timeout=5)
  301. if frame is None:
  302. raise Exception("MGMT RX wait timed out")
  303. if frame['subtype'] != 13:
  304. continue
  305. payload = frame['payload']
  306. if len(payload) < 3:
  307. continue
  308. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  309. if category != 4:
  310. continue
  311. if action != 0:
  312. continue
  313. if ie == 72:
  314. logger.info("20/40 BSS Coexistence report received")
  315. received = True
  316. break
  317. if not received:
  318. raise Exception("20/40 BSS Coexistence report not seen")
  319. def test_olbc(dev, apdev):
  320. """OLBC detection"""
  321. params = { "ssid": "test-olbc",
  322. "channel": "6",
  323. "ht_capab": "[HT40-]",
  324. "ap_table_expiration_time": "2" }
  325. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  326. status = hapd.get_status()
  327. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  328. raise Exception("Unexpected OLBC information")
  329. params = { "ssid": "olbc-ap",
  330. "hw_mode": "b",
  331. "channel": "6",
  332. "wmm_enabled": "0" }
  333. hostapd.add_ap(apdev[1]['ifname'], params)
  334. time.sleep(0.5)
  335. status = hapd.get_status()
  336. if status['olbc'] != '1' or status['olbc_ht'] != '1':
  337. raise Exception("Missing OLBC information")
  338. hapd_global = hostapd.HostapdGlobal()
  339. hapd_global.remove(apdev[1]['ifname'])
  340. logger.info("Waiting for OLBC state to time out")
  341. cleared = False
  342. for i in range(0, 15):
  343. time.sleep(1)
  344. status = hapd.get_status()
  345. if status['olbc'] == '0' and status['olbc_ht'] == '0':
  346. cleared = True
  347. break
  348. if not cleared:
  349. raise Exception("OLBC state did nto time out")
  350. def test_olbc_5ghz(dev, apdev):
  351. """OLBC detection on 5 GHz"""
  352. try:
  353. params = { "ssid": "test-olbc",
  354. "country_code": "FI",
  355. "hw_mode": "a",
  356. "channel": "36",
  357. "ht_capab": "[HT40+]" }
  358. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  359. status = hapd.get_status()
  360. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  361. raise Exception("Unexpected OLBC information")
  362. params = { "ssid": "olbc-ap",
  363. "country_code": "FI",
  364. "hw_mode": "a",
  365. "channel": "36",
  366. "ieee80211n": "0",
  367. "wmm_enabled": "0" }
  368. hostapd.add_ap(apdev[1]['ifname'], params)
  369. time.sleep(0.5)
  370. status = hapd.get_status()
  371. if status['olbc_ht'] != '1':
  372. raise Exception("Missing OLBC information")
  373. finally:
  374. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  375. def test_ap_require_ht(dev, apdev):
  376. """Require HT"""
  377. params = { "ssid": "require-ht",
  378. "require_ht": "1" }
  379. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  380. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  381. disable_ht="1", wait_connect=False)
  382. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  383. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  384. if ev is None:
  385. raise Exception("Association rejection timed out")
  386. if "status_code=27" not in ev:
  387. raise Exception("Unexpected rejection status code")
  388. dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  389. ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
  390. disable_max_amsdu="1", ampdu_factor="2",
  391. ampdu_density="1", disable_ht40="1", disable_sgi="1",
  392. disable_ldpc="1")
  393. def test_ap_require_ht_limited_rates(dev, apdev):
  394. """Require HT with limited supported rates"""
  395. params = { "ssid": "require-ht",
  396. "supported_rates": "60 120 240 360 480 540",
  397. "require_ht": "1" }
  398. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  399. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  400. disable_ht="1", wait_connect=False)
  401. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  402. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  403. if ev is None:
  404. raise Exception("Association rejection timed out")
  405. if "status_code=27" not in ev:
  406. raise Exception("Unexpected rejection status code")
  407. def test_ap_ht_capab_not_supported(dev, apdev):
  408. """HT configuration with driver not supporting all ht_capab entries"""
  409. params = { "ssid": "test-ht40",
  410. "channel": "5",
  411. "ht_capab": "[HT40-][LDPC][SMPS-STATIC][SMPS-DYNAMIC][GF][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][RX-STBC12][RX-STBC123][DELAYED-BA][MAX-AMSDU-7935][DSSS_CCK-40][LSIG-TXOP-PROT]"}
  412. hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
  413. if "FAIL" not in hapd.request("ENABLE"):
  414. raise Exception("Unexpected ENABLE success")
  415. def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
  416. """Associated STA indicating 40 MHz intolerant"""
  417. clear_scan_cache(apdev[0]['ifname'])
  418. params = { "ssid": "intolerant",
  419. "channel": "6",
  420. "ht_capab": "[HT40-]" }
  421. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  422. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  423. raise Exception("Unexpected num_sta_ht40_intolerant value")
  424. if hapd.get_status_field("secondary_channel") != "-1":
  425. raise Exception("Unexpected secondary_channel")
  426. dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
  427. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  428. raise Exception("Unexpected num_sta_ht40_intolerant value")
  429. if hapd.get_status_field("secondary_channel") != "-1":
  430. raise Exception("Unexpected secondary_channel")
  431. dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
  432. ht40_intolerant="1")
  433. time.sleep(1)
  434. if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
  435. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
  436. if hapd.get_status_field("secondary_channel") != "0":
  437. raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
  438. dev[2].request("DISCONNECT")
  439. time.sleep(1)
  440. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  441. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
  442. if hapd.get_status_field("secondary_channel") != "-1":
  443. raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
  444. def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
  445. """Associated STA reports 40 MHz intolerant AP after association"""
  446. clear_scan_cache(apdev[0]['ifname'])
  447. params = { "ssid": "ht",
  448. "channel": "6",
  449. "ht_capab": "[HT40-]",
  450. "obss_interval": "1" }
  451. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  452. dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
  453. if hapd.get_status_field("secondary_channel") != "-1":
  454. raise Exception("Unexpected secondary channel information")
  455. logger.info("Start 40 MHz intolerant AP")
  456. params = { "ssid": "intolerant",
  457. "channel": "5",
  458. "ht_capab": "[40-INTOLERANT]" }
  459. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  460. logger.info("Waiting for co-ex report from STA")
  461. ok = False
  462. for i in range(0, 20):
  463. time.sleep(1)
  464. if hapd.get_status_field("secondary_channel") == "0":
  465. logger.info("AP moved to 20 MHz channel")
  466. ok = True
  467. break
  468. if not ok:
  469. raise Exception("AP did not move to 20 MHz channel")
  470. if "OK" not in hapd2.request("DISABLE"):
  471. raise Exception("Failed to disable 40 MHz intolerant AP")
  472. # make sure the intolerant AP disappears from scan results more quickly
  473. dev[0].scan(only_new=True)
  474. dev[0].scan(freq="2432", only_new=True)
  475. logger.info("Waiting for AP to move back to 40 MHz channel")
  476. ok = False
  477. for i in range(0, 30):
  478. time.sleep(1)
  479. if hapd.get_status_field("secondary_channel") == "-1":
  480. ok = True
  481. if not ok:
  482. raise Exception("AP did not move to 40 MHz channel")