dfs.c 24 KB

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