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