test_ap_ht.py 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200
  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(apdev):
  16. ifname = apdev['ifname']
  17. subprocess.call(['ifconfig', ifname, 'up'])
  18. subprocess.call(['iw', ifname, 'scan', 'trigger', 'freq', '2412', 'flush'])
  19. time.sleep(0.1)
  20. subprocess.call(['ifconfig', ifname, 'down'])
  21. def test_ap_ht40_scan(dev, apdev):
  22. """HT40 co-ex scan"""
  23. clear_scan_cache(apdev[0])
  24. params = { "ssid": "test-ht40",
  25. "channel": "5",
  26. "ht_capab": "[HT40-]"}
  27. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  28. state = hapd.get_status_field("state")
  29. if state != "HT_SCAN":
  30. time.sleep(0.1)
  31. state = hapd.get_status_field("state")
  32. if state != "HT_SCAN":
  33. raise Exception("Unexpected interface state - expected HT_SCAN")
  34. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  35. if not ev:
  36. raise Exception("AP setup timed out")
  37. state = hapd.get_status_field("state")
  38. if state != "ENABLED":
  39. raise Exception("Unexpected interface state - expected ENABLED")
  40. freq = hapd.get_status_field("freq")
  41. if freq != "2432":
  42. raise Exception("Unexpected frequency")
  43. pri = hapd.get_status_field("channel")
  44. if pri != "5":
  45. raise Exception("Unexpected primary channel")
  46. sec = hapd.get_status_field("secondary_channel")
  47. if sec != "-1":
  48. raise Exception("Unexpected secondary channel")
  49. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  50. def test_ap_ht40_scan_conflict(dev, apdev):
  51. """HT40 co-ex scan conflict"""
  52. clear_scan_cache(apdev[0])
  53. params = { "ssid": "test-ht40",
  54. "channel": "6",
  55. "ht_capab": "[HT40+]"}
  56. hostapd.add_ap(apdev[1], params)
  57. params = { "ssid": "test-ht40",
  58. "channel": "5",
  59. "ht_capab": "[HT40-]"}
  60. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  61. state = hapd.get_status_field("state")
  62. if state != "HT_SCAN":
  63. time.sleep(0.1)
  64. state = hapd.get_status_field("state")
  65. if state != "HT_SCAN":
  66. raise Exception("Unexpected interface state - expected HT_SCAN")
  67. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  68. if not ev:
  69. raise Exception("AP setup timed out")
  70. state = hapd.get_status_field("state")
  71. if state != "ENABLED":
  72. raise Exception("Unexpected interface state - expected ENABLED")
  73. freq = hapd.get_status_field("freq")
  74. if freq != "2432":
  75. raise Exception("Unexpected frequency")
  76. pri = hapd.get_status_field("channel")
  77. if pri != "5":
  78. raise Exception("Unexpected primary channel")
  79. sec = hapd.get_status_field("secondary_channel")
  80. if sec != "0":
  81. raise Exception("Unexpected secondary channel: " + sec)
  82. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  83. def test_ap_ht40_scan_conflict2(dev, apdev):
  84. """HT40 co-ex scan conflict (HT40-)"""
  85. clear_scan_cache(apdev[0])
  86. params = { "ssid": "test-ht40",
  87. "channel": "11",
  88. "ht_capab": "[HT40-]"}
  89. hostapd.add_ap(apdev[1], params)
  90. params = { "ssid": "test-ht40",
  91. "channel": "1",
  92. "ht_capab": "[HT40+]"}
  93. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  94. state = hapd.get_status_field("state")
  95. if state != "HT_SCAN":
  96. time.sleep(0.1)
  97. state = hapd.get_status_field("state")
  98. if state != "HT_SCAN":
  99. raise Exception("Unexpected interface state - expected HT_SCAN")
  100. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  101. if not ev:
  102. raise Exception("AP setup timed out")
  103. state = hapd.get_status_field("state")
  104. if state != "ENABLED":
  105. raise Exception("Unexpected interface state - expected ENABLED")
  106. freq = hapd.get_status_field("freq")
  107. if freq != "2412":
  108. raise Exception("Unexpected frequency")
  109. pri = hapd.get_status_field("channel")
  110. if pri != "1":
  111. raise Exception("Unexpected primary channel")
  112. sec = hapd.get_status_field("secondary_channel")
  113. if sec != "0":
  114. raise Exception("Unexpected secondary channel: " + sec)
  115. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  116. def test_ap_ht40_scan_not_affected(dev, apdev):
  117. """HT40 co-ex scan and other BSS not affected"""
  118. clear_scan_cache(apdev[0])
  119. params = { "ssid": "test-ht20",
  120. "channel": "11" }
  121. hostapd.add_ap(apdev[1], params)
  122. subprocess.call(['ifconfig', apdev[0]['ifname'], 'up'])
  123. subprocess.call(['iw', apdev[0]['ifname'], 'scan', 'trigger', 'freq', '2462'])
  124. time.sleep(0.5)
  125. subprocess.call(['iw', apdev[0]['ifname'], 'scan', 'dump'],
  126. stdout=open('/dev/null', 'w'))
  127. time.sleep(0.1)
  128. subprocess.call(['ifconfig', apdev[0]['ifname'], 'down'])
  129. params = { "ssid": "test-ht40",
  130. "channel": "1",
  131. "ht_capab": "[HT40+]"}
  132. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  133. state = hapd.get_status_field("state")
  134. if state != "HT_SCAN":
  135. time.sleep(0.1)
  136. state = hapd.get_status_field("state")
  137. if state != "HT_SCAN":
  138. raise Exception("Unexpected interface state - expected HT_SCAN")
  139. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  140. if not ev:
  141. raise Exception("AP setup timed out")
  142. state = hapd.get_status_field("state")
  143. if state != "ENABLED":
  144. raise Exception("Unexpected interface state - expected ENABLED")
  145. freq = hapd.get_status_field("freq")
  146. if freq != "2412":
  147. raise Exception("Unexpected frequency")
  148. pri = hapd.get_status_field("channel")
  149. if pri != "1":
  150. raise Exception("Unexpected primary channel")
  151. sec = hapd.get_status_field("secondary_channel")
  152. if sec != "1":
  153. raise Exception("Unexpected secondary channel: " + sec)
  154. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  155. def test_ap_ht40_scan_legacy_conflict(dev, apdev):
  156. """HT40 co-ex scan conflict with legacy 20 MHz AP"""
  157. clear_scan_cache(apdev[0])
  158. params = { "ssid": "legacy-20",
  159. "channel": "7", "ieee80211n": "0" }
  160. hostapd.add_ap(apdev[1], params)
  161. params = { "ssid": "test-ht40",
  162. "channel": "5",
  163. "ht_capab": "[HT40-]"}
  164. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  165. state = hapd.get_status_field("state")
  166. if state != "HT_SCAN":
  167. time.sleep(0.1)
  168. state = hapd.get_status_field("state")
  169. if state != "HT_SCAN":
  170. raise Exception("Unexpected interface state - expected HT_SCAN")
  171. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  172. if not ev:
  173. raise Exception("AP setup timed out")
  174. state = hapd.get_status_field("state")
  175. if state != "ENABLED":
  176. raise Exception("Unexpected interface state - expected ENABLED")
  177. freq = hapd.get_status_field("freq")
  178. if freq != "2432":
  179. raise Exception("Unexpected frequency: " + freq)
  180. pri = hapd.get_status_field("channel")
  181. if pri != "5":
  182. raise Exception("Unexpected primary channel: " + pri)
  183. sec = hapd.get_status_field("secondary_channel")
  184. if sec != "0":
  185. raise Exception("Unexpected secondary channel: " + sec)
  186. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  187. def test_ap_ht40_scan_ht20_conflict(dev, apdev):
  188. """HT40 co-ex scan conflict with HT 20 MHz AP"""
  189. clear_scan_cache(apdev[0])
  190. params = { "ssid": "ht-20",
  191. "channel": "7", "ieee80211n": "1" }
  192. hostapd.add_ap(apdev[1], params)
  193. params = { "ssid": "test-ht40",
  194. "channel": "5",
  195. "ht_capab": "[HT40-]"}
  196. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  197. state = hapd.get_status_field("state")
  198. if state != "HT_SCAN":
  199. time.sleep(0.1)
  200. state = hapd.get_status_field("state")
  201. if state != "HT_SCAN":
  202. raise Exception("Unexpected interface state - expected HT_SCAN")
  203. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  204. if not ev:
  205. raise Exception("AP setup timed out")
  206. state = hapd.get_status_field("state")
  207. if state != "ENABLED":
  208. raise Exception("Unexpected interface state - expected ENABLED")
  209. freq = hapd.get_status_field("freq")
  210. if freq != "2432":
  211. raise Exception("Unexpected frequency: " + freq)
  212. pri = hapd.get_status_field("channel")
  213. if pri != "5":
  214. raise Exception("Unexpected primary channel: " + pri)
  215. sec = hapd.get_status_field("secondary_channel")
  216. if sec != "0":
  217. raise Exception("Unexpected secondary channel: " + sec)
  218. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  219. def test_ap_ht40_scan_intolerant(dev, apdev):
  220. """HT40 co-ex scan finding an AP advertising 40 MHz intolerant"""
  221. clear_scan_cache(apdev[0])
  222. params = { "ssid": "another-bss",
  223. "channel": "1",
  224. "ht_capab": "[40-INTOLERANT]" }
  225. hostapd.add_ap(apdev[1], params)
  226. params = { "ssid": "test-ht40",
  227. "channel": "1",
  228. "ht_capab": "[HT40+]"}
  229. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  230. state = hapd.get_status_field("state")
  231. if state != "HT_SCAN":
  232. time.sleep(0.1)
  233. state = hapd.get_status_field("state")
  234. if state != "HT_SCAN":
  235. raise Exception("Unexpected interface state - expected HT_SCAN")
  236. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  237. if not ev:
  238. raise Exception("AP setup timed out")
  239. state = hapd.get_status_field("state")
  240. if state != "ENABLED":
  241. raise Exception("Unexpected interface state - expected ENABLED")
  242. freq = hapd.get_status_field("freq")
  243. if freq != "2412":
  244. raise Exception("Unexpected frequency: " + freq)
  245. pri = hapd.get_status_field("channel")
  246. if pri != "1":
  247. raise Exception("Unexpected primary channel: " + pri)
  248. sec = hapd.get_status_field("secondary_channel")
  249. if sec != "0":
  250. raise Exception("Unexpected secondary channel: " + sec)
  251. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  252. def test_ap_ht40_scan_match(dev, apdev):
  253. """HT40 co-ex scan matching configuration"""
  254. clear_scan_cache(apdev[0])
  255. params = { "ssid": "test-ht40",
  256. "channel": "5",
  257. "ht_capab": "[HT40-]"}
  258. hostapd.add_ap(apdev[1], params)
  259. params = { "ssid": "test-ht40",
  260. "channel": "5",
  261. "ht_capab": "[HT40-]"}
  262. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  263. state = hapd.get_status_field("state")
  264. if state != "HT_SCAN":
  265. time.sleep(0.1)
  266. state = hapd.get_status_field("state")
  267. if state != "HT_SCAN":
  268. raise Exception("Unexpected interface state - expected HT_SCAN")
  269. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  270. if not ev:
  271. raise Exception("AP setup timed out")
  272. state = hapd.get_status_field("state")
  273. if state != "ENABLED":
  274. raise Exception("Unexpected interface state - expected ENABLED")
  275. freq = hapd.get_status_field("freq")
  276. if freq != "2432":
  277. raise Exception("Unexpected frequency")
  278. pri = hapd.get_status_field("channel")
  279. if pri != "5":
  280. raise Exception("Unexpected primary channel")
  281. sec = hapd.get_status_field("secondary_channel")
  282. if sec != "-1":
  283. raise Exception("Unexpected secondary channel: " + sec)
  284. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  285. def test_ap_ht40_5ghz_match(dev, apdev):
  286. """HT40 co-ex scan on 5 GHz with matching pri/sec channel"""
  287. clear_scan_cache(apdev[0])
  288. try:
  289. hapd = None
  290. hapd2 = None
  291. params = { "ssid": "test-ht40",
  292. "hw_mode": "a",
  293. "channel": "36",
  294. "country_code": "US",
  295. "ht_capab": "[HT40+]"}
  296. hapd2 = hostapd.add_ap(apdev[1], params)
  297. params = { "ssid": "test-ht40",
  298. "hw_mode": "a",
  299. "channel": "36",
  300. "ht_capab": "[HT40+]"}
  301. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  302. state = hapd.get_status_field("state")
  303. if state != "HT_SCAN":
  304. time.sleep(0.1)
  305. state = hapd.get_status_field("state")
  306. if state != "HT_SCAN":
  307. raise Exception("Unexpected interface state - expected HT_SCAN")
  308. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  309. if not ev:
  310. raise Exception("AP setup timed out")
  311. state = hapd.get_status_field("state")
  312. if state != "ENABLED":
  313. raise Exception("Unexpected interface state - expected ENABLED")
  314. freq = hapd.get_status_field("freq")
  315. if freq != "5180":
  316. raise Exception("Unexpected frequency")
  317. pri = hapd.get_status_field("channel")
  318. if pri != "36":
  319. raise Exception("Unexpected primary channel")
  320. sec = hapd.get_status_field("secondary_channel")
  321. if sec != "1":
  322. raise Exception("Unexpected secondary channel: " + sec)
  323. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  324. finally:
  325. dev[0].request("DISCONNECT")
  326. if hapd:
  327. hapd.request("DISABLE")
  328. if hapd2:
  329. hapd2.request("DISABLE")
  330. subprocess.call(['iw', 'reg', 'set', '00'])
  331. dev[0].flush_scan_cache()
  332. def test_ap_ht40_5ghz_switch(dev, apdev):
  333. """HT40 co-ex scan on 5 GHz switching pri/sec channel"""
  334. clear_scan_cache(apdev[0])
  335. try:
  336. hapd = None
  337. hapd2 = None
  338. params = { "ssid": "test-ht40",
  339. "hw_mode": "a",
  340. "channel": "36",
  341. "country_code": "US",
  342. "ht_capab": "[HT40+]"}
  343. hapd2 = hostapd.add_ap(apdev[1], params)
  344. params = { "ssid": "test-ht40",
  345. "hw_mode": "a",
  346. "channel": "40",
  347. "ht_capab": "[HT40-]"}
  348. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  349. state = hapd.get_status_field("state")
  350. if state != "HT_SCAN":
  351. time.sleep(0.1)
  352. state = hapd.get_status_field("state")
  353. if state != "HT_SCAN":
  354. raise Exception("Unexpected interface state - expected HT_SCAN")
  355. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  356. if not ev:
  357. raise Exception("AP setup timed out")
  358. state = hapd.get_status_field("state")
  359. if state != "ENABLED":
  360. raise Exception("Unexpected interface state - expected ENABLED")
  361. freq = hapd.get_status_field("freq")
  362. if freq != "5180":
  363. raise Exception("Unexpected frequency: " + freq)
  364. pri = hapd.get_status_field("channel")
  365. if pri != "36":
  366. raise Exception("Unexpected primary channel: " + pri)
  367. sec = hapd.get_status_field("secondary_channel")
  368. if sec != "1":
  369. raise Exception("Unexpected secondary channel: " + sec)
  370. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  371. finally:
  372. dev[0].request("DISCONNECT")
  373. if hapd:
  374. hapd.request("DISABLE")
  375. if hapd2:
  376. hapd2.request("DISABLE")
  377. subprocess.call(['iw', 'reg', 'set', '00'])
  378. def test_ap_ht40_5ghz_switch2(dev, apdev):
  379. """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
  380. clear_scan_cache(apdev[0])
  381. try:
  382. hapd = None
  383. hapd2 = None
  384. params = { "ssid": "test-ht40",
  385. "hw_mode": "a",
  386. "channel": "36",
  387. "country_code": "US",
  388. "ht_capab": "[HT40+]"}
  389. hapd2 = hostapd.add_ap(apdev[1], params)
  390. id = dev[0].add_network()
  391. dev[0].set_network(id, "mode", "2")
  392. dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
  393. dev[0].set_network(id, "key_mgmt", "NONE")
  394. dev[0].set_network(id, "frequency", "5200")
  395. dev[0].set_network(id, "scan_freq", "5200")
  396. dev[0].select_network(id)
  397. time.sleep(1)
  398. params = { "ssid": "test-ht40",
  399. "hw_mode": "a",
  400. "channel": "40",
  401. "ht_capab": "[HT40-]"}
  402. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  403. state = hapd.get_status_field("state")
  404. if state != "HT_SCAN":
  405. time.sleep(0.1)
  406. state = hapd.get_status_field("state")
  407. if state != "HT_SCAN":
  408. raise Exception("Unexpected interface state - expected HT_SCAN")
  409. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  410. if not ev:
  411. raise Exception("AP setup timed out")
  412. state = hapd.get_status_field("state")
  413. if state != "ENABLED":
  414. raise Exception("Unexpected interface state - expected ENABLED")
  415. freq = hapd.get_status_field("freq")
  416. if freq != "5180":
  417. raise Exception("Unexpected frequency: " + freq)
  418. pri = hapd.get_status_field("channel")
  419. if pri != "36":
  420. raise Exception("Unexpected primary channel: " + pri)
  421. sec = hapd.get_status_field("secondary_channel")
  422. if sec != "1":
  423. raise Exception("Unexpected secondary channel: " + sec)
  424. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  425. finally:
  426. dev[0].request("DISCONNECT")
  427. if hapd:
  428. hapd.request("DISABLE")
  429. if hapd2:
  430. hapd2.request("DISABLE")
  431. subprocess.call(['iw', 'reg', 'set', '00'])
  432. dev[0].flush_scan_cache()
  433. def test_obss_scan(dev, apdev):
  434. """Overlapping BSS scan request"""
  435. params = { "ssid": "obss-scan",
  436. "channel": "6",
  437. "ht_capab": "[HT40-]",
  438. "obss_interval": "10" }
  439. hapd = hostapd.add_ap(apdev[0], params)
  440. params = { "ssid": "another-bss",
  441. "channel": "9",
  442. "ieee80211n": "0" }
  443. hostapd.add_ap(apdev[1], params)
  444. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  445. hapd.set("ext_mgmt_frame_handling", "1")
  446. logger.info("Waiting for OBSS scan to occur")
  447. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  448. if ev is None:
  449. raise Exception("Timed out while waiting for OBSS scan to start")
  450. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  451. if ev is None:
  452. raise Exception("Timed out while waiting for OBSS scan results")
  453. received = False
  454. for i in range(0, 4):
  455. frame = hapd.mgmt_rx(timeout=5)
  456. if frame is None:
  457. raise Exception("MGMT RX wait timed out")
  458. if frame['subtype'] != 13:
  459. continue
  460. payload = frame['payload']
  461. if len(payload) < 3:
  462. continue
  463. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  464. if category != 4:
  465. continue
  466. if action != 0:
  467. continue
  468. if ie == 72:
  469. logger.info("20/40 BSS Coexistence report received")
  470. received = True
  471. break
  472. if not received:
  473. raise Exception("20/40 BSS Coexistence report not seen")
  474. def test_obss_scan_40_intolerant(dev, apdev):
  475. """Overlapping BSS scan request with 40 MHz intolerant AP"""
  476. params = { "ssid": "obss-scan",
  477. "channel": "6",
  478. "ht_capab": "[HT40-]",
  479. "obss_interval": "10" }
  480. hapd = hostapd.add_ap(apdev[0], params)
  481. params = { "ssid": "another-bss",
  482. "channel": "7",
  483. "ht_capab": "[40-INTOLERANT]" }
  484. hostapd.add_ap(apdev[1], params)
  485. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  486. hapd.set("ext_mgmt_frame_handling", "1")
  487. logger.info("Waiting for OBSS scan to occur")
  488. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  489. if ev is None:
  490. raise Exception("Timed out while waiting for OBSS scan to start")
  491. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  492. if ev is None:
  493. raise Exception("Timed out while waiting for OBSS scan results")
  494. received = False
  495. for i in range(0, 4):
  496. frame = hapd.mgmt_rx(timeout=5)
  497. if frame is None:
  498. raise Exception("MGMT RX wait timed out")
  499. if frame['subtype'] != 13:
  500. continue
  501. payload = frame['payload']
  502. if len(payload) < 3:
  503. continue
  504. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  505. if category != 4:
  506. continue
  507. if action != 0:
  508. continue
  509. if ie == 72:
  510. logger.info("20/40 BSS Coexistence report received")
  511. received = True
  512. break
  513. if not received:
  514. raise Exception("20/40 BSS Coexistence report not seen")
  515. def test_obss_coex_report_handling(dev, apdev):
  516. """Overlapping BSS scan report handling with obss_interval=0"""
  517. clear_scan_cache(apdev[0])
  518. params = { "ssid": "obss-scan",
  519. "channel": "6",
  520. "ht_capab": "[HT40-]" }
  521. hapd = hostapd.add_ap(apdev[0], params)
  522. bssid = apdev[0]['bssid']
  523. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  524. sec = hapd.get_status_field("secondary_channel")
  525. if sec != "-1":
  526. raise Exception("AP is not using 40 MHz channel")
  527. # 20/40 MHz co-ex report tests: number of invalid reports and a valid report
  528. # that forces 20 MHz channel.
  529. tests = [ '0400', '040048', '04004801', '0400480000', '0400490100',
  530. '040048ff0000', '04004801ff49ff00', '04004801004900',
  531. '0400480100490101', '0400480100490201ff',
  532. '040048010449020005' ]
  533. for msg in tests:
  534. req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg)
  535. if "OK" not in dev[0].request(req):
  536. raise Exception("Could not send management frame")
  537. time.sleep(0.5)
  538. sec = hapd.get_status_field("secondary_channel")
  539. if sec != "0":
  540. raise Exception("AP did not move to 20 MHz channel")
  541. def test_obss_coex_report_handling1(dev, apdev):
  542. """Overlapping BSS scan report handling with obss_interval=1"""
  543. clear_scan_cache(apdev[0])
  544. params = { "ssid": "obss-scan",
  545. "channel": "6",
  546. "ht_capab": "[HT40+]",
  547. "obss_interval": "1" }
  548. hapd = hostapd.add_ap(apdev[0], params)
  549. bssid = apdev[0]['bssid']
  550. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  551. sec = hapd.get_status_field("secondary_channel")
  552. if sec != "1":
  553. raise Exception("AP is not using 40 MHz channel")
  554. # 20/40 MHz co-ex report forcing 20 MHz channel
  555. msg = '040048010449020005'
  556. req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg)
  557. if "OK" not in dev[0].request(req):
  558. raise Exception("Could not send management frame")
  559. time.sleep(0.5)
  560. sec = hapd.get_status_field("secondary_channel")
  561. if sec != "0":
  562. raise Exception("AP did not move to 20 MHz channel")
  563. # No 20/40 MHz co-ex reports forcing 20 MHz channel during next interval
  564. for i in range(20):
  565. sec = hapd.get_status_field("secondary_channel")
  566. if sec == "1":
  567. break
  568. time.sleep(0.5)
  569. if sec != "1":
  570. raise Exception("AP did not return to 40 MHz channel")
  571. def test_olbc(dev, apdev):
  572. """OLBC detection"""
  573. params = { "ssid": "test-olbc",
  574. "channel": "6",
  575. "ht_capab": "[HT40-]",
  576. "ap_table_expiration_time": "2" }
  577. hapd = hostapd.add_ap(apdev[0], params)
  578. status = hapd.get_status()
  579. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  580. raise Exception("Unexpected OLBC information")
  581. params = { "ssid": "olbc-ap",
  582. "hw_mode": "b",
  583. "channel": "6",
  584. "wmm_enabled": "0" }
  585. hostapd.add_ap(apdev[1], params)
  586. time.sleep(0.5)
  587. status = hapd.get_status()
  588. if status['olbc'] != '1' or status['olbc_ht'] != '1':
  589. raise Exception("Missing OLBC information")
  590. hostapd.remove_bss(apdev[1])
  591. logger.info("Waiting for OLBC state to time out")
  592. cleared = False
  593. for i in range(0, 15):
  594. time.sleep(1)
  595. status = hapd.get_status()
  596. if status['olbc'] == '0' and status['olbc_ht'] == '0':
  597. cleared = True
  598. break
  599. if not cleared:
  600. raise Exception("OLBC state did nto time out")
  601. def test_olbc_table_limit(dev, apdev):
  602. """OLBC AP table size limit"""
  603. ifname1 = apdev[0]['ifname']
  604. ifname2 = apdev[0]['ifname'] + '-2'
  605. ifname3 = apdev[0]['ifname'] + '-3'
  606. hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf')
  607. hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf')
  608. hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf')
  609. params = { "ssid": "test-olbc",
  610. "channel": "1",
  611. "ap_table_max_size": "2" }
  612. hapd = hostapd.add_ap(apdev[1], params)
  613. time.sleep(0.3)
  614. with alloc_fail(hapd, 1, "ap_list_process_beacon"):
  615. time.sleep(0.3)
  616. hapd.set("ap_table_max_size", "1")
  617. time.sleep(0.3)
  618. hapd.set("ap_table_max_size", "0")
  619. time.sleep(0.3)
  620. def test_olbc_5ghz(dev, apdev):
  621. """OLBC detection on 5 GHz"""
  622. try:
  623. hapd = None
  624. hapd2 = None
  625. params = { "ssid": "test-olbc",
  626. "country_code": "FI",
  627. "hw_mode": "a",
  628. "channel": "36",
  629. "ht_capab": "[HT40+]" }
  630. hapd = hostapd.add_ap(apdev[0], params)
  631. status = hapd.get_status()
  632. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  633. raise Exception("Unexpected OLBC information")
  634. params = { "ssid": "olbc-ap",
  635. "country_code": "FI",
  636. "hw_mode": "a",
  637. "channel": "36",
  638. "ieee80211n": "0",
  639. "wmm_enabled": "0" }
  640. hapd2 = hostapd.add_ap(apdev[1], params)
  641. found = False
  642. for i in range(20):
  643. time.sleep(0.1)
  644. status = hapd.get_status()
  645. logger.debug('olbc_ht: ' + status['olbc_ht'])
  646. if status['olbc_ht'] == '1':
  647. found = True
  648. break
  649. if not found:
  650. raise Exception("Missing OLBC information")
  651. finally:
  652. if hapd:
  653. hapd.request("DISABLE")
  654. if hapd2:
  655. hapd2.request("DISABLE")
  656. subprocess.call(['iw', 'reg', 'set', '00'])
  657. def test_ap_require_ht(dev, apdev):
  658. """Require HT"""
  659. params = { "ssid": "require-ht",
  660. "require_ht": "1" }
  661. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  662. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  663. disable_ht="1", wait_connect=False)
  664. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  665. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  666. dev[1].request("DISCONNECT")
  667. if ev is None:
  668. raise Exception("Association rejection timed out")
  669. if "status_code=27" not in ev:
  670. raise Exception("Unexpected rejection status code")
  671. dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  672. ht_mcs="0x01 00 00 00 00 00 00 00 00 00",
  673. disable_max_amsdu="1", ampdu_factor="2",
  674. ampdu_density="1", disable_ht40="1", disable_sgi="1",
  675. disable_ldpc="1")
  676. def test_ap_require_ht_limited_rates(dev, apdev):
  677. """Require HT with limited supported rates"""
  678. params = { "ssid": "require-ht",
  679. "supported_rates": "60 120 240 360 480 540",
  680. "require_ht": "1" }
  681. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  682. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  683. disable_ht="1", wait_connect=False)
  684. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  685. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  686. dev[1].request("DISCONNECT")
  687. if ev is None:
  688. raise Exception("Association rejection timed out")
  689. if "status_code=27" not in ev:
  690. raise Exception("Unexpected rejection status code")
  691. def test_ap_ht_capab_not_supported(dev, apdev):
  692. """HT configuration with driver not supporting all ht_capab entries"""
  693. params = { "ssid": "test-ht40",
  694. "channel": "5",
  695. "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]"}
  696. hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
  697. if "FAIL" not in hapd.request("ENABLE"):
  698. raise Exception("Unexpected ENABLE success")
  699. def test_ap_ht_40mhz_intolerant_sta(dev, apdev):
  700. """Associated STA indicating 40 MHz intolerant"""
  701. clear_scan_cache(apdev[0])
  702. params = { "ssid": "intolerant",
  703. "channel": "6",
  704. "ht_capab": "[HT40-]" }
  705. hapd = hostapd.add_ap(apdev[0], params)
  706. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  707. raise Exception("Unexpected num_sta_ht40_intolerant value")
  708. if hapd.get_status_field("secondary_channel") != "-1":
  709. raise Exception("Unexpected secondary_channel")
  710. dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437")
  711. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  712. raise Exception("Unexpected num_sta_ht40_intolerant value")
  713. if hapd.get_status_field("secondary_channel") != "-1":
  714. raise Exception("Unexpected secondary_channel")
  715. dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437",
  716. ht40_intolerant="1")
  717. time.sleep(1)
  718. if hapd.get_status_field("num_sta_ht40_intolerant") != "1":
  719. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)")
  720. if hapd.get_status_field("secondary_channel") != "0":
  721. raise Exception("Unexpected secondary_channel (did not disable 40 MHz)")
  722. dev[2].request("DISCONNECT")
  723. time.sleep(1)
  724. if hapd.get_status_field("num_sta_ht40_intolerant") != "0":
  725. raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)")
  726. if hapd.get_status_field("secondary_channel") != "-1":
  727. raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)")
  728. def test_ap_ht_40mhz_intolerant_ap(dev, apdev):
  729. """Associated STA reports 40 MHz intolerant AP after association"""
  730. clear_scan_cache(apdev[0])
  731. params = { "ssid": "ht",
  732. "channel": "6",
  733. "ht_capab": "[HT40-]",
  734. "obss_interval": "3" }
  735. hapd = hostapd.add_ap(apdev[0], params)
  736. dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437")
  737. if hapd.get_status_field("secondary_channel") != "-1":
  738. raise Exception("Unexpected secondary channel information")
  739. logger.info("Start 40 MHz intolerant AP")
  740. params = { "ssid": "intolerant",
  741. "channel": "5",
  742. "ht_capab": "[40-INTOLERANT]" }
  743. hapd2 = hostapd.add_ap(apdev[1], params)
  744. logger.info("Waiting for co-ex report from STA")
  745. ok = False
  746. for i in range(0, 20):
  747. time.sleep(1)
  748. if hapd.get_status_field("secondary_channel") == "0":
  749. logger.info("AP moved to 20 MHz channel")
  750. ok = True
  751. break
  752. if not ok:
  753. raise Exception("AP did not move to 20 MHz channel")
  754. if "OK" not in hapd2.request("DISABLE"):
  755. raise Exception("Failed to disable 40 MHz intolerant AP")
  756. # make sure the intolerant AP disappears from scan results more quickly
  757. dev[0].scan(type="ONLY", freq="2432", only_new=True)
  758. dev[0].scan(type="ONLY", freq="2432", only_new=True)
  759. dev[0].dump_monitor()
  760. logger.info("Waiting for AP to move back to 40 MHz channel")
  761. ok = False
  762. for i in range(0, 30):
  763. time.sleep(1)
  764. if hapd.get_status_field("secondary_channel") == "-1":
  765. logger.info("AP moved to 40 MHz channel")
  766. ok = True
  767. break
  768. if not ok:
  769. raise Exception("AP did not move to 40 MHz channel")
  770. def test_ap_ht40_csa(dev, apdev):
  771. """HT with 40 MHz channel width and CSA"""
  772. csa_supported(dev[0])
  773. try:
  774. hapd = None
  775. params = { "ssid": "ht",
  776. "country_code": "US",
  777. "hw_mode": "a",
  778. "channel": "36",
  779. "ht_capab": "[HT40+]",
  780. "ieee80211n": "1" }
  781. hapd = hostapd.add_ap(apdev[0], params)
  782. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  783. hwsim_utils.test_connectivity(dev[0], hapd)
  784. hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40")
  785. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  786. if ev is None:
  787. raise Exception("CSA finished event timed out")
  788. if "freq=5200" not in ev:
  789. raise Exception("Unexpected channel in CSA finished event")
  790. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  791. if ev is not None:
  792. raise Exception("Unexpected STA disconnection during CSA")
  793. hwsim_utils.test_connectivity(dev[0], hapd)
  794. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  795. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  796. if ev is None:
  797. raise Exception("CSA finished event timed out")
  798. if "freq=5180" not in ev:
  799. raise Exception("Unexpected channel in CSA finished event")
  800. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  801. if ev is not None:
  802. raise Exception("Unexpected STA disconnection during CSA")
  803. hwsim_utils.test_connectivity(dev[0], hapd)
  804. finally:
  805. dev[0].request("DISCONNECT")
  806. if hapd:
  807. hapd.request("DISABLE")
  808. subprocess.call(['iw', 'reg', 'set', '00'])
  809. dev[0].flush_scan_cache()
  810. def test_ap_ht40_csa2(dev, apdev):
  811. """HT with 40 MHz channel width and CSA"""
  812. csa_supported(dev[0])
  813. try:
  814. hapd = None
  815. params = { "ssid": "ht",
  816. "country_code": "US",
  817. "hw_mode": "a",
  818. "channel": "36",
  819. "ht_capab": "[HT40+]",
  820. "ieee80211n": "1" }
  821. hapd = hostapd.add_ap(apdev[0], params)
  822. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  823. hwsim_utils.test_connectivity(dev[0], hapd)
  824. hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40")
  825. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  826. if ev is None:
  827. raise Exception("CSA finished event timed out")
  828. if "freq=5220" not in ev:
  829. raise Exception("Unexpected channel in CSA finished event")
  830. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  831. if ev is not None:
  832. raise Exception("Unexpected STA disconnection during CSA")
  833. hwsim_utils.test_connectivity(dev[0], hapd)
  834. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  835. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  836. if ev is None:
  837. raise Exception("CSA finished event timed out")
  838. if "freq=5180" not in ev:
  839. raise Exception("Unexpected channel in CSA finished event")
  840. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  841. if ev is not None:
  842. raise Exception("Unexpected STA disconnection during CSA")
  843. hwsim_utils.test_connectivity(dev[0], hapd)
  844. finally:
  845. dev[0].request("DISCONNECT")
  846. if hapd:
  847. hapd.request("DISABLE")
  848. subprocess.call(['iw', 'reg', 'set', '00'])
  849. dev[0].flush_scan_cache()
  850. def test_ap_ht40_csa3(dev, apdev):
  851. """HT with 40 MHz channel width and CSA"""
  852. csa_supported(dev[0])
  853. try:
  854. hapd = None
  855. params = { "ssid": "ht",
  856. "country_code": "US",
  857. "hw_mode": "a",
  858. "channel": "36",
  859. "ht_capab": "[HT40+]",
  860. "ieee80211n": "1" }
  861. hapd = hostapd.add_ap(apdev[0], params)
  862. dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180")
  863. hwsim_utils.test_connectivity(dev[0], hapd)
  864. hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40")
  865. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  866. if ev is None:
  867. raise Exception("CSA finished event timed out")
  868. if "freq=5240" not in ev:
  869. raise Exception("Unexpected channel in CSA finished event")
  870. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  871. if ev is not None:
  872. raise Exception("Unexpected STA disconnection during CSA")
  873. hwsim_utils.test_connectivity(dev[0], hapd)
  874. hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40")
  875. ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10)
  876. if ev is None:
  877. raise Exception("CSA finished event timed out")
  878. if "freq=5180" not in ev:
  879. raise Exception("Unexpected channel in CSA finished event")
  880. ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
  881. if ev is not None:
  882. raise Exception("Unexpected STA disconnection during CSA")
  883. hwsim_utils.test_connectivity(dev[0], hapd)
  884. finally:
  885. dev[0].request("DISCONNECT")
  886. if hapd:
  887. hapd.request("DISABLE")
  888. subprocess.call(['iw', 'reg', 'set', '00'])
  889. dev[0].flush_scan_cache()
  890. def test_ap_ht_smps(dev, apdev):
  891. """SMPS AP configuration options"""
  892. params = { "ssid": "ht1", "ht_capab": "[SMPS-STATIC]" }
  893. try:
  894. hapd = hostapd.add_ap(apdev[0], params)
  895. except:
  896. raise HwsimSkip("Assume mac80211_hwsim was not recent enough to support SMPS")
  897. params = { "ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]" }
  898. hapd2 = hostapd.add_ap(apdev[1], params)
  899. dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412")
  900. dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412")
  901. hwsim_utils.test_connectivity(dev[0], hapd)
  902. hwsim_utils.test_connectivity(dev[1], hapd2)
  903. def test_prefer_ht20(dev, apdev):
  904. """Preference on HT20 over no-HT"""
  905. params = { "ssid": "test",
  906. "channel": "1",
  907. "ieee80211n": "0" }
  908. hapd = hostapd.add_ap(apdev[0], params)
  909. bssid = apdev[0]['bssid']
  910. params = { "ssid": "test",
  911. "channel": "1",
  912. "ieee80211n": "1" }
  913. hapd2 = hostapd.add_ap(apdev[1], params)
  914. bssid2 = apdev[1]['bssid']
  915. dev[0].scan_for_bss(bssid, freq=2412)
  916. dev[0].scan_for_bss(bssid2, freq=2412)
  917. dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
  918. if dev[0].get_status_field('bssid') != bssid2:
  919. raise Exception("Unexpected BSS selected")
  920. est = dev[0].get_bss(bssid)['est_throughput']
  921. if est != "54000":
  922. raise Exception("Unexpected BSS0 est_throughput: " + est)
  923. est = dev[0].get_bss(bssid2)['est_throughput']
  924. if est != "65000":
  925. raise Exception("Unexpected BSS1 est_throughput: " + est)
  926. def test_prefer_ht40(dev, apdev):
  927. """Preference on HT40 over HT20"""
  928. params = { "ssid": "test",
  929. "channel": "1",
  930. "ieee80211n": "1" }
  931. hapd = hostapd.add_ap(apdev[0], params)
  932. bssid = apdev[0]['bssid']
  933. params = { "ssid": "test",
  934. "channel": "1",
  935. "ieee80211n": "1",
  936. "ht_capab": "[HT40+]" }
  937. hapd2 = hostapd.add_ap(apdev[1], params)
  938. bssid2 = apdev[1]['bssid']
  939. dev[0].scan_for_bss(bssid, freq=2412)
  940. dev[0].scan_for_bss(bssid2, freq=2412)
  941. dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
  942. if dev[0].get_status_field('bssid') != bssid2:
  943. raise Exception("Unexpected BSS selected")
  944. est = dev[0].get_bss(bssid)['est_throughput']
  945. if est != "65000":
  946. raise Exception("Unexpected BSS0 est_throughput: " + est)
  947. est = dev[0].get_bss(bssid2)['est_throughput']
  948. if est != "135000":
  949. raise Exception("Unexpected BSS1 est_throughput: " + est)
  950. def test_prefer_ht20_during_roam(dev, apdev):
  951. """Preference on HT20 over no-HT in roaming consideration"""
  952. params = { "ssid": "test",
  953. "channel": "1",
  954. "ieee80211n": "0" }
  955. hapd = hostapd.add_ap(apdev[0], params)
  956. bssid = apdev[0]['bssid']
  957. dev[0].scan_for_bss(bssid, freq=2412)
  958. dev[0].connect("test", key_mgmt="NONE", scan_freq="2412")
  959. params = { "ssid": "test",
  960. "channel": "1",
  961. "ieee80211n": "1" }
  962. hapd2 = hostapd.add_ap(apdev[1], params)
  963. bssid2 = apdev[1]['bssid']
  964. dev[0].scan_for_bss(bssid2, freq=2412)
  965. dev[0].scan(freq=2412)
  966. dev[0].wait_connected()
  967. if dev[0].get_status_field('bssid') != bssid2:
  968. raise Exception("Unexpected BSS selected")
  969. def test_ap_ht40_5ghz_invalid_pair(dev, apdev):
  970. """HT40 on 5 GHz with invalid channel pair"""
  971. clear_scan_cache(apdev[0])
  972. try:
  973. params = { "ssid": "test-ht40",
  974. "hw_mode": "a",
  975. "channel": "40",
  976. "country_code": "US",
  977. "ht_capab": "[HT40+]"}
  978. hapd = hostapd.add_ap(apdev[1], params, wait_enabled=False)
  979. ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10)
  980. if not ev:
  981. raise Exception("AP setup failure timed out")
  982. if "AP-ENABLED" in ev:
  983. sec = hapd.get_status_field("secondary_channel")
  984. if sec != "0":
  985. raise Exception("Invalid 40 MHz channel accepted")
  986. finally:
  987. subprocess.call(['iw', 'reg', 'set', '00'])
  988. def test_ap_ht40_5ghz_disabled_sec(dev, apdev):
  989. """HT40 on 5 GHz with disabled secondary channel"""
  990. clear_scan_cache(apdev[0])
  991. try:
  992. params = { "ssid": "test-ht40",
  993. "hw_mode": "a",
  994. "channel": "48",
  995. "country_code": "US",
  996. "ht_capab": "[HT40+]"}
  997. hapd = hostapd.add_ap(apdev[1], params, wait_enabled=False)
  998. ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10)
  999. if not ev:
  1000. raise Exception("AP setup failure timed out")
  1001. if "AP-ENABLED" in ev:
  1002. sec = hapd.get_status_field("secondary_channel")
  1003. if sec != "0":
  1004. raise Exception("Invalid 40 MHz channel accepted")
  1005. finally:
  1006. subprocess.call(['iw', 'reg', 'set', '00'])
  1007. def test_ap_ht40_scan_broken_ap(dev, apdev):
  1008. """HT40 co-ex scan and broken legacy/HT AP"""
  1009. clear_scan_cache(apdev[0])
  1010. # Broken AP: Include HT Capabilities element but not HT Operation element
  1011. params = { "ssid": "legacy-20",
  1012. "channel": "7", "ieee80211n": "0",
  1013. "wmm_enabled": "1",
  1014. "vendor_elements": "2d1a0e001bffff000000000000000000000100000000000000000000" }
  1015. hapd2 = hostapd.add_ap(apdev[1], params)
  1016. params = { "ssid": "test-ht40",
  1017. "channel": "5",
  1018. "ht_capab": "[HT40-]"}
  1019. hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
  1020. state = hapd.get_status_field("state")
  1021. if state != "HT_SCAN":
  1022. time.sleep(0.1)
  1023. state = hapd.get_status_field("state")
  1024. if state != "HT_SCAN":
  1025. raise Exception("Unexpected interface state - expected HT_SCAN")
  1026. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  1027. if not ev:
  1028. raise Exception("AP setup timed out")
  1029. state = hapd.get_status_field("state")
  1030. if state != "ENABLED":
  1031. raise Exception("Unexpected interface state - expected ENABLED")
  1032. freq = hapd.get_status_field("freq")
  1033. if freq != "2432":
  1034. raise Exception("Unexpected frequency: " + freq)
  1035. pri = hapd.get_status_field("channel")
  1036. if pri != "5":
  1037. raise Exception("Unexpected primary channel: " + pri)
  1038. sec = hapd.get_status_field("secondary_channel")
  1039. if sec != "-1":
  1040. raise Exception("Unexpected secondary channel: " + sec)
  1041. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  1042. dev[1].connect("legacy-20", key_mgmt="NONE", scan_freq="2442")
  1043. hwsim_utils.test_connectivity(dev[0], hapd)
  1044. hwsim_utils.test_connectivity(dev[1], hapd2)