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 7from remotehost import remote_compatible 8import time 9import logging 10logger = logging.getLogger() 11import struct 12 13import hostapd 14from wpasupplicant import WpaSupplicant 15from utils import * 16import hwsim_utils 17 18def test_ap_ht40_scan(dev, apdev): 19 """HT40 co-ex scan""" 20 clear_scan_cache(apdev[0]) 21 params = {"ssid": "test-ht40", 22 "channel": "5", 23 "ht_capab": "[HT40-]"} 24 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 25 26 state = hapd.get_status_field("state") 27 if state != "HT_SCAN": 28 time.sleep(0.1) 29 state = hapd.get_status_field("state") 30 if state != "HT_SCAN": 31 raise Exception("Unexpected interface state - expected HT_SCAN") 32 33 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 34 if not ev: 35 raise Exception("AP setup timed out") 36 37 state = hapd.get_status_field("state") 38 if state != "ENABLED": 39 raise Exception("Unexpected interface state - expected ENABLED") 40 41 freq = hapd.get_status_field("freq") 42 if freq != "2432": 43 raise Exception("Unexpected frequency") 44 pri = hapd.get_status_field("channel") 45 if pri != "5": 46 raise Exception("Unexpected primary channel") 47 sec = hapd.get_status_field("secondary_channel") 48 if sec != "-1": 49 raise Exception("Unexpected secondary channel") 50 51 status = hapd.get_status() 52 logger.info("hostapd STATUS: " + str(status)) 53 54 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 55 sta = hapd.get_sta(dev[0].own_addr()) 56 logger.info("hostapd STA: " + str(sta)) 57 58 res = dev[0].request("SIGNAL_POLL") 59 logger.info("STA SIGNAL_POLL:\n" + res.strip()) 60 sig = res.splitlines() 61 if "WIDTH=40 MHz" not in sig: 62 raise Exception("Not a 40 MHz connection") 63 64 if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: 65 raise Exception("No Supported Operating Classes information for STA") 66 opclass = int(sta['supp_op_classes'][0:2], 16) 67 if opclass != 84: 68 raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) 69 70def test_ap_ht_wifi_generation(dev, apdev): 71 """HT and wifi_generation""" 72 clear_scan_cache(apdev[0]) 73 params = {"ssid": "test-ht", 74 "channel": "6"} 75 hapd = hostapd.add_ap(apdev[0], params) 76 77 dev[0].connect("test-ht", key_mgmt="NONE", scan_freq="2437") 78 status = dev[0].get_status() 79 if 'wifi_generation' not in status: 80 # For now, assume this is because of missing kernel support 81 raise HwsimSkip("Association Request IE reporting not supported") 82 #raise Exception("Missing wifi_generation information") 83 if status['wifi_generation'] != "4": 84 raise Exception("Unexpected wifi_generation value: " + status['wifi_generation']) 85 86 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 87 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") 88 wpas.connect("test-ht", key_mgmt="NONE", scan_freq="2437") 89 status = wpas.get_status() 90 if 'wifi_generation' not in status: 91 # For now, assume this is because of missing kernel support 92 raise HwsimSkip("Association Request IE reporting not supported") 93 #raise Exception("Missing wifi_generation information (connect)") 94 if status['wifi_generation'] != "4": 95 raise Exception("Unexpected wifi_generation value (connect): " + status['wifi_generation']) 96 97@remote_compatible 98def test_ap_ht40_scan_conflict(dev, apdev): 99 """HT40 co-ex scan conflict""" 100 clear_scan_cache(apdev[0]) 101 params = {"ssid": "test-ht40", 102 "channel": "6", 103 "ht_capab": "[HT40+]"} 104 hostapd.add_ap(apdev[1], params) 105 106 params = {"ssid": "test-ht40", 107 "channel": "5", 108 "ht_capab": "[HT40-]"} 109 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 110 111 state = hapd.get_status_field("state") 112 if state != "HT_SCAN": 113 time.sleep(0.1) 114 state = hapd.get_status_field("state") 115 if state != "HT_SCAN": 116 raise Exception("Unexpected interface state - expected HT_SCAN") 117 118 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 119 if not ev: 120 raise Exception("AP setup timed out") 121 122 state = hapd.get_status_field("state") 123 if state != "ENABLED": 124 raise Exception("Unexpected interface state - expected ENABLED") 125 126 freq = hapd.get_status_field("freq") 127 if freq != "2432": 128 raise Exception("Unexpected frequency") 129 pri = hapd.get_status_field("channel") 130 if pri != "5": 131 raise Exception("Unexpected primary channel") 132 sec = hapd.get_status_field("secondary_channel") 133 if sec != "0": 134 raise Exception("Unexpected secondary channel: " + sec) 135 136 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 137 138@remote_compatible 139def test_ap_ht40_scan_conflict2(dev, apdev): 140 """HT40 co-ex scan conflict (HT40-)""" 141 clear_scan_cache(apdev[0]) 142 params = {"ssid": "test-ht40", 143 "channel": "11", 144 "ht_capab": "[HT40-]"} 145 hostapd.add_ap(apdev[1], params) 146 147 params = {"ssid": "test-ht40", 148 "channel": "1", 149 "ht_capab": "[HT40+]"} 150 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 151 152 state = hapd.get_status_field("state") 153 if state != "HT_SCAN": 154 time.sleep(0.1) 155 state = hapd.get_status_field("state") 156 if state != "HT_SCAN": 157 raise Exception("Unexpected interface state - expected HT_SCAN") 158 159 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 160 if not ev: 161 raise Exception("AP setup timed out") 162 163 state = hapd.get_status_field("state") 164 if state != "ENABLED": 165 raise Exception("Unexpected interface state - expected ENABLED") 166 167 freq = hapd.get_status_field("freq") 168 if freq != "2412": 169 raise Exception("Unexpected frequency") 170 pri = hapd.get_status_field("channel") 171 if pri != "1": 172 raise Exception("Unexpected primary channel") 173 sec = hapd.get_status_field("secondary_channel") 174 if sec != "0": 175 raise Exception("Unexpected secondary channel: " + sec) 176 177 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 178 179def test_ap_ht40_scan_not_affected(dev, apdev): 180 """HT40 co-ex scan and other BSS not affected""" 181 clear_scan_cache(apdev[0]) 182 params = {"ssid": "test-ht20", 183 "channel": "11"} 184 hostapd.add_ap(apdev[1], params) 185 186 hostapd.cmd_execute(apdev[0], ['ifconfig', apdev[0]['ifname'], 'up']) 187 hostapd.cmd_execute(apdev[0], ['iw', apdev[0]['ifname'], 'scan', 'trigger', 188 'freq', '2462']) 189 time.sleep(0.5) 190 hostapd.cmd_execute(apdev[0], ['iw', apdev[0]['ifname'], 'scan', 'dump']) 191 time.sleep(0.1) 192 hostapd.cmd_execute(apdev[0], ['ifconfig', apdev[0]['ifname'], 'down']) 193 194 params = {"ssid": "test-ht40", 195 "channel": "1", 196 "ht_capab": "[HT40+]"} 197 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 198 199 state = hapd.get_status_field("state") 200 if state != "HT_SCAN": 201 time.sleep(0.1) 202 state = hapd.get_status_field("state") 203 if state != "HT_SCAN": 204 raise Exception("Unexpected interface state - expected HT_SCAN") 205 206 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 207 if not ev: 208 raise Exception("AP setup timed out") 209 210 state = hapd.get_status_field("state") 211 if state != "ENABLED": 212 raise Exception("Unexpected interface state - expected ENABLED") 213 214 freq = hapd.get_status_field("freq") 215 if freq != "2412": 216 raise Exception("Unexpected frequency") 217 pri = hapd.get_status_field("channel") 218 if pri != "1": 219 raise Exception("Unexpected primary channel") 220 sec = hapd.get_status_field("secondary_channel") 221 if sec != "1": 222 raise Exception("Unexpected secondary channel: " + sec) 223 224 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 225 226@remote_compatible 227def test_ap_ht40_scan_legacy_conflict(dev, apdev): 228 """HT40 co-ex scan conflict with legacy 20 MHz AP""" 229 clear_scan_cache(apdev[0]) 230 params = {"ssid": "legacy-20", 231 "channel": "7", "ieee80211n": "0"} 232 hostapd.add_ap(apdev[1], params) 233 234 params = {"ssid": "test-ht40", 235 "channel": "5", 236 "ht_capab": "[HT40-]"} 237 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 238 239 state = hapd.get_status_field("state") 240 if state != "HT_SCAN": 241 time.sleep(0.1) 242 state = hapd.get_status_field("state") 243 if state != "HT_SCAN": 244 raise Exception("Unexpected interface state - expected HT_SCAN") 245 246 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 247 if not ev: 248 raise Exception("AP setup timed out") 249 250 state = hapd.get_status_field("state") 251 if state != "ENABLED": 252 raise Exception("Unexpected interface state - expected ENABLED") 253 254 freq = hapd.get_status_field("freq") 255 if freq != "2432": 256 raise Exception("Unexpected frequency: " + freq) 257 pri = hapd.get_status_field("channel") 258 if pri != "5": 259 raise Exception("Unexpected primary channel: " + pri) 260 sec = hapd.get_status_field("secondary_channel") 261 if sec != "0": 262 raise Exception("Unexpected secondary channel: " + sec) 263 264 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 265 266@remote_compatible 267def test_ap_ht40_scan_ht20_conflict(dev, apdev): 268 """HT40 co-ex scan conflict with HT 20 MHz AP""" 269 clear_scan_cache(apdev[0]) 270 params = {"ssid": "ht-20", 271 "channel": "7", "ieee80211n": "1"} 272 hostapd.add_ap(apdev[1], params) 273 274 params = {"ssid": "test-ht40", 275 "channel": "5", 276 "ht_capab": "[HT40-]"} 277 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 278 279 state = hapd.get_status_field("state") 280 if state != "HT_SCAN": 281 time.sleep(0.1) 282 state = hapd.get_status_field("state") 283 if state != "HT_SCAN": 284 raise Exception("Unexpected interface state - expected HT_SCAN") 285 286 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 287 if not ev: 288 raise Exception("AP setup timed out") 289 290 state = hapd.get_status_field("state") 291 if state != "ENABLED": 292 raise Exception("Unexpected interface state - expected ENABLED") 293 294 freq = hapd.get_status_field("freq") 295 if freq != "2432": 296 raise Exception("Unexpected frequency: " + freq) 297 pri = hapd.get_status_field("channel") 298 if pri != "5": 299 raise Exception("Unexpected primary channel: " + pri) 300 sec = hapd.get_status_field("secondary_channel") 301 if sec != "0": 302 raise Exception("Unexpected secondary channel: " + sec) 303 304 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 305 306def test_ap_ht40_scan_intolerant(dev, apdev): 307 """HT40 co-ex scan finding an AP advertising 40 MHz intolerant""" 308 clear_scan_cache(apdev[0]) 309 params = {"ssid": "another-bss", 310 "channel": "1", 311 "ht_capab": "[40-INTOLERANT]"} 312 hostapd.add_ap(apdev[1], params) 313 314 params = {"ssid": "test-ht40", 315 "channel": "1", 316 "ht_capab": "[HT40+]"} 317 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 318 319 state = hapd.get_status_field("state") 320 if state != "HT_SCAN": 321 time.sleep(0.1) 322 state = hapd.get_status_field("state") 323 if state != "HT_SCAN": 324 raise Exception("Unexpected interface state - expected HT_SCAN") 325 326 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 327 if not ev: 328 raise Exception("AP setup timed out") 329 330 state = hapd.get_status_field("state") 331 if state != "ENABLED": 332 raise Exception("Unexpected interface state - expected ENABLED") 333 334 freq = hapd.get_status_field("freq") 335 if freq != "2412": 336 raise Exception("Unexpected frequency: " + freq) 337 pri = hapd.get_status_field("channel") 338 if pri != "1": 339 raise Exception("Unexpected primary channel: " + pri) 340 sec = hapd.get_status_field("secondary_channel") 341 if sec != "0": 342 raise Exception("Unexpected secondary channel: " + sec) 343 344 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 345 346def test_ap_ht40_scan_match(dev, apdev): 347 """HT40 co-ex scan matching configuration""" 348 clear_scan_cache(apdev[0]) 349 params = {"ssid": "test-ht40", 350 "channel": "5", 351 "ht_capab": "[HT40-]"} 352 hostapd.add_ap(apdev[1], params) 353 354 params = {"ssid": "test-ht40", 355 "channel": "5", 356 "ht_capab": "[HT40-]"} 357 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 358 359 state = hapd.get_status_field("state") 360 if state != "HT_SCAN": 361 time.sleep(0.1) 362 state = hapd.get_status_field("state") 363 if state != "HT_SCAN": 364 raise Exception("Unexpected interface state - expected HT_SCAN") 365 366 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 367 if not ev: 368 raise Exception("AP setup timed out") 369 370 state = hapd.get_status_field("state") 371 if state != "ENABLED": 372 raise Exception("Unexpected interface state - expected ENABLED") 373 374 freq = hapd.get_status_field("freq") 375 if freq != "2432": 376 raise Exception("Unexpected frequency") 377 pri = hapd.get_status_field("channel") 378 if pri != "5": 379 raise Exception("Unexpected primary channel") 380 sec = hapd.get_status_field("secondary_channel") 381 if sec != "-1": 382 raise Exception("Unexpected secondary channel: " + sec) 383 384 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 385 386def test_ap_ht40_5ghz_match(dev, apdev): 387 """HT40 co-ex scan on 5 GHz with matching pri/sec channel""" 388 clear_scan_cache(apdev[0]) 389 try: 390 hapd = None 391 hapd2 = None 392 params = {"ssid": "test-ht40", 393 "hw_mode": "a", 394 "channel": "36", 395 "country_code": "US", 396 "ht_capab": "[HT40+]"} 397 hapd2 = hostapd.add_ap(apdev[1], params) 398 399 params = {"ssid": "test-ht40", 400 "hw_mode": "a", 401 "channel": "36", 402 "ht_capab": "[HT40+]"} 403 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 404 405 state = hapd.get_status_field("state") 406 if state != "HT_SCAN": 407 time.sleep(0.1) 408 state = hapd.get_status_field("state") 409 if state != "HT_SCAN": 410 raise Exception("Unexpected interface state - expected HT_SCAN") 411 412 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 413 if not ev: 414 raise Exception("AP setup timed out") 415 416 state = hapd.get_status_field("state") 417 if state != "ENABLED": 418 raise Exception("Unexpected interface state - expected ENABLED") 419 420 freq = hapd.get_status_field("freq") 421 if freq != "5180": 422 raise Exception("Unexpected frequency") 423 pri = hapd.get_status_field("channel") 424 if pri != "36": 425 raise Exception("Unexpected primary channel") 426 sec = hapd.get_status_field("secondary_channel") 427 if sec != "1": 428 raise Exception("Unexpected secondary channel: " + sec) 429 430 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 431 finally: 432 dev[0].request("DISCONNECT") 433 if hapd: 434 hapd.request("DISABLE") 435 if hapd2: 436 hapd2.request("DISABLE") 437 set_world_reg(apdev[0], apdev[1], dev[0]) 438 dev[0].flush_scan_cache() 439 440def test_ap_ht40_5ghz_switch(dev, apdev): 441 """HT40 co-ex scan on 5 GHz switching pri/sec channel""" 442 clear_scan_cache(apdev[0]) 443 try: 444 hapd = None 445 hapd2 = None 446 params = {"ssid": "test-ht40", 447 "hw_mode": "a", 448 "channel": "36", 449 "country_code": "US", 450 "ht_capab": "[HT40+]"} 451 hapd2 = hostapd.add_ap(apdev[1], params) 452 453 params = {"ssid": "test-ht40", 454 "hw_mode": "a", 455 "channel": "40", 456 "ht_capab": "[HT40-]"} 457 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 458 459 state = hapd.get_status_field("state") 460 if state != "HT_SCAN": 461 time.sleep(0.1) 462 state = hapd.get_status_field("state") 463 if state != "HT_SCAN": 464 raise Exception("Unexpected interface state - expected HT_SCAN") 465 466 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 467 if not ev: 468 raise Exception("AP setup timed out") 469 470 state = hapd.get_status_field("state") 471 if state != "ENABLED": 472 raise Exception("Unexpected interface state - expected ENABLED") 473 474 freq = hapd.get_status_field("freq") 475 if freq != "5180": 476 raise Exception("Unexpected frequency: " + freq) 477 pri = hapd.get_status_field("channel") 478 if pri != "36": 479 raise Exception("Unexpected primary channel: " + pri) 480 sec = hapd.get_status_field("secondary_channel") 481 if sec != "1": 482 raise Exception("Unexpected secondary channel: " + sec) 483 484 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 485 finally: 486 dev[0].request("DISCONNECT") 487 if hapd: 488 hapd.request("DISABLE") 489 if hapd2: 490 hapd2.request("DISABLE") 491 set_world_reg(apdev[0], apdev[1], dev[0]) 492 493def test_ap_ht40_5ghz_switch2(dev, apdev): 494 """HT40 co-ex scan on 5 GHz switching pri/sec channel (2)""" 495 clear_scan_cache(apdev[0]) 496 try: 497 hapd = None 498 hapd2 = None 499 params = {"ssid": "test-ht40", 500 "hw_mode": "a", 501 "channel": "36", 502 "country_code": "US", 503 "ht_capab": "[HT40+]"} 504 hapd2 = hostapd.add_ap(apdev[1], params) 505 506 id = dev[0].add_network() 507 dev[0].set_network(id, "mode", "2") 508 dev[0].set_network_quoted(id, "ssid", "wpas-ap-open") 509 dev[0].set_network(id, "key_mgmt", "NONE") 510 dev[0].set_network(id, "frequency", "5200") 511 dev[0].set_network(id, "scan_freq", "5200") 512 dev[0].select_network(id) 513 time.sleep(1) 514 515 params = {"ssid": "test-ht40", 516 "hw_mode": "a", 517 "channel": "40", 518 "ht_capab": "[HT40-]"} 519 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 520 521 state = hapd.get_status_field("state") 522 if state != "HT_SCAN": 523 time.sleep(0.1) 524 state = hapd.get_status_field("state") 525 if state != "HT_SCAN": 526 raise Exception("Unexpected interface state - expected HT_SCAN") 527 528 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 529 if not ev: 530 raise Exception("AP setup timed out") 531 532 state = hapd.get_status_field("state") 533 if state != "ENABLED": 534 raise Exception("Unexpected interface state - expected ENABLED") 535 536 freq = hapd.get_status_field("freq") 537 if freq != "5180": 538 raise Exception("Unexpected frequency: " + freq) 539 pri = hapd.get_status_field("channel") 540 if pri != "36": 541 raise Exception("Unexpected primary channel: " + pri) 542 sec = hapd.get_status_field("secondary_channel") 543 if sec != "1": 544 raise Exception("Unexpected secondary channel: " + sec) 545 546 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 547 finally: 548 dev[0].request("DISCONNECT") 549 if hapd: 550 hapd.request("DISABLE") 551 if hapd2: 552 hapd2.request("DISABLE") 553 set_world_reg(apdev[0], apdev[1], dev[0]) 554 dev[0].flush_scan_cache() 555 556def test_obss_scan(dev, apdev): 557 """Overlapping BSS scan request""" 558 clear_scan_cache(apdev[0]) 559 params = {"ssid": "obss-scan", 560 "channel": "6", 561 "ht_capab": "[HT40-]", 562 "obss_interval": "10"} 563 hapd = hostapd.add_ap(apdev[0], params) 564 565 params = {"ssid": "another-bss", 566 "channel": "9", 567 "ieee80211n": "0"} 568 hostapd.add_ap(apdev[1], params) 569 run_obss_scan(hapd, dev) 570 571def test_obss_scan_ht40_plus(dev, apdev): 572 """Overlapping BSS scan request (HT40+)""" 573 clear_scan_cache(apdev[0]) 574 params = {"ssid": "obss-scan", 575 "channel": "6", 576 "ht_capab": "[HT40+]", 577 "obss_interval": "10"} 578 hapd = hostapd.add_ap(apdev[0], params) 579 580 params = {"ssid": "another-bss", 581 "channel": "9", 582 "ieee80211n": "0"} 583 hostapd.add_ap(apdev[1], params) 584 run_obss_scan(hapd, dev, ht40plus=True) 585 586def run_obss_scan(hapd, dev, ht40plus=False): 587 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437") 588 res = dev[0].request("SIGNAL_POLL") 589 logger.info("SIGNAL_POLL:\n" + res) 590 sig = res.splitlines() 591 if "FREQUENCY=2437" not in sig: 592 raise Exception("Unexpected frequency") 593 if "WIDTH=40 MHz" not in sig: 594 raise Exception("Not a 40 MHz connection") 595 if ht40plus and "CENTER_FRQ1=2447" not in sig: 596 raise Exception("Not HT40+") 597 if not ht40plus and "CENTER_FRQ1=2427" not in sig: 598 raise Exception("Not HT40-") 599 hapd.set("ext_mgmt_frame_handling", "1") 600 logger.info("Waiting for OBSS scan to occur") 601 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15) 602 if ev is None: 603 raise Exception("Timed out while waiting for OBSS scan to start") 604 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10) 605 if ev is None: 606 raise Exception("Timed out while waiting for OBSS scan results") 607 received = False 608 for i in range(0, 4): 609 frame = hapd.mgmt_rx(timeout=5) 610 if frame is None: 611 raise Exception("MGMT RX wait timed out") 612 if frame['subtype'] != 13: 613 continue 614 payload = frame['payload'] 615 if len(payload) < 3: 616 continue 617 (category, action, ie) = struct.unpack('BBB', payload[0:3]) 618 if category != 4: 619 continue 620 if action != 0: 621 continue 622 if ie == 72: 623 logger.info("20/40 BSS Coexistence report received") 624 received = True 625 break 626 if not received: 627 raise Exception("20/40 BSS Coexistence report not seen") 628 629def test_obss_scan_40_intolerant(dev, apdev): 630 """Overlapping BSS scan request with 40 MHz intolerant AP""" 631 params = {"ssid": "obss-scan", 632 "channel": "6", 633 "ht_capab": "[HT40-]", 634 "obss_interval": "10"} 635 hapd = hostapd.add_ap(apdev[0], params) 636 637 params = {"ssid": "another-bss", 638 "channel": "7", 639 "ht_capab": "[40-INTOLERANT]"} 640 hostapd.add_ap(apdev[1], params) 641 642 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437") 643 hapd.set("ext_mgmt_frame_handling", "1") 644 logger.info("Waiting for OBSS scan to occur") 645 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-STARTED"], timeout=15) 646 if ev is None: 647 raise Exception("Timed out while waiting for OBSS scan to start") 648 ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10) 649 if ev is None: 650 raise Exception("Timed out while waiting for OBSS scan results") 651 received = False 652 for i in range(0, 4): 653 frame = hapd.mgmt_rx(timeout=5) 654 if frame is None: 655 raise Exception("MGMT RX wait timed out") 656 if frame['subtype'] != 13: 657 continue 658 payload = frame['payload'] 659 if len(payload) < 3: 660 continue 661 (category, action, ie) = struct.unpack('BBB', payload[0:3]) 662 if category != 4: 663 continue 664 if action != 0: 665 continue 666 if ie == 72: 667 logger.info("20/40 BSS Coexistence report received") 668 received = True 669 break 670 if not received: 671 raise Exception("20/40 BSS Coexistence report not seen") 672 673def test_obss_coex_report_handling(dev, apdev): 674 """Overlapping BSS scan report handling with obss_interval=0""" 675 clear_scan_cache(apdev[0]) 676 params = {"ssid": "obss-scan", 677 "channel": "6", 678 "ht_capab": "[HT40-]"} 679 hapd = hostapd.add_ap(apdev[0], params) 680 bssid = apdev[0]['bssid'] 681 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437") 682 683 sec = hapd.get_status_field("secondary_channel") 684 if sec != "-1": 685 raise Exception("AP is not using 40 MHz channel") 686 687 # 20/40 MHz co-ex report tests: number of invalid reports and a valid report 688 # that forces 20 MHz channel. 689 tests = ['0400', '040048', '04004801', '0400480000', '0400490100', 690 '040048ff0000', '04004801ff49ff00', '04004801004900', 691 '0400480100490101', '0400480100490201ff', 692 '040048010449020005'] 693 for msg in tests: 694 req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg) 695 if "OK" not in dev[0].request(req): 696 raise Exception("Could not send management frame") 697 time.sleep(0.5) 698 sec = hapd.get_status_field("secondary_channel") 699 if sec != "0": 700 raise Exception("AP did not move to 20 MHz channel") 701 702def test_obss_coex_report_handling1(dev, apdev): 703 """Overlapping BSS scan report handling with obss_interval=1""" 704 clear_scan_cache(apdev[0]) 705 params = {"ssid": "obss-scan", 706 "channel": "6", 707 "ht_capab": "[HT40+]", 708 "obss_interval": "1"} 709 hapd = hostapd.add_ap(apdev[0], params) 710 bssid = apdev[0]['bssid'] 711 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437") 712 713 sec = hapd.get_status_field("secondary_channel") 714 if sec != "1": 715 raise Exception("AP is not using 40 MHz channel") 716 717 # 20/40 MHz co-ex report forcing 20 MHz channel 718 msg = '040048010449020005' 719 req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg) 720 if "OK" not in dev[0].request(req): 721 raise Exception("Could not send management frame") 722 time.sleep(0.5) 723 sec = hapd.get_status_field("secondary_channel") 724 if sec != "0": 725 raise Exception("AP did not move to 20 MHz channel") 726 727 # No 20/40 MHz co-ex reports forcing 20 MHz channel during next interval 728 for i in range(20): 729 sec = hapd.get_status_field("secondary_channel") 730 if sec == "1": 731 break 732 time.sleep(0.5) 733 if sec != "1": 734 raise Exception("AP did not return to 40 MHz channel") 735 736def test_obss_coex_report_handling2(dev, apdev): 737 """Overlapping BSS scan report handling with obss_interval=1 and no overlap""" 738 clear_scan_cache(apdev[0]) 739 params = {"ssid": "obss-scan", 740 "channel": "6", 741 "ht_capab": "[HT40+]", 742 "obss_interval": "1"} 743 hapd = hostapd.add_ap(apdev[0], params) 744 bssid = apdev[0]['bssid'] 745 dev[0].connect("obss-scan", key_mgmt="NONE", scan_freq="2437") 746 747 sec = hapd.get_status_field("secondary_channel") 748 if sec != "1": 749 raise Exception("AP is not using 40 MHz channel") 750 751 # 20/40 MHz co-ex report that does not force a move to 20 MHz channel 752 # (out of affected range and matching primary channel cases) 753 msg = '0400' + '480100' + '49020001' + '49020006' 754 req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg) 755 if "OK" not in dev[0].request(req): 756 raise Exception("Could not send management frame") 757 time.sleep(0.5) 758 sec = hapd.get_status_field("secondary_channel") 759 if sec != "1": 760 raise Exception("Unexpected move to 20 MHz channel") 761 762 # 20/40 MHz co-ex report forcing 20 MHz channel 763 # (out of affected range and in affected range but not matching primary) 764 msg = '0400' + '480100' + '4903000105' 765 req = "MGMT_TX {} {} freq=2437 action={}".format(bssid, bssid, msg) 766 if "OK" not in dev[0].request(req): 767 raise Exception("Could not send management frame") 768 time.sleep(0.5) 769 sec = hapd.get_status_field("secondary_channel") 770 if sec != "0": 771 raise Exception("AP did not move to 20 MHz channel") 772 773def test_olbc(dev, apdev): 774 """OLBC detection""" 775 params = {"ssid": "test-olbc", 776 "channel": "6", 777 "ht_capab": "[HT40-]", 778 "ap_table_expiration_time": "2"} 779 hapd = hostapd.add_ap(apdev[0], params) 780 status = hapd.get_status() 781 if status['olbc'] != '0' or status['olbc_ht'] != '0': 782 raise Exception("Unexpected OLBC information") 783 784 params = {"ssid": "olbc-ap", 785 "hw_mode": "b", 786 "channel": "6", 787 "wmm_enabled": "0"} 788 hostapd.add_ap(apdev[1], params) 789 time.sleep(0.5) 790 status = hapd.get_status() 791 if status['olbc'] != '1' or status['olbc_ht'] != '1': 792 raise Exception("Missing OLBC information") 793 794 hostapd.remove_bss(apdev[1]) 795 796 logger.info("Waiting for OLBC state to time out") 797 cleared = False 798 for i in range(0, 15): 799 time.sleep(1) 800 status = hapd.get_status() 801 if status['olbc'] == '0' and status['olbc_ht'] == '0': 802 cleared = True 803 break 804 if not cleared: 805 raise Exception("OLBC state did nto time out") 806 807def test_olbc_table_limit(dev, apdev): 808 """OLBC AP table size limit""" 809 ifname1 = apdev[0]['ifname'] 810 ifname2 = apdev[0]['ifname'] + '-2' 811 ifname3 = apdev[0]['ifname'] + '-3' 812 hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') 813 hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') 814 hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') 815 816 params = {"ssid": "test-olbc", 817 "channel": "1", 818 "ap_table_max_size": "2"} 819 hapd = hostapd.add_ap(apdev[1], params) 820 821 time.sleep(0.3) 822 with alloc_fail(hapd, 1, "ap_list_process_beacon"): 823 time.sleep(0.3) 824 hapd.set("ap_table_max_size", "1") 825 time.sleep(0.3) 826 hapd.set("ap_table_max_size", "0") 827 time.sleep(0.3) 828 829def test_olbc_5ghz(dev, apdev): 830 """OLBC detection on 5 GHz""" 831 try: 832 hapd = None 833 hapd2 = None 834 params = {"ssid": "test-olbc", 835 "country_code": "FI", 836 "hw_mode": "a", 837 "channel": "36", 838 "ht_capab": "[HT40+]"} 839 hapd = hostapd.add_ap(apdev[0], params) 840 status = hapd.get_status() 841 if status['olbc'] != '0' or status['olbc_ht'] != '0': 842 raise Exception("Unexpected OLBC information") 843 844 params = {"ssid": "olbc-ap", 845 "country_code": "FI", 846 "hw_mode": "a", 847 "channel": "36", 848 "ieee80211n": "0", 849 "wmm_enabled": "0"} 850 hapd2 = hostapd.add_ap(apdev[1], params) 851 found = False 852 for i in range(20): 853 time.sleep(0.1) 854 status = hapd.get_status() 855 logger.debug('olbc_ht: ' + status['olbc_ht']) 856 if status['olbc_ht'] == '1': 857 found = True 858 break 859 if not found: 860 raise Exception("Missing OLBC information") 861 finally: 862 if hapd: 863 hapd.request("DISABLE") 864 if hapd2: 865 hapd2.request("DISABLE") 866 set_world_reg(apdev[0], apdev[1], None) 867 868def test_ap_require_ht(dev, apdev): 869 """Require HT""" 870 params = {"ssid": "require-ht", 871 "require_ht": "1"} 872 hapd = hostapd.add_ap(apdev[0], params) 873 874 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 875 wpas.interface_add("wlan5", drv_params="extra_bss_membership_selectors=127") 876 877 wpas.connect("require-ht", key_mgmt="NONE", scan_freq="2412", 878 disable_ht="1", wait_connect=False) 879 dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412") 880 ev = wpas.wait_event(["CTRL-EVENT-ASSOC-REJECT"]) 881 wpas.request("DISCONNECT") 882 if ev is None: 883 raise Exception("Association rejection timed out") 884 if "status_code=27" not in ev: 885 raise Exception("Unexpected rejection status code") 886 dev[2].connect("require-ht", key_mgmt="NONE", scan_freq="2412", 887 ht_mcs="0x01 00 00 00 00 00 00 00 00 00", 888 disable_max_amsdu="1", ampdu_factor="2", 889 ampdu_density="1", disable_ht40="1", disable_sgi="1", 890 disable_ldpc="1", rx_stbc="2", tx_stbc="1") 891 892 sta = hapd.get_sta(dev[0].own_addr()) 893 if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: 894 raise Exception("No Supported Operating Classes information for STA") 895 opclass = int(sta['supp_op_classes'][0:2], 16) 896 if opclass != 81: 897 raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) 898 899def test_ap_ht_stbc(dev, apdev): 900 """HT STBC overrides""" 901 params = {"ssid": "ht"} 902 hapd = hostapd.add_ap(apdev[0], params) 903 904 dev[0].connect("ht", key_mgmt="NONE", scan_freq="2412") 905 dev[1].connect("ht", key_mgmt="NONE", scan_freq="2412", 906 rx_stbc="0", tx_stbc="0") 907 dev[2].connect("ht", key_mgmt="NONE", scan_freq="2412", 908 rx_stbc="1", tx_stbc="1") 909 910@remote_compatible 911def test_ap_require_ht_limited_rates(dev, apdev): 912 """Require HT with limited supported rates""" 913 params = {"ssid": "require-ht", 914 "supported_rates": "60 120 240 360 480 540", 915 "require_ht": "1"} 916 hapd = hostapd.add_ap(apdev[0], params) 917 918 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 919 wpas.interface_add("wlan5", drv_params="extra_bss_membership_selectors=127") 920 921 wpas.connect("require-ht", key_mgmt="NONE", scan_freq="2412", 922 disable_ht="1", wait_connect=False) 923 dev[0].connect("require-ht", key_mgmt="NONE", scan_freq="2412") 924 ev = wpas.wait_event(["CTRL-EVENT-ASSOC-REJECT"]) 925 wpas.request("DISCONNECT") 926 if ev is None: 927 raise Exception("Association rejection timed out") 928 if "status_code=27" not in ev: 929 raise Exception("Unexpected rejection status code") 930 931@remote_compatible 932def test_ap_ht_capab_not_supported(dev, apdev): 933 """HT configuration with driver not supporting all ht_capab entries""" 934 params = {"ssid": "test-ht40", 935 "channel": "5", 936 "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]"} 937 hapd = hostapd.add_ap(apdev[0], params, no_enable=True) 938 if "FAIL" not in hapd.request("ENABLE"): 939 raise Exception("Unexpected ENABLE success") 940 941def test_ap_ht_40mhz_intolerant_sta(dev, apdev): 942 """Associated STA indicating 40 MHz intolerant""" 943 clear_scan_cache(apdev[0]) 944 params = {"ssid": "intolerant", 945 "channel": "6", 946 "ht_capab": "[HT40-]", 947 "obss_interval": "2"} 948 hapd = hostapd.add_ap(apdev[0], params) 949 if hapd.get_status_field("num_sta_ht40_intolerant") != "0": 950 raise Exception("Unexpected num_sta_ht40_intolerant value") 951 if hapd.get_status_field("secondary_channel") != "-1": 952 raise Exception("Unexpected secondary_channel") 953 954 dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437") 955 if hapd.get_status_field("num_sta_ht40_intolerant") != "0": 956 raise Exception("Unexpected num_sta_ht40_intolerant value") 957 if hapd.get_status_field("secondary_channel") != "-1": 958 raise Exception("Unexpected secondary_channel") 959 960 dev[2].connect("intolerant", key_mgmt="NONE", scan_freq="2437", 961 ht40_intolerant="1") 962 time.sleep(1) 963 if hapd.get_status_field("num_sta_ht40_intolerant") != "1": 964 raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)") 965 if hapd.get_status_field("secondary_channel") != "0": 966 raise Exception("Unexpected secondary_channel (did not disable 40 MHz)") 967 968 dev[2].request("DISCONNECT") 969 time.sleep(12) 970 if hapd.get_status_field("num_sta_ht40_intolerant") != "0": 971 raise Exception("Unexpected num_sta_ht40_intolerant value (expected 0)") 972 if hapd.get_status_field("secondary_channel") != "-1": 973 raise Exception("Unexpected secondary_channel (did not re-enable 40 MHz)") 974 975def test_ap_ht_40mhz_intolerant_sta_deinit(dev, apdev): 976 """Associated STA indicating 40 MHz intolerant and hostapd deinit""" 977 clear_scan_cache(apdev[0]) 978 params = {"ssid": "intolerant", 979 "channel": "6", 980 "ht_capab": "[HT40-]", 981 "obss_interval": "0"} 982 hapd = hostapd.add_ap(apdev[0], params) 983 984 dev[0].connect("intolerant", key_mgmt="NONE", scan_freq="2437", 985 ht40_intolerant="1") 986 time.sleep(1) 987 if hapd.get_status_field("num_sta_ht40_intolerant") != "1": 988 raise Exception("Unexpected num_sta_ht40_intolerant value (expected 1)") 989 hglobal = hostapd.HostapdGlobal() 990 hglobal.remove(apdev[0]['ifname']) 991 992 dev[0].request("DISCONNECT") 993 994def test_ap_ht_40mhz_intolerant_ap(dev, apdev): 995 """Associated STA reports 40 MHz intolerant AP after association""" 996 clear_scan_cache(apdev[0]) 997 params = {"ssid": "ht", 998 "channel": "6", 999 "ht_capab": "[HT40-]", 1000 "obss_interval": "3"} 1001 hapd = hostapd.add_ap(apdev[0], params) 1002 1003 dev[0].connect("ht", key_mgmt="NONE", scan_freq="2437") 1004 1005 if hapd.get_status_field("secondary_channel") != "-1": 1006 raise Exception("Unexpected secondary channel information") 1007 1008 logger.info("Start 40 MHz intolerant AP") 1009 params = {"ssid": "intolerant", 1010 "channel": "5", 1011 "ht_capab": "[40-INTOLERANT]"} 1012 hapd2 = hostapd.add_ap(apdev[1], params) 1013 1014 logger.info("Waiting for co-ex report from STA") 1015 ok = False 1016 for i in range(4): 1017 ev = dev[0].wait_event(['CTRL-EVENT-SCAN-RESULTS'], timeout=20) 1018 if ev is None: 1019 raise Exception("No OBSS scan seen") 1020 time.sleep(1) 1021 if hapd.get_status_field("secondary_channel") == "0": 1022 logger.info("AP moved to 20 MHz channel") 1023 ok = True 1024 break 1025 if not ok: 1026 raise Exception("AP did not move to 20 MHz channel") 1027 1028 if "OK" not in hapd2.request("DISABLE"): 1029 raise Exception("Failed to disable 40 MHz intolerant AP") 1030 1031 # make sure the intolerant AP disappears from scan results more quickly 1032 dev[0].scan(type="ONLY", freq="2432", only_new=True) 1033 dev[0].scan(type="ONLY", freq="2432", only_new=True) 1034 dev[0].dump_monitor() 1035 1036 logger.info("Waiting for AP to move back to 40 MHz channel") 1037 ok = False 1038 for i in range(0, 30): 1039 time.sleep(1) 1040 if hapd.get_status_field("secondary_channel") == "-1": 1041 logger.info("AP moved to 40 MHz channel") 1042 ok = True 1043 break 1044 if not ok: 1045 raise Exception("AP did not move to 40 MHz channel") 1046 1047def test_ap_ht40_csa(dev, apdev): 1048 """HT with 40 MHz channel width and CSA""" 1049 csa_supported(dev[0]) 1050 try: 1051 hapd = None 1052 params = {"ssid": "ht", 1053 "country_code": "US", 1054 "hw_mode": "a", 1055 "channel": "36", 1056 "ht_capab": "[HT40+]", 1057 "ieee80211n": "1"} 1058 hapd = hostapd.add_ap(apdev[0], params) 1059 1060 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180") 1061 hwsim_utils.test_connectivity(dev[0], hapd) 1062 1063 hapd.request("CHAN_SWITCH 5 5200 ht sec_channel_offset=-1 bandwidth=40") 1064 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) 1065 if ev is None: 1066 raise Exception("CSA finished event timed out") 1067 if "freq=5200" not in ev: 1068 raise Exception("Unexpected channel in CSA finished event") 1069 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) 1070 if ev is not None: 1071 raise Exception("Unexpected STA disconnection during CSA") 1072 hwsim_utils.test_connectivity(dev[0], hapd) 1073 1074 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40") 1075 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) 1076 if ev is None: 1077 raise Exception("CSA finished event timed out") 1078 if "freq=5180" not in ev: 1079 raise Exception("Unexpected channel in CSA finished event") 1080 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) 1081 if ev is not None: 1082 raise Exception("Unexpected STA disconnection during CSA") 1083 hwsim_utils.test_connectivity(dev[0], hapd) 1084 finally: 1085 dev[0].request("DISCONNECT") 1086 if hapd: 1087 hapd.request("DISABLE") 1088 set_world_reg(apdev[0], None, dev[0]) 1089 dev[0].flush_scan_cache() 1090 1091def test_ap_ht40_csa2(dev, apdev): 1092 """HT with 40 MHz channel width and CSA""" 1093 csa_supported(dev[0]) 1094 try: 1095 hapd = None 1096 params = {"ssid": "ht", 1097 "country_code": "US", 1098 "hw_mode": "a", 1099 "channel": "36", 1100 "ht_capab": "[HT40+]", 1101 "ieee80211n": "1"} 1102 hapd = hostapd.add_ap(apdev[0], params) 1103 1104 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180") 1105 hwsim_utils.test_connectivity(dev[0], hapd) 1106 1107 hapd.request("CHAN_SWITCH 5 5220 ht sec_channel_offset=1 bandwidth=40") 1108 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) 1109 if ev is None: 1110 raise Exception("CSA finished event timed out") 1111 if "freq=5220" not in ev: 1112 raise Exception("Unexpected channel in CSA finished event") 1113 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) 1114 if ev is not None: 1115 raise Exception("Unexpected STA disconnection during CSA") 1116 hwsim_utils.test_connectivity(dev[0], hapd) 1117 1118 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40") 1119 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) 1120 if ev is None: 1121 raise Exception("CSA finished event timed out") 1122 if "freq=5180" not in ev: 1123 raise Exception("Unexpected channel in CSA finished event") 1124 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) 1125 if ev is not None: 1126 raise Exception("Unexpected STA disconnection during CSA") 1127 hwsim_utils.test_connectivity(dev[0], hapd) 1128 finally: 1129 dev[0].request("DISCONNECT") 1130 if hapd: 1131 hapd.request("DISABLE") 1132 set_world_reg(apdev[0], None, dev[0]) 1133 dev[0].flush_scan_cache() 1134 1135def test_ap_ht40_csa3(dev, apdev): 1136 """HT with 40 MHz channel width and CSA""" 1137 csa_supported(dev[0]) 1138 try: 1139 hapd = None 1140 params = {"ssid": "ht", 1141 "country_code": "US", 1142 "hw_mode": "a", 1143 "channel": "36", 1144 "ht_capab": "[HT40+]", 1145 "ieee80211n": "1"} 1146 hapd = hostapd.add_ap(apdev[0], params) 1147 1148 dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180") 1149 hwsim_utils.test_connectivity(dev[0], hapd) 1150 1151 hapd.request("CHAN_SWITCH 5 5240 ht sec_channel_offset=-1 bandwidth=40") 1152 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) 1153 if ev is None: 1154 raise Exception("CSA finished event timed out") 1155 if "freq=5240" not in ev: 1156 raise Exception("Unexpected channel in CSA finished event") 1157 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) 1158 if ev is not None: 1159 raise Exception("Unexpected STA disconnection during CSA") 1160 hwsim_utils.test_connectivity(dev[0], hapd) 1161 1162 hapd.request("CHAN_SWITCH 5 5180 ht sec_channel_offset=1 bandwidth=40") 1163 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) 1164 if ev is None: 1165 raise Exception("CSA finished event timed out") 1166 if "freq=5180" not in ev: 1167 raise Exception("Unexpected channel in CSA finished event") 1168 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) 1169 if ev is not None: 1170 raise Exception("Unexpected STA disconnection during CSA") 1171 hwsim_utils.test_connectivity(dev[0], hapd) 1172 finally: 1173 dev[0].request("DISCONNECT") 1174 if hapd: 1175 hapd.request("DISABLE") 1176 set_world_reg(apdev[0], None, dev[0]) 1177 dev[0].flush_scan_cache() 1178 1179def test_ap_ht_20_to_40_csa(dev, apdev): 1180 """HT with 20 MHz channel width doing CSA to 40 MHz""" 1181 csa_supported(dev[0]) 1182 1183 params = {"ssid": "ht", 1184 "channel": "1", 1185 "ieee80211n": "1"} 1186 hapd = hostapd.add_ap(apdev[0], params) 1187 1188 dev[0].connect("ht", key_mgmt="NONE", scan_freq="2412") 1189 hapd.wait_sta() 1190 res = dev[0].request("SIGNAL_POLL") 1191 logger.info("SIGNAL_POLL:\n" + res) 1192 sig = res.splitlines() 1193 if 'WIDTH=20 MHz' not in sig: 1194 raise Exception("20 MHz channel bandwidth not used on the original channel") 1195 1196 hapd.request("CHAN_SWITCH 5 2462 ht sec_channel_offset=-1 bandwidth=40") 1197 ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) 1198 if ev is None: 1199 raise Exception("CSA finished event timed out") 1200 if "freq=2462" not in ev: 1201 raise Exception("Unexpected channel in CSA finished event") 1202 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) 1203 if ev is not None: 1204 raise Exception("Unexpected STA disconnection during CSA") 1205 res = dev[0].request("SIGNAL_POLL") 1206 logger.info("SIGNAL_POLL:\n" + res) 1207 sig = res.splitlines() 1208 if 'WIDTH=40 MHz' not in sig: 1209 raise Exception("40 MHz channel bandwidth not used on the new channel") 1210 1211@remote_compatible 1212def test_prefer_ht20(dev, apdev): 1213 """Preference on HT20 over no-HT""" 1214 params = {"ssid": "test", 1215 "channel": "1", 1216 "ieee80211n": "0"} 1217 hapd = hostapd.add_ap(apdev[0], params) 1218 bssid = apdev[0]['bssid'] 1219 params = {"ssid": "test", 1220 "channel": "1", 1221 "ieee80211n": "1"} 1222 hapd2 = hostapd.add_ap(apdev[1], params) 1223 bssid2 = apdev[1]['bssid'] 1224 1225 dev[0].scan_for_bss(bssid, freq=2412) 1226 dev[0].scan_for_bss(bssid2, freq=2412) 1227 dev[0].connect("test", key_mgmt="NONE", scan_freq="2412") 1228 if dev[0].get_status_field('bssid') != bssid2: 1229 raise Exception("Unexpected BSS selected") 1230 1231 est = dev[0].get_bss(bssid)['est_throughput'] 1232 if est != "54000": 1233 raise Exception("Unexpected BSS0 est_throughput: " + est) 1234 1235 est = dev[0].get_bss(bssid2)['est_throughput'] 1236 if est != "65000": 1237 raise Exception("Unexpected BSS1 est_throughput: " + est) 1238 1239def test_prefer_ht40(dev, apdev): 1240 """Preference on HT40 over HT20""" 1241 hostapd.cmd_execute(apdev[1], ['ifconfig', apdev[1]['ifname'], 'up']) 1242 hostapd.cmd_execute(apdev[1], ['iw', apdev[1]['ifname'], 'scan', 1243 'flush', 'freq', '2417']) 1244 time.sleep(1) 1245 hostapd.cmd_execute(apdev[1], ['ifconfig', apdev[1]['ifname'], 'down']) 1246 1247 params = {"ssid": "test", 1248 "channel": "1", 1249 "ieee80211n": "1"} 1250 hapd = hostapd.add_ap(apdev[0], params) 1251 bssid = apdev[0]['bssid'] 1252 1253 params = {"ssid": "test", 1254 "channel": "1", 1255 "ieee80211n": "1", 1256 "ht_capab": "[HT40+]"} 1257 hapd2 = hostapd.add_ap(apdev[1], params) 1258 bssid2 = apdev[1]['bssid'] 1259 if hapd2.get_status_field("secondary_channel") != "1": 1260 raise Exception("AP2 did not enable HT40+") 1261 1262 dev[0].scan_for_bss(bssid, freq=2412) 1263 dev[0].scan_for_bss(bssid2, freq=2412) 1264 dev[0].connect("test", key_mgmt="NONE", scan_freq="2412") 1265 if dev[0].get_status_field('bssid') != bssid2: 1266 raise Exception("Unexpected BSS selected") 1267 1268 est = dev[0].get_bss(bssid)['est_throughput'] 1269 if est != "65000": 1270 raise Exception("Unexpected BSS0 est_throughput: " + est) 1271 1272 est = dev[0].get_bss(bssid2)['est_throughput'] 1273 if est != "135000": 1274 raise Exception("Unexpected BSS1 est_throughput: " + est) 1275 1276@remote_compatible 1277def test_prefer_ht20_during_roam(dev, apdev): 1278 """Preference on HT20 over no-HT in roaming consideration""" 1279 params = {"ssid": "test", 1280 "channel": "1", 1281 "ieee80211n": "0"} 1282 hapd = hostapd.add_ap(apdev[0], params) 1283 bssid = apdev[0]['bssid'] 1284 1285 dev[0].scan_for_bss(bssid, freq=2412) 1286 dev[0].connect("test", key_mgmt="NONE", scan_freq="2412") 1287 1288 params = {"ssid": "test", 1289 "channel": "1", 1290 "ieee80211n": "1"} 1291 hapd2 = hostapd.add_ap(apdev[1], params) 1292 bssid2 = apdev[1]['bssid'] 1293 dev[0].scan_for_bss(bssid2, freq=2412) 1294 dev[0].scan(freq=2412) 1295 dev[0].wait_connected() 1296 1297 if dev[0].get_status_field('bssid') != bssid2: 1298 raise Exception("Unexpected BSS selected") 1299 1300@remote_compatible 1301def test_ap_ht40_5ghz_invalid_pair(dev, apdev): 1302 """HT40 on 5 GHz with invalid channel pair""" 1303 clear_scan_cache(apdev[0]) 1304 try: 1305 params = {"ssid": "test-ht40", 1306 "hw_mode": "a", 1307 "channel": "40", 1308 "country_code": "US", 1309 "ht_capab": "[HT40+]"} 1310 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 1311 ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10) 1312 if not ev: 1313 raise Exception("AP setup failure timed out") 1314 if "AP-ENABLED" in ev: 1315 sec = hapd.get_status_field("secondary_channel") 1316 if sec != "0": 1317 raise Exception("Invalid 40 MHz channel accepted") 1318 finally: 1319 clear_regdom(hapd, dev) 1320 1321@remote_compatible 1322def test_ap_ht40_5ghz_disabled_sec(dev, apdev): 1323 """HT40 on 5 GHz with disabled secondary channel""" 1324 clear_scan_cache(apdev[0]) 1325 try: 1326 params = {"ssid": "test-ht40", 1327 "hw_mode": "a", 1328 "channel": "48", 1329 "country_code": "US", 1330 "ht_capab": "[HT40+]"} 1331 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 1332 ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10) 1333 if not ev: 1334 raise Exception("AP setup failure timed out") 1335 if "AP-ENABLED" in ev: 1336 sec = hapd.get_status_field("secondary_channel") 1337 if sec != "0": 1338 raise Exception("Invalid 40 MHz channel accepted") 1339 finally: 1340 clear_regdom(hapd, dev) 1341 1342def test_ap_ht40_scan_broken_ap(dev, apdev): 1343 """HT40 co-ex scan and broken legacy/HT AP""" 1344 clear_scan_cache(apdev[0]) 1345 1346 # Broken AP: Include HT Capabilities element but not HT Operation element 1347 params = {"ssid": "legacy-20", 1348 "channel": "7", "ieee80211n": "0", 1349 "wmm_enabled": "1", 1350 "vendor_elements": "2d1a0e001bffff000000000000000000000100000000000000000000"} 1351 hapd2 = hostapd.add_ap(apdev[1], params) 1352 1353 params = {"ssid": "test-ht40", 1354 "channel": "5", 1355 "ht_capab": "[HT40-]"} 1356 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 1357 1358 state = hapd.get_status_field("state") 1359 if state != "HT_SCAN": 1360 time.sleep(0.1) 1361 state = hapd.get_status_field("state") 1362 if state != "HT_SCAN": 1363 raise Exception("Unexpected interface state - expected HT_SCAN") 1364 1365 ev = hapd.wait_event(["AP-ENABLED"], timeout=10) 1366 if not ev: 1367 raise Exception("AP setup timed out") 1368 1369 state = hapd.get_status_field("state") 1370 if state != "ENABLED": 1371 raise Exception("Unexpected interface state - expected ENABLED") 1372 1373 freq = hapd.get_status_field("freq") 1374 if freq != "2432": 1375 raise Exception("Unexpected frequency: " + freq) 1376 pri = hapd.get_status_field("channel") 1377 if pri != "5": 1378 raise Exception("Unexpected primary channel: " + pri) 1379 sec = hapd.get_status_field("secondary_channel") 1380 if sec != "-1": 1381 raise Exception("Unexpected secondary channel: " + sec) 1382 1383 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 1384 dev[1].connect("legacy-20", key_mgmt="NONE", scan_freq="2442") 1385 hwsim_utils.test_connectivity(dev[0], hapd) 1386 hwsim_utils.test_connectivity(dev[1], hapd2) 1387 1388def run_op_class(dev, apdev, hw_mode, channel, country, ht_capab, sec_chan, 1389 freq, opclass, use_op_class=False): 1390 clear_scan_cache(apdev[0]) 1391 try: 1392 params = {"ssid": "test-ht40", 1393 "hw_mode": hw_mode, 1394 "channel": channel, 1395 "ht_capab": ht_capab} 1396 if use_op_class: 1397 params['op_class'] = str(opclass) 1398 if country: 1399 params['country_code'] = country 1400 hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) 1401 ev = hapd.wait_event(["AP-DISABLED", "AP-ENABLED"], timeout=10) 1402 if not ev: 1403 raise Exception("AP setup failure timed out") 1404 if "AP-DISABLED" in ev: 1405 raise HwsimSkip("Channel not supported") 1406 sec = hapd.get_status_field("secondary_channel") 1407 if sec != sec_chan: 1408 raise Exception("Unexpected secondary_channel: " + sec) 1409 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 1410 bss = dev[0].get_bss(hapd.own_addr()) 1411 ie = parse_ie(bss['ie']) 1412 if 59 not in ie: 1413 raise Exception("Missing Supported Operating Classes element") 1414 rx_opclass, = struct.unpack('B', ie[59][0:1]) 1415 if rx_opclass != opclass: 1416 raise Exception("Unexpected operating class: %d" % rx_opclass) 1417 hapd.disable() 1418 hapd.dump_monitor() 1419 dev[0].request("REMOVE_NETWORK all") 1420 dev[0].request("ABORT_SCAN") 1421 dev[0].wait_disconnected() 1422 dev[0].dump_monitor() 1423 finally: 1424 set_world_reg(apdev[0], None, dev[0]) 1425 time.sleep(0.1) 1426 1427def test_ap_ht_op_class_81(dev, apdev): 1428 """HT20 on operating class 81""" 1429 for o in [False, True]: 1430 run_op_class(dev, apdev, "g", "1", None, "", "0", "2412", 81, 1431 use_op_class=o) 1432 1433def test_ap_ht_op_class_83(dev, apdev): 1434 """HT40 on operating class 83""" 1435 for o in [False, True]: 1436 run_op_class(dev, apdev, "g", "1", None, "[HT40+]", "1", "2412", 83, 1437 use_op_class=o) 1438 1439def test_ap_ht_op_class_84(dev, apdev): 1440 """HT40 on operating class 84""" 1441 for o in [False, True]: 1442 run_op_class(dev, apdev, "g", "11", None, "[HT40-]", "-1", "2462", 84, 1443 use_op_class=o) 1444 1445def test_ap_ht_op_class_115(dev, apdev): 1446 """HT20 on operating class 115""" 1447 for o in [False, True]: 1448 run_op_class(dev, apdev, "a", "36", "FI", "", "0", "5180", 115, 1449 use_op_class=o) 1450 1451def test_ap_ht_op_class_116(dev, apdev): 1452 """HT40 on operating class 116""" 1453 for o in [False, True]: 1454 run_op_class(dev, apdev, "a", "36", "FI", "[HT40+]", "1", "5180", 116, 1455 use_op_class=o) 1456 1457def test_ap_ht_op_class_117(dev, apdev): 1458 """HT40 on operating class 117""" 1459 for o in [False, True]: 1460 run_op_class(dev, apdev, "a", "40", "FI", "[HT40-]", "-1", "5200", 117, 1461 use_op_class=o) 1462 1463def test_ap_ht_op_class_118(dev, apdev): 1464 """HT20 on operating class 118""" 1465 for o in [False, True]: 1466 run_op_class(dev, apdev, "a", "60", "PA", "", "0", "5300", 118, 1467 use_op_class=o) 1468 1469def test_ap_ht_op_class_119(dev, apdev): 1470 """HT40 on operating class 119""" 1471 for o in [False, True]: 1472 run_op_class(dev, apdev, "a", "60", "PA", "[HT40+]", "1", "5300", 119, 1473 use_op_class=o) 1474 1475def test_ap_ht_op_class_120(dev, apdev): 1476 """HT40 on operating class 120""" 1477 for o in [False, True]: 1478 run_op_class(dev, apdev, "a", "64", "PA", "[HT40-]", "-1", "5320", 120, 1479 use_op_class=o) 1480 1481def test_ap_ht_op_class_121(dev, apdev): 1482 """HT20 on operating class 121""" 1483 for o in [False, True]: 1484 run_op_class(dev, apdev, "a", "100", "ZA", "", "0", "5500", 121, 1485 use_op_class=o) 1486 1487def test_ap_ht_op_class_122(dev, apdev): 1488 """HT40 on operating class 122""" 1489 for o in [False, True]: 1490 run_op_class(dev, apdev, "a", "100", "ZA", "[HT40+]", "1", "5500", 122, 1491 use_op_class=o) 1492 1493def test_ap_ht_op_class_123(dev, apdev): 1494 """HT40 on operating class 123""" 1495 for o in [False, True]: 1496 run_op_class(dev, apdev, "a", "104", "ZA", "[HT40-]", "-1", "5520", 123, 1497 use_op_class=o) 1498 1499def test_ap_ht_op_class_125_chan149(dev, apdev): 1500 """HT20 on operating class 125 with channel 149""" 1501 for o in [False, True]: 1502 run_op_class(dev, apdev, "a", "149", "US", "", "0", "5745", 125, 1503 use_op_class=o) 1504 1505def test_ap_ht_op_class_125(dev, apdev): 1506 """HT20 on operating class 125""" 1507 for o in [False, True]: 1508 run_op_class(dev, apdev, "a", "169", "NL", "", "0", "5845", 125, 1509 use_op_class=o) 1510 1511def test_ap_ht_op_class_126(dev, apdev): 1512 """HT40 on operating class 126""" 1513 for o in [False, True]: 1514 run_op_class(dev, apdev, "a", "149", "US", "[HT40+]", "1", "5745", 126, 1515 use_op_class=o) 1516 1517def test_ap_ht_op_class_127(dev, apdev): 1518 """HT40 on operating class 127""" 1519 for o in [False, True]: 1520 run_op_class(dev, apdev, "a", "153", "US", "[HT40-]", "-1", "5765", 127, 1521 use_op_class=o) 1522 1523def test_ap_ht40_plus_minus1(dev, apdev): 1524 """HT40 with both plus and minus allowed (1)""" 1525 clear_scan_cache(apdev[0]) 1526 params = {"ssid": "test-ht40", 1527 "channel": "11", 1528 "ht_capab": "[HT40+][HT40-]"} 1529 hapd = hostapd.add_ap(apdev[0], params) 1530 1531 freq = hapd.get_status_field("freq") 1532 if freq != "2462": 1533 raise Exception("Unexpected frequency: " + freq) 1534 pri = hapd.get_status_field("channel") 1535 if pri != "11": 1536 raise Exception("Unexpected primary channel: " + pri) 1537 sec = hapd.get_status_field("secondary_channel") 1538 if sec != "-1": 1539 raise Exception("Unexpected secondary channel: " + sec) 1540 1541 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 1542 1543def test_ap_ht40_plus_minus2(dev, apdev): 1544 """HT40 with both plus and minus allowed (2)""" 1545 clear_scan_cache(apdev[0]) 1546 params = {"ssid": "test-ht40", 1547 "channel": "1", 1548 "ht_capab": "[HT40+][HT40-]"} 1549 hapd = hostapd.add_ap(apdev[0], params) 1550 1551 freq = hapd.get_status_field("freq") 1552 if freq != "2412": 1553 raise Exception("Unexpected frequency: " + freq) 1554 pri = hapd.get_status_field("channel") 1555 if pri != "1": 1556 raise Exception("Unexpected primary channel: " + pri) 1557 sec = hapd.get_status_field("secondary_channel") 1558 if sec != "1": 1559 raise Exception("Unexpected secondary channel: " + sec) 1560 1561 dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq=freq) 1562 1563def test_ap_ht40_disable(dev, apdev): 1564 """HT40 disabling""" 1565 clear_scan_cache(apdev[0]) 1566 params = {"ssid": "test-ht40", 1567 "channel": "6", 1568 "ht_capab": "[HT40-]"} 1569 hapd = hostapd.add_ap(apdev[0], params) 1570 1571 sec = hapd.get_status_field("secondary_channel") 1572 if sec != "-1": 1573 raise Exception("Unexpected secondary channel: " + sec) 1574 1575 id = dev[0].connect("test-ht40", key_mgmt="NONE", scan_freq="2437") 1576 sig = dev[0].request("SIGNAL_POLL").splitlines() 1577 logger.info("SIGNAL_POLL: " + str(sig)) 1578 if "WIDTH=40 MHz" not in sig: 1579 raise Exception("Station did not report 40 MHz bandwidth") 1580 dev[0].request("DISCONNECT") 1581 dev[0].wait_disconnected() 1582 1583 hapd.disable() 1584 hapd.set("ht_capab", "") 1585 hapd.enable() 1586 sec = hapd.get_status_field("secondary_channel") 1587 if sec != "0": 1588 raise Exception("Unexpected secondary channel(2): " + sec) 1589 1590 dev[0].flush_scan_cache() 1591 dev[0].select_network(id, freq=2437) 1592 dev[0].wait_connected() 1593 sig = dev[0].request("SIGNAL_POLL").splitlines() 1594 logger.info("SIGNAL_POLL: " + str(sig)) 1595 if "WIDTH=20 MHz" not in sig: 1596 raise Exception("Station did not report 20 MHz bandwidth") 1597 1598def test_ap_ht_wmm_etsi(dev, apdev): 1599 """HT and WMM contents in ETSI""" 1600 run_ap_ht_wmm(dev, apdev, "FI") 1601 1602def test_ap_ht_wmm_fcc(dev, apdev): 1603 """HT and WMM contents in FCC""" 1604 run_ap_ht_wmm(dev, apdev, "US") 1605 1606def run_ap_ht_wmm(dev, apdev, country): 1607 clear_scan_cache(apdev[0]) 1608 try: 1609 hapd = None 1610 params = {"ssid": "test", 1611 "hw_mode": "a", 1612 "channel": "36", 1613 "country_code": country} 1614 hapd = hostapd.add_ap(apdev[0], params) 1615 freq = hapd.get_status_field("freq") 1616 bssid = hapd.own_addr() 1617 dev[0].connect("test", key_mgmt="NONE", scan_freq=freq) 1618 bss = dev[0].get_bss(bssid) 1619 ie = parse_ie(bss['ie']) 1620 if 221 not in ie: 1621 raise Exception("Could not find WMM IE") 1622 wmm = ie[221] 1623 if len(wmm) != 24: 1624 raise Exception("Unexpected WMM IE length") 1625 id, subtype, version, info, reserved = struct.unpack('>LBBBB', wmm[0:8]) 1626 if id != 0x0050f202 or subtype != 1 or version != 1: 1627 raise Exception("Not a WMM IE") 1628 ac = [] 1629 for i in range(4): 1630 ac.append(struct.unpack('<BBH', wmm[8 + i * 4: 12 + i * 4])) 1631 logger.info("WMM AC info: " + str(ac)) 1632 1633 aifsn = (ac[0][0] & 0x0f, ac[1][0] & 0x0f, 1634 ac[2][0] & 0x0f, ac[3][0] & 0x0f) 1635 logger.info("AIFSN: " + str(aifsn)) 1636 if aifsn != (3, 7, 2, 2): 1637 raise Exception("Unexpected AIFSN value: " + str(aifsn)) 1638 1639 ecw_min = (ac[0][1] & 0x0f, ac[1][1] & 0x0f, 1640 ac[2][1] & 0x0f, ac[3][1] & 0x0f) 1641 logger.info("ECW min: " + str(ecw_min)) 1642 if ecw_min != (4, 4, 3, 2): 1643 raise Exception("Unexpected ECW min value: " + str(ecw_min)) 1644 1645 ecw_max = ((ac[0][1] & 0xf0) >> 4, (ac[1][1] & 0xf0) >> 4, 1646 (ac[2][1] & 0xf0) >> 4, (ac[3][1] & 0xf0) >> 4) 1647 logger.info("ECW max: " + str(ecw_max)) 1648 if ecw_max != (10, 10, 4, 3): 1649 raise Exception("Unexpected ECW max value: " + str(ecw_max)) 1650 1651 txop = (ac[0][2], ac[1][2], ac[2][2], ac[3][2]) 1652 logger.info("TXOP: " + str(txop)) 1653 if txop != (0, 0, 94, 47): 1654 raise Exception("Unexpected TXOP value: " + str(txop)) 1655 finally: 1656 dev[0].request("DISCONNECT") 1657 if hapd: 1658 hapd.request("DISABLE") 1659 set_world_reg(apdev[0], None, dev[0]) 1660 dev[0].flush_scan_cache() 1661