test_ap_ht.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  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(['ifconfig', ifname, 'up'])
  17. subprocess.call(['iw', ifname, 'scan', 'freq', '2412', 'flush'])
  18. time.sleep(0.1)
  19. subprocess.call(['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(['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(['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(['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_obss_coex_report_handling(dev, apdev):
  378. """Overlapping BSS scan report handling with obss_interval=0"""
  379. clear_scan_cache(apdev[0]['ifname'])
  380. params = { "ssid": "obss-scan",
  381. "channel": "6",
  382. "ht_capab": "[HT40-]" }
  383. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  384. bssid = apdev[0]['bssid']
  385. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  386. sec = hapd.get_status_field("secondary_channel")
  387. if sec != "-1":
  388. raise Exception("AP is not using 40 MHz channel")
  389. # 20/40 MHz co-ex report tests: number of invalid reports and a valid report
  390. # that forces 20 MHz channel.
  391. tests = [ '0400', '040048', '04004801', '0400480000', '0400490100',
  392. '040048ff0000', '04004801ff49ff00', '04004801004900',
  393. '0400480100490101', '0400480100490201ff',
  394. '040048010449020005' ]
  395. for msg in tests:
  396. req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg)
  397. if "OK" not in dev[0].request(req):
  398. raise Exception("Could not send management frame")
  399. time.sleep(0.5)
  400. sec = hapd.get_status_field("secondary_channel")
  401. if sec != "0":
  402. raise Exception("AP did not move to 20 MHz channel")
  403. def test_obss_coex_report_handling1(dev, apdev):
  404. """Overlapping BSS scan report handling with obss_interval=1"""
  405. clear_scan_cache(apdev[0]['ifname'])
  406. params = { "ssid": "obss-scan",
  407. "channel": "6",
  408. "ht_capab": "[HT40+]",
  409. "obss_interval": "1" }
  410. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  411. bssid = apdev[0]['bssid']
  412. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  413. sec = hapd.get_status_field("secondary_channel")
  414. if sec != "1":
  415. raise Exception("AP is not using 40 MHz channel")
  416. # 20/40 MHz co-ex report forcing 20 MHz channel
  417. msg = '040048010449020005'
  418. req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg)
  419. if "OK" not in dev[0].request(req):
  420. raise Exception("Could not send management frame")
  421. time.sleep(0.5)
  422. sec = hapd.get_status_field("secondary_channel")
  423. if sec != "0":
  424. raise Exception("AP did not move to 20 MHz channel")
  425. # No 20/40 MHz co-ex reports forcing 20 MHz channel during next interval
  426. for i in range(20):
  427. sec = hapd.get_status_field("secondary_channel")
  428. if sec == "1":
  429. break
  430. time.sleep(0.5)
  431. if sec != "1":
  432. raise Exception("AP did not return to 40 MHz channel")
  433. def test_olbc(dev, apdev):
  434. """OLBC detection"""
  435. params = { "ssid": "test-olbc",
  436. "channel": "6",
  437. "ht_capab": "[HT40-]",
  438. "ap_table_expiration_time": "2" }
  439. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  440. status = hapd.get_status()
  441. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  442. raise Exception("Unexpected OLBC information")
  443. params = { "ssid": "olbc-ap",
  444. "hw_mode": "b",
  445. "channel": "6",
  446. "wmm_enabled": "0" }
  447. hostapd.add_ap(apdev[1]['ifname'], params)
  448. time.sleep(0.5)
  449. status = hapd.get_status()
  450. if status['olbc'] != '1' or status['olbc_ht'] != '1':
  451. raise Exception("Missing OLBC information")
  452. hapd_global = hostapd.HostapdGlobal()
  453. hapd_global.remove(apdev[1]['ifname'])
  454. logger.info("Waiting for OLBC state to time out")
  455. cleared = False
  456. for i in range(0, 15):
  457. time.sleep(1)
  458. status = hapd.get_status()
  459. if status['olbc'] == '0' and status['olbc_ht'] == '0':
  460. cleared = True
  461. break
  462. if not cleared:
  463. raise Exception("OLBC state did nto time out")
  464. def test_olbc_table_limit(dev, apdev):
  465. """OLBC AP table size limit"""
  466. ifname1 = apdev[0]['ifname']
  467. ifname2 = apdev[0]['ifname'] + '-2'
  468. ifname3 = apdev[0]['ifname'] + '-3'
  469. hostapd.add_bss('phy3', ifname1, 'bss-1.conf')
  470. hostapd.add_bss('phy3', ifname2, 'bss-2.conf')
  471. hostapd.add_bss('phy3', ifname3, 'bss-3.conf')
  472. params = { "ssid": "test-olbc",
  473. "channel": "1",
  474. "ap_table_max_size": "2" }
  475. hapd = hostapd.add_ap(apdev[1]['ifname'], params)
  476. time.sleep(0.3)
  477. with alloc_fail(hapd, 1, "ap_list_process_beacon"):
  478. time.sleep(0.3)
  479. hapd.set("ap_table_max_size", "1")
  480. time.sleep(0.3)
  481. hapd.set("ap_table_max_size", "0")
  482. time.sleep(0.3)
  483. def test_olbc_5ghz(dev, apdev):
  484. """OLBC detection on 5 GHz"""
  485. try:
  486. hapd = None
  487. hapd2 = None
  488. params = { "ssid": "test-olbc",
  489. "country_code": "FI",
  490. "hw_mode": "a",
  491. "channel": "36",
  492. "ht_capab": "[HT40+]" }
  493. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  494. status = hapd.get_status()
  495. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  496. raise Exception("Unexpected OLBC information")
  497. params = { "ssid": "olbc-ap",
  498. "country_code": "FI",
  499. "hw_mode": "a",
  500. "channel": "36",
  501. "ieee80211n": "0",
  502. "wmm_enabled": "0" }
  503. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  504. found = False
  505. for i in range(20):
  506. time.sleep(0.1)
  507. status = hapd.get_status()
  508. logger.debug('olbc_ht: ' + status['olbc_ht'])
  509. if status['olbc_ht'] == '1':
  510. found = True
  511. break
  512. if not found:
  513. raise Exception("Missing OLBC information")
  514. finally:
  515. if hapd:
  516. hapd.request("DISABLE")
  517. if hapd2:
  518. hapd2.request("DISABLE")
  519. subprocess.call(['iw', 'reg', 'set', '00'])
  520. def test_ap_require_ht(dev, apdev):
  521. """Require HT"""
  522. params = { "ssid": "require-ht",
  523. "require_ht": "1" }
  524. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  525. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  526. disable_ht="1", wait_connect=False)
  527. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  528. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  529. if ev is None:
  530. raise Exception("Association rejection timed out")
  531. if "status_code=27" not in ev:
  532. raise Exception("Unexpected rejection status code")
  533. dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  534. ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
  535. disable_max_amsdu="1", ampdu_factor="2",
  536. ampdu_density="1", disable_ht40="1", disable_sgi="1",
  537. disable_ldpc="1")
  538. def test_ap_require_ht_limited_rates(dev, apdev):
  539. """Require HT with limited supported rates"""
  540. params = { "ssid": "require-ht",
  541. "supported_rates": "60 120 240 360 480 540",
  542. "require_ht": "1" }
  543. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  544. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  545. disable_ht="1", wait_connect=False)
  546. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  547. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  548. if ev is None:
  549. raise Exception("Association rejection timed out")
  550. if "status_code=27" not in ev:
  551. raise Exception("Unexpected rejection status code")
  552. def test_ap_ht_capab_not_supported(dev, apdev):
  553. """HT configuration with driver not supporting all ht_capab entries"""
  554. params = { "ssid": "test-ht40",
  555. "channel": "5",
  556. "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]"}
  557. hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
  558. if "FAIL" not in hapd.request("ENABLE"):
  559. raise Exception("Unexpected ENABLE success")
  560. def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
  561. """Associated STA indicating 40 MHz intolerant"""
  562. clear_scan_cache(apdev[0]['ifname'])
  563. params = { "ssid": "intolerant",
  564. "channel": "6",
  565. "ht_capab": "[HT40-]" }
  566. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  567. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  568. raise Exception("Unexpected num_sta_ht40_intolerant value")
  569. if hapd.get_status_field("secondary_channel") != "-1":
  570. raise Exception("Unexpected secondary_channel")
  571. dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
  572. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  573. raise Exception("Unexpected num_sta_ht40_intolerant value")
  574. if hapd.get_status_field("secondary_channel") != "-1":
  575. raise Exception("Unexpected secondary_channel")
  576. dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
  577. ht40_intolerant="1")
  578. time.sleep(1)
  579. if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
  580. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
  581. if hapd.get_status_field("secondary_channel") != "0":
  582. raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
  583. dev[2].request("DISCONNECT")
  584. time.sleep(1)
  585. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  586. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
  587. if hapd.get_status_field("secondary_channel") != "-1":
  588. raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
  589. def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
  590. """Associated STA reports 40 MHz intolerant AP after association"""
  591. clear_scan_cache(apdev[0]['ifname'])
  592. params = { "ssid": "ht",
  593. "channel": "6",
  594. "ht_capab": "[HT40-]",
  595. "obss_interval": "3" }
  596. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  597. dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
  598. if hapd.get_status_field("secondary_channel") != "-1":
  599. raise Exception("Unexpected secondary channel information")
  600. logger.info("Start 40 MHz intolerant AP")
  601. params = { "ssid": "intolerant",
  602. "channel": "5",
  603. "ht_capab": "[40-INTOLERANT]" }
  604. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  605. logger.info("Waiting for co-ex report from STA")
  606. ok = False
  607. for i in range(0, 20):
  608. time.sleep(1)
  609. if hapd.get_status_field("secondary_channel") == "0":
  610. logger.info("AP moved to 20 MHz channel")
  611. ok = True
  612. break
  613. if not ok:
  614. raise Exception("AP did not move to 20 MHz channel")
  615. if "OK" not in hapd2.request("DISABLE"):
  616. raise Exception("Failed to disable 40 MHz intolerant AP")
  617. # make sure the intolerant AP disappears from scan results more quickly
  618. dev[0].scan(type="ONLY", freq="2432", only_new=True)
  619. dev[0].scan(type="ONLY", freq="2432", only_new=True)
  620. dev[0].dump_monitor()
  621. logger.info("Waiting for AP to move back to 40 MHz channel")
  622. ok = False
  623. for i in range(0, 30):
  624. time.sleep(1)
  625. if hapd.get_status_field("secondary_channel") == "-1":
  626. logger.info("AP moved to 40 MHz channel")
  627. ok = True
  628. break
  629. if not ok:
  630. raise Exception("AP did not move to 40 MHz channel")
  631. def test_ap_ht40_csa(dev, apdev):
  632. """HT with 40 MHz channel width and CSA"""
  633. csa_supported(dev[0])
  634. try:
  635. hapd = None
  636. params = { "ssid": "ht",
  637. "country_code": "US",
  638. "hw_mode": "a",
  639. "channel": "36",
  640. "ht_capab": "[HT40+]",
  641. "ieee80211n": "1" }
  642. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  643. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  644. hwsim_utils.test_connectivity(dev[0], hapd)
  645. hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
  646. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  647. if ev is None:
  648. raise Exception("CSA finished event timed out")
  649. if "freq=5200" not in ev:
  650. raise Exception("Unexpected channel in CSA finished event")
  651. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  652. if ev is not None:
  653. raise Exception("Unexpected STA disconnection during CSA")
  654. hwsim_utils.test_connectivity(dev[0], hapd)
  655. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  656. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  657. if ev is None:
  658. raise Exception("CSA finished event timed out")
  659. if "freq=5180" not in ev:
  660. raise Exception("Unexpected channel in CSA finished event")
  661. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  662. if ev is not None:
  663. raise Exception("Unexpected STA disconnection during CSA")
  664. hwsim_utils.test_connectivity(dev[0], hapd)
  665. finally:
  666. dev[0].request("DISCONNECT")
  667. if hapd:
  668. hapd.request("DISABLE")
  669. subprocess.call(['iw', 'reg', 'set', '00'])
  670. dev[0].flush_scan_cache()
  671. def test_ap_ht40_csa2(dev, apdev):
  672. """HT with 40 MHz channel width and CSA"""
  673. csa_supported(dev[0])
  674. try:
  675. hapd = None
  676. params = { "ssid": "ht",
  677. "country_code": "US",
  678. "hw_mode": "a",
  679. "channel": "36",
  680. "ht_capab": "[HT40+]",
  681. "ieee80211n": "1" }
  682. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  683. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  684. hwsim_utils.test_connectivity(dev[0], hapd)
  685. hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
  686. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  687. if ev is None:
  688. raise Exception("CSA finished event timed out")
  689. if "freq=5220" not in ev:
  690. raise Exception("Unexpected channel in CSA finished event")
  691. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  692. if ev is not None:
  693. raise Exception("Unexpected STA disconnection during CSA")
  694. hwsim_utils.test_connectivity(dev[0], hapd)
  695. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  696. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  697. if ev is None:
  698. raise Exception("CSA finished event timed out")
  699. if "freq=5180" not in ev:
  700. raise Exception("Unexpected channel in CSA finished event")
  701. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  702. if ev is not None:
  703. raise Exception("Unexpected STA disconnection during CSA")
  704. hwsim_utils.test_connectivity(dev[0], hapd)
  705. finally:
  706. dev[0].request("DISCONNECT")
  707. if hapd:
  708. hapd.request("DISABLE")
  709. subprocess.call(['iw', 'reg', 'set', '00'])
  710. dev[0].flush_scan_cache()
  711. def test_ap_ht40_csa3(dev, apdev):
  712. """HT with 40 MHz channel width and CSA"""
  713. csa_supported(dev[0])
  714. try:
  715. hapd = None
  716. params = { "ssid": "ht",
  717. "country_code": "US",
  718. "hw_mode": "a",
  719. "channel": "36",
  720. "ht_capab": "[HT40+]",
  721. "ieee80211n": "1" }
  722. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  723. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  724. hwsim_utils.test_connectivity(dev[0], hapd)
  725. hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
  726. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  727. if ev is None:
  728. raise Exception("CSA finished event timed out")
  729. if "freq=5240" not in ev:
  730. raise Exception("Unexpected channel in CSA finished event")
  731. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  732. if ev is not None:
  733. raise Exception("Unexpected STA disconnection during CSA")
  734. hwsim_utils.test_connectivity(dev[0], hapd)
  735. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  736. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  737. if ev is None:
  738. raise Exception("CSA finished event timed out")
  739. if "freq=5180" not in ev:
  740. raise Exception("Unexpected channel in CSA finished event")
  741. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  742. if ev is not None:
  743. raise Exception("Unexpected STA disconnection during CSA")
  744. hwsim_utils.test_connectivity(dev[0], hapd)
  745. finally:
  746. dev[0].request("DISCONNECT")
  747. if hapd:
  748. hapd.request("DISABLE")
  749. subprocess.call(['iw', 'reg', 'set', '00'])
  750. dev[0].flush_scan_cache()
  751. def test_ap_ht_smps(dev, apdev):
  752. """SMPS AP configuration options"""
  753. params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
  754. try:
  755. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  756. except:
  757. raise HwsimSkip("Assume mac80211_hwsim was not recent enough to support SMPS")
  758. params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
  759. hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
  760. dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
  761. dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
  762. hwsim_utils.test_connectivity(dev[0], hapd)
  763. hwsim_utils.test_connectivity(dev[1], hapd2)