test_ap_ht.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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. hapd = None
  151. hapd2 = None
  152. params = { "ssid": "test-ht40",
  153. "hw_mode": "a",
  154. "channel": "36",
  155. "country_code": "US",
  156. "ht_capab": "[HT40+]"}
  157. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  158. params = { "ssid": "test-ht40",
  159. "hw_mode": "a",
  160. "channel": "36",
  161. "ht_capab": "[HT40+]"}
  162. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  163. state = hapd.get_status_field("state")
  164. if state != "HT_SCAN":
  165. time.sleep(0.1)
  166. state = hapd.get_status_field("state")
  167. if state != "HT_SCAN":
  168. raise Exception("Unexpected interface state - expected HT_SCAN")
  169. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  170. if not ev:
  171. raise Exception("AP setup timed out")
  172. state = hapd.get_status_field("state")
  173. if state != "ENABLED":
  174. raise Exception("Unexpected interface state - expected ENABLED")
  175. freq = hapd.get_status_field("freq")
  176. if freq != "5180":
  177. raise Exception("Unexpected frequency")
  178. pri = hapd.get_status_field("channel")
  179. if pri != "36":
  180. raise Exception("Unexpected primary channel")
  181. sec = hapd.get_status_field("secondary_channel")
  182. if sec != "1":
  183. raise Exception("Unexpected secondary channel: " + sec)
  184. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  185. finally:
  186. dev[0].request("DISCONNECT")
  187. if hapd:
  188. hapd.request("DISABLE")
  189. if hapd2:
  190. hapd2.request("DISABLE")
  191. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  192. dev[0].flush_scan_cache()
  193. def test_ap_ht40_5ghz_switch(dev, apdev):
  194. """HT40 co-ex scan on 5 GHz switching pri/sec channel"""
  195. clear_scan_cache(apdev[0]['ifname'])
  196. try:
  197. hapd = None
  198. hapd2 = None
  199. params = { "ssid": "test-ht40",
  200. "hw_mode": "a",
  201. "channel": "36",
  202. "country_code": "US",
  203. "ht_capab": "[HT40+]"}
  204. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  205. params = { "ssid": "test-ht40",
  206. "hw_mode": "a",
  207. "channel": "40",
  208. "ht_capab": "[HT40-]"}
  209. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  210. state = hapd.get_status_field("state")
  211. if state != "HT_SCAN":
  212. time.sleep(0.1)
  213. state = hapd.get_status_field("state")
  214. if state != "HT_SCAN":
  215. raise Exception("Unexpected interface state - expected HT_SCAN")
  216. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  217. if not ev:
  218. raise Exception("AP setup timed out")
  219. state = hapd.get_status_field("state")
  220. if state != "ENABLED":
  221. raise Exception("Unexpected interface state - expected ENABLED")
  222. freq = hapd.get_status_field("freq")
  223. if freq != "5180":
  224. raise Exception("Unexpected frequency: " + freq)
  225. pri = hapd.get_status_field("channel")
  226. if pri != "36":
  227. raise Exception("Unexpected primary channel: " + pri)
  228. sec = hapd.get_status_field("secondary_channel")
  229. if sec != "1":
  230. raise Exception("Unexpected secondary channel: " + sec)
  231. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  232. finally:
  233. dev[0].request("DISCONNECT")
  234. if hapd:
  235. hapd.request("DISABLE")
  236. if hapd2:
  237. hapd2.request("DISABLE")
  238. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  239. def test_ap_ht40_5ghz_switch2(dev, apdev):
  240. """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
  241. clear_scan_cache(apdev[0]['ifname'])
  242. try:
  243. hapd = None
  244. hapd2 = None
  245. params = { "ssid": "test-ht40",
  246. "hw_mode": "a",
  247. "channel": "36",
  248. "country_code": "US",
  249. "ht_capab": "[HT40+]"}
  250. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  251. id = dev[0].add_network()
  252. dev[0].set_network(id, "mode", "2")
  253. dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
  254. dev[0].set_network(id, "key_mgmt", "NONE")
  255. dev[0].set_network(id, "frequency", "5200")
  256. dev[0].set_network(id, "scan_freq", "5200")
  257. dev[0].select_network(id)
  258. time.sleep(1)
  259. params = { "ssid": "test-ht40",
  260. "hw_mode": "a",
  261. "channel": "40",
  262. "ht_capab": "[HT40-]"}
  263. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  264. state = hapd.get_status_field("state")
  265. if state != "HT_SCAN":
  266. time.sleep(0.1)
  267. state = hapd.get_status_field("state")
  268. if state != "HT_SCAN":
  269. raise Exception("Unexpected interface state - expected HT_SCAN")
  270. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  271. if not ev:
  272. raise Exception("AP setup timed out")
  273. state = hapd.get_status_field("state")
  274. if state != "ENABLED":
  275. raise Exception("Unexpected interface state - expected ENABLED")
  276. freq = hapd.get_status_field("freq")
  277. if freq != "5180":
  278. raise Exception("Unexpected frequency: " + freq)
  279. pri = hapd.get_status_field("channel")
  280. if pri != "36":
  281. raise Exception("Unexpected primary channel: " + pri)
  282. sec = hapd.get_status_field("secondary_channel")
  283. if sec != "1":
  284. raise Exception("Unexpected secondary channel: " + sec)
  285. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  286. finally:
  287. dev[0].request("DISCONNECT")
  288. if hapd:
  289. hapd.request("DISABLE")
  290. if hapd2:
  291. hapd2.request("DISABLE")
  292. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  293. dev[0].flush_scan_cache()
  294. def test_obss_scan(dev, apdev):
  295. """Overlapping BSS scan request"""
  296. params = { "ssid": "obss-scan",
  297. "channel": "6",
  298. "ht_capab": "[HT40-]",
  299. "obss_interval": "10" }
  300. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  301. params = { "ssid": "another-bss",
  302. "channel": "9",
  303. "ieee80211n": "0" }
  304. hostapd.add_ap(apdev[1]['ifname'], params)
  305. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  306. hapd.set("ext_mgmt_frame_handling", "1")
  307. logger.info("Waiting for OBSS scan to occur")
  308. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  309. if ev is None:
  310. raise Exception("Timed out while waiting for OBSS scan to start")
  311. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  312. if ev is None:
  313. raise Exception("Timed out while waiting for OBSS scan results")
  314. received = False
  315. for i in range(0, 4):
  316. frame = hapd.mgmt_rx(timeout=5)
  317. if frame is None:
  318. raise Exception("MGMT RX wait timed out")
  319. if frame['subtype'] != 13:
  320. continue
  321. payload = frame['payload']
  322. if len(payload) < 3:
  323. continue
  324. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  325. if category != 4:
  326. continue
  327. if action != 0:
  328. continue
  329. if ie == 72:
  330. logger.info("20/40 BSS Coexistence report received")
  331. received = True
  332. break
  333. if not received:
  334. raise Exception("20/40 BSS Coexistence report not seen")
  335. def test_obss_scan_40_intolerant(dev, apdev):
  336. """Overlapping BSS scan request with 40 MHz intolerant AP"""
  337. params = { "ssid": "obss-scan",
  338. "channel": "6",
  339. "ht_capab": "[HT40-]",
  340. "obss_interval": "10" }
  341. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  342. params = { "ssid": "another-bss",
  343. "channel": "7",
  344. "ht_capab": "[40-INTOLERANT]" }
  345. hostapd.add_ap(apdev[1]['ifname'], params)
  346. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  347. hapd.set("ext_mgmt_frame_handling", "1")
  348. logger.info("Waiting for OBSS scan to occur")
  349. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  350. if ev is None:
  351. raise Exception("Timed out while waiting for OBSS scan to start")
  352. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  353. if ev is None:
  354. raise Exception("Timed out while waiting for OBSS scan results")
  355. received = False
  356. for i in range(0, 4):
  357. frame = hapd.mgmt_rx(timeout=5)
  358. if frame is None:
  359. raise Exception("MGMT RX wait timed out")
  360. if frame['subtype'] != 13:
  361. continue
  362. payload = frame['payload']
  363. if len(payload) < 3:
  364. continue
  365. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  366. if category != 4:
  367. continue
  368. if action != 0:
  369. continue
  370. if ie == 72:
  371. logger.info("20/40 BSS Coexistence report received")
  372. received = True
  373. break
  374. if not received:
  375. raise Exception("20/40 BSS Coexistence report not seen")
  376. def test_olbc(dev, apdev):
  377. """OLBC detection"""
  378. params = { "ssid": "test-olbc",
  379. "channel": "6",
  380. "ht_capab": "[HT40-]",
  381. "ap_table_expiration_time": "2" }
  382. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  383. status = hapd.get_status()
  384. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  385. raise Exception("Unexpected OLBC information")
  386. params = { "ssid": "olbc-ap",
  387. "hw_mode": "b",
  388. "channel": "6",
  389. "wmm_enabled": "0" }
  390. hostapd.add_ap(apdev[1]['ifname'], params)
  391. time.sleep(0.5)
  392. status = hapd.get_status()
  393. if status['olbc'] != '1' or status['olbc_ht'] != '1':
  394. raise Exception("Missing OLBC information")
  395. hapd_global = hostapd.HostapdGlobal()
  396. hapd_global.remove(apdev[1]['ifname'])
  397. logger.info("Waiting for OLBC state to time out")
  398. cleared = False
  399. for i in range(0, 15):
  400. time.sleep(1)
  401. status = hapd.get_status()
  402. if status['olbc'] == '0' and status['olbc_ht'] == '0':
  403. cleared = True
  404. break
  405. if not cleared:
  406. raise Exception("OLBC state did nto time out")
  407. def test_olbc_5ghz(dev, apdev):
  408. """OLBC detection on 5 GHz"""
  409. try:
  410. hapd = None
  411. hapd2 = None
  412. params = { "ssid": "test-olbc",
  413. "country_code": "FI",
  414. "hw_mode": "a",
  415. "channel": "36",
  416. "ht_capab": "[HT40+]" }
  417. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  418. status = hapd.get_status()
  419. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  420. raise Exception("Unexpected OLBC information")
  421. params = { "ssid": "olbc-ap",
  422. "country_code": "FI",
  423. "hw_mode": "a",
  424. "channel": "36",
  425. "ieee80211n": "0",
  426. "wmm_enabled": "0" }
  427. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  428. time.sleep(0.5)
  429. status = hapd.get_status()
  430. if status['olbc_ht'] != '1':
  431. raise Exception("Missing OLBC information")
  432. finally:
  433. if hapd:
  434. hapd.request("DISABLE")
  435. if hapd2:
  436. hapd2.request("DISABLE")
  437. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  438. def test_ap_require_ht(dev, apdev):
  439. """Require HT"""
  440. params = { "ssid": "require-ht",
  441. "require_ht": "1" }
  442. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  443. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  444. disable_ht="1", wait_connect=False)
  445. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  446. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  447. if ev is None:
  448. raise Exception("Association rejection timed out")
  449. if "status_code=27" not in ev:
  450. raise Exception("Unexpected rejection status code")
  451. dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  452. ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
  453. disable_max_amsdu="1", ampdu_factor="2",
  454. ampdu_density="1", disable_ht40="1", disable_sgi="1",
  455. disable_ldpc="1")
  456. def test_ap_require_ht_limited_rates(dev, apdev):
  457. """Require HT with limited supported rates"""
  458. params = { "ssid": "require-ht",
  459. "supported_rates": "60 120 240 360 480 540",
  460. "require_ht": "1" }
  461. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  462. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  463. disable_ht="1", wait_connect=False)
  464. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  465. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  466. if ev is None:
  467. raise Exception("Association rejection timed out")
  468. if "status_code=27" not in ev:
  469. raise Exception("Unexpected rejection status code")
  470. def test_ap_ht_capab_not_supported(dev, apdev):
  471. """HT configuration with driver not supporting all ht_capab entries"""
  472. params = { "ssid": "test-ht40",
  473. "channel": "5",
  474. "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]"}
  475. hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
  476. if "FAIL" not in hapd.request("ENABLE"):
  477. raise Exception("Unexpected ENABLE success")
  478. def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
  479. """Associated STA indicating 40 MHz intolerant"""
  480. clear_scan_cache(apdev[0]['ifname'])
  481. params = { "ssid": "intolerant",
  482. "channel": "6",
  483. "ht_capab": "[HT40-]" }
  484. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  485. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  486. raise Exception("Unexpected num_sta_ht40_intolerant value")
  487. if hapd.get_status_field("secondary_channel") != "-1":
  488. raise Exception("Unexpected secondary_channel")
  489. dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
  490. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  491. raise Exception("Unexpected num_sta_ht40_intolerant value")
  492. if hapd.get_status_field("secondary_channel") != "-1":
  493. raise Exception("Unexpected secondary_channel")
  494. dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
  495. ht40_intolerant="1")
  496. time.sleep(1)
  497. if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
  498. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
  499. if hapd.get_status_field("secondary_channel") != "0":
  500. raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
  501. dev[2].request("DISCONNECT")
  502. time.sleep(1)
  503. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  504. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
  505. if hapd.get_status_field("secondary_channel") != "-1":
  506. raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
  507. def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
  508. """Associated STA reports 40 MHz intolerant AP after association"""
  509. clear_scan_cache(apdev[0]['ifname'])
  510. params = { "ssid": "ht",
  511. "channel": "6",
  512. "ht_capab": "[HT40-]",
  513. "obss_interval": "3" }
  514. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  515. dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
  516. if hapd.get_status_field("secondary_channel") != "-1":
  517. raise Exception("Unexpected secondary channel information")
  518. logger.info("Start 40 MHz intolerant AP")
  519. params = { "ssid": "intolerant",
  520. "channel": "5",
  521. "ht_capab": "[40-INTOLERANT]" }
  522. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  523. logger.info("Waiting for co-ex report from STA")
  524. ok = False
  525. for i in range(0, 20):
  526. time.sleep(1)
  527. if hapd.get_status_field("secondary_channel") == "0":
  528. logger.info("AP moved to 20 MHz channel")
  529. ok = True
  530. break
  531. if not ok:
  532. raise Exception("AP did not move to 20 MHz channel")
  533. if "OK" not in hapd2.request("DISABLE"):
  534. raise Exception("Failed to disable 40 MHz intolerant AP")
  535. # make sure the intolerant AP disappears from scan results more quickly
  536. dev[0].scan(type="ONLY", freq="2432", only_new=True)
  537. dev[0].scan(type="ONLY", freq="2432", only_new=True)
  538. dev[0].dump_monitor()
  539. logger.info("Waiting for AP to move back to 40 MHz channel")
  540. ok = False
  541. for i in range(0, 30):
  542. time.sleep(1)
  543. if hapd.get_status_field("secondary_channel") == "-1":
  544. logger.info("AP moved to 40 MHz channel")
  545. ok = True
  546. break
  547. if not ok:
  548. raise Exception("AP did not move to 40 MHz channel")
  549. def test_ap_ht40_csa(dev, apdev):
  550. """HT with 40 MHz channel width and CSA"""
  551. if not csa_supported(dev[0]):
  552. return "skip"
  553. try:
  554. hapd = None
  555. params = { "ssid": "ht",
  556. "country_code": "US",
  557. "hw_mode": "a",
  558. "channel": "36",
  559. "ht_capab": "[HT40+]",
  560. "ieee80211n": "1" }
  561. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  562. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  563. hwsim_utils.test_connectivity(dev[0], hapd)
  564. hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
  565. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  566. if ev is None:
  567. raise Exception("CSA finished event timed out")
  568. if "freq=5200" not in ev:
  569. raise Exception("Unexpected channel in CSA finished event")
  570. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  571. if ev is not None:
  572. raise Exception("Unexpected STA disconnection during CSA")
  573. hwsim_utils.test_connectivity(dev[0], hapd)
  574. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  575. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  576. if ev is None:
  577. raise Exception("CSA finished event timed out")
  578. if "freq=5180" not in ev:
  579. raise Exception("Unexpected channel in CSA finished event")
  580. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  581. if ev is not None:
  582. raise Exception("Unexpected STA disconnection during CSA")
  583. hwsim_utils.test_connectivity(dev[0], hapd)
  584. finally:
  585. dev[0].request("DISCONNECT")
  586. if hapd:
  587. hapd.request("DISABLE")
  588. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  589. dev[0].flush_scan_cache()
  590. def test_ap_ht40_csa2(dev, apdev):
  591. """HT with 40 MHz channel width and CSA"""
  592. if not csa_supported(dev[0]):
  593. return "skip"
  594. try:
  595. hapd = None
  596. params = { "ssid": "ht",
  597. "country_code": "US",
  598. "hw_mode": "a",
  599. "channel": "36",
  600. "ht_capab": "[HT40+]",
  601. "ieee80211n": "1" }
  602. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  603. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  604. hwsim_utils.test_connectivity(dev[0], hapd)
  605. hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
  606. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  607. if ev is None:
  608. raise Exception("CSA finished event timed out")
  609. if "freq=5220" not in ev:
  610. raise Exception("Unexpected channel in CSA finished event")
  611. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  612. if ev is not None:
  613. raise Exception("Unexpected STA disconnection during CSA")
  614. hwsim_utils.test_connectivity(dev[0], hapd)
  615. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  616. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  617. if ev is None:
  618. raise Exception("CSA finished event timed out")
  619. if "freq=5180" not in ev:
  620. raise Exception("Unexpected channel in CSA finished event")
  621. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  622. if ev is not None:
  623. raise Exception("Unexpected STA disconnection during CSA")
  624. hwsim_utils.test_connectivity(dev[0], hapd)
  625. finally:
  626. dev[0].request("DISCONNECT")
  627. if hapd:
  628. hapd.request("DISABLE")
  629. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  630. dev[0].flush_scan_cache()
  631. def test_ap_ht40_csa3(dev, apdev):
  632. """HT with 40 MHz channel width and CSA"""
  633. if not csa_supported(dev[0]):
  634. return "skip"
  635. try:
  636. hapd = None
  637. params = { "ssid": "ht",
  638. "country_code": "US",
  639. "hw_mode": "a",
  640. "channel": "36",
  641. "ht_capab": "[HT40+]",
  642. "ieee80211n": "1" }
  643. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  644. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  645. hwsim_utils.test_connectivity(dev[0], hapd)
  646. hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
  647. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  648. if ev is None:
  649. raise Exception("CSA finished event timed out")
  650. if "freq=5240" not in ev:
  651. raise Exception("Unexpected channel in CSA finished event")
  652. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  653. if ev is not None:
  654. raise Exception("Unexpected STA disconnection during CSA")
  655. hwsim_utils.test_connectivity(dev[0], hapd)
  656. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  657. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  658. if ev is None:
  659. raise Exception("CSA finished event timed out")
  660. if "freq=5180" not in ev:
  661. raise Exception("Unexpected channel in CSA finished event")
  662. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  663. if ev is not None:
  664. raise Exception("Unexpected STA disconnection during CSA")
  665. hwsim_utils.test_connectivity(dev[0], hapd)
  666. finally:
  667. dev[0].request("DISCONNECT")
  668. if hapd:
  669. hapd.request("DISABLE")
  670. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  671. dev[0].flush_scan_cache()
  672. def test_ap_ht_smps(dev, apdev):
  673. """SMPS AP configuration options"""
  674. params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
  675. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  676. params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
  677. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  678. dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
  679. dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
  680. hwsim_utils.test_connectivity(dev[0], hapd)
  681. hwsim_utils.test_connectivity(dev[1], hapd2)