test_ap_ht.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  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, alloc_fail
  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_table_limit(dev, apdev):
  409. """OLBC AP table size limit"""
  410. ifname1 = apdev[0]['ifname']
  411. ifname2 = apdev[0]['ifname'] + '-2'
  412. ifname3 = apdev[0]['ifname'] + '-3'
  413. hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
  414. hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
  415. hostapd.add_bss('phy3', ifname3, 'bss-3.conf')
  416. params = { "ssid": "test-olbc",
  417. "channel": "1",
  418. "ap_table_max_size": "2" }
  419. hapd = hostapd.add_ap(apdev[1]['ifname'], params)
  420. time.sleep(0.3)
  421. with alloc_fail(hapd, 1, "ap_list_process_beacon"):
  422. time.sleep(0.3)
  423. hapd.set("ap_table_max_size", "1")
  424. time.sleep(0.3)
  425. hapd.set("ap_table_max_size", "0")
  426. time.sleep(0.3)
  427. def test_olbc_5ghz(dev, apdev):
  428. """OLBC detection on 5 GHz"""
  429. try:
  430. hapd = None
  431. hapd2 = None
  432. params = { "ssid": "test-olbc",
  433. "country_code": "FI",
  434. "hw_mode": "a",
  435. "channel": "36",
  436. "ht_capab": "[HT40+]" }
  437. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  438. status = hapd.get_status()
  439. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  440. raise Exception("Unexpected OLBC information")
  441. params = { "ssid": "olbc-ap",
  442. "country_code": "FI",
  443. "hw_mode": "a",
  444. "channel": "36",
  445. "ieee80211n": "0",
  446. "wmm_enabled": "0" }
  447. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  448. found = False
  449. for i in range(20):
  450. time.sleep(0.1)
  451. status = hapd.get_status()
  452. logger.debug('olbc_ht: ' + status['olbc_ht'])
  453. if status['olbc_ht'] == '1':
  454. found = True
  455. break
  456. if not found:
  457. raise Exception("Missing OLBC information")
  458. finally:
  459. if hapd:
  460. hapd.request("DISABLE")
  461. if hapd2:
  462. hapd2.request("DISABLE")
  463. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  464. def test_ap_require_ht(dev, apdev):
  465. """Require HT"""
  466. params = { "ssid": "require-ht",
  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. dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  478. ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
  479. disable_max_amsdu="1", ampdu_factor="2",
  480. ampdu_density="1", disable_ht40="1", disable_sgi="1",
  481. disable_ldpc="1")
  482. def test_ap_require_ht_limited_rates(dev, apdev):
  483. """Require HT with limited supported rates"""
  484. params = { "ssid": "require-ht",
  485. "supported_rates": "60 120 240 360 480 540",
  486. "require_ht": "1" }
  487. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  488. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  489. disable_ht="1", wait_connect=False)
  490. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  491. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  492. if ev is None:
  493. raise Exception("Association rejection timed out")
  494. if "status_code=27" not in ev:
  495. raise Exception("Unexpected rejection status code")
  496. def test_ap_ht_capab_not_supported(dev, apdev):
  497. """HT configuration with driver not supporting all ht_capab entries"""
  498. params = { "ssid": "test-ht40",
  499. "channel": "5",
  500. "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]"}
  501. hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
  502. if "FAIL" not in hapd.request("ENABLE"):
  503. raise Exception("Unexpected ENABLE success")
  504. def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
  505. """Associated STA indicating 40 MHz intolerant"""
  506. clear_scan_cache(apdev[0]['ifname'])
  507. params = { "ssid": "intolerant",
  508. "channel": "6",
  509. "ht_capab": "[HT40-]" }
  510. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  511. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  512. raise Exception("Unexpected num_sta_ht40_intolerant value")
  513. if hapd.get_status_field("secondary_channel") != "-1":
  514. raise Exception("Unexpected secondary_channel")
  515. dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
  516. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  517. raise Exception("Unexpected num_sta_ht40_intolerant value")
  518. if hapd.get_status_field("secondary_channel") != "-1":
  519. raise Exception("Unexpected secondary_channel")
  520. dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
  521. ht40_intolerant="1")
  522. time.sleep(1)
  523. if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
  524. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
  525. if hapd.get_status_field("secondary_channel") != "0":
  526. raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
  527. dev[2].request("DISCONNECT")
  528. time.sleep(1)
  529. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  530. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
  531. if hapd.get_status_field("secondary_channel") != "-1":
  532. raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
  533. def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
  534. """Associated STA reports 40 MHz intolerant AP after association"""
  535. clear_scan_cache(apdev[0]['ifname'])
  536. params = { "ssid": "ht",
  537. "channel": "6",
  538. "ht_capab": "[HT40-]",
  539. "obss_interval": "3" }
  540. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  541. dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
  542. if hapd.get_status_field("secondary_channel") != "-1":
  543. raise Exception("Unexpected secondary channel information")
  544. logger.info("Start 40 MHz intolerant AP")
  545. params = { "ssid": "intolerant",
  546. "channel": "5",
  547. "ht_capab": "[40-INTOLERANT]" }
  548. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  549. logger.info("Waiting for co-ex report from STA")
  550. ok = False
  551. for i in range(0, 20):
  552. time.sleep(1)
  553. if hapd.get_status_field("secondary_channel") == "0":
  554. logger.info("AP moved to 20 MHz channel")
  555. ok = True
  556. break
  557. if not ok:
  558. raise Exception("AP did not move to 20 MHz channel")
  559. if "OK" not in hapd2.request("DISABLE"):
  560. raise Exception("Failed to disable 40 MHz intolerant AP")
  561. # make sure the intolerant AP disappears from scan results more quickly
  562. dev[0].scan(type="ONLY", freq="2432", only_new=True)
  563. dev[0].scan(type="ONLY", freq="2432", only_new=True)
  564. dev[0].dump_monitor()
  565. logger.info("Waiting for AP to move back to 40 MHz channel")
  566. ok = False
  567. for i in range(0, 30):
  568. time.sleep(1)
  569. if hapd.get_status_field("secondary_channel") == "-1":
  570. logger.info("AP moved to 40 MHz channel")
  571. ok = True
  572. break
  573. if not ok:
  574. raise Exception("AP did not move to 40 MHz channel")
  575. def test_ap_ht40_csa(dev, apdev):
  576. """HT with 40 MHz channel width and CSA"""
  577. csa_supported(dev[0])
  578. try:
  579. hapd = None
  580. params = { "ssid": "ht",
  581. "country_code": "US",
  582. "hw_mode": "a",
  583. "channel": "36",
  584. "ht_capab": "[HT40+]",
  585. "ieee80211n": "1" }
  586. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  587. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  588. hwsim_utils.test_connectivity(dev[0], hapd)
  589. hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
  590. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  591. if ev is None:
  592. raise Exception("CSA finished event timed out")
  593. if "freq=5200" not in ev:
  594. raise Exception("Unexpected channel in CSA finished event")
  595. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  596. if ev is not None:
  597. raise Exception("Unexpected STA disconnection during CSA")
  598. hwsim_utils.test_connectivity(dev[0], hapd)
  599. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  600. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  601. if ev is None:
  602. raise Exception("CSA finished event timed out")
  603. if "freq=5180" not in ev:
  604. raise Exception("Unexpected channel in CSA finished event")
  605. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  606. if ev is not None:
  607. raise Exception("Unexpected STA disconnection during CSA")
  608. hwsim_utils.test_connectivity(dev[0], hapd)
  609. finally:
  610. dev[0].request("DISCONNECT")
  611. if hapd:
  612. hapd.request("DISABLE")
  613. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  614. dev[0].flush_scan_cache()
  615. def test_ap_ht40_csa2(dev, apdev):
  616. """HT with 40 MHz channel width and CSA"""
  617. csa_supported(dev[0])
  618. try:
  619. hapd = None
  620. params = { "ssid": "ht",
  621. "country_code": "US",
  622. "hw_mode": "a",
  623. "channel": "36",
  624. "ht_capab": "[HT40+]",
  625. "ieee80211n": "1" }
  626. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  627. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  628. hwsim_utils.test_connectivity(dev[0], hapd)
  629. hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
  630. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  631. if ev is None:
  632. raise Exception("CSA finished event timed out")
  633. if "freq=5220" not in ev:
  634. raise Exception("Unexpected channel in CSA finished event")
  635. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  636. if ev is not None:
  637. raise Exception("Unexpected STA disconnection during CSA")
  638. hwsim_utils.test_connectivity(dev[0], hapd)
  639. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  640. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  641. if ev is None:
  642. raise Exception("CSA finished event timed out")
  643. if "freq=5180" not in ev:
  644. raise Exception("Unexpected channel in CSA finished event")
  645. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  646. if ev is not None:
  647. raise Exception("Unexpected STA disconnection during CSA")
  648. hwsim_utils.test_connectivity(dev[0], hapd)
  649. finally:
  650. dev[0].request("DISCONNECT")
  651. if hapd:
  652. hapd.request("DISABLE")
  653. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  654. dev[0].flush_scan_cache()
  655. def test_ap_ht40_csa3(dev, apdev):
  656. """HT with 40 MHz channel width and CSA"""
  657. csa_supported(dev[0])
  658. try:
  659. hapd = None
  660. params = { "ssid": "ht",
  661. "country_code": "US",
  662. "hw_mode": "a",
  663. "channel": "36",
  664. "ht_capab": "[HT40+]",
  665. "ieee80211n": "1" }
  666. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  667. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  668. hwsim_utils.test_connectivity(dev[0], hapd)
  669. hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
  670. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  671. if ev is None:
  672. raise Exception("CSA finished event timed out")
  673. if "freq=5240" not in ev:
  674. raise Exception("Unexpected channel in CSA finished event")
  675. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  676. if ev is not None:
  677. raise Exception("Unexpected STA disconnection during CSA")
  678. hwsim_utils.test_connectivity(dev[0], hapd)
  679. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  680. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  681. if ev is None:
  682. raise Exception("CSA finished event timed out")
  683. if "freq=5180" not in ev:
  684. raise Exception("Unexpected channel in CSA finished event")
  685. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  686. if ev is not None:
  687. raise Exception("Unexpected STA disconnection during CSA")
  688. hwsim_utils.test_connectivity(dev[0], hapd)
  689. finally:
  690. dev[0].request("DISCONNECT")
  691. if hapd:
  692. hapd.request("DISABLE")
  693. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  694. dev[0].flush_scan_cache()
  695. def test_ap_ht_smps(dev, apdev):
  696. """SMPS AP configuration options"""
  697. params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
  698. try:
  699. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  700. except:
  701. raise HwsimSkip("Assume mac80211_hwsim was not recent enough to support SMPS")
  702. params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
  703. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  704. dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
  705. dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
  706. hwsim_utils.test_connectivity(dev[0], hapd)
  707. hwsim_utils.test_connectivity(dev[1], hapd2)