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