test_ap_ht.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  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. import hwsim_utils
  13. from test_ap_csa import csa_supported
  14. def clear_scan_cache(ifname):
  15. subprocess.call(['sudo', 'ifconfig', ifname, 'up'])
  16. subprocess.call(['sudo', 'iw', ifname, 'scan', 'freq', '2412', 'flush'])
  17. time.sleep(0.1)
  18. subprocess.call(['sudo', 'ifconfig', ifname, 'down'])
  19. def test_ap_ht40_scan(dev, apdev):
  20. """HT40 co-ex scan"""
  21. clear_scan_cache(apdev[0]['ifname'])
  22. params = { "ssid": "test-ht40",
  23. "channel": "5",
  24. "ht_capab": "[HT40-]"}
  25. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  26. state = hapd.get_status_field("state")
  27. if state != "HT_SCAN":
  28. time.sleep(0.1)
  29. state = hapd.get_status_field("state")
  30. if state != "HT_SCAN":
  31. raise Exception("Unexpected interface state - expected HT_SCAN")
  32. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  33. if not ev:
  34. raise Exception("AP setup timed out")
  35. state = hapd.get_status_field("state")
  36. if state != "ENABLED":
  37. raise Exception("Unexpected interface state - expected ENABLED")
  38. freq = hapd.get_status_field("freq")
  39. if freq != "2432":
  40. raise Exception("Unexpected frequency")
  41. pri = hapd.get_status_field("channel")
  42. if pri != "5":
  43. raise Exception("Unexpected primary channel")
  44. sec = hapd.get_status_field("secondary_channel")
  45. if sec != "-1":
  46. raise Exception("Unexpected secondary channel")
  47. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  48. def test_ap_ht40_scan_conflict(dev, apdev):
  49. """HT40 co-ex scan conflict"""
  50. clear_scan_cache(apdev[0]['ifname'])
  51. params = { "ssid": "test-ht40",
  52. "channel": "6",
  53. "ht_capab": "[HT40+]"}
  54. hostapd.add_ap(apdev[1]['ifname'], params)
  55. params = { "ssid": "test-ht40",
  56. "channel": "5",
  57. "ht_capab": "[HT40-]"}
  58. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  59. state = hapd.get_status_field("state")
  60. if state != "HT_SCAN":
  61. time.sleep(0.1)
  62. state = hapd.get_status_field("state")
  63. if state != "HT_SCAN":
  64. raise Exception("Unexpected interface state - expected HT_SCAN")
  65. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  66. if not ev:
  67. raise Exception("AP setup timed out")
  68. state = hapd.get_status_field("state")
  69. if state != "ENABLED":
  70. raise Exception("Unexpected interface state - expected ENABLED")
  71. freq = hapd.get_status_field("freq")
  72. if freq != "2432":
  73. raise Exception("Unexpected frequency")
  74. pri = hapd.get_status_field("channel")
  75. if pri != "5":
  76. raise Exception("Unexpected primary channel")
  77. sec = hapd.get_status_field("secondary_channel")
  78. if sec != "0":
  79. raise Exception("Unexpected secondary channel: " + sec)
  80. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  81. def test_ap_ht40_scan_legacy_conflict(dev, apdev):
  82. """HT40 co-ex scan conflict with legacy 20 MHz AP"""
  83. clear_scan_cache(apdev[0]['ifname'])
  84. params = { "ssid": "legacy-20",
  85. "channel": "7", "ieee80211n": "0" }
  86. hostapd.add_ap(apdev[1]['ifname'], params)
  87. params = { "ssid": "test-ht40",
  88. "channel": "5",
  89. "ht_capab": "[HT40-]"}
  90. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  91. state = hapd.get_status_field("state")
  92. if state != "HT_SCAN":
  93. time.sleep(0.1)
  94. state = hapd.get_status_field("state")
  95. if state != "HT_SCAN":
  96. raise Exception("Unexpected interface state - expected HT_SCAN")
  97. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  98. if not ev:
  99. raise Exception("AP setup timed out")
  100. state = hapd.get_status_field("state")
  101. if state != "ENABLED":
  102. raise Exception("Unexpected interface state - expected ENABLED")
  103. freq = hapd.get_status_field("freq")
  104. if freq != "2432":
  105. raise Exception("Unexpected frequency: " + freq)
  106. pri = hapd.get_status_field("channel")
  107. if pri != "5":
  108. raise Exception("Unexpected primary channel: " + pri)
  109. sec = hapd.get_status_field("secondary_channel")
  110. if sec != "0":
  111. raise Exception("Unexpected secondary channel: " + sec)
  112. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  113. def test_ap_ht40_scan_match(dev, apdev):
  114. """HT40 co-ex scan matching configuration"""
  115. clear_scan_cache(apdev[0]['ifname'])
  116. params = { "ssid": "test-ht40",
  117. "channel": "5",
  118. "ht_capab": "[HT40-]"}
  119. hostapd.add_ap(apdev[1]['ifname'], params)
  120. params = { "ssid": "test-ht40",
  121. "channel": "5",
  122. "ht_capab": "[HT40-]"}
  123. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  124. state = hapd.get_status_field("state")
  125. if state != "HT_SCAN":
  126. time.sleep(0.1)
  127. state = hapd.get_status_field("state")
  128. if state != "HT_SCAN":
  129. raise Exception("Unexpected interface state - expected HT_SCAN")
  130. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  131. if not ev:
  132. raise Exception("AP setup timed out")
  133. state = hapd.get_status_field("state")
  134. if state != "ENABLED":
  135. raise Exception("Unexpected interface state - expected ENABLED")
  136. freq = hapd.get_status_field("freq")
  137. if freq != "2432":
  138. raise Exception("Unexpected frequency")
  139. pri = hapd.get_status_field("channel")
  140. if pri != "5":
  141. raise Exception("Unexpected primary channel")
  142. sec = hapd.get_status_field("secondary_channel")
  143. if sec != "-1":
  144. raise Exception("Unexpected secondary channel: " + sec)
  145. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  146. def test_ap_ht40_5ghz_match(dev, apdev):
  147. """HT40 co-ex scan on 5 GHz with matching pri/sec channel"""
  148. clear_scan_cache(apdev[0]['ifname'])
  149. try:
  150. params = { "ssid": "test-ht40",
  151. "hw_mode": "a",
  152. "channel": "36",
  153. "country_code": "US",
  154. "ht_capab": "[HT40+]"}
  155. hostapd.add_ap(apdev[1]['ifname'], params)
  156. params = { "ssid": "test-ht40",
  157. "hw_mode": "a",
  158. "channel": "36",
  159. "ht_capab": "[HT40+]"}
  160. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  161. state = hapd.get_status_field("state")
  162. if state != "HT_SCAN":
  163. time.sleep(0.1)
  164. state = hapd.get_status_field("state")
  165. if state != "HT_SCAN":
  166. raise Exception("Unexpected interface state - expected HT_SCAN")
  167. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  168. if not ev:
  169. raise Exception("AP setup timed out")
  170. state = hapd.get_status_field("state")
  171. if state != "ENABLED":
  172. raise Exception("Unexpected interface state - expected ENABLED")
  173. freq = hapd.get_status_field("freq")
  174. if freq != "5180":
  175. raise Exception("Unexpected frequency")
  176. pri = hapd.get_status_field("channel")
  177. if pri != "36":
  178. raise Exception("Unexpected primary channel")
  179. sec = hapd.get_status_field("secondary_channel")
  180. if sec != "1":
  181. raise Exception("Unexpected secondary channel: " + sec)
  182. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  183. finally:
  184. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  185. def test_ap_ht40_5ghz_switch(dev, apdev):
  186. """HT40 co-ex scan on 5 GHz switching pri/sec channel"""
  187. clear_scan_cache(apdev[0]['ifname'])
  188. try:
  189. params = { "ssid": "test-ht40",
  190. "hw_mode": "a",
  191. "channel": "36",
  192. "country_code": "US",
  193. "ht_capab": "[HT40+]"}
  194. hostapd.add_ap(apdev[1]['ifname'], params)
  195. params = { "ssid": "test-ht40",
  196. "hw_mode": "a",
  197. "channel": "40",
  198. "ht_capab": "[HT40-]"}
  199. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  200. state = hapd.get_status_field("state")
  201. if state != "HT_SCAN":
  202. time.sleep(0.1)
  203. state = hapd.get_status_field("state")
  204. if state != "HT_SCAN":
  205. raise Exception("Unexpected interface state - expected HT_SCAN")
  206. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  207. if not ev:
  208. raise Exception("AP setup timed out")
  209. state = hapd.get_status_field("state")
  210. if state != "ENABLED":
  211. raise Exception("Unexpected interface state - expected ENABLED")
  212. freq = hapd.get_status_field("freq")
  213. if freq != "5180":
  214. raise Exception("Unexpected frequency: " + freq)
  215. pri = hapd.get_status_field("channel")
  216. if pri != "36":
  217. raise Exception("Unexpected primary channel: " + pri)
  218. sec = hapd.get_status_field("secondary_channel")
  219. if sec != "1":
  220. raise Exception("Unexpected secondary channel: " + sec)
  221. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  222. finally:
  223. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  224. def test_ap_ht40_5ghz_switch2(dev, apdev):
  225. """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
  226. clear_scan_cache(apdev[0]['ifname'])
  227. try:
  228. params = { "ssid": "test-ht40",
  229. "hw_mode": "a",
  230. "channel": "36",
  231. "country_code": "US",
  232. "ht_capab": "[HT40+]"}
  233. hostapd.add_ap(apdev[1]['ifname'], params)
  234. id = dev[0].add_network()
  235. dev[0].set_network(id, "mode", "2")
  236. dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
  237. dev[0].set_network(id, "key_mgmt", "NONE")
  238. dev[0].set_network(id, "frequency", "5200")
  239. dev[0].set_network(id, "scan_freq", "5200")
  240. dev[0].select_network(id)
  241. time.sleep(1)
  242. params = { "ssid": "test-ht40",
  243. "hw_mode": "a",
  244. "channel": "40",
  245. "ht_capab": "[HT40-]"}
  246. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  247. state = hapd.get_status_field("state")
  248. if state != "HT_SCAN":
  249. time.sleep(0.1)
  250. state = hapd.get_status_field("state")
  251. if state != "HT_SCAN":
  252. raise Exception("Unexpected interface state - expected HT_SCAN")
  253. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  254. if not ev:
  255. raise Exception("AP setup timed out")
  256. state = hapd.get_status_field("state")
  257. if state != "ENABLED":
  258. raise Exception("Unexpected interface state - expected ENABLED")
  259. freq = hapd.get_status_field("freq")
  260. if freq != "5180":
  261. raise Exception("Unexpected frequency: " + freq)
  262. pri = hapd.get_status_field("channel")
  263. if pri != "36":
  264. raise Exception("Unexpected primary channel: " + pri)
  265. sec = hapd.get_status_field("secondary_channel")
  266. if sec != "1":
  267. raise Exception("Unexpected secondary channel: " + sec)
  268. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  269. finally:
  270. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  271. def test_obss_scan(dev, apdev):
  272. """Overlapping BSS scan request"""
  273. params = { "ssid": "obss-scan",
  274. "channel": "6",
  275. "ht_capab": "[HT40-]",
  276. "obss_interval": "10" }
  277. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  278. params = { "ssid": "another-bss",
  279. "channel": "9",
  280. "ieee80211n": "0" }
  281. hostapd.add_ap(apdev[1]['ifname'], params)
  282. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  283. hapd.set("ext_mgmt_frame_handling", "1")
  284. logger.info("Waiting for OBSS scan to occur")
  285. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  286. if ev is None:
  287. raise Exception("Timed out while waiting for OBSS scan to start")
  288. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  289. if ev is None:
  290. raise Exception("Timed out while waiting for OBSS scan results")
  291. received = False
  292. for i in range(0, 4):
  293. frame = hapd.mgmt_rx(timeout=5)
  294. if frame is None:
  295. raise Exception("MGMT RX wait timed out")
  296. if frame['subtype'] != 13:
  297. continue
  298. payload = frame['payload']
  299. if len(payload) < 3:
  300. continue
  301. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  302. if category != 4:
  303. continue
  304. if action != 0:
  305. continue
  306. if ie == 72:
  307. logger.info("20/40 BSS Coexistence report received")
  308. received = True
  309. break
  310. if not received:
  311. raise Exception("20/40 BSS Coexistence report not seen")
  312. def test_obss_scan_40_intolerant(dev, apdev):
  313. """Overlapping BSS scan request with 40 MHz intolerant AP"""
  314. params = { "ssid": "obss-scan",
  315. "channel": "6",
  316. "ht_capab": "[HT40-]",
  317. "obss_interval": "10" }
  318. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  319. params = { "ssid": "another-bss",
  320. "channel": "7",
  321. "ht_capab": "[40-INTOLERANT]" }
  322. hostapd.add_ap(apdev[1]['ifname'], params)
  323. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  324. hapd.set("ext_mgmt_frame_handling", "1")
  325. logger.info("Waiting for OBSS scan to occur")
  326. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  327. if ev is None:
  328. raise Exception("Timed out while waiting for OBSS scan to start")
  329. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  330. if ev is None:
  331. raise Exception("Timed out while waiting for OBSS scan results")
  332. received = False
  333. for i in range(0, 4):
  334. frame = hapd.mgmt_rx(timeout=5)
  335. if frame is None:
  336. raise Exception("MGMT RX wait timed out")
  337. if frame['subtype'] != 13:
  338. continue
  339. payload = frame['payload']
  340. if len(payload) < 3:
  341. continue
  342. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  343. if category != 4:
  344. continue
  345. if action != 0:
  346. continue
  347. if ie == 72:
  348. logger.info("20/40 BSS Coexistence report received")
  349. received = True
  350. break
  351. if not received:
  352. raise Exception("20/40 BSS Coexistence report not seen")
  353. def test_olbc(dev, apdev):
  354. """OLBC detection"""
  355. params = { "ssid": "test-olbc",
  356. "channel": "6",
  357. "ht_capab": "[HT40-]",
  358. "ap_table_expiration_time": "2" }
  359. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  360. status = hapd.get_status()
  361. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  362. raise Exception("Unexpected OLBC information")
  363. params = { "ssid": "olbc-ap",
  364. "hw_mode": "b",
  365. "channel": "6",
  366. "wmm_enabled": "0" }
  367. hostapd.add_ap(apdev[1]['ifname'], params)
  368. time.sleep(0.5)
  369. status = hapd.get_status()
  370. if status['olbc'] != '1' or status['olbc_ht'] != '1':
  371. raise Exception("Missing OLBC information")
  372. hapd_global = hostapd.HostapdGlobal()
  373. hapd_global.remove(apdev[1]['ifname'])
  374. logger.info("Waiting for OLBC state to time out")
  375. cleared = False
  376. for i in range(0, 15):
  377. time.sleep(1)
  378. status = hapd.get_status()
  379. if status['olbc'] == '0' and status['olbc_ht'] == '0':
  380. cleared = True
  381. break
  382. if not cleared:
  383. raise Exception("OLBC state did nto time out")
  384. def test_olbc_5ghz(dev, apdev):
  385. """OLBC detection on 5 GHz"""
  386. try:
  387. params = { "ssid": "test-olbc",
  388. "country_code": "FI",
  389. "hw_mode": "a",
  390. "channel": "36",
  391. "ht_capab": "[HT40+]" }
  392. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  393. status = hapd.get_status()
  394. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  395. raise Exception("Unexpected OLBC information")
  396. params = { "ssid": "olbc-ap",
  397. "country_code": "FI",
  398. "hw_mode": "a",
  399. "channel": "36",
  400. "ieee80211n": "0",
  401. "wmm_enabled": "0" }
  402. hostapd.add_ap(apdev[1]['ifname'], params)
  403. time.sleep(0.5)
  404. status = hapd.get_status()
  405. if status['olbc_ht'] != '1':
  406. raise Exception("Missing OLBC information")
  407. finally:
  408. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  409. def test_ap_require_ht(dev, apdev):
  410. """Require HT"""
  411. params = { "ssid": "require-ht",
  412. "require_ht": "1" }
  413. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  414. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  415. disable_ht="1", wait_connect=False)
  416. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  417. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  418. if ev is None:
  419. raise Exception("Association rejection timed out")
  420. if "status_code=27" not in ev:
  421. raise Exception("Unexpected rejection status code")
  422. dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  423. ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
  424. disable_max_amsdu="1", ampdu_factor="2",
  425. ampdu_density="1", disable_ht40="1", disable_sgi="1",
  426. disable_ldpc="1")
  427. def test_ap_require_ht_limited_rates(dev, apdev):
  428. """Require HT with limited supported rates"""
  429. params = { "ssid": "require-ht",
  430. "supported_rates": "60 120 240 360 480 540",
  431. "require_ht": "1" }
  432. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  433. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  434. disable_ht="1", wait_connect=False)
  435. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  436. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  437. if ev is None:
  438. raise Exception("Association rejection timed out")
  439. if "status_code=27" not in ev:
  440. raise Exception("Unexpected rejection status code")
  441. def test_ap_ht_capab_not_supported(dev, apdev):
  442. """HT configuration with driver not supporting all ht_capab entries"""
  443. params = { "ssid": "test-ht40",
  444. "channel": "5",
  445. "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]"}
  446. hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
  447. if "FAIL" not in hapd.request("ENABLE"):
  448. raise Exception("Unexpected ENABLE success")
  449. def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
  450. """Associated STA indicating 40 MHz intolerant"""
  451. clear_scan_cache(apdev[0]['ifname'])
  452. params = { "ssid": "intolerant",
  453. "channel": "6",
  454. "ht_capab": "[HT40-]" }
  455. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  456. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  457. raise Exception("Unexpected num_sta_ht40_intolerant value")
  458. if hapd.get_status_field("secondary_channel") != "-1":
  459. raise Exception("Unexpected secondary_channel")
  460. dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
  461. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  462. raise Exception("Unexpected num_sta_ht40_intolerant value")
  463. if hapd.get_status_field("secondary_channel") != "-1":
  464. raise Exception("Unexpected secondary_channel")
  465. dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
  466. ht40_intolerant="1")
  467. time.sleep(1)
  468. if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
  469. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
  470. if hapd.get_status_field("secondary_channel") != "0":
  471. raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
  472. dev[2].request("DISCONNECT")
  473. time.sleep(1)
  474. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  475. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
  476. if hapd.get_status_field("secondary_channel") != "-1":
  477. raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
  478. def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
  479. """Associated STA reports 40 MHz intolerant AP after association"""
  480. clear_scan_cache(apdev[0]['ifname'])
  481. params = { "ssid": "ht",
  482. "channel": "6",
  483. "ht_capab": "[HT40-]",
  484. "obss_interval": "1" }
  485. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  486. dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
  487. if hapd.get_status_field("secondary_channel") != "-1":
  488. raise Exception("Unexpected secondary channel information")
  489. logger.info("Start 40 MHz intolerant AP")
  490. params = { "ssid": "intolerant",
  491. "channel": "5",
  492. "ht_capab": "[40-INTOLERANT]" }
  493. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  494. logger.info("Waiting for co-ex report from STA")
  495. ok = False
  496. for i in range(0, 20):
  497. time.sleep(1)
  498. if hapd.get_status_field("secondary_channel") == "0":
  499. logger.info("AP moved to 20 MHz channel")
  500. ok = True
  501. break
  502. if not ok:
  503. raise Exception("AP did not move to 20 MHz channel")
  504. if "OK" not in hapd2.request("DISABLE"):
  505. raise Exception("Failed to disable 40 MHz intolerant AP")
  506. # make sure the intolerant AP disappears from scan results more quickly
  507. dev[0].scan(only_new=True)
  508. dev[0].scan(freq="2432", only_new=True)
  509. logger.info("Waiting for AP to move back to 40 MHz channel")
  510. ok = False
  511. for i in range(0, 30):
  512. time.sleep(1)
  513. if hapd.get_status_field("secondary_channel") == "-1":
  514. ok = True
  515. if not ok:
  516. raise Exception("AP did not move to 40 MHz channel")
  517. def test_ap_ht40_csa(dev, apdev):
  518. """HT with 40 MHz channel width and CSA"""
  519. if not csa_supported(dev[0]):
  520. return "skip"
  521. try:
  522. params = { "ssid": "ht",
  523. "country_code": "US",
  524. "hw_mode": "a",
  525. "channel": "36",
  526. "ht_capab": "[HT40+]",
  527. "ieee80211n": "1" }
  528. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  529. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  530. hwsim_utils.test_connectivity(dev[0], hapd)
  531. hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
  532. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  533. if ev is None:
  534. raise Exception("CSA finished event timed out")
  535. if "freq=5200" not in ev:
  536. raise Exception("Unexpected channel in CSA finished event")
  537. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  538. if ev is not None:
  539. raise Exception("Unexpected STA disconnection during CSA")
  540. hwsim_utils.test_connectivity(dev[0], hapd)
  541. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  542. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  543. if ev is None:
  544. raise Exception("CSA finished event timed out")
  545. if "freq=5180" not in ev:
  546. raise Exception("Unexpected channel in CSA finished event")
  547. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  548. if ev is not None:
  549. raise Exception("Unexpected STA disconnection during CSA")
  550. hwsim_utils.test_connectivity(dev[0], hapd)
  551. finally:
  552. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  553. def test_ap_ht40_csa2(dev, apdev):
  554. """HT with 40 MHz channel width and CSA"""
  555. if not csa_supported(dev[0]):
  556. return "skip"
  557. try:
  558. params = { "ssid": "ht",
  559. "country_code": "US",
  560. "hw_mode": "a",
  561. "channel": "36",
  562. "ht_capab": "[HT40+]",
  563. "ieee80211n": "1" }
  564. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  565. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  566. hwsim_utils.test_connectivity(dev[0], hapd)
  567. hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
  568. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  569. if ev is None:
  570. raise Exception("CSA finished event timed out")
  571. if "freq=5220" not in ev:
  572. raise Exception("Unexpected channel in CSA finished event")
  573. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  574. if ev is not None:
  575. raise Exception("Unexpected STA disconnection during CSA")
  576. hwsim_utils.test_connectivity(dev[0], hapd)
  577. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  578. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  579. if ev is None:
  580. raise Exception("CSA finished event timed out")
  581. if "freq=5180" not in ev:
  582. raise Exception("Unexpected channel in CSA finished event")
  583. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  584. if ev is not None:
  585. raise Exception("Unexpected STA disconnection during CSA")
  586. hwsim_utils.test_connectivity(dev[0], hapd)
  587. finally:
  588. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  589. def test_ap_ht40_csa3(dev, apdev):
  590. """HT with 40 MHz channel width and CSA"""
  591. if not csa_supported(dev[0]):
  592. return "skip"
  593. try:
  594. params = { "ssid": "ht",
  595. "country_code": "US",
  596. "hw_mode": "a",
  597. "channel": "36",
  598. "ht_capab": "[HT40+]",
  599. "ieee80211n": "1" }
  600. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  601. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  602. hwsim_utils.test_connectivity(dev[0], hapd)
  603. hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
  604. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  605. if ev is None:
  606. raise Exception("CSA finished event timed out")
  607. if "freq=5240" not in ev:
  608. raise Exception("Unexpected channel in CSA finished event")
  609. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  610. if ev is not None:
  611. raise Exception("Unexpected STA disconnection during CSA")
  612. hwsim_utils.test_connectivity(dev[0], hapd)
  613. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  614. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  615. if ev is None:
  616. raise Exception("CSA finished event timed out")
  617. if "freq=5180" not in ev:
  618. raise Exception("Unexpected channel in CSA finished event")
  619. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  620. if ev is not None:
  621. raise Exception("Unexpected STA disconnection during CSA")
  622. hwsim_utils.test_connectivity(dev[0], hapd)
  623. finally:
  624. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])