1 /* 2 * DFS - Dynamic Frequency Selection 3 * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 4 * Copyright (c) 2013-2015, Qualcomm Atheros, Inc. 5 * 6 * This software may be distributed under the terms of the BSD license. 7 * See README for more details. 8 */ 9 10 #include "utils/includes.h" 11 12 #include "utils/common.h" 13 #include "common/ieee802_11_defs.h" 14 #include "common/hw_features_common.h" 15 #include "common/wpa_ctrl.h" 16 #include "hostapd.h" 17 #include "ap_drv_ops.h" 18 #include "drivers/driver.h" 19 #include "dfs.h" 20 21 22 static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) 23 { 24 int n_chans = 1; 25 26 *seg1 = 0; 27 28 if (iface->conf->ieee80211n && iface->conf->secondary_channel) 29 n_chans = 2; 30 31 if (iface->conf->ieee80211ac) { 32 switch (iface->conf->vht_oper_chwidth) { 33 case VHT_CHANWIDTH_USE_HT: 34 break; 35 case VHT_CHANWIDTH_80MHZ: 36 n_chans = 4; 37 break; 38 case VHT_CHANWIDTH_160MHZ: 39 n_chans = 8; 40 break; 41 case VHT_CHANWIDTH_80P80MHZ: 42 n_chans = 4; 43 *seg1 = 4; 44 break; 45 default: 46 break; 47 } 48 } 49 50 return n_chans; 51 } 52 53 54 static int dfs_channel_available(struct hostapd_channel_data *chan, 55 int skip_radar) 56 { 57 /* 58 * When radar detection happens, CSA is performed. However, there's no 59 * time for CAC, so radar channels must be skipped when finding a new 60 * channel for CSA, unless they are available for immediate use. 61 */ 62 if (skip_radar && (chan->flag & HOSTAPD_CHAN_RADAR) && 63 ((chan->flag & HOSTAPD_CHAN_DFS_MASK) != 64 HOSTAPD_CHAN_DFS_AVAILABLE)) 65 return 0; 66 67 if (chan->flag & HOSTAPD_CHAN_DISABLED) 68 return 0; 69 if ((chan->flag & HOSTAPD_CHAN_RADAR) && 70 ((chan->flag & HOSTAPD_CHAN_DFS_MASK) == 71 HOSTAPD_CHAN_DFS_UNAVAILABLE)) 72 return 0; 73 return 1; 74 } 75 76 77 static int dfs_is_chan_allowed(struct hostapd_channel_data *chan, int n_chans) 78 { 79 /* 80 * The tables contain first valid channel number based on channel width. 81 * We will also choose this first channel as the control one. 82 */ 83 int allowed_40[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 84 184, 192 }; 85 /* 86 * VHT80, valid channels based on center frequency: 87 * 42, 58, 106, 122, 138, 155 88 */ 89 int allowed_80[] = { 36, 52, 100, 116, 132, 149 }; 90 /* 91 * VHT160 valid channels based on center frequency: 92 * 50, 114 93 */ 94 int allowed_160[] = { 36, 100 }; 95 int *allowed = allowed_40; 96 unsigned int i, allowed_no = 0; 97 98 switch (n_chans) { 99 case 2: 100 allowed = allowed_40; 101 allowed_no = ARRAY_SIZE(allowed_40); 102 break; 103 case 4: 104 allowed = allowed_80; 105 allowed_no = ARRAY_SIZE(allowed_80); 106 break; 107 case 8: 108 allowed = allowed_160; 109 allowed_no = ARRAY_SIZE(allowed_160); 110 break; 111 default: 112 wpa_printf(MSG_DEBUG, "Unknown width for %d channels", n_chans); 113 break; 114 } 115 116 for (i = 0; i < allowed_no; i++) { 117 if (chan->chan == allowed[i]) 118 return 1; 119 } 120 121 return 0; 122 } 123 124 125 static struct hostapd_channel_data * 126 dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx) 127 { 128 int i; 129 130 for (i = first_chan_idx; i < mode->num_channels; i++) { 131 if (mode->channels[i].freq == freq) 132 return &mode->channels[i]; 133 } 134 135 return NULL; 136 } 137 138 139 static int dfs_chan_range_available(struct hostapd_hw_modes *mode, 140 int first_chan_idx, int num_chans, 141 int skip_radar) 142 { 143 struct hostapd_channel_data *first_chan, *chan; 144 int i; 145 146 if (first_chan_idx + num_chans > mode->num_channels) 147 return 0; 148 149 first_chan = &mode->channels[first_chan_idx]; 150 151 for (i = 0; i < num_chans; i++) { 152 chan = dfs_get_chan_data(mode, first_chan->freq + i * 20, 153 first_chan_idx); 154 if (!chan) 155 return 0; 156 157 if (!dfs_channel_available(chan, skip_radar)) 158 return 0; 159 } 160 161 return 1; 162 } 163 164 165 static int is_in_chanlist(struct hostapd_iface *iface, 166 struct hostapd_channel_data *chan) 167 { 168 if (!iface->conf->acs_ch_list.num) 169 return 1; 170 171 return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan); 172 } 173 174 175 /* 176 * The function assumes HT40+ operation. 177 * Make sure to adjust the following variables after calling this: 178 * - hapd->secondary_channel 179 * - hapd->vht_oper_centr_freq_seg0_idx 180 * - hapd->vht_oper_centr_freq_seg1_idx 181 */ 182 static int dfs_find_channel(struct hostapd_iface *iface, 183 struct hostapd_channel_data **ret_chan, 184 int idx, int skip_radar) 185 { 186 struct hostapd_hw_modes *mode; 187 struct hostapd_channel_data *chan; 188 int i, channel_idx = 0, n_chans, n_chans1; 189 190 mode = iface->current_mode; 191 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 192 193 wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans); 194 for (i = 0; i < mode->num_channels; i++) { 195 chan = &mode->channels[i]; 196 197 /* Skip HT40/VHT incompatible channels */ 198 if (iface->conf->ieee80211n && 199 iface->conf->secondary_channel && 200 !dfs_is_chan_allowed(chan, n_chans)) 201 continue; 202 203 /* Skip incompatible chandefs */ 204 if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) 205 continue; 206 207 if (!is_in_chanlist(iface, chan)) 208 continue; 209 210 if (ret_chan && idx == channel_idx) { 211 wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan); 212 *ret_chan = chan; 213 return idx; 214 } 215 wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan); 216 channel_idx++; 217 } 218 return channel_idx; 219 } 220 221 222 static void dfs_adjust_vht_center_freq(struct hostapd_iface *iface, 223 struct hostapd_channel_data *chan, 224 int secondary_channel, 225 u8 *vht_oper_centr_freq_seg0_idx, 226 u8 *vht_oper_centr_freq_seg1_idx) 227 { 228 if (!iface->conf->ieee80211ac) 229 return; 230 231 if (!chan) 232 return; 233 234 *vht_oper_centr_freq_seg1_idx = 0; 235 236 switch (iface->conf->vht_oper_chwidth) { 237 case VHT_CHANWIDTH_USE_HT: 238 if (secondary_channel == 1) 239 *vht_oper_centr_freq_seg0_idx = chan->chan + 2; 240 else if (secondary_channel == -1) 241 *vht_oper_centr_freq_seg0_idx = chan->chan - 2; 242 else 243 *vht_oper_centr_freq_seg0_idx = chan->chan; 244 break; 245 case VHT_CHANWIDTH_80MHZ: 246 *vht_oper_centr_freq_seg0_idx = chan->chan + 6; 247 break; 248 case VHT_CHANWIDTH_160MHZ: 249 *vht_oper_centr_freq_seg0_idx = chan->chan + 14; 250 break; 251 default: 252 wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now"); 253 *vht_oper_centr_freq_seg0_idx = 0; 254 break; 255 } 256 257 wpa_printf(MSG_DEBUG, "DFS adjusting VHT center frequency: %d, %d", 258 *vht_oper_centr_freq_seg0_idx, 259 *vht_oper_centr_freq_seg1_idx); 260 } 261 262 263 /* Return start channel idx we will use for mode->channels[idx] */ 264 static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start) 265 { 266 struct hostapd_hw_modes *mode; 267 struct hostapd_channel_data *chan; 268 int channel_no = iface->conf->channel; 269 int res = -1, i; 270 int chan_seg1 = -1; 271 272 *seg1_start = -1; 273 274 /* HT40- */ 275 if (iface->conf->ieee80211n && iface->conf->secondary_channel == -1) 276 channel_no -= 4; 277 278 /* VHT */ 279 if (iface->conf->ieee80211ac) { 280 switch (iface->conf->vht_oper_chwidth) { 281 case VHT_CHANWIDTH_USE_HT: 282 break; 283 case VHT_CHANWIDTH_80MHZ: 284 channel_no = 285 iface->conf->vht_oper_centr_freq_seg0_idx - 6; 286 break; 287 case VHT_CHANWIDTH_160MHZ: 288 channel_no = 289 iface->conf->vht_oper_centr_freq_seg0_idx - 14; 290 break; 291 case VHT_CHANWIDTH_80P80MHZ: 292 channel_no = 293 iface->conf->vht_oper_centr_freq_seg0_idx - 6; 294 chan_seg1 = 295 iface->conf->vht_oper_centr_freq_seg1_idx - 6; 296 break; 297 default: 298 wpa_printf(MSG_INFO, 299 "DFS only VHT20/40/80/160/80+80 is supported now"); 300 channel_no = -1; 301 break; 302 } 303 } 304 305 /* Get idx */ 306 mode = iface->current_mode; 307 for (i = 0; i < mode->num_channels; i++) { 308 chan = &mode->channels[i]; 309 if (chan->chan == channel_no) { 310 res = i; 311 break; 312 } 313 } 314 315 if (res != -1 && chan_seg1 > -1) { 316 int found = 0; 317 318 /* Get idx for seg1 */ 319 mode = iface->current_mode; 320 for (i = 0; i < mode->num_channels; i++) { 321 chan = &mode->channels[i]; 322 if (chan->chan == chan_seg1) { 323 *seg1_start = i; 324 found = 1; 325 break; 326 } 327 } 328 if (!found) 329 res = -1; 330 } 331 332 if (res == -1) { 333 wpa_printf(MSG_DEBUG, 334 "DFS chan_idx seems wrong; num-ch: %d ch-no: %d conf-ch-no: %d 11n: %d sec-ch: %d vht-oper-width: %d", 335 mode->num_channels, channel_no, iface->conf->channel, 336 iface->conf->ieee80211n, 337 iface->conf->secondary_channel, 338 iface->conf->vht_oper_chwidth); 339 340 for (i = 0; i < mode->num_channels; i++) { 341 wpa_printf(MSG_DEBUG, "Available channel: %d", 342 mode->channels[i].chan); 343 } 344 } 345 346 return res; 347 } 348 349 350 /* At least one channel have radar flag */ 351 static int dfs_check_chans_radar(struct hostapd_iface *iface, 352 int start_chan_idx, int n_chans) 353 { 354 struct hostapd_channel_data *channel; 355 struct hostapd_hw_modes *mode; 356 int i, res = 0; 357 358 mode = iface->current_mode; 359 360 for (i = 0; i < n_chans; i++) { 361 channel = &mode->channels[start_chan_idx + i]; 362 if (channel->flag & HOSTAPD_CHAN_RADAR) 363 res++; 364 } 365 366 return res; 367 } 368 369 370 /* All channels available */ 371 static int dfs_check_chans_available(struct hostapd_iface *iface, 372 int start_chan_idx, int n_chans) 373 { 374 struct hostapd_channel_data *channel; 375 struct hostapd_hw_modes *mode; 376 int i; 377 378 mode = iface->current_mode; 379 380 for (i = 0; i < n_chans; i++) { 381 channel = &mode->channels[start_chan_idx + i]; 382 383 if (channel->flag & HOSTAPD_CHAN_DISABLED) 384 break; 385 386 if (!(channel->flag & HOSTAPD_CHAN_RADAR)) 387 continue; 388 389 if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) != 390 HOSTAPD_CHAN_DFS_AVAILABLE) 391 break; 392 } 393 394 return i == n_chans; 395 } 396 397 398 /* At least one channel unavailable */ 399 static int dfs_check_chans_unavailable(struct hostapd_iface *iface, 400 int start_chan_idx, 401 int n_chans) 402 { 403 struct hostapd_channel_data *channel; 404 struct hostapd_hw_modes *mode; 405 int i, res = 0; 406 407 mode = iface->current_mode; 408 409 for (i = 0; i < n_chans; i++) { 410 channel = &mode->channels[start_chan_idx + i]; 411 if (channel->flag & HOSTAPD_CHAN_DISABLED) 412 res++; 413 if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) == 414 HOSTAPD_CHAN_DFS_UNAVAILABLE) 415 res++; 416 } 417 418 return res; 419 } 420 421 422 static struct hostapd_channel_data * 423 dfs_get_valid_channel(struct hostapd_iface *iface, 424 int *secondary_channel, 425 u8 *vht_oper_centr_freq_seg0_idx, 426 u8 *vht_oper_centr_freq_seg1_idx, 427 int skip_radar) 428 { 429 struct hostapd_hw_modes *mode; 430 struct hostapd_channel_data *chan = NULL; 431 int num_available_chandefs; 432 int chan_idx; 433 u32 _rand; 434 435 wpa_printf(MSG_DEBUG, "DFS: Selecting random channel"); 436 *secondary_channel = 0; 437 *vht_oper_centr_freq_seg0_idx = 0; 438 *vht_oper_centr_freq_seg1_idx = 0; 439 440 if (iface->current_mode == NULL) 441 return NULL; 442 443 mode = iface->current_mode; 444 if (mode->mode != HOSTAPD_MODE_IEEE80211A) 445 return NULL; 446 447 /* Get the count first */ 448 num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar); 449 if (num_available_chandefs == 0) 450 return NULL; 451 452 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) 453 _rand = os_random(); 454 chan_idx = _rand % num_available_chandefs; 455 dfs_find_channel(iface, &chan, chan_idx, skip_radar); 456 457 /* dfs_find_channel() calculations assume HT40+ */ 458 if (iface->conf->secondary_channel) 459 *secondary_channel = 1; 460 else 461 *secondary_channel = 0; 462 463 dfs_adjust_vht_center_freq(iface, chan, 464 *secondary_channel, 465 vht_oper_centr_freq_seg0_idx, 466 vht_oper_centr_freq_seg1_idx); 467 468 return chan; 469 } 470 471 472 static int set_dfs_state_freq(struct hostapd_iface *iface, int freq, u32 state) 473 { 474 struct hostapd_hw_modes *mode; 475 struct hostapd_channel_data *chan = NULL; 476 int i; 477 478 mode = iface->current_mode; 479 if (mode == NULL) 480 return 0; 481 482 wpa_printf(MSG_DEBUG, "set_dfs_state 0x%X for %d MHz", state, freq); 483 for (i = 0; i < iface->current_mode->num_channels; i++) { 484 chan = &iface->current_mode->channels[i]; 485 if (chan->freq == freq) { 486 if (chan->flag & HOSTAPD_CHAN_RADAR) { 487 chan->flag &= ~HOSTAPD_CHAN_DFS_MASK; 488 chan->flag |= state; 489 return 1; /* Channel found */ 490 } 491 } 492 } 493 wpa_printf(MSG_WARNING, "Can't set DFS state for freq %d MHz", freq); 494 return 0; 495 } 496 497 498 static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled, 499 int chan_offset, int chan_width, int cf1, 500 int cf2, u32 state) 501 { 502 int n_chans = 1, i; 503 struct hostapd_hw_modes *mode; 504 int frequency = freq; 505 int ret = 0; 506 507 mode = iface->current_mode; 508 if (mode == NULL) 509 return 0; 510 511 if (mode->mode != HOSTAPD_MODE_IEEE80211A) { 512 wpa_printf(MSG_WARNING, "current_mode != IEEE80211A"); 513 return 0; 514 } 515 516 /* Seems cf1 and chan_width is enough here */ 517 switch (chan_width) { 518 case CHAN_WIDTH_20_NOHT: 519 case CHAN_WIDTH_20: 520 n_chans = 1; 521 if (frequency == 0) 522 frequency = cf1; 523 break; 524 case CHAN_WIDTH_40: 525 n_chans = 2; 526 frequency = cf1 - 10; 527 break; 528 case CHAN_WIDTH_80: 529 n_chans = 4; 530 frequency = cf1 - 30; 531 break; 532 case CHAN_WIDTH_160: 533 n_chans = 8; 534 frequency = cf1 - 70; 535 break; 536 default: 537 wpa_printf(MSG_INFO, "DFS chan_width %d not supported", 538 chan_width); 539 break; 540 } 541 542 wpa_printf(MSG_DEBUG, "DFS freq: %dMHz, n_chans: %d", frequency, 543 n_chans); 544 for (i = 0; i < n_chans; i++) { 545 ret += set_dfs_state_freq(iface, frequency, state); 546 frequency = frequency + 20; 547 } 548 549 return ret; 550 } 551 552 553 static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq, 554 int chan_width, int cf1, int cf2) 555 { 556 int start_chan_idx, start_chan_idx1; 557 struct hostapd_hw_modes *mode; 558 struct hostapd_channel_data *chan; 559 int n_chans, n_chans1, i, j, frequency = freq, radar_n_chans = 1; 560 u8 radar_chan; 561 int res = 0; 562 563 /* Our configuration */ 564 mode = iface->current_mode; 565 start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); 566 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 567 568 /* Check we are on DFS channel(s) */ 569 if (!dfs_check_chans_radar(iface, start_chan_idx, n_chans)) 570 return 0; 571 572 /* Reported via radar event */ 573 switch (chan_width) { 574 case CHAN_WIDTH_20_NOHT: 575 case CHAN_WIDTH_20: 576 radar_n_chans = 1; 577 if (frequency == 0) 578 frequency = cf1; 579 break; 580 case CHAN_WIDTH_40: 581 radar_n_chans = 2; 582 frequency = cf1 - 10; 583 break; 584 case CHAN_WIDTH_80: 585 radar_n_chans = 4; 586 frequency = cf1 - 30; 587 break; 588 case CHAN_WIDTH_160: 589 radar_n_chans = 8; 590 frequency = cf1 - 70; 591 break; 592 default: 593 wpa_printf(MSG_INFO, "DFS chan_width %d not supported", 594 chan_width); 595 break; 596 } 597 598 ieee80211_freq_to_chan(frequency, &radar_chan); 599 600 for (i = 0; i < n_chans; i++) { 601 chan = &mode->channels[start_chan_idx + i]; 602 if (!(chan->flag & HOSTAPD_CHAN_RADAR)) 603 continue; 604 for (j = 0; j < radar_n_chans; j++) { 605 wpa_printf(MSG_DEBUG, "checking our: %d, radar: %d", 606 chan->chan, radar_chan + j * 4); 607 if (chan->chan == radar_chan + j * 4) 608 res++; 609 } 610 } 611 612 wpa_printf(MSG_DEBUG, "overlapped: %d", res); 613 614 return res; 615 } 616 617 618 static unsigned int dfs_get_cac_time(struct hostapd_iface *iface, 619 int start_chan_idx, int n_chans) 620 { 621 struct hostapd_channel_data *channel; 622 struct hostapd_hw_modes *mode; 623 int i; 624 unsigned int cac_time_ms = 0; 625 626 mode = iface->current_mode; 627 628 for (i = 0; i < n_chans; i++) { 629 channel = &mode->channels[start_chan_idx + i]; 630 if (!(channel->flag & HOSTAPD_CHAN_RADAR)) 631 continue; 632 if (channel->dfs_cac_ms > cac_time_ms) 633 cac_time_ms = channel->dfs_cac_ms; 634 } 635 636 return cac_time_ms; 637 } 638 639 640 /* 641 * Main DFS handler 642 * 1 - continue channel/ap setup 643 * 0 - channel/ap setup will be continued after CAC 644 * -1 - hit critical error 645 */ 646 int hostapd_handle_dfs(struct hostapd_iface *iface) 647 { 648 struct hostapd_channel_data *channel; 649 int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1; 650 int skip_radar = 0; 651 652 if (!iface->current_mode) { 653 /* 654 * This can happen with drivers that do not provide mode 655 * information and as such, cannot really use hostapd for DFS. 656 */ 657 wpa_printf(MSG_DEBUG, 658 "DFS: No current_mode information - assume no need to perform DFS operations by hostapd"); 659 return 1; 660 } 661 662 iface->cac_started = 0; 663 664 do { 665 /* Get start (first) channel for current configuration */ 666 start_chan_idx = dfs_get_start_chan_idx(iface, 667 &start_chan_idx1); 668 if (start_chan_idx == -1) 669 return -1; 670 671 /* Get number of used channels, depend on width */ 672 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 673 674 /* Setup CAC time */ 675 iface->dfs_cac_ms = dfs_get_cac_time(iface, start_chan_idx, 676 n_chans); 677 678 /* Check if any of configured channels require DFS */ 679 res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); 680 wpa_printf(MSG_DEBUG, 681 "DFS %d channels required radar detection", 682 res); 683 if (!res) 684 return 1; 685 686 /* Check if all channels are DFS available */ 687 res = dfs_check_chans_available(iface, start_chan_idx, n_chans); 688 wpa_printf(MSG_DEBUG, 689 "DFS all channels available, (SKIP CAC): %s", 690 res ? "yes" : "no"); 691 if (res) 692 return 1; 693 694 /* Check if any of configured channels is unavailable */ 695 res = dfs_check_chans_unavailable(iface, start_chan_idx, 696 n_chans); 697 wpa_printf(MSG_DEBUG, "DFS %d chans unavailable - choose other channel: %s", 698 res, res ? "yes": "no"); 699 if (res) { 700 int sec = 0; 701 u8 cf1 = 0, cf2 = 0; 702 703 channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, 704 skip_radar); 705 if (!channel) { 706 wpa_printf(MSG_ERROR, "could not get valid channel"); 707 return -1; 708 } 709 710 iface->freq = channel->freq; 711 iface->conf->channel = channel->chan; 712 iface->conf->secondary_channel = sec; 713 iface->conf->vht_oper_centr_freq_seg0_idx = cf1; 714 iface->conf->vht_oper_centr_freq_seg1_idx = cf2; 715 } 716 } while (res); 717 718 /* Finally start CAC */ 719 hostapd_set_state(iface, HAPD_IFACE_DFS); 720 wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq); 721 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START 722 "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds", 723 iface->freq, 724 iface->conf->channel, iface->conf->secondary_channel, 725 iface->conf->vht_oper_chwidth, 726 iface->conf->vht_oper_centr_freq_seg0_idx, 727 iface->conf->vht_oper_centr_freq_seg1_idx, 728 iface->dfs_cac_ms / 1000); 729 730 res = hostapd_start_dfs_cac(iface, iface->conf->hw_mode, 731 iface->freq, 732 iface->conf->channel, 733 iface->conf->ieee80211n, 734 iface->conf->ieee80211ac, 735 iface->conf->secondary_channel, 736 iface->conf->vht_oper_chwidth, 737 iface->conf->vht_oper_centr_freq_seg0_idx, 738 iface->conf->vht_oper_centr_freq_seg1_idx); 739 740 if (res) { 741 wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res); 742 return -1; 743 } 744 745 return 0; 746 } 747 748 749 int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, 750 int ht_enabled, int chan_offset, int chan_width, 751 int cf1, int cf2) 752 { 753 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED 754 "success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 755 success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 756 757 if (success) { 758 /* Complete iface/ap configuration */ 759 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { 760 /* Complete AP configuration for the first bring up. */ 761 if (iface->state != HAPD_IFACE_ENABLED) 762 hostapd_setup_interface_complete(iface, 0); 763 else 764 iface->cac_started = 0; 765 } else { 766 set_dfs_state(iface, freq, ht_enabled, chan_offset, 767 chan_width, cf1, cf2, 768 HOSTAPD_CHAN_DFS_AVAILABLE); 769 iface->cac_started = 0; 770 hostapd_setup_interface_complete(iface, 0); 771 } 772 } 773 774 return 0; 775 } 776 777 778 static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) 779 { 780 struct hostapd_channel_data *channel; 781 int secondary_channel; 782 u8 vht_oper_centr_freq_seg0_idx = 0; 783 u8 vht_oper_centr_freq_seg1_idx = 0; 784 int skip_radar = 0; 785 int err = 1; 786 787 /* Radar detected during active CAC */ 788 iface->cac_started = 0; 789 channel = dfs_get_valid_channel(iface, &secondary_channel, 790 &vht_oper_centr_freq_seg0_idx, 791 &vht_oper_centr_freq_seg1_idx, 792 skip_radar); 793 794 if (!channel) { 795 wpa_printf(MSG_ERROR, "No valid channel available"); 796 hostapd_setup_interface_complete(iface, err); 797 return err; 798 } 799 800 wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", 801 channel->chan); 802 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 803 "freq=%d chan=%d sec_chan=%d", channel->freq, 804 channel->chan, secondary_channel); 805 806 iface->freq = channel->freq; 807 iface->conf->channel = channel->chan; 808 iface->conf->secondary_channel = secondary_channel; 809 iface->conf->vht_oper_centr_freq_seg0_idx = 810 vht_oper_centr_freq_seg0_idx; 811 iface->conf->vht_oper_centr_freq_seg1_idx = 812 vht_oper_centr_freq_seg1_idx; 813 err = 0; 814 815 hostapd_setup_interface_complete(iface, err); 816 return err; 817 } 818 819 820 static int hostapd_csa_in_progress(struct hostapd_iface *iface) 821 { 822 unsigned int i; 823 for (i = 0; i < iface->num_bss; i++) 824 if (iface->bss[i]->csa_in_progress) 825 return 1; 826 return 0; 827 } 828 829 830 static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) 831 { 832 struct hostapd_channel_data *channel; 833 int secondary_channel; 834 u8 vht_oper_centr_freq_seg0_idx; 835 u8 vht_oper_centr_freq_seg1_idx; 836 int skip_radar = 1; 837 struct csa_settings csa_settings; 838 unsigned int i; 839 int err = 1; 840 841 wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", 842 __func__, iface->cac_started ? "yes" : "no", 843 hostapd_csa_in_progress(iface) ? "yes" : "no"); 844 845 /* Check if CSA in progress */ 846 if (hostapd_csa_in_progress(iface)) 847 return 0; 848 849 /* Check if active CAC */ 850 if (iface->cac_started) 851 return hostapd_dfs_start_channel_switch_cac(iface); 852 853 /* Perform channel switch/CSA */ 854 channel = dfs_get_valid_channel(iface, &secondary_channel, 855 &vht_oper_centr_freq_seg0_idx, 856 &vht_oper_centr_freq_seg1_idx, 857 skip_radar); 858 859 if (!channel) { 860 /* 861 * If there is no channel to switch immediately to, check if 862 * there is another channel where we can switch even if it 863 * requires to perform a CAC first. 864 */ 865 skip_radar = 0; 866 channel = dfs_get_valid_channel(iface, &secondary_channel, 867 &vht_oper_centr_freq_seg0_idx, 868 &vht_oper_centr_freq_seg1_idx, 869 skip_radar); 870 if (!channel) { 871 /* FIXME: Wait for channel(s) to become available */ 872 hostapd_disable_iface(iface); 873 return err; 874 } 875 876 iface->freq = channel->freq; 877 iface->conf->channel = channel->chan; 878 iface->conf->secondary_channel = secondary_channel; 879 iface->conf->vht_oper_centr_freq_seg0_idx = 880 vht_oper_centr_freq_seg0_idx; 881 iface->conf->vht_oper_centr_freq_seg1_idx = 882 vht_oper_centr_freq_seg1_idx; 883 884 hostapd_disable_iface(iface); 885 hostapd_enable_iface(iface); 886 return 0; 887 } 888 889 wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", 890 channel->chan); 891 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 892 "freq=%d chan=%d sec_chan=%d", channel->freq, 893 channel->chan, secondary_channel); 894 895 /* Setup CSA request */ 896 os_memset(&csa_settings, 0, sizeof(csa_settings)); 897 csa_settings.cs_count = 5; 898 csa_settings.block_tx = 1; 899 err = hostapd_set_freq_params(&csa_settings.freq_params, 900 iface->conf->hw_mode, 901 channel->freq, 902 channel->chan, 903 iface->conf->ieee80211n, 904 iface->conf->ieee80211ac, 905 secondary_channel, 906 iface->conf->vht_oper_chwidth, 907 vht_oper_centr_freq_seg0_idx, 908 vht_oper_centr_freq_seg1_idx, 909 iface->current_mode->vht_capab); 910 911 if (err) { 912 wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); 913 hostapd_disable_iface(iface); 914 return err; 915 } 916 917 for (i = 0; i < iface->num_bss; i++) { 918 err = hostapd_switch_channel(iface->bss[i], &csa_settings); 919 if (err) 920 break; 921 } 922 923 if (err) { 924 wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback", 925 err); 926 iface->freq = channel->freq; 927 iface->conf->channel = channel->chan; 928 iface->conf->secondary_channel = secondary_channel; 929 iface->conf->vht_oper_centr_freq_seg0_idx = 930 vht_oper_centr_freq_seg0_idx; 931 iface->conf->vht_oper_centr_freq_seg1_idx = 932 vht_oper_centr_freq_seg1_idx; 933 934 hostapd_disable_iface(iface); 935 hostapd_enable_iface(iface); 936 return 0; 937 } 938 939 /* Channel configuration will be updated once CSA completes and 940 * ch_switch_notify event is received */ 941 942 wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); 943 return 0; 944 } 945 946 947 int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, 948 int ht_enabled, int chan_offset, int chan_width, 949 int cf1, int cf2) 950 { 951 int res; 952 953 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED 954 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 955 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 956 957 /* Proceed only if DFS is not offloaded to the driver */ 958 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 959 return 0; 960 961 if (!iface->conf->ieee80211h) 962 return 0; 963 964 /* mark radar frequency as invalid */ 965 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 966 cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE); 967 968 /* Skip if reported radar event not overlapped our channels */ 969 res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2); 970 if (!res) 971 return 0; 972 973 /* radar detected while operating, switch the channel. */ 974 res = hostapd_dfs_start_channel_switch(iface); 975 976 return res; 977 } 978 979 980 int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, 981 int ht_enabled, int chan_offset, int chan_width, 982 int cf1, int cf2) 983 { 984 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED 985 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 986 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 987 988 /* Proceed only if DFS is not offloaded to the driver */ 989 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 990 return 0; 991 992 /* TODO add correct implementation here */ 993 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 994 cf1, cf2, HOSTAPD_CHAN_DFS_USABLE); 995 return 0; 996 } 997 998 999 int hostapd_is_dfs_required(struct hostapd_iface *iface) 1000 { 1001 int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res; 1002 1003 if (!iface->conf->ieee80211h || !iface->current_mode || 1004 iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) 1005 return 0; 1006 1007 /* Get start (first) channel for current configuration */ 1008 start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); 1009 if (start_chan_idx == -1) 1010 return -1; 1011 1012 /* Get number of used channels, depend on width */ 1013 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 1014 1015 /* Check if any of configured channels require DFS */ 1016 res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); 1017 if (res) 1018 return res; 1019 if (start_chan_idx1 >= 0 && n_chans1 > 0) 1020 res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1); 1021 return res; 1022 } 1023 1024 1025 int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, 1026 int ht_enabled, int chan_offset, int chan_width, 1027 int cf1, int cf2) 1028 { 1029 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START 1030 "freq=%d chan=%d chan_offset=%d width=%d seg0=%d " 1031 "seg1=%d cac_time=%ds", 1032 freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60); 1033 iface->cac_started = 1; 1034 return 0; 1035 } 1036 1037 1038 /* 1039 * Main DFS handler for offloaded case. 1040 * 2 - continue channel/AP setup for non-DFS channel 1041 * 1 - continue channel/AP setup for DFS channel 1042 * 0 - channel/AP setup will be continued after CAC 1043 * -1 - hit critical error 1044 */ 1045 int hostapd_handle_dfs_offload(struct hostapd_iface *iface) 1046 { 1047 wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d", 1048 __func__, iface->cac_started); 1049 1050 /* 1051 * If DFS has already been started, then we are being called from a 1052 * callback to continue AP/channel setup. Reset the CAC start flag and 1053 * return. 1054 */ 1055 if (iface->cac_started) { 1056 wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d", 1057 __func__, iface->cac_started); 1058 iface->cac_started = 0; 1059 return 1; 1060 } 1061 1062 if (ieee80211_is_dfs(iface->freq)) { 1063 wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS", 1064 __func__, iface->freq); 1065 return 0; 1066 } 1067 1068 wpa_printf(MSG_DEBUG, 1069 "%s: freq %d MHz does not require DFS. Continue channel/AP setup", 1070 __func__, iface->freq); 1071 return 2; 1072 } 1073