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 "beacon.h" 18 #include "ap_drv_ops.h" 19 #include "drivers/driver.h" 20 #include "dfs.h" 21 22 23 enum dfs_channel_type { 24 DFS_ANY_CHANNEL, 25 DFS_AVAILABLE, /* non-radar or radar-available */ 26 DFS_NO_CAC_YET, /* radar-not-yet-available */ 27 }; 28 29 static struct hostapd_channel_data * 30 dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel, 31 u8 *oper_centr_freq_seg0_idx, 32 u8 *oper_centr_freq_seg1_idx, 33 enum dfs_channel_type *channel_type); 34 35 36 static bool dfs_use_radar_background(struct hostapd_iface *iface) 37 { 38 return (iface->drv_flags2 & WPA_DRIVER_FLAGS2_RADAR_BACKGROUND) && 39 iface->conf->enable_background_radar; 40 } 41 42 43 static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1) 44 { 45 int n_chans = 1; 46 47 *seg1 = 0; 48 49 if (iface->conf->ieee80211n && iface->conf->secondary_channel) 50 n_chans = 2; 51 52 if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { 53 switch (hostapd_get_oper_chwidth(iface->conf)) { 54 case CONF_OPER_CHWIDTH_USE_HT: 55 break; 56 case CONF_OPER_CHWIDTH_80MHZ: 57 n_chans = 4; 58 break; 59 case CONF_OPER_CHWIDTH_160MHZ: 60 n_chans = 8; 61 break; 62 case CONF_OPER_CHWIDTH_80P80MHZ: 63 n_chans = 4; 64 *seg1 = 4; 65 break; 66 default: 67 break; 68 } 69 } 70 71 return n_chans; 72 } 73 74 75 /* dfs_channel_available: select new channel according to type parameter */ 76 static int dfs_channel_available(struct hostapd_channel_data *chan, 77 enum dfs_channel_type type) 78 { 79 if (type == DFS_NO_CAC_YET) { 80 /* Select only radar channel where CAC has not been 81 * performed yet 82 */ 83 if ((chan->flag & HOSTAPD_CHAN_RADAR) && 84 (chan->flag & HOSTAPD_CHAN_DFS_MASK) == 85 HOSTAPD_CHAN_DFS_USABLE) 86 return 1; 87 return 0; 88 } 89 90 /* 91 * When radar detection happens, CSA is performed. However, there's no 92 * time for CAC, so radar channels must be skipped when finding a new 93 * channel for CSA, unless they are available for immediate use. 94 */ 95 if (type == DFS_AVAILABLE && (chan->flag & HOSTAPD_CHAN_RADAR) && 96 ((chan->flag & HOSTAPD_CHAN_DFS_MASK) != 97 HOSTAPD_CHAN_DFS_AVAILABLE)) 98 return 0; 99 100 if (chan->flag & HOSTAPD_CHAN_DISABLED) 101 return 0; 102 if ((chan->flag & HOSTAPD_CHAN_RADAR) && 103 ((chan->flag & HOSTAPD_CHAN_DFS_MASK) == 104 HOSTAPD_CHAN_DFS_UNAVAILABLE)) 105 return 0; 106 return 1; 107 } 108 109 110 static int dfs_is_chan_allowed(struct hostapd_channel_data *chan, int n_chans) 111 { 112 /* 113 * The tables contain first valid channel number based on channel width. 114 * We will also choose this first channel as the control one. 115 */ 116 int allowed_40[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 117 165, 173, 184, 192 }; 118 /* 119 * VHT80, valid channels based on center frequency: 120 * 42, 58, 106, 122, 138, 155, 171 121 */ 122 int allowed_80[] = { 36, 52, 100, 116, 132, 149, 165 }; 123 /* 124 * VHT160 valid channels based on center frequency: 125 * 50, 114, 163 126 */ 127 int allowed_160[] = { 36, 100, 149 }; 128 int *allowed = allowed_40; 129 unsigned int i, allowed_no = 0; 130 131 switch (n_chans) { 132 case 2: 133 allowed = allowed_40; 134 allowed_no = ARRAY_SIZE(allowed_40); 135 break; 136 case 4: 137 allowed = allowed_80; 138 allowed_no = ARRAY_SIZE(allowed_80); 139 break; 140 case 8: 141 allowed = allowed_160; 142 allowed_no = ARRAY_SIZE(allowed_160); 143 break; 144 default: 145 wpa_printf(MSG_DEBUG, "Unknown width for %d channels", n_chans); 146 break; 147 } 148 149 for (i = 0; i < allowed_no; i++) { 150 if (chan->chan == allowed[i]) 151 return 1; 152 } 153 154 return 0; 155 } 156 157 158 static struct hostapd_channel_data * 159 dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx) 160 { 161 int i; 162 163 for (i = first_chan_idx; i < mode->num_channels; i++) { 164 if (mode->channels[i].freq == freq) 165 return &mode->channels[i]; 166 } 167 168 return NULL; 169 } 170 171 172 static int dfs_chan_range_available(struct hostapd_hw_modes *mode, 173 int first_chan_idx, int num_chans, 174 enum dfs_channel_type type) 175 { 176 struct hostapd_channel_data *first_chan, *chan; 177 int i; 178 u32 bw = num_chan_to_bw(num_chans); 179 180 if (first_chan_idx + num_chans > mode->num_channels) { 181 wpa_printf(MSG_DEBUG, 182 "DFS: some channels in range not defined"); 183 return 0; 184 } 185 186 first_chan = &mode->channels[first_chan_idx]; 187 188 /* hostapd DFS implementation assumes the first channel as primary. 189 * If it's not allowed to use the first channel as primary, decline the 190 * whole channel range. */ 191 if (!chan_pri_allowed(first_chan)) { 192 wpa_printf(MSG_DEBUG, "DFS: primary channel not allowed"); 193 return 0; 194 } 195 196 for (i = 0; i < num_chans; i++) { 197 chan = dfs_get_chan_data(mode, first_chan->freq + i * 20, 198 first_chan_idx); 199 if (!chan) { 200 wpa_printf(MSG_DEBUG, "DFS: no channel data for %d", 201 first_chan->freq + i * 20); 202 return 0; 203 } 204 205 /* HT 40 MHz secondary channel availability checked only for 206 * primary channel */ 207 if (!chan_bw_allowed(chan, bw, 1, !i)) { 208 wpa_printf(MSG_DEBUG, "DFS: bw now allowed for %d", 209 first_chan->freq + i * 20); 210 return 0; 211 } 212 213 if (!dfs_channel_available(chan, type)) { 214 wpa_printf(MSG_DEBUG, "DFS: channel not available %d", 215 first_chan->freq + i * 20); 216 return 0; 217 } 218 } 219 220 return 1; 221 } 222 223 224 static int is_in_chanlist(struct hostapd_iface *iface, 225 struct hostapd_channel_data *chan) 226 { 227 if (!iface->conf->acs_ch_list.num) 228 return 1; 229 230 return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan); 231 } 232 233 234 /* 235 * The function assumes HT40+ operation. 236 * Make sure to adjust the following variables after calling this: 237 * - hapd->secondary_channel 238 * - hapd->vht/he_oper_centr_freq_seg0_idx 239 * - hapd->vht/he_oper_centr_freq_seg1_idx 240 */ 241 static int dfs_find_channel(struct hostapd_iface *iface, 242 struct hostapd_channel_data **ret_chan, 243 int idx, enum dfs_channel_type type) 244 { 245 struct hostapd_hw_modes *mode; 246 struct hostapd_channel_data *chan; 247 int i, channel_idx = 0, n_chans, n_chans1; 248 249 mode = iface->current_mode; 250 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 251 252 wpa_printf(MSG_DEBUG, "DFS new chan checking %d channels", n_chans); 253 for (i = 0; i < mode->num_channels; i++) { 254 chan = &mode->channels[i]; 255 256 /* Skip HT40/VHT incompatible channels */ 257 if (iface->conf->ieee80211n && 258 iface->conf->secondary_channel && 259 (!dfs_is_chan_allowed(chan, n_chans) || 260 !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))) { 261 wpa_printf(MSG_DEBUG, 262 "DFS: channel %d (%d) is incompatible", 263 chan->freq, chan->chan); 264 continue; 265 } 266 267 /* Skip incompatible chandefs */ 268 if (!dfs_chan_range_available(mode, i, n_chans, type)) { 269 wpa_printf(MSG_DEBUG, 270 "DFS: range not available for %d (%d)", 271 chan->freq, chan->chan); 272 continue; 273 } 274 275 if (!is_in_chanlist(iface, chan)) { 276 wpa_printf(MSG_DEBUG, 277 "DFS: channel %d (%d) not in chanlist", 278 chan->freq, chan->chan); 279 continue; 280 } 281 282 if (chan->max_tx_power < iface->conf->min_tx_power) 283 continue; 284 285 if ((chan->flag & HOSTAPD_CHAN_INDOOR_ONLY) && 286 iface->conf->country[2] == 0x4f) 287 continue; 288 289 if (ret_chan && idx == channel_idx) { 290 wpa_printf(MSG_DEBUG, "Selected channel %d (%d)", 291 chan->freq, chan->chan); 292 *ret_chan = chan; 293 return idx; 294 } 295 wpa_printf(MSG_DEBUG, "Adding channel %d (%d)", 296 chan->freq, chan->chan); 297 channel_idx++; 298 } 299 return channel_idx; 300 } 301 302 303 static void dfs_adjust_center_freq(struct hostapd_iface *iface, 304 struct hostapd_channel_data *chan, 305 int secondary_channel, 306 int sec_chan_idx_80p80, 307 u8 *oper_centr_freq_seg0_idx, 308 u8 *oper_centr_freq_seg1_idx) 309 { 310 if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax) 311 return; 312 313 if (!chan) 314 return; 315 316 *oper_centr_freq_seg1_idx = 0; 317 318 switch (hostapd_get_oper_chwidth(iface->conf)) { 319 case CONF_OPER_CHWIDTH_USE_HT: 320 if (secondary_channel == 1) 321 *oper_centr_freq_seg0_idx = chan->chan + 2; 322 else if (secondary_channel == -1) 323 *oper_centr_freq_seg0_idx = chan->chan - 2; 324 else 325 *oper_centr_freq_seg0_idx = chan->chan; 326 break; 327 case CONF_OPER_CHWIDTH_80MHZ: 328 *oper_centr_freq_seg0_idx = chan->chan + 6; 329 break; 330 case CONF_OPER_CHWIDTH_160MHZ: 331 *oper_centr_freq_seg0_idx = chan->chan + 14; 332 break; 333 case CONF_OPER_CHWIDTH_80P80MHZ: 334 *oper_centr_freq_seg0_idx = chan->chan + 6; 335 *oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6; 336 break; 337 338 default: 339 wpa_printf(MSG_INFO, 340 "DFS: Unsupported channel width configuration"); 341 *oper_centr_freq_seg0_idx = 0; 342 break; 343 } 344 345 wpa_printf(MSG_DEBUG, "DFS adjusting VHT center frequency: %d, %d", 346 *oper_centr_freq_seg0_idx, 347 *oper_centr_freq_seg1_idx); 348 } 349 350 351 /* Return start channel idx we will use for mode->channels[idx] */ 352 static int dfs_get_start_chan_idx(struct hostapd_iface *iface, int *seg1_start) 353 { 354 struct hostapd_hw_modes *mode; 355 struct hostapd_channel_data *chan; 356 int channel_no = iface->conf->channel; 357 int res = -1, i; 358 int chan_seg1 = -1; 359 360 *seg1_start = -1; 361 362 /* HT40- */ 363 if (iface->conf->ieee80211n && iface->conf->secondary_channel == -1) 364 channel_no -= 4; 365 366 /* VHT/HE/EHT */ 367 if (iface->conf->ieee80211ac || iface->conf->ieee80211ax || 368 iface->conf->ieee80211be) { 369 switch (hostapd_get_oper_chwidth(iface->conf)) { 370 case CONF_OPER_CHWIDTH_USE_HT: 371 break; 372 case CONF_OPER_CHWIDTH_80MHZ: 373 channel_no = hostapd_get_oper_centr_freq_seg0_idx( 374 iface->conf) - 6; 375 break; 376 case CONF_OPER_CHWIDTH_160MHZ: 377 channel_no = hostapd_get_oper_centr_freq_seg0_idx( 378 iface->conf) - 14; 379 break; 380 case CONF_OPER_CHWIDTH_80P80MHZ: 381 channel_no = hostapd_get_oper_centr_freq_seg0_idx( 382 iface->conf) - 6; 383 chan_seg1 = hostapd_get_oper_centr_freq_seg1_idx( 384 iface->conf) - 6; 385 break; 386 case CONF_OPER_CHWIDTH_320MHZ: 387 channel_no = hostapd_get_oper_centr_freq_seg0_idx( 388 iface->conf) - 30; 389 break; 390 default: 391 wpa_printf(MSG_INFO, 392 "DFS only EHT20/40/80/160/80+80/320 is supported now"); 393 channel_no = -1; 394 break; 395 } 396 } 397 398 /* Get idx */ 399 mode = iface->current_mode; 400 for (i = 0; i < mode->num_channels; i++) { 401 chan = &mode->channels[i]; 402 if (chan->chan == channel_no) { 403 res = i; 404 break; 405 } 406 } 407 408 if (res != -1 && chan_seg1 > -1) { 409 int found = 0; 410 411 /* Get idx for seg1 */ 412 mode = iface->current_mode; 413 for (i = 0; i < mode->num_channels; i++) { 414 chan = &mode->channels[i]; 415 if (chan->chan == chan_seg1) { 416 *seg1_start = i; 417 found = 1; 418 break; 419 } 420 } 421 if (!found) 422 res = -1; 423 } 424 425 if (res == -1) { 426 wpa_printf(MSG_DEBUG, 427 "DFS chan_idx seems wrong; num-ch: %d ch-no: %d conf-ch-no: %d 11n: %d sec-ch: %d vht-oper-width: %d", 428 mode->num_channels, channel_no, iface->conf->channel, 429 iface->conf->ieee80211n, 430 iface->conf->secondary_channel, 431 hostapd_get_oper_chwidth(iface->conf)); 432 433 for (i = 0; i < mode->num_channels; i++) { 434 wpa_printf(MSG_DEBUG, "Available channel: %d", 435 mode->channels[i].chan); 436 } 437 } 438 439 return res; 440 } 441 442 443 /* At least one channel have radar flag */ 444 static int dfs_check_chans_radar(struct hostapd_iface *iface, 445 int start_chan_idx, int n_chans) 446 { 447 struct hostapd_channel_data *channel; 448 struct hostapd_hw_modes *mode; 449 int i, res = 0; 450 451 mode = iface->current_mode; 452 453 for (i = 0; i < n_chans; i++) { 454 if (start_chan_idx + i >= mode->num_channels) 455 break; 456 channel = &mode->channels[start_chan_idx + i]; 457 if (channel->flag & HOSTAPD_CHAN_RADAR) 458 res++; 459 } 460 461 return res; 462 } 463 464 465 /* All channels available */ 466 static int dfs_check_chans_available(struct hostapd_iface *iface, 467 int start_chan_idx, int n_chans) 468 { 469 struct hostapd_channel_data *channel; 470 struct hostapd_hw_modes *mode; 471 int i; 472 473 mode = iface->current_mode; 474 475 for (i = 0; i < n_chans; i++) { 476 channel = &mode->channels[start_chan_idx + i]; 477 478 if (channel->flag & HOSTAPD_CHAN_DISABLED) 479 break; 480 481 if (!(channel->flag & HOSTAPD_CHAN_RADAR)) 482 continue; 483 484 if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) != 485 HOSTAPD_CHAN_DFS_AVAILABLE) 486 break; 487 } 488 489 return i == n_chans; 490 } 491 492 493 /* At least one channel unavailable */ 494 static int dfs_check_chans_unavailable(struct hostapd_iface *iface, 495 int start_chan_idx, 496 int n_chans) 497 { 498 struct hostapd_channel_data *channel; 499 struct hostapd_hw_modes *mode; 500 int i, res = 0; 501 502 mode = iface->current_mode; 503 504 for (i = 0; i < n_chans; i++) { 505 channel = &mode->channels[start_chan_idx + i]; 506 if (channel->flag & HOSTAPD_CHAN_DISABLED) 507 res++; 508 if ((channel->flag & HOSTAPD_CHAN_DFS_MASK) == 509 HOSTAPD_CHAN_DFS_UNAVAILABLE) 510 res++; 511 } 512 513 return res; 514 } 515 516 517 static struct hostapd_channel_data * 518 dfs_get_valid_channel(struct hostapd_iface *iface, 519 int *secondary_channel, 520 u8 *oper_centr_freq_seg0_idx, 521 u8 *oper_centr_freq_seg1_idx, 522 enum dfs_channel_type type) 523 { 524 struct hostapd_hw_modes *mode; 525 struct hostapd_channel_data *chan = NULL; 526 struct hostapd_channel_data *chan2 = NULL; 527 int num_available_chandefs; 528 int chan_idx, chan_idx2; 529 int sec_chan_idx_80p80 = -1; 530 int i; 531 u32 _rand; 532 533 wpa_printf(MSG_DEBUG, "DFS: Selecting random channel"); 534 *secondary_channel = 0; 535 *oper_centr_freq_seg0_idx = 0; 536 *oper_centr_freq_seg1_idx = 0; 537 538 if (iface->current_mode == NULL) 539 return NULL; 540 541 mode = iface->current_mode; 542 if (mode->mode != HOSTAPD_MODE_IEEE80211A) 543 return NULL; 544 545 /* Get the count first */ 546 num_available_chandefs = dfs_find_channel(iface, NULL, 0, type); 547 wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d", 548 num_available_chandefs); 549 if (num_available_chandefs == 0) 550 return NULL; 551 552 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0) 553 return NULL; 554 chan_idx = _rand % num_available_chandefs; 555 wpa_printf(MSG_DEBUG, "DFS: Picked random entry from the list: %d/%d", 556 chan_idx, num_available_chandefs); 557 dfs_find_channel(iface, &chan, chan_idx, type); 558 if (!chan) { 559 wpa_printf(MSG_DEBUG, "DFS: no random channel found"); 560 return NULL; 561 } 562 wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)", 563 chan->freq, chan->chan); 564 565 /* dfs_find_channel() calculations assume HT40+ */ 566 if (iface->conf->secondary_channel) 567 *secondary_channel = 1; 568 else 569 *secondary_channel = 0; 570 571 /* Get secondary channel for HT80P80 */ 572 if (hostapd_get_oper_chwidth(iface->conf) == 573 CONF_OPER_CHWIDTH_80P80MHZ) { 574 if (num_available_chandefs <= 1) { 575 wpa_printf(MSG_ERROR, 576 "only 1 valid chan, can't support 80+80"); 577 return NULL; 578 } 579 580 /* 581 * Loop all channels except channel1 to find a valid channel2 582 * that is not adjacent to channel1. 583 */ 584 for (i = 0; i < num_available_chandefs - 1; i++) { 585 /* start from chan_idx + 1, end when chan_idx - 1 */ 586 chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs; 587 dfs_find_channel(iface, &chan2, chan_idx2, type); 588 if (chan2 && abs(chan2->chan - chan->chan) > 12) { 589 /* two channels are not adjacent */ 590 sec_chan_idx_80p80 = chan2->chan; 591 wpa_printf(MSG_DEBUG, 592 "DFS: got second chan: %d (%d)", 593 chan2->freq, chan2->chan); 594 break; 595 } 596 } 597 598 /* Check if we got a valid secondary channel which is not 599 * adjacent to the first channel. 600 */ 601 if (sec_chan_idx_80p80 == -1) { 602 wpa_printf(MSG_INFO, 603 "DFS: failed to get chan2 for 80+80"); 604 return NULL; 605 } 606 } 607 608 dfs_adjust_center_freq(iface, chan, 609 *secondary_channel, 610 sec_chan_idx_80p80, 611 oper_centr_freq_seg0_idx, 612 oper_centr_freq_seg1_idx); 613 614 return chan; 615 } 616 617 618 static int dfs_set_valid_channel(struct hostapd_iface *iface, int skip_radar) 619 { 620 struct hostapd_channel_data *channel; 621 u8 cf1 = 0, cf2 = 0; 622 int sec = 0; 623 624 channel = dfs_get_valid_channel(iface, &sec, &cf1, &cf2, 625 skip_radar ? DFS_AVAILABLE : 626 DFS_ANY_CHANNEL); 627 if (!channel) { 628 wpa_printf(MSG_ERROR, "could not get valid channel"); 629 return -1; 630 } 631 632 iface->freq = channel->freq; 633 iface->conf->channel = channel->chan; 634 iface->conf->secondary_channel = sec; 635 hostapd_set_oper_centr_freq_seg0_idx(iface->conf, cf1); 636 hostapd_set_oper_centr_freq_seg1_idx(iface->conf, cf2); 637 638 return 0; 639 } 640 641 642 static int set_dfs_state_freq(struct hostapd_iface *iface, int freq, u32 state) 643 { 644 struct hostapd_hw_modes *mode; 645 struct hostapd_channel_data *chan = NULL; 646 int i; 647 648 mode = iface->current_mode; 649 if (mode == NULL) 650 return 0; 651 652 wpa_printf(MSG_DEBUG, "set_dfs_state 0x%X for %d MHz", state, freq); 653 for (i = 0; i < iface->current_mode->num_channels; i++) { 654 chan = &iface->current_mode->channels[i]; 655 if (chan->freq == freq) { 656 if (chan->flag & HOSTAPD_CHAN_RADAR) { 657 chan->flag &= ~HOSTAPD_CHAN_DFS_MASK; 658 chan->flag |= state; 659 return 1; /* Channel found */ 660 } 661 } 662 } 663 wpa_printf(MSG_WARNING, "Can't set DFS state for freq %d MHz", freq); 664 return 0; 665 } 666 667 668 static int set_dfs_state(struct hostapd_iface *iface, int freq, int ht_enabled, 669 int chan_offset, int chan_width, int cf1, 670 int cf2, u32 state) 671 { 672 int n_chans = 1, i; 673 struct hostapd_hw_modes *mode; 674 int frequency = freq; 675 int frequency2 = 0; 676 int ret = 0; 677 678 mode = iface->current_mode; 679 if (mode == NULL) 680 return 0; 681 682 if (mode->mode != HOSTAPD_MODE_IEEE80211A) { 683 wpa_printf(MSG_WARNING, "current_mode != IEEE80211A"); 684 return 0; 685 } 686 687 /* Seems cf1 and chan_width is enough here */ 688 switch (chan_width) { 689 case CHAN_WIDTH_20_NOHT: 690 case CHAN_WIDTH_20: 691 n_chans = 1; 692 if (frequency == 0) 693 frequency = cf1; 694 break; 695 case CHAN_WIDTH_40: 696 n_chans = 2; 697 frequency = cf1 - 10; 698 break; 699 case CHAN_WIDTH_80: 700 n_chans = 4; 701 frequency = cf1 - 30; 702 break; 703 case CHAN_WIDTH_80P80: 704 n_chans = 4; 705 frequency = cf1 - 30; 706 frequency2 = cf2 - 30; 707 break; 708 case CHAN_WIDTH_160: 709 n_chans = 8; 710 frequency = cf1 - 70; 711 break; 712 default: 713 wpa_printf(MSG_INFO, "DFS chan_width %d not supported", 714 chan_width); 715 break; 716 } 717 718 wpa_printf(MSG_DEBUG, "DFS freq: %dMHz, n_chans: %d", frequency, 719 n_chans); 720 for (i = 0; i < n_chans; i++) { 721 ret += set_dfs_state_freq(iface, frequency, state); 722 frequency = frequency + 20; 723 724 if (chan_width == CHAN_WIDTH_80P80) { 725 ret += set_dfs_state_freq(iface, frequency2, state); 726 frequency2 = frequency2 + 20; 727 } 728 } 729 730 return ret; 731 } 732 733 734 static int dfs_are_channels_overlapped(struct hostapd_iface *iface, int freq, 735 int chan_width, int cf1, int cf2) 736 { 737 int start_chan_idx, start_chan_idx1; 738 struct hostapd_hw_modes *mode; 739 struct hostapd_channel_data *chan; 740 int n_chans, n_chans1, i, j, frequency = freq, radar_n_chans = 1; 741 u8 radar_chan; 742 int res = 0; 743 744 /* Our configuration */ 745 mode = iface->current_mode; 746 start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); 747 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 748 749 /* Check we are on DFS channel(s) */ 750 if (!dfs_check_chans_radar(iface, start_chan_idx, n_chans)) 751 return 0; 752 753 /* Reported via radar event */ 754 switch (chan_width) { 755 case CHAN_WIDTH_20_NOHT: 756 case CHAN_WIDTH_20: 757 radar_n_chans = 1; 758 if (frequency == 0) 759 frequency = cf1; 760 break; 761 case CHAN_WIDTH_40: 762 radar_n_chans = 2; 763 frequency = cf1 - 10; 764 break; 765 case CHAN_WIDTH_80: 766 radar_n_chans = 4; 767 frequency = cf1 - 30; 768 break; 769 case CHAN_WIDTH_160: 770 radar_n_chans = 8; 771 frequency = cf1 - 70; 772 break; 773 default: 774 wpa_printf(MSG_INFO, "DFS chan_width %d not supported", 775 chan_width); 776 break; 777 } 778 779 ieee80211_freq_to_chan(frequency, &radar_chan); 780 781 for (i = 0; i < n_chans; i++) { 782 chan = &mode->channels[start_chan_idx + i]; 783 if (!(chan->flag & HOSTAPD_CHAN_RADAR)) 784 continue; 785 for (j = 0; j < radar_n_chans; j++) { 786 wpa_printf(MSG_DEBUG, "checking our: %d, radar: %d", 787 chan->chan, radar_chan + j * 4); 788 if (chan->chan == radar_chan + j * 4) 789 res++; 790 } 791 } 792 793 wpa_printf(MSG_DEBUG, "overlapped: %d", res); 794 795 return res; 796 } 797 798 799 static unsigned int dfs_get_cac_time(struct hostapd_iface *iface, 800 int start_chan_idx, int n_chans) 801 { 802 struct hostapd_channel_data *channel; 803 struct hostapd_hw_modes *mode; 804 int i; 805 unsigned int cac_time_ms = 0; 806 807 mode = iface->current_mode; 808 809 for (i = 0; i < n_chans; i++) { 810 if (start_chan_idx + i >= mode->num_channels) 811 break; 812 channel = &mode->channels[start_chan_idx + i]; 813 if (!(channel->flag & HOSTAPD_CHAN_RADAR)) 814 continue; 815 if (channel->dfs_cac_ms > cac_time_ms) 816 cac_time_ms = channel->dfs_cac_ms; 817 } 818 819 return cac_time_ms; 820 } 821 822 823 /* 824 * Main DFS handler 825 * 1 - continue channel/ap setup 826 * 0 - channel/ap setup will be continued after CAC 827 * -1 - hit critical error 828 */ 829 int hostapd_handle_dfs(struct hostapd_iface *iface) 830 { 831 int res, n_chans, n_chans1, start_chan_idx, start_chan_idx1; 832 int skip_radar = 0; 833 834 if (is_6ghz_freq(iface->freq)) 835 return 1; 836 837 if (!iface->current_mode) { 838 /* 839 * This can happen with drivers that do not provide mode 840 * information and as such, cannot really use hostapd for DFS. 841 */ 842 wpa_printf(MSG_DEBUG, 843 "DFS: No current_mode information - assume no need to perform DFS operations by hostapd"); 844 return 1; 845 } 846 847 iface->cac_started = 0; 848 849 do { 850 /* Get start (first) channel for current configuration */ 851 start_chan_idx = dfs_get_start_chan_idx(iface, 852 &start_chan_idx1); 853 if (start_chan_idx == -1) 854 return -1; 855 856 /* Get number of used channels, depend on width */ 857 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 858 859 /* Setup CAC time */ 860 iface->dfs_cac_ms = dfs_get_cac_time(iface, start_chan_idx, 861 n_chans); 862 863 /* Check if any of configured channels require DFS */ 864 res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); 865 wpa_printf(MSG_DEBUG, 866 "DFS %d channels required radar detection", 867 res); 868 if (!res) 869 return 1; 870 871 /* Check if all channels are DFS available */ 872 res = dfs_check_chans_available(iface, start_chan_idx, n_chans); 873 wpa_printf(MSG_DEBUG, 874 "DFS all channels available, (SKIP CAC): %s", 875 res ? "yes" : "no"); 876 if (res) 877 return 1; 878 879 /* Check if any of configured channels is unavailable */ 880 res = dfs_check_chans_unavailable(iface, start_chan_idx, 881 n_chans); 882 wpa_printf(MSG_DEBUG, "DFS %d chans unavailable - choose other channel: %s", 883 res, res ? "yes": "no"); 884 if (res) { 885 if (dfs_set_valid_channel(iface, skip_radar) < 0) { 886 hostapd_set_state(iface, HAPD_IFACE_DFS); 887 return 0; 888 } 889 } 890 } while (res); 891 892 /* Finally start CAC */ 893 hostapd_set_state(iface, HAPD_IFACE_DFS); 894 wpa_printf(MSG_DEBUG, "DFS start CAC on %d MHz%s", iface->freq, 895 dfs_use_radar_background(iface) ? " (background)" : ""); 896 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START 897 "freq=%d chan=%d sec_chan=%d, width=%d, seg0=%d, seg1=%d, cac_time=%ds", 898 iface->freq, 899 iface->conf->channel, iface->conf->secondary_channel, 900 hostapd_get_oper_chwidth(iface->conf), 901 hostapd_get_oper_centr_freq_seg0_idx(iface->conf), 902 hostapd_get_oper_centr_freq_seg1_idx(iface->conf), 903 iface->dfs_cac_ms / 1000); 904 905 res = hostapd_start_dfs_cac( 906 iface, iface->conf->hw_mode, iface->freq, iface->conf->channel, 907 iface->conf->ieee80211n, iface->conf->ieee80211ac, 908 iface->conf->ieee80211ax, iface->conf->ieee80211be, 909 iface->conf->secondary_channel, 910 hostapd_get_oper_chwidth(iface->conf), 911 hostapd_get_oper_centr_freq_seg0_idx(iface->conf), 912 hostapd_get_oper_centr_freq_seg1_idx(iface->conf), 913 dfs_use_radar_background(iface)); 914 915 if (res) { 916 wpa_printf(MSG_ERROR, "DFS start_dfs_cac() failed, %d", res); 917 return -1; 918 } 919 920 if (dfs_use_radar_background(iface)) { 921 /* Cache background radar parameters. */ 922 iface->radar_background.channel = iface->conf->channel; 923 iface->radar_background.secondary_channel = 924 iface->conf->secondary_channel; 925 iface->radar_background.freq = iface->freq; 926 iface->radar_background.centr_freq_seg0_idx = 927 hostapd_get_oper_centr_freq_seg0_idx(iface->conf); 928 iface->radar_background.centr_freq_seg1_idx = 929 hostapd_get_oper_centr_freq_seg1_idx(iface->conf); 930 931 /* 932 * Let's select a random channel according to the 933 * regulations and perform CAC on dedicated radar chain. 934 */ 935 res = dfs_set_valid_channel(iface, 1); 936 if (res < 0) 937 return res; 938 939 iface->radar_background.temp_ch = 1; 940 return 1; 941 } 942 943 return 0; 944 } 945 946 947 int hostapd_is_dfs_chan_available(struct hostapd_iface *iface) 948 { 949 int n_chans, n_chans1, start_chan_idx, start_chan_idx1; 950 951 /* Get the start (first) channel for current configuration */ 952 start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); 953 if (start_chan_idx < 0) 954 return 0; 955 956 /* Get the number of used channels, depending on width */ 957 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 958 959 /* Check if all channels are DFS available */ 960 return dfs_check_chans_available(iface, start_chan_idx, n_chans); 961 } 962 963 964 static int hostapd_dfs_request_channel_switch(struct hostapd_iface *iface, 965 int channel, int freq, 966 int secondary_channel, 967 u8 current_vht_oper_chwidth, 968 u8 oper_centr_freq_seg0_idx, 969 u8 oper_centr_freq_seg1_idx) 970 { 971 struct hostapd_hw_modes *cmode = iface->current_mode; 972 int ieee80211_mode = IEEE80211_MODE_AP, err; 973 struct csa_settings csa_settings; 974 u8 new_vht_oper_chwidth; 975 unsigned int i; 976 unsigned int num_err = 0; 977 978 wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel); 979 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 980 "freq=%d chan=%d sec_chan=%d", freq, channel, 981 secondary_channel); 982 983 new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); 984 hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth); 985 986 /* Setup CSA request */ 987 os_memset(&csa_settings, 0, sizeof(csa_settings)); 988 csa_settings.cs_count = 5; 989 csa_settings.block_tx = 1; 990 csa_settings.link_id = -1; 991 #ifdef CONFIG_IEEE80211BE 992 if (iface->bss[0]->conf->mld_ap) 993 csa_settings.link_id = iface->bss[0]->mld_link_id; 994 #endif /* CONFIG_IEEE80211BE */ 995 #ifdef CONFIG_MESH 996 if (iface->mconf) 997 ieee80211_mode = IEEE80211_MODE_MESH; 998 #endif /* CONFIG_MESH */ 999 err = hostapd_set_freq_params(&csa_settings.freq_params, 1000 iface->conf->hw_mode, 1001 freq, channel, 1002 iface->conf->enable_edmg, 1003 iface->conf->edmg_channel, 1004 iface->conf->ieee80211n, 1005 iface->conf->ieee80211ac, 1006 iface->conf->ieee80211ax, 1007 iface->conf->ieee80211be, 1008 secondary_channel, 1009 new_vht_oper_chwidth, 1010 oper_centr_freq_seg0_idx, 1011 oper_centr_freq_seg1_idx, 1012 cmode->vht_capab, 1013 &cmode->he_capab[ieee80211_mode], 1014 &cmode->eht_capab[ieee80211_mode], 1015 hostapd_get_punct_bitmap(iface->bss[0])); 1016 1017 if (err) { 1018 wpa_printf(MSG_ERROR, 1019 "DFS failed to calculate CSA freq params"); 1020 hostapd_disable_iface(iface); 1021 return err; 1022 } 1023 1024 for (i = 0; i < iface->num_bss; i++) { 1025 err = hostapd_switch_channel(iface->bss[i], &csa_settings); 1026 if (err) 1027 num_err++; 1028 } 1029 1030 if (num_err == iface->num_bss) { 1031 wpa_printf(MSG_WARNING, 1032 "DFS failed to schedule CSA (%d) - trying fallback", 1033 err); 1034 iface->freq = freq; 1035 iface->conf->channel = channel; 1036 iface->conf->secondary_channel = secondary_channel; 1037 hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth); 1038 hostapd_set_oper_centr_freq_seg0_idx(iface->conf, 1039 oper_centr_freq_seg0_idx); 1040 hostapd_set_oper_centr_freq_seg1_idx(iface->conf, 1041 oper_centr_freq_seg1_idx); 1042 1043 hostapd_disable_iface(iface); 1044 hostapd_enable_iface(iface); 1045 1046 return 0; 1047 } 1048 1049 /* Channel configuration will be updated once CSA completes and 1050 * ch_switch_notify event is received */ 1051 wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); 1052 1053 return 0; 1054 } 1055 1056 1057 static void hostapd_dfs_update_background_chain(struct hostapd_iface *iface) 1058 { 1059 int sec = 0; 1060 enum dfs_channel_type channel_type = DFS_NO_CAC_YET; 1061 struct hostapd_channel_data *channel; 1062 u8 oper_centr_freq_seg0_idx = 0; 1063 u8 oper_centr_freq_seg1_idx = 0; 1064 1065 /* 1066 * Allow selection of DFS channel in ETSI to comply with 1067 * uniform spreading. 1068 */ 1069 if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI) 1070 channel_type = DFS_ANY_CHANNEL; 1071 1072 channel = dfs_get_valid_channel(iface, &sec, &oper_centr_freq_seg0_idx, 1073 &oper_centr_freq_seg1_idx, 1074 channel_type); 1075 if (!channel || 1076 channel->chan == iface->conf->channel || 1077 channel->chan == iface->radar_background.channel) 1078 channel = dfs_downgrade_bandwidth(iface, &sec, 1079 &oper_centr_freq_seg0_idx, 1080 &oper_centr_freq_seg1_idx, 1081 &channel_type); 1082 if (!channel || 1083 hostapd_start_dfs_cac(iface, iface->conf->hw_mode, 1084 channel->freq, channel->chan, 1085 iface->conf->ieee80211n, 1086 iface->conf->ieee80211ac, 1087 iface->conf->ieee80211ax, 1088 iface->conf->ieee80211be, 1089 sec, hostapd_get_oper_chwidth(iface->conf), 1090 oper_centr_freq_seg0_idx, 1091 oper_centr_freq_seg1_idx, true)) { 1092 wpa_printf(MSG_ERROR, "DFS failed to start CAC offchannel"); 1093 iface->radar_background.channel = -1; 1094 return; 1095 } 1096 1097 iface->radar_background.channel = channel->chan; 1098 iface->radar_background.freq = channel->freq; 1099 iface->radar_background.secondary_channel = sec; 1100 iface->radar_background.centr_freq_seg0_idx = oper_centr_freq_seg0_idx; 1101 iface->radar_background.centr_freq_seg1_idx = oper_centr_freq_seg1_idx; 1102 1103 wpa_printf(MSG_DEBUG, 1104 "%s: setting background chain to chan %d (%d MHz)", 1105 __func__, channel->chan, channel->freq); 1106 } 1107 1108 1109 static bool 1110 hostapd_dfs_is_background_event(struct hostapd_iface *iface, int freq) 1111 { 1112 return dfs_use_radar_background(iface) && 1113 iface->radar_background.channel != -1 && 1114 iface->radar_background.freq == freq; 1115 } 1116 1117 1118 static int 1119 hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface) 1120 { 1121 u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); 1122 1123 iface->conf->channel = iface->radar_background.channel; 1124 iface->freq = iface->radar_background.freq; 1125 iface->conf->secondary_channel = 1126 iface->radar_background.secondary_channel; 1127 hostapd_set_oper_centr_freq_seg0_idx( 1128 iface->conf, iface->radar_background.centr_freq_seg0_idx); 1129 hostapd_set_oper_centr_freq_seg1_idx( 1130 iface->conf, iface->radar_background.centr_freq_seg1_idx); 1131 1132 hostapd_dfs_update_background_chain(iface); 1133 1134 return hostapd_dfs_request_channel_switch( 1135 iface, iface->conf->channel, iface->freq, 1136 iface->conf->secondary_channel, current_vht_oper_chwidth, 1137 hostapd_get_oper_centr_freq_seg0_idx(iface->conf), 1138 hostapd_get_oper_centr_freq_seg1_idx(iface->conf)); 1139 } 1140 1141 1142 int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, 1143 int ht_enabled, int chan_offset, int chan_width, 1144 int cf1, int cf2) 1145 { 1146 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_COMPLETED 1147 "success=%d freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d radar_detected=%d", 1148 success, freq, ht_enabled, chan_offset, chan_width, cf1, cf2, 1149 iface->radar_detected); 1150 1151 if (success) { 1152 /* Complete iface/ap configuration */ 1153 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { 1154 /* Complete AP configuration for the first bring up. If 1155 * a radar was detected in this channel, interface setup 1156 * will be handled in 1157 * 1. hostapd_event_ch_switch() if switching to a 1158 * non-DFS channel 1159 * 2. on next CAC complete event if switching to another 1160 * DFS channel. 1161 */ 1162 if (iface->state != HAPD_IFACE_ENABLED && 1163 !iface->radar_detected) 1164 hostapd_setup_interface_complete(iface, 0); 1165 else 1166 iface->cac_started = 0; 1167 } else { 1168 set_dfs_state(iface, freq, ht_enabled, chan_offset, 1169 chan_width, cf1, cf2, 1170 HOSTAPD_CHAN_DFS_AVAILABLE); 1171 1172 /* 1173 * Radar event from background chain for the selected 1174 * channel. Perform CSA, move the main chain to the 1175 * selected channel and configure the background chain 1176 * to a new DFS channel. 1177 */ 1178 if (hostapd_dfs_is_background_event(iface, freq)) { 1179 iface->radar_background.cac_started = 0; 1180 if (!iface->radar_background.temp_ch) 1181 return 0; 1182 1183 iface->radar_background.temp_ch = 0; 1184 return hostapd_dfs_start_channel_switch_background(iface); 1185 } 1186 1187 /* 1188 * Just mark the channel available when CAC completion 1189 * event is received in enabled state. CAC result could 1190 * have been propagated from another radio having the 1191 * same regulatory configuration. When CAC completion is 1192 * received during non-HAPD_IFACE_ENABLED state, make 1193 * sure the configured channel is available because this 1194 * CAC completion event could have been propagated from 1195 * another radio. 1196 */ 1197 if (iface->state != HAPD_IFACE_ENABLED && 1198 hostapd_is_dfs_chan_available(iface)) { 1199 hostapd_setup_interface_complete(iface, 0); 1200 iface->cac_started = 0; 1201 } 1202 } 1203 } else if (hostapd_dfs_is_background_event(iface, freq)) { 1204 iface->radar_background.cac_started = 0; 1205 hostapd_dfs_update_background_chain(iface); 1206 } 1207 1208 iface->radar_detected = false; 1209 return 0; 1210 } 1211 1212 1213 int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq, 1214 int ht_enabled, int chan_offset, int chan_width, 1215 int cf1, int cf2) 1216 { 1217 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_PRE_CAC_EXPIRED 1218 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 1219 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 1220 1221 /* Proceed only if DFS is not offloaded to the driver */ 1222 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 1223 return 0; 1224 1225 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 1226 cf1, cf2, HOSTAPD_CHAN_DFS_USABLE); 1227 1228 return 0; 1229 } 1230 1231 1232 static struct hostapd_channel_data * 1233 dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel, 1234 u8 *oper_centr_freq_seg0_idx, 1235 u8 *oper_centr_freq_seg1_idx, 1236 enum dfs_channel_type *channel_type) 1237 { 1238 struct hostapd_channel_data *channel; 1239 1240 for (;;) { 1241 channel = dfs_get_valid_channel(iface, secondary_channel, 1242 oper_centr_freq_seg0_idx, 1243 oper_centr_freq_seg1_idx, 1244 *channel_type); 1245 if (channel) { 1246 wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d", 1247 channel->chan); 1248 return channel; 1249 } 1250 1251 if (*channel_type != DFS_ANY_CHANNEL) { 1252 *channel_type = DFS_ANY_CHANNEL; 1253 } else { 1254 int oper_chwidth; 1255 1256 oper_chwidth = hostapd_get_oper_chwidth(iface->conf); 1257 if (oper_chwidth == CONF_OPER_CHWIDTH_USE_HT) 1258 break; 1259 *channel_type = DFS_AVAILABLE; 1260 hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1); 1261 } 1262 } 1263 1264 wpa_printf(MSG_INFO, 1265 "%s: no DFS channels left, waiting for NOP to finish", 1266 __func__); 1267 return NULL; 1268 } 1269 1270 1271 static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) 1272 { 1273 struct hostapd_channel_data *channel; 1274 int secondary_channel; 1275 u8 oper_centr_freq_seg0_idx = 0; 1276 u8 oper_centr_freq_seg1_idx = 0; 1277 enum dfs_channel_type channel_type = DFS_ANY_CHANNEL; 1278 int err = 1; 1279 1280 /* Radar detected during active CAC */ 1281 iface->cac_started = 0; 1282 channel = dfs_get_valid_channel(iface, &secondary_channel, 1283 &oper_centr_freq_seg0_idx, 1284 &oper_centr_freq_seg1_idx, 1285 channel_type); 1286 1287 if (!channel) { 1288 channel = dfs_downgrade_bandwidth(iface, &secondary_channel, 1289 &oper_centr_freq_seg0_idx, 1290 &oper_centr_freq_seg1_idx, 1291 &channel_type); 1292 if (!channel) { 1293 wpa_printf(MSG_ERROR, "No valid channel available"); 1294 return err; 1295 } 1296 } 1297 1298 wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", 1299 channel->chan); 1300 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL 1301 "freq=%d chan=%d sec_chan=%d", channel->freq, 1302 channel->chan, secondary_channel); 1303 1304 iface->freq = channel->freq; 1305 iface->conf->channel = channel->chan; 1306 iface->conf->secondary_channel = secondary_channel; 1307 hostapd_set_oper_centr_freq_seg0_idx(iface->conf, 1308 oper_centr_freq_seg0_idx); 1309 hostapd_set_oper_centr_freq_seg1_idx(iface->conf, 1310 oper_centr_freq_seg1_idx); 1311 err = 0; 1312 1313 hostapd_setup_interface_complete(iface, err); 1314 return err; 1315 } 1316 1317 1318 static int 1319 hostapd_dfs_background_start_channel_switch(struct hostapd_iface *iface, 1320 int freq) 1321 { 1322 if (!dfs_use_radar_background(iface)) 1323 return -1; /* Background radar chain not supported. */ 1324 1325 wpa_printf(MSG_DEBUG, 1326 "%s called (background CAC active: %s, CSA active: %s)", 1327 __func__, iface->radar_background.cac_started ? "yes" : "no", 1328 hostapd_csa_in_progress(iface) ? "yes" : "no"); 1329 1330 /* Check if CSA in progress */ 1331 if (hostapd_csa_in_progress(iface)) 1332 return 0; 1333 1334 if (hostapd_dfs_is_background_event(iface, freq)) { 1335 /* 1336 * Radar pattern is reported on the background chain. 1337 * Just select a new random channel according to the 1338 * regulations for monitoring. 1339 */ 1340 hostapd_dfs_update_background_chain(iface); 1341 return 0; 1342 } 1343 1344 /* 1345 * If background radar detection is supported and the radar channel 1346 * monitored by the background chain is available switch to it without 1347 * waiting for the CAC. 1348 */ 1349 if (iface->radar_background.channel == -1) 1350 return -1; /* Background radar chain not available. */ 1351 1352 if (iface->radar_background.cac_started) { 1353 /* 1354 * Background channel not available yet. Perform CAC on the 1355 * main chain. 1356 */ 1357 iface->radar_background.temp_ch = 1; 1358 return -1; 1359 } 1360 1361 return hostapd_dfs_start_channel_switch_background(iface); 1362 } 1363 1364 1365 static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) 1366 { 1367 struct hostapd_channel_data *channel; 1368 int secondary_channel; 1369 u8 oper_centr_freq_seg0_idx; 1370 u8 oper_centr_freq_seg1_idx; 1371 enum dfs_channel_type channel_type = DFS_AVAILABLE; 1372 u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); 1373 1374 wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", 1375 __func__, iface->cac_started ? "yes" : "no", 1376 hostapd_csa_in_progress(iface) ? "yes" : "no"); 1377 1378 /* Check if CSA in progress */ 1379 if (hostapd_csa_in_progress(iface)) 1380 return 0; 1381 1382 /* Check if active CAC */ 1383 if (iface->cac_started) 1384 return hostapd_dfs_start_channel_switch_cac(iface); 1385 1386 /* 1387 * Allow selection of DFS channel in ETSI to comply with 1388 * uniform spreading. 1389 */ 1390 if (iface->dfs_domain == HOSTAPD_DFS_REGION_ETSI) 1391 channel_type = DFS_ANY_CHANNEL; 1392 1393 /* Perform channel switch/CSA */ 1394 channel = dfs_get_valid_channel(iface, &secondary_channel, 1395 &oper_centr_freq_seg0_idx, 1396 &oper_centr_freq_seg1_idx, 1397 channel_type); 1398 1399 if (!channel) { 1400 /* 1401 * If there is no channel to switch immediately to, check if 1402 * there is another channel where we can switch even if it 1403 * requires to perform a CAC first. 1404 */ 1405 channel_type = DFS_ANY_CHANNEL; 1406 channel = dfs_downgrade_bandwidth(iface, &secondary_channel, 1407 &oper_centr_freq_seg0_idx, 1408 &oper_centr_freq_seg1_idx, 1409 &channel_type); 1410 if (!channel) { 1411 /* 1412 * Toggle interface state to enter DFS state 1413 * until NOP is finished. 1414 */ 1415 hostapd_disable_iface(iface); 1416 hostapd_enable_iface(iface); 1417 return 0; 1418 } 1419 1420 if (channel_type == DFS_ANY_CHANNEL) { 1421 iface->freq = channel->freq; 1422 iface->conf->channel = channel->chan; 1423 iface->conf->secondary_channel = secondary_channel; 1424 hostapd_set_oper_centr_freq_seg0_idx( 1425 iface->conf, oper_centr_freq_seg0_idx); 1426 hostapd_set_oper_centr_freq_seg1_idx( 1427 iface->conf, oper_centr_freq_seg1_idx); 1428 1429 hostapd_disable_iface(iface); 1430 hostapd_enable_iface(iface); 1431 return 0; 1432 } 1433 } 1434 1435 return hostapd_dfs_request_channel_switch(iface, channel->chan, 1436 channel->freq, 1437 secondary_channel, 1438 current_vht_oper_chwidth, 1439 oper_centr_freq_seg0_idx, 1440 oper_centr_freq_seg1_idx); 1441 } 1442 1443 1444 int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, 1445 int ht_enabled, int chan_offset, int chan_width, 1446 int cf1, int cf2) 1447 { 1448 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_RADAR_DETECTED 1449 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 1450 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 1451 1452 iface->radar_detected = true; 1453 1454 /* Proceed only if DFS is not offloaded to the driver */ 1455 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 1456 return 0; 1457 1458 if (!iface->conf->ieee80211h) 1459 return 0; 1460 1461 /* mark radar frequency as invalid */ 1462 if (!set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 1463 cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE)) 1464 return 0; 1465 1466 if (!hostapd_dfs_is_background_event(iface, freq)) { 1467 /* Skip if reported radar event not overlapped our channels */ 1468 if (!dfs_are_channels_overlapped(iface, freq, chan_width, 1469 cf1, cf2)) 1470 return 0; 1471 } 1472 1473 if (hostapd_dfs_background_start_channel_switch(iface, freq)) { 1474 /* Radar detected while operating, switch the channel. */ 1475 return hostapd_dfs_start_channel_switch(iface); 1476 } 1477 1478 return 0; 1479 } 1480 1481 1482 int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, 1483 int ht_enabled, int chan_offset, int chan_width, 1484 int cf1, int cf2) 1485 { 1486 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NOP_FINISHED 1487 "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d", 1488 freq, ht_enabled, chan_offset, chan_width, cf1, cf2); 1489 1490 /* Proceed only if DFS is not offloaded to the driver */ 1491 if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) 1492 return 0; 1493 1494 /* TODO add correct implementation here */ 1495 set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, 1496 cf1, cf2, HOSTAPD_CHAN_DFS_USABLE); 1497 1498 if (iface->state == HAPD_IFACE_DFS && !iface->cac_started) { 1499 /* Handle cases where all channels were initially unavailable */ 1500 hostapd_handle_dfs(iface); 1501 } else if (dfs_use_radar_background(iface) && 1502 iface->radar_background.channel == -1) { 1503 /* Reset radar background chain if disabled */ 1504 hostapd_dfs_update_background_chain(iface); 1505 } 1506 1507 return 0; 1508 } 1509 1510 1511 int hostapd_is_dfs_required(struct hostapd_iface *iface) 1512 { 1513 int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res; 1514 1515 if ((!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) && 1516 !iface->conf->ieee80211h) || 1517 !iface->current_mode || 1518 iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) 1519 return 0; 1520 1521 /* Get start (first) channel for current configuration */ 1522 start_chan_idx = dfs_get_start_chan_idx(iface, &start_chan_idx1); 1523 if (start_chan_idx == -1) 1524 return -1; 1525 1526 /* Get number of used channels, depend on width */ 1527 n_chans = dfs_get_used_n_chans(iface, &n_chans1); 1528 1529 /* Check if any of configured channels require DFS */ 1530 res = dfs_check_chans_radar(iface, start_chan_idx, n_chans); 1531 if (res) 1532 return res; 1533 if (start_chan_idx1 >= 0 && n_chans1 > 0) 1534 res = dfs_check_chans_radar(iface, start_chan_idx1, n_chans1); 1535 return res; 1536 } 1537 1538 1539 int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, 1540 int ht_enabled, int chan_offset, int chan_width, 1541 int cf1, int cf2) 1542 { 1543 if (hostapd_dfs_is_background_event(iface, freq)) { 1544 iface->radar_background.cac_started = 1; 1545 } else { 1546 /* This is called when the driver indicates that an offloaded 1547 * DFS has started CAC. radar_detected might be set for previous 1548 * DFS channel. Clear it for this new CAC process. */ 1549 hostapd_set_state(iface, HAPD_IFACE_DFS); 1550 iface->cac_started = 1; 1551 1552 /* Clear radar_detected in case it is for the previous 1553 * frequency. Also remove disabled link's information in RNR 1554 * element from other links. */ 1555 iface->radar_detected = false; 1556 if (iface->interfaces && iface->interfaces->count > 1) 1557 ieee802_11_set_beacons(iface); 1558 } 1559 /* TODO: How to check CAC time for ETSI weather channels? */ 1560 iface->dfs_cac_ms = 60000; 1561 wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_CAC_START 1562 "freq=%d chan=%d chan_offset=%d width=%d seg0=%d " 1563 "seg1=%d cac_time=%ds%s", 1564 freq, (freq - 5000) / 5, chan_offset, chan_width, cf1, cf2, 1565 iface->dfs_cac_ms / 1000, 1566 hostapd_dfs_is_background_event(iface, freq) ? 1567 " (background)" : ""); 1568 1569 os_get_reltime(&iface->dfs_cac_start); 1570 return 0; 1571 } 1572 1573 1574 /* 1575 * Main DFS handler for offloaded case. 1576 * 2 - continue channel/AP setup for non-DFS channel 1577 * 1 - continue channel/AP setup for DFS channel 1578 * 0 - channel/AP setup will be continued after CAC 1579 * -1 - hit critical error 1580 */ 1581 int hostapd_handle_dfs_offload(struct hostapd_iface *iface) 1582 { 1583 int dfs_res; 1584 1585 wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d", 1586 __func__, iface->cac_started); 1587 1588 /* 1589 * If DFS has already been started, then we are being called from a 1590 * callback to continue AP/channel setup. Reset the CAC start flag and 1591 * return. 1592 */ 1593 if (iface->cac_started) { 1594 wpa_printf(MSG_DEBUG, "%s: iface->cac_started: %d", 1595 __func__, iface->cac_started); 1596 iface->cac_started = 0; 1597 return 1; 1598 } 1599 1600 dfs_res = hostapd_is_dfs_required(iface); 1601 if (dfs_res > 0) { 1602 wpa_printf(MSG_DEBUG, 1603 "%s: freq %d MHz requires DFS for %d chans", 1604 __func__, iface->freq, dfs_res); 1605 return 0; 1606 } 1607 1608 wpa_printf(MSG_DEBUG, 1609 "%s: freq %d MHz does not require DFS. Continue channel/AP setup", 1610 __func__, iface->freq); 1611 return 2; 1612 } 1613 1614 1615 int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, 1616 int center_freq) 1617 { 1618 struct hostapd_channel_data *chan; 1619 struct hostapd_hw_modes *mode = iface->current_mode; 1620 int half_width; 1621 int res = 0; 1622 int i; 1623 1624 if (!iface->conf->ieee80211h || !mode || 1625 mode->mode != HOSTAPD_MODE_IEEE80211A) 1626 return 0; 1627 1628 switch (width) { 1629 case CHAN_WIDTH_20_NOHT: 1630 case CHAN_WIDTH_20: 1631 half_width = 10; 1632 break; 1633 case CHAN_WIDTH_40: 1634 half_width = 20; 1635 break; 1636 case CHAN_WIDTH_80: 1637 case CHAN_WIDTH_80P80: 1638 half_width = 40; 1639 break; 1640 case CHAN_WIDTH_160: 1641 half_width = 80; 1642 break; 1643 default: 1644 wpa_printf(MSG_WARNING, "DFS chanwidth %d not supported", 1645 width); 1646 return 0; 1647 } 1648 1649 for (i = 0; i < mode->num_channels; i++) { 1650 chan = &mode->channels[i]; 1651 1652 if (!(chan->flag & HOSTAPD_CHAN_RADAR)) 1653 continue; 1654 1655 if ((chan->flag & HOSTAPD_CHAN_DFS_MASK) == 1656 HOSTAPD_CHAN_DFS_AVAILABLE) 1657 continue; 1658 1659 if (center_freq - chan->freq < half_width && 1660 chan->freq - center_freq < half_width) 1661 res++; 1662 } 1663 1664 wpa_printf(MSG_DEBUG, "DFS CAC required: (%d, %d): in range: %s", 1665 center_freq - half_width, center_freq + half_width, 1666 res ? "yes" : "no"); 1667 1668 return res; 1669 } 1670