test_ap_ht.py 22 KB

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