test_ap_ht.py 29 KB

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