test_ap_ht.py 44 KB

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