1 /* 2 * DFS - Dynamic Frequency Selection 3 * Copyright (c) 2002-2013, Jouni Malinen <j (at) 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 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 int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, 751 int ht_enabled, int chan_offset, int chan_width, 752 int cf1, int cf2) 753 { 754 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED 755 "success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 756 success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 757 758 if (success) { 759 /* Complete iface/ap configuration */ 760 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { 761 /* Complete AP configuration for the first bring up. */ 762 if (iface->state != HAPD_IFACE_ENABLED) 763 hostapd_setup_interface_complete(iface, 0); 764 else 765 iface->cac_started = 0; 766 } else { 767 set_dfs_state(iface, freq, ht_enabled, chan_offset, 768 chan_width, cf1, cf2, 769 HOSTAPD_CHAN_DFS_AVAILABLE); 770 iface->cac_started = 0; 771 hostapd_setup_interface_complete(iface, 0); 772 } 773 } 774 775 return 0; 776 } 777 778 779 static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) 780 { 781 struct hostapd_channel_data *channel; 782 int secondary_channel; 783 u8 vht_oper_centr_freq_seg0_idx = 0; 784 u8 vht_oper_centr_freq_seg1_idx = 0; 785 int skip_radar = 0; 786 int err = 1; 787 788 /* Radar detected during active CAC */ 789 iface->cac_started = 0; 790 channel = dfs_get_valid_channel(iface, &secondary_channel, 791 &vht_oper_centr_freq_seg0_idx, 792 &vht_oper_centr_freq_seg1_idx, 793 skip_radar); 794 795 if (!channel) { 796 wpa_printf(MSG_ERROR, "No valid channel available"); 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_dfs_start_channel_switch(struct hostapd_iface *iface) 821 { 822 struct hostapd_channel_data *channel; 823 int secondary_channel; 824 u8 vht_oper_centr_freq_seg0_idx; 825 u8 vht_oper_centr_freq_seg1_idx; 826 int skip_radar = 1; 827 struct csa_settings csa_settings; 828 unsigned int i; 829 int err = 1; 830 831 wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", 832 __func__, iface->cac_started ? "yes" : "no", 833 hostapd_csa_in_progress(iface) ? "yes" : "no"); 834 835 /* Check if CSA in progress */ 836 if (hostapd_csa_in_progress(iface)) 837 return 0; 838 839 /* Check if active CAC */ 840 if (iface->cac_started) 841 return hostapd_dfs_start_channel_switch_cac(iface); 842 843 /* Perform channel switch/CSA */ 844 channel = dfs_get_valid_channel(iface, &secondary_channel, 845 &vht_oper_centr_freq_seg0_idx, 846 &vht_oper_centr_freq_seg1_idx, 847 skip_radar); 848 849 if (!channel) { 850 /* 851 * If there is no channel to switch immediately to, check if 852 * there is another channel where we can switch even if it 853 * requires to perform a CAC first. 854 */ 855 skip_radar = 0; 856 channel = dfs_get_valid_channel(iface, &secondary_channel, 857 &vht_oper_centr_freq_seg0_idx, 858 &vht_oper_centr_freq_seg1_idx, 859 skip_radar); 860 if (!channel) { 861 wpa_printf(MSG_INFO, 862 "%s: no DFS channels left, waiting for NOP to finish", 863 __func__); 864 return err; 865 } 866 867 iface->freq = channel->freq; 868 iface->conf->channel = channel->chan; 869 iface->conf->secondary_channel = secondary_channel; 870 iface->conf->vht_oper_centr_freq_seg0_idx = 871 vht_oper_centr_freq_seg0_idx; 872 iface->conf->vht_oper_centr_freq_seg1_idx = 873 vht_oper_centr_freq_seg1_idx; 874 875 hostapd_disable_iface(iface); 876 hostapd_enable_iface(iface); 877 return 0; 878 } 879 880 wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", 881 channel->chan); 882 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 883 "freq=%d chan=%d sec_chan=%d", channel->freq, 884 channel->chan, secondary_channel); 885 886 /* Setup CSA request */ 887 os_memset(&csa_settings, 0, sizeof(csa_settings)); 888 csa_settings.cs_count = 5; 889 csa_settings.block_tx = 1; 890 err = hostapd_set_freq_params(&csa_settings.freq_params, 891 iface->conf->hw_mode, 892 channel->freq, 893 channel->chan, 894 iface->conf->ieee80211n, 895 iface->conf->ieee80211ac, 896 secondary_channel, 897 iface->conf->vht_oper_chwidth, 898 vht_oper_centr_freq_seg0_idx, 899 vht_oper_centr_freq_seg1_idx, 900 iface->current_mode->vht_capab); 901 902 if (err) { 903 wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); 904 hostapd_disable_iface(iface); 905 return err; 906 } 907 908 for (i = 0; i < iface->num_bss; i++) { 909 err = hostapd_switch_channel(iface->bss[i], &csa_settings); 910 if (err) 911 break; 912 } 913 914 if (err) { 915 wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback", 916 err); 917 iface->freq = channel->freq; 918 iface->conf->channel = channel->chan; 919 iface->conf->secondary_channel = secondary_channel; 920 iface->conf->vht_oper_centr_freq_seg0_idx = 921 vht_oper_centr_freq_seg0_idx; 922 iface->conf->vht_oper_centr_freq_seg1_idx = 923 vht_oper_centr_freq_seg1_idx; 924 925 hostapd_disable_iface(iface); 926 hostapd_enable_iface(iface); 927 return 0; 928 } 929 930 /* Channel configuration will be updated once CSA completes and 931 * ch_switch_notify event is received */ 932 933 wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); 934 return 0; 935 } 936 937 938 int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, 939 int ht_enabled, int chan_offset, int chan_width, 940 int cf1, int cf2) 941 { 942 int res; 943 944 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED 945 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 946 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 947 948 /* Proceed only if DFS is not offloaded to the driver */ 949 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 950 return 0; 951 952 if (!iface->conf->ieee80211h) 953 return 0; 954 955 /* mark radar frequency as invalid */ 956 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 957 cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE); 958 959 /* Skip if reported radar event not overlapped our channels */ 960 res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2); 961 if (!res) 962 return 0; 963 964 /* radar detected while operating, switch the channel. */ 965 res = hostapd_dfs_start_channel_switch(iface); 966 967 return res; 968 } 969 970 971 int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, 972 int ht_enabled, int chan_offset, int chan_width, 973 int cf1, int cf2) 974 { 975 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED 976 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 977 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 978 979 /* Proceed only if DFS is not offloaded to the driver */ 980 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 981 return 0; 982 983 /* TODO add correct implementation here */ 984 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 985 cf1, cf2, HOSTAPD_CHAN_DFS_USABLE); 986 987 /* Handle cases where all channels were initially unavailable */ 988 if (iface->state == HAPD_IFACE_DFS && !iface->cac_started) 989 hostapd_handle_dfs(iface); 990 991 return 0; 992 } 993 994 995 int hostapd_is_dfs_required(struct hostapd_iface *iface) 996 { 997 int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res; 998 999 if (!iface->conf->ieee80211h || !iface->current_mode || 1000 iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) 1001 return 0; 1002 1003 /* Get start (first) channel for current configuration */ 1004 start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); 1005 if (start_chan_idx == -1) 1006 return -1; 1007 1008 /* Get number of used channels, depend on width */ 1009 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 1010 1011 /* Check if any of configured channels require DFS */ 1012 res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); 1013 if (res) 1014 return res; 1015 if (start_chan_idx1 >= 0 && n_chans1 > 0) 1016 res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1); 1017 return res; 1018 } 1019 1020 1021 int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, 1022 int ht_enabled, int chan_offset, int chan_width, 1023 int cf1, int cf2) 1024 { 1025 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START 1026 "freq=%d chan=%d chan_offset=%d width=%d seg0=%d " 1027 "seg1=%d cac_time=%ds", 1028 freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 60); 1029 iface->cac_started = 1; 1030 return 0; 1031 } 1032 1033 1034 /* 1035 * Main DFS handler for offloaded case. 1036 * 2 - continue channel/AP setup for non-DFS channel 1037 * 1 - continue channel/AP setup for DFS channel 1038 * 0 - channel/AP setup will be continued after CAC 1039 * -1 - hit critical error 1040 */ 1041 int hostapd_handle_dfs_offload(struct hostapd_iface *iface) 1042 { 1043 wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d", 1044 __func__, iface->cac_started); 1045 1046 /* 1047 * If DFS has already been started, then we are being called from a 1048 * callback to continue AP/channel setup. Reset the CAC start flag and 1049 * return. 1050 */ 1051 if (iface->cac_started) { 1052 wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d", 1053 __func__, iface->cac_started); 1054 iface->cac_started = 0; 1055 return 1; 1056 } 1057 1058 if (ieee80211_is_dfs(iface->freq)) { 1059 wpa_printf(MSG_DEBUG, "%s: freq %d MHz requires DFS", 1060 __func__, iface->freq); 1061 return 0; 1062 } 1063 1064 wpa_printf(MSG_DEBUG, 1065 "%s: freq %d MHz does not require DFS. Continue channel/AP setup", 1066 __func__, iface->freq); 1067 return 2; 1068 } 1069