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