test_ap_ht.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  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": "1" }
  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(only_new=True)
  537. dev[0].scan(freq="2432", only_new=True)
  538. logger.info("Waiting for AP to move back to 40 MHz channel")
  539. ok = False
  540. for i in range(0, 30):
  541. time.sleep(1)
  542. if hapd.get_status_field("secondary_channel") == "-1":
  543. ok = True
  544. if not ok:
  545. raise Exception("AP did not move to 40 MHz channel")
  546. def test_ap_ht40_csa(dev, apdev):
  547. """HT with 40 MHz channel width and CSA"""
  548. if not csa_supported(dev[0]):
  549. return "skip"
  550. try:
  551. hapd = None
  552. params = { "ssid": "ht",
  553. "country_code": "US",
  554. "hw_mode": "a",
  555. "channel": "36",
  556. "ht_capab": "[HT40+]",
  557. "ieee80211n": "1" }
  558. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  559. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  560. hwsim_utils.test_connectivity(dev[0], hapd)
  561. hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
  562. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  563. if ev is None:
  564. raise Exception("CSA finished event timed out")
  565. if "freq=5200" not in ev:
  566. raise Exception("Unexpected channel in CSA finished event")
  567. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  568. if ev is not None:
  569. raise Exception("Unexpected STA disconnection during CSA")
  570. hwsim_utils.test_connectivity(dev[0], hapd)
  571. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  572. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  573. if ev is None:
  574. raise Exception("CSA finished event timed out")
  575. if "freq=5180" not in ev:
  576. raise Exception("Unexpected channel in CSA finished event")
  577. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  578. if ev is not None:
  579. raise Exception("Unexpected STA disconnection during CSA")
  580. hwsim_utils.test_connectivity(dev[0], hapd)
  581. finally:
  582. dev[0].request("DISCONNECT")
  583. if hapd:
  584. hapd.request("DISABLE")
  585. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  586. dev[0].flush_scan_cache()
  587. def test_ap_ht40_csa2(dev, apdev):
  588. """HT with 40 MHz channel width and CSA"""
  589. if not csa_supported(dev[0]):
  590. return "skip"
  591. try:
  592. hapd = None
  593. params = { "ssid": "ht",
  594. "country_code": "US",
  595. "hw_mode": "a",
  596. "channel": "36",
  597. "ht_capab": "[HT40+]",
  598. "ieee80211n": "1" }
  599. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  600. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  601. hwsim_utils.test_connectivity(dev[0], hapd)
  602. hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
  603. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  604. if ev is None:
  605. raise Exception("CSA finished event timed out")
  606. if "freq=5220" not in ev:
  607. raise Exception("Unexpected channel in CSA finished event")
  608. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  609. if ev is not None:
  610. raise Exception("Unexpected STA disconnection during CSA")
  611. hwsim_utils.test_connectivity(dev[0], hapd)
  612. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  613. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  614. if ev is None:
  615. raise Exception("CSA finished event timed out")
  616. if "freq=5180" not in ev:
  617. raise Exception("Unexpected channel in CSA finished event")
  618. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  619. if ev is not None:
  620. raise Exception("Unexpected STA disconnection during CSA")
  621. hwsim_utils.test_connectivity(dev[0], hapd)
  622. finally:
  623. dev[0].request("DISCONNECT")
  624. if hapd:
  625. hapd.request("DISABLE")
  626. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  627. dev[0].flush_scan_cache()
  628. def test_ap_ht40_csa3(dev, apdev):
  629. """HT with 40 MHz channel width and CSA"""
  630. if not csa_supported(dev[0]):
  631. return "skip"
  632. try:
  633. hapd = None
  634. params = { "ssid": "ht",
  635. "country_code": "US",
  636. "hw_mode": "a",
  637. "channel": "36",
  638. "ht_capab": "[HT40+]",
  639. "ieee80211n": "1" }
  640. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  641. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  642. hwsim_utils.test_connectivity(dev[0], hapd)
  643. hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
  644. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  645. if ev is None:
  646. raise Exception("CSA finished event timed out")
  647. if "freq=5240" not in ev:
  648. raise Exception("Unexpected channel in CSA finished event")
  649. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  650. if ev is not None:
  651. raise Exception("Unexpected STA disconnection during CSA")
  652. hwsim_utils.test_connectivity(dev[0], hapd)
  653. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  654. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  655. if ev is None:
  656. raise Exception("CSA finished event timed out")
  657. if "freq=5180" not in ev:
  658. raise Exception("Unexpected channel in CSA finished event")
  659. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  660. if ev is not None:
  661. raise Exception("Unexpected STA disconnection during CSA")
  662. hwsim_utils.test_connectivity(dev[0], hapd)
  663. finally:
  664. dev[0].request("DISCONNECT")
  665. if hapd:
  666. hapd.request("DISABLE")
  667. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  668. dev[0].flush_scan_cache()
  669. def test_ap_ht_smps(dev, apdev):
  670. """SMPS AP configuration options"""
  671. params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
  672. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  673. params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
  674. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  675. dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
  676. dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
  677. hwsim_utils.test_connectivity(dev[0], hapd)
  678. hwsim_utils.test_connectivity(dev[1], hapd2)