1 /* 2 * DFS - Dynamic Frequency Selection 3 * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi> 4 * Copyright (c) 2013-2017, 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 return NULL; 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 hostapd_set_state(iface, HAPD_IFACE_DFS); 708 return 0; 709 } 710 711 iface->freq = channel->freq; 712 iface->conf->channel = channel->chan; 713 iface->conf->secondary_channel = sec; 714 iface->conf->vht_oper_centr_freq_seg0_idx = cf1; 715 iface->conf->vht_oper_centr_freq_seg1_idx = cf2; 716 } 717 } while (res); 718 719 /* Finally start CAC */ 720 hostapd_set_state(iface, HAPD_IFACE_DFS); 721 wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz", iface->freq); 722 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START 723 "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds", 724 iface->freq, 725 iface->conf->channel, iface->conf->secondary_channel, 726 iface->conf->vht_oper_chwidth, 727 iface->conf->vht_oper_centr_freq_seg0_idx, 728 iface->conf->vht_oper_centr_freq_seg1_idx, 729 iface->dfs_cac_ms / 1000); 730 731 res = hostapd_start_dfs_cac(iface, iface->conf->hw_mode, 732 iface->freq, 733 iface->conf->channel, 734 iface->conf->ieee80211n, 735 iface->conf->ieee80211ac, 736 iface->conf->secondary_channel, 737 iface->conf->vht_oper_chwidth, 738 iface->conf->vht_oper_centr_freq_seg0_idx, 739 iface->conf->vht_oper_centr_freq_seg1_idx); 740 741 if (res) { 742 wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res); 743 return -1; 744 } 745 746 return 0; 747 } 748 749 750 static int hostapd_config_dfs_chan_available(struct hostapd_iface *iface) 751 { 752 int n_chans, n_chans1, start_chan_idx, start_chan_idx1; 753 754 /* Get the start (first) channel for current configuration */ 755 start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); 756 if (start_chan_idx < 0) 757 return 0; 758 759 /* Get the number of used channels, depending on width */ 760 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 761 762 /* Check if all channels are DFS available */ 763 return dfs_check_chans_available(iface, start_chan_idx, n_chans); 764 } 765 766 767 int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, 768 int ht_enabled, int chan_offset, int chan_width, 769 int cf1, int cf2) 770 { 771 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED 772 "success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 773 success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 774 775 if (success) { 776 /* Complete iface/ap configuration */ 777 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { 778 /* Complete AP configuration for the first bring up. */ 779 if (iface->state != HAPD_IFACE_ENABLED) 780 hostapd_setup_interface_complete(iface, 0); 781 else 782 iface->cac_started = 0; 783 } else { 784 set_dfs_state(iface, freq, ht_enabled, chan_offset, 785 chan_width, cf1, cf2, 786 HOSTAPD_CHAN_DFS_AVAILABLE); 787 /* 788 * Just mark the channel available when CAC completion 789 * event is received in enabled state. CAC result could 790 * have been propagated from another radio having the 791 * same regulatory configuration. When CAC completion is 792 * received during non-HAPD_IFACE_ENABLED state, make 793 * sure the configured channel is available because this 794 * CAC completion event could have been propagated from 795 * another radio. 796 */ 797 if (iface->state != HAPD_IFACE_ENABLED && 798 hostapd_config_dfs_chan_available(iface)) { 799 hostapd_setup_interface_complete(iface, 0); 800 iface->cac_started = 0; 801 } 802 } 803 } 804 805 return 0; 806 } 807 808 809 int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq, 810 int ht_enabled, int chan_offset, int chan_width, 811 int cf1, int cf2) 812 { 813 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_PRE_CAC_EXPIRED 814 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 815 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 816 817 /* Proceed only if DFS is not offloaded to the driver */ 818 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 819 return 0; 820 821 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 822 cf1, cf2, HOSTAPD_CHAN_DFS_USABLE); 823 824 return 0; 825 } 826 827 828 static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) 829 { 830 struct hostapd_channel_data *channel; 831 int secondary_channel; 832 u8 vht_oper_centr_freq_seg0_idx = 0; 833 u8 vht_oper_centr_freq_seg1_idx = 0; 834 int skip_radar = 0; 835 int err = 1; 836 837 /* Radar detected during active CAC */ 838 iface->cac_started = 0; 839 channel = dfs_get_valid_channel(iface, &secondary_channel, 840 &vht_oper_centr_freq_seg0_idx, 841 &vht_oper_centr_freq_seg1_idx, 842 skip_radar); 843 844 if (!channel) { 845 wpa_printf(MSG_ERROR, "No valid channel available"); 846 return err; 847 } 848 849 wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", 850 channel->chan); 851 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 852 "freq=%d chan=%d sec_chan=%d", channel->freq, 853 channel->chan, secondary_channel); 854 855 iface->freq = channel->freq; 856 iface->conf->channel = channel->chan; 857 iface->conf->secondary_channel = secondary_channel; 858 iface->conf->vht_oper_centr_freq_seg0_idx = 859 vht_oper_centr_freq_seg0_idx; 860 iface->conf->vht_oper_centr_freq_seg1_idx = 861 vht_oper_centr_freq_seg1_idx; 862 err = 0; 863 864 hostapd_setup_interface_complete(iface, err); 865 return err; 866 } 867 868 869 static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) 870 { 871 struct hostapd_channel_data *channel; 872 int secondary_channel; 873 u8 vht_oper_centr_freq_seg0_idx; 874 u8 vht_oper_centr_freq_seg1_idx; 875 int skip_radar = 1; 876 struct csa_settings csa_settings; 877 unsigned int i; 878 int err = 1; 879 880 wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", 881 __func__, iface->cac_started ? "yes" : "no", 882 hostapd_csa_in_progress(iface) ? "yes" : "no"); 883 884 /* Check if CSA in progress */ 885 if (hostapd_csa_in_progress(iface)) 886 return 0; 887 888 /* Check if active CAC */ 889 if (iface->cac_started) 890 return hostapd_dfs_start_channel_switch_cac(iface); 891 892 /* 893 * Allow selection of DFS channel in ETSI to comply with 894 * uniform spreading. 895 */ 896 if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI) 897 skip_radar = 0; 898 899 /* Perform channel switch/CSA */ 900 channel = dfs_get_valid_channel(iface, &secondary_channel, 901 &vht_oper_centr_freq_seg0_idx, 902 &vht_oper_centr_freq_seg1_idx, 903 skip_radar); 904 905 if (!channel) { 906 /* 907 * If there is no channel to switch immediately to, check if 908 * there is another channel where we can switch even if it 909 * requires to perform a CAC first. 910 */ 911 skip_radar = 0; 912 channel = dfs_get_valid_channel(iface, &secondary_channel, 913 &vht_oper_centr_freq_seg0_idx, 914 &vht_oper_centr_freq_seg1_idx, 915 skip_radar); 916 if (!channel) { 917 wpa_printf(MSG_INFO, 918 "%s: no DFS channels left, waiting for NOP to finish", 919 __func__); 920 return err; 921 } 922 923 iface->freq = channel->freq; 924 iface->conf->channel = channel->chan; 925 iface->conf->secondary_channel = secondary_channel; 926 iface->conf->vht_oper_centr_freq_seg0_idx = 927 vht_oper_centr_freq_seg0_idx; 928 iface->conf->vht_oper_centr_freq_seg1_idx = 929 vht_oper_centr_freq_seg1_idx; 930 931 hostapd_disable_iface(iface); 932 hostapd_enable_iface(iface); 933 return 0; 934 } 935 936 wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", 937 channel->chan); 938 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 939 "freq=%d chan=%d sec_chan=%d", channel->freq, 940 channel->chan, secondary_channel); 941 942 /* Setup CSA request */ 943 os_memset(&csa_settings, 0, sizeof(csa_settings)); 944 csa_settings.cs_count = 5; 945 csa_settings.block_tx = 1; 946 err = hostapd_set_freq_params(&csa_settings.freq_params, 947 iface->conf->hw_mode, 948 channel->freq, 949 channel->chan, 950 iface->conf->ieee80211n, 951 iface->conf->ieee80211ac, 952 secondary_channel, 953 iface->conf->vht_oper_chwidth, 954 vht_oper_centr_freq_seg0_idx, 955 vht_oper_centr_freq_seg1_idx, 956 iface->current_mode->vht_capab); 957 958 if (err) { 959 wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); 960 hostapd_disable_iface(iface); 961 return err; 962 } 963 964 for (i = 0; i < iface->num_bss; i++) { 965 err = hostapd_switch_channel(iface->bss[i], &csa_settings); 966 if (err) 967 break; 968 } 969 970 if (err) { 971 wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback", 972 err); 973 iface->freq = channel->freq; 974 iface->conf->channel = channel->chan; 975 iface->conf->secondary_channel = secondary_channel; 976 iface->conf->vht_oper_centr_freq_seg0_idx = 977 vht_oper_centr_freq_seg0_idx; 978 iface->conf->vht_oper_centr_freq_seg1_idx = 979 vht_oper_centr_freq_seg1_idx; 980 981 hostapd_disable_iface(iface); 982 hostapd_enable_iface(iface); 983 return 0; 984 } 985 986 /* Channel configuration will be updated once CSA completes and 987 * ch_switch_notify event is received */ 988 989 wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); 990 return 0; 991 } 992 993 994 int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, 995 int ht_enabled, int chan_offset, int chan_width, 996 int cf1, int cf2) 997 { 998 int res; 999 1000 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED 1001 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 1002 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 1003 1004 /* Proceed only if DFS is not offloaded to the driver */ 1005 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 1006 return 0; 1007 1008 if (!iface->conf->ieee80211h) 1009 return 0; 1010 1011 /* mark radar frequency as invalid */ 1012 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 1013 cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE); 1014 1015 /* Skip if reported radar event not overlapped our channels */ 1016 res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2); 1017 if (!res) 1018 return 0; 1019 1020 /* radar detected while operating, switch the channel. */ 1021 res = hostapd_dfs_start_channel_switch(iface); 1022 1023 return res; 1024 } 1025 1026 1027 int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, 1028 int ht_enabled, int chan_offset, int chan_width, 1029 int cf1, int cf2) 1030 { 1031 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED 1032 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 1033 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 1034 1035 /* Proceed only if DFS is not offloaded to the driver */ 1036 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 1037 return 0; 1038 1039 /* TODO add correct implementation here */ 1040 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 1041 cf1, cf2, HOSTAPD_CHAN_DFS_USABLE); 1042 1043 /* Handle cases where all channels were initially unavailable */ 1044 if (iface->state == HAPD_IFACE_DFS && !iface->cac_started) 1045 hostapd_handle_dfs(iface); 1046 1047 return 0; 1048 } 1049 1050 1051 int hostapd_is_dfs_required(struct hostapd_iface *iface) 1052 { 1053 int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res; 1054 1055 if (!iface->conf->ieee80211h || !iface->current_mode || 1056 iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) 1057 return 0; 1058 1059 /* Get start (first) channel for current configuration */ 1060 start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); 1061 if (start_chan_idx == -1) 1062 return -1; 1063 1064 /* Get number of used channels, depend on width */ 1065 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 1066 1067 /* Check if any of configured channels require DFS */ 1068 res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); 1069 if (res) 1070 return res; 1071 if (start_chan_idx1 >= 0 && n_chans1 > 0) 1072 res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1); 1073 return res; 1074 } 1075 1076 1077 int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, 1078 int ht_enabled, int chan_offset, int chan_width, 1079 int cf1, int cf2) 1080 { 1081 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START 1082 "freq=%d chan=%d chan_offset=%d width=%d seg0=%d " 1083 "seg1=%d cac_time=%ds", 1084 freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60); 1085 iface->cac_started = 1; 1086 return 0; 1087 } 1088 1089 1090 /* 1091 * Main DFS handler for offloaded case. 1092 * 2 - continue channel/AP setup for non-DFS channel 1093 * 1 - continue channel/AP setup for DFS channel 1094 * 0 - channel/AP setup will be continued after CAC 1095 * -1 - hit critical error 1096 */ 1097 int hostapd_handle_dfs_offload(struct hostapd_iface *iface) 1098 { 1099 wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d", 1100 __func__, iface->cac_started); 1101 1102 /* 1103 * If DFS has already been started, then we are being called from a 1104 * callback to continue AP/channel setup. Reset the CAC start flag and 1105 * return. 1106 */ 1107 if (iface->cac_started) { 1108 wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d", 1109 __func__, iface->cac_started); 1110 iface->cac_started = 0; 1111 return 1; 1112 } 1113 1114 if (ieee80211_is_dfs(iface->freq, iface->hw_features, 1115 iface->num_hw_features)) { 1116 wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS", 1117 __func__, iface->freq); 1118 return 0; 1119 } 1120 1121 wpa_printf(MSG_DEBUG, 1122 "%s: freq %d MHz does not require DFS. Continue channel/AP setup", 1123 __func__, iface->freq); 1124 return 2; 1125 } 1126