test_ap_ht.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  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. def test_ap_ht40_scan(dev, apdev):
  13. """HT40 co-ex scan"""
  14. params = { "ssid": "test-ht40",
  15. "channel": "5",
  16. "ht_capab": "[HT40-]"}
  17. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  18. state = hapd.get_status_field("state")
  19. if state != "HT_SCAN":
  20. time.sleep(0.1)
  21. state = hapd.get_status_field("state")
  22. if state != "HT_SCAN":
  23. raise Exception("Unexpected interface state - expected HT_SCAN")
  24. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  25. if not ev:
  26. raise Exception("AP setup timed out")
  27. state = hapd.get_status_field("state")
  28. if state != "ENABLED":
  29. raise Exception("Unexpected interface state - expected ENABLED")
  30. freq = hapd.get_status_field("freq")
  31. if freq != "2432":
  32. raise Exception("Unexpected frequency")
  33. pri = hapd.get_status_field("channel")
  34. if pri != "5":
  35. raise Exception("Unexpected primary channel")
  36. sec = hapd.get_status_field("secondary_channel")
  37. if sec != "-1":
  38. raise Exception("Unexpected secondary channel")
  39. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  40. def test_ap_ht40_scan_conflict(dev, apdev):
  41. """HT40 co-ex scan conflict"""
  42. params = { "ssid": "test-ht40",
  43. "channel": "6",
  44. "ht_capab": "[HT40+]"}
  45. hostapd.add_ap(apdev[1]['ifname'], params)
  46. params = { "ssid": "test-ht40",
  47. "channel": "5",
  48. "ht_capab": "[HT40-]"}
  49. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  50. state = hapd.get_status_field("state")
  51. if state != "HT_SCAN":
  52. time.sleep(0.1)
  53. state = hapd.get_status_field("state")
  54. if state != "HT_SCAN":
  55. raise Exception("Unexpected interface state - expected HT_SCAN")
  56. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  57. if not ev:
  58. raise Exception("AP setup timed out")
  59. state = hapd.get_status_field("state")
  60. if state != "ENABLED":
  61. raise Exception("Unexpected interface state - expected ENABLED")
  62. freq = hapd.get_status_field("freq")
  63. if freq != "2432":
  64. raise Exception("Unexpected frequency")
  65. pri = hapd.get_status_field("channel")
  66. if pri != "5":
  67. raise Exception("Unexpected primary channel")
  68. sec = hapd.get_status_field("secondary_channel")
  69. if sec != "0":
  70. raise Exception("Unexpected secondary channel: " + sec)
  71. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  72. def test_ap_ht40_scan_match(dev, apdev):
  73. """HT40 co-ex scan matching configuration"""
  74. params = { "ssid": "test-ht40",
  75. "channel": "5",
  76. "ht_capab": "[HT40-]"}
  77. hostapd.add_ap(apdev[1]['ifname'], params)
  78. params = { "ssid": "test-ht40",
  79. "channel": "5",
  80. "ht_capab": "[HT40-]"}
  81. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  82. state = hapd.get_status_field("state")
  83. if state != "HT_SCAN":
  84. time.sleep(0.1)
  85. state = hapd.get_status_field("state")
  86. if state != "HT_SCAN":
  87. raise Exception("Unexpected interface state - expected HT_SCAN")
  88. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  89. if not ev:
  90. raise Exception("AP setup timed out")
  91. state = hapd.get_status_field("state")
  92. if state != "ENABLED":
  93. raise Exception("Unexpected interface state - expected ENABLED")
  94. freq = hapd.get_status_field("freq")
  95. if freq != "2432":
  96. raise Exception("Unexpected frequency")
  97. pri = hapd.get_status_field("channel")
  98. if pri != "5":
  99. raise Exception("Unexpected primary channel")
  100. sec = hapd.get_status_field("secondary_channel")
  101. if sec != "-1":
  102. raise Exception("Unexpected secondary channel: " + sec)
  103. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  104. def test_ap_ht40_5ghz_match(dev, apdev):
  105. """HT40 co-ex scan on 5 GHz with matching pri/sec channel"""
  106. try:
  107. params = { "ssid": "test-ht40",
  108. "hw_mode": "a",
  109. "channel": "36",
  110. "country_code": "US",
  111. "ht_capab": "[HT40+]"}
  112. hostapd.add_ap(apdev[1]['ifname'], params)
  113. params = { "ssid": "test-ht40",
  114. "hw_mode": "a",
  115. "channel": "36",
  116. "ht_capab": "[HT40+]"}
  117. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  118. state = hapd.get_status_field("state")
  119. if state != "HT_SCAN":
  120. time.sleep(0.1)
  121. state = hapd.get_status_field("state")
  122. if state != "HT_SCAN":
  123. raise Exception("Unexpected interface state - expected HT_SCAN")
  124. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  125. if not ev:
  126. raise Exception("AP setup timed out")
  127. state = hapd.get_status_field("state")
  128. if state != "ENABLED":
  129. raise Exception("Unexpected interface state - expected ENABLED")
  130. freq = hapd.get_status_field("freq")
  131. if freq != "5180":
  132. raise Exception("Unexpected frequency")
  133. pri = hapd.get_status_field("channel")
  134. if pri != "36":
  135. raise Exception("Unexpected primary channel")
  136. sec = hapd.get_status_field("secondary_channel")
  137. if sec != "1":
  138. raise Exception("Unexpected secondary channel: " + sec)
  139. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  140. finally:
  141. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  142. def test_ap_ht40_5ghz_switch(dev, apdev):
  143. """HT40 co-ex scan on 5 GHz switching pri/sec channel"""
  144. try:
  145. params = { "ssid": "test-ht40",
  146. "hw_mode": "a",
  147. "channel": "36",
  148. "country_code": "US",
  149. "ht_capab": "[HT40+]"}
  150. hostapd.add_ap(apdev[1]['ifname'], params)
  151. params = { "ssid": "test-ht40",
  152. "hw_mode": "a",
  153. "channel": "40",
  154. "ht_capab": "[HT40-]"}
  155. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  156. state = hapd.get_status_field("state")
  157. if state != "HT_SCAN":
  158. time.sleep(0.1)
  159. state = hapd.get_status_field("state")
  160. if state != "HT_SCAN":
  161. raise Exception("Unexpected interface state - expected HT_SCAN")
  162. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  163. if not ev:
  164. raise Exception("AP setup timed out")
  165. state = hapd.get_status_field("state")
  166. if state != "ENABLED":
  167. raise Exception("Unexpected interface state - expected ENABLED")
  168. freq = hapd.get_status_field("freq")
  169. if freq != "5180":
  170. raise Exception("Unexpected frequency: " + freq)
  171. pri = hapd.get_status_field("channel")
  172. if pri != "36":
  173. raise Exception("Unexpected primary channel: " + pri)
  174. sec = hapd.get_status_field("secondary_channel")
  175. if sec != "1":
  176. raise Exception("Unexpected secondary channel: " + sec)
  177. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  178. finally:
  179. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  180. def test_ap_ht40_5ghz_switch2(dev, apdev):
  181. """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)"""
  182. try:
  183. params = { "ssid": "test-ht40",
  184. "hw_mode": "a",
  185. "channel": "36",
  186. "country_code": "US",
  187. "ht_capab": "[HT40+]"}
  188. hostapd.add_ap(apdev[1]['ifname'], params)
  189. id = dev[0].add_network()
  190. dev[0].set_network(id, "mode", "2")
  191. dev[0].set_network_quoted(id, "ssid", "wpas-ap-open")
  192. dev[0].set_network(id, "key_mgmt", "NONE")
  193. dev[0].set_network(id, "frequency", "5200")
  194. dev[0].set_network(id, "scan_freq", "5200")
  195. dev[0].select_network(id)
  196. time.sleep(1)
  197. params = { "ssid": "test-ht40",
  198. "hw_mode": "a",
  199. "channel": "40",
  200. "ht_capab": "[HT40-]"}
  201. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  202. state = hapd.get_status_field("state")
  203. if state != "HT_SCAN":
  204. time.sleep(0.1)
  205. state = hapd.get_status_field("state")
  206. if state != "HT_SCAN":
  207. raise Exception("Unexpected interface state - expected HT_SCAN")
  208. ev = hapd.wait_event(["AP-ENABLED"], timeout=10)
  209. if not ev:
  210. raise Exception("AP setup timed out")
  211. state = hapd.get_status_field("state")
  212. if state != "ENABLED":
  213. raise Exception("Unexpected interface state - expected ENABLED")
  214. freq = hapd.get_status_field("freq")
  215. if freq != "5180":
  216. raise Exception("Unexpected frequency: " + freq)
  217. pri = hapd.get_status_field("channel")
  218. if pri != "36":
  219. raise Exception("Unexpected primary channel: " + pri)
  220. sec = hapd.get_status_field("secondary_channel")
  221. if sec != "1":
  222. raise Exception("Unexpected secondary channel: " + sec)
  223. dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq)
  224. finally:
  225. subprocess.call(['sudo', 'iw', 'reg', 'set', '00'])
  226. def test_obss_scan(dev, apdev):
  227. """Overlapping BSS scan request"""
  228. params = { "ssid": "obss-scan",
  229. "channel": "6",
  230. "ht_capab": "[HT40-]",
  231. "obss_interval": "10" }
  232. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  233. params = { "ssid": "another-bss",
  234. "channel": "9",
  235. "ieee80211n": "0" }
  236. hostapd.add_ap(apdev[1]['ifname'], params)
  237. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  238. hapd.set("ext_mgmt_frame_handling", "1")
  239. logger.info("Waiting for OBSS scan to occur")
  240. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  241. if ev is None:
  242. raise Exception("Timed out while waiting for OBSS scan to start")
  243. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  244. if ev is None:
  245. raise Exception("Timed out while waiting for OBSS scan results")
  246. received = False
  247. for i in range(0, 4):
  248. frame = hapd.mgmt_rx(timeout=5)
  249. if frame is None:
  250. raise Exception("MGMT RX wait timed out")
  251. if frame['subtype'] != 13:
  252. continue
  253. payload = frame['payload']
  254. if len(payload) < 3:
  255. continue
  256. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  257. if category != 4:
  258. continue
  259. if action != 0:
  260. continue
  261. if ie == 72:
  262. logger.info("20/40 BSS Coexistence report received")
  263. received = True
  264. break
  265. if not received:
  266. raise Exception("20/40 BSS Coexistence report not seen")
  267. def test_obss_scan_40_intolerant(dev, apdev):
  268. """Overlapping BSS scan request with 40 MHz intolerant AP"""
  269. params = { "ssid": "obss-scan",
  270. "channel": "6",
  271. "ht_capab": "[HT40-]",
  272. "obss_interval": "10" }
  273. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  274. params = { "ssid": "another-bss",
  275. "channel": "7",
  276. "ht_capab": "[40-INTOLERANT]" }
  277. hostapd.add_ap(apdev[1]['ifname'], params)
  278. dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437")
  279. hapd.set("ext_mgmt_frame_handling", "1")
  280. logger.info("Waiting for OBSS scan to occur")
  281. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15)
  282. if ev is None:
  283. raise Exception("Timed out while waiting for OBSS scan to start")
  284. ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
  285. if ev is None:
  286. raise Exception("Timed out while waiting for OBSS scan results")
  287. received = False
  288. for i in range(0, 4):
  289. frame = hapd.mgmt_rx(timeout=5)
  290. if frame is None:
  291. raise Exception("MGMT RX wait timed out")
  292. if frame['subtype'] != 13:
  293. continue
  294. payload = frame['payload']
  295. if len(payload) < 3:
  296. continue
  297. (category, action, ie) = struct.unpack('BBB', payload[0:3])
  298. if category != 4:
  299. continue
  300. if action != 0:
  301. continue
  302. if ie == 72:
  303. logger.info("20/40 BSS Coexistence report received")
  304. received = True
  305. break
  306. if not received:
  307. raise Exception("20/40 BSS Coexistence report not seen")
  308. def test_olbc(dev, apdev):
  309. """OLBC detection"""
  310. params = { "ssid": "test-olbc",
  311. "channel": "6",
  312. "ht_capab": "[HT40-]" }
  313. hapd = hostapd.add_ap(apdev[0]['ifname'], params)
  314. status = hapd.get_status()
  315. if status['olbc'] != '0' or status['olbc_ht'] != '0':
  316. raise Exception("Unexpected OLBC information")
  317. params = { "ssid": "olbc-ap",
  318. "hw_mode": "b",
  319. "channel": "6",
  320. "wmm_enabled": "0" }
  321. hostapd.add_ap(apdev[1]['ifname'], params)
  322. time.sleep(0.5)
  323. status = hapd.get_status()
  324. if status['olbc'] != '1' or status['olbc_ht'] != '1':
  325. raise Exception("Missing OLBC information")
  326. def test_ap_require_ht(dev, apdev):
  327. """Require HT"""
  328. params = { "ssid": "require-ht",
  329. "require_ht": "1" }
  330. hapd = hostapd.add_ap(apdev[0]['ifname'], params, wait_enabled=False)
  331. dev[1].connect("require-ht", key_mgmt="NONE", scan_freq="2412",
  332. disable_ht="1", wait_connect=False)
  333. dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412")
  334. ev = dev[1].wait_event(["CTRL-EVENT-ASSOC-REJECT"])
  335. if ev is None:
  336. raise Exception("Association rejection timed out")
  337. if "status_code=27" not in ev:
  338. raise Exception("Unexpected rejection status code")