| From 22eb74742a126bd356e6f25e3522e1c5bb5229ef Mon Sep 17 00:00:00 2001 |
| From: dzou <dzou@company.com> |
| Date: Sun, 5 Jun 2022 23:21:17 +0800 |
| Subject: [PATCH 906/911] DFS: Introduce hostapd_dfs_request_channel_switch() |
| |
| This is a preliminary patch to add Channel Switch Announcement for |
| background radar detection. |
| |
| Tested-by: Owen Peng <owen.peng@mediatek.com> |
| Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> |
| --- |
| src/ap/dfs.c | 163 ++++++++++++++++++++++++++++----------------------- |
| 1 file changed, 90 insertions(+), 73 deletions(-) |
| |
| diff --git a/src/ap/dfs.c b/src/ap/dfs.c |
| index 5dc261589..000b411be 100644 |
| --- a/src/ap/dfs.c |
| +++ b/src/ap/dfs.c |
| @@ -961,6 +961,90 @@ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface) |
| } |
| |
| |
| +static int 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) |
| +{ |
| + struct hostapd_hw_modes *cmode = iface->current_mode; |
| + int ieee80211_mode = IEEE80211_MODE_AP, err; |
| + struct csa_settings csa_settings; |
| + u8 new_vht_oper_chwidth; |
| + unsigned int i; |
| + |
| + wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", channel); |
| + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL |
| + "freq=%d chan=%d sec_chan=%d", freq, channel, |
| + secondary_channel); |
| + |
| + new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); |
| + hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth); |
| + |
| + /* Setup CSA request */ |
| + os_memset(&csa_settings, 0, sizeof(csa_settings)); |
| + csa_settings.cs_count = 5; |
| + csa_settings.block_tx = 1; |
| +#ifdef CONFIG_MESH |
| + if (iface->mconf) |
| + ieee80211_mode = IEEE80211_MODE_MESH; |
| +#endif /* CONFIG_MESH */ |
| + err = hostapd_set_freq_params(&csa_settings.freq_params, |
| + iface->conf->hw_mode, |
| + freq, channel, |
| + iface->conf->enable_edmg, |
| + iface->conf->edmg_channel, |
| + iface->conf->ieee80211n, |
| + iface->conf->ieee80211ac, |
| + iface->conf->ieee80211ax, |
| + secondary_channel, |
| + new_vht_oper_chwidth, |
| + oper_centr_freq_seg0_idx, |
| + oper_centr_freq_seg1_idx, |
| + cmode->vht_capab, |
| + &cmode->he_capab[ieee80211_mode]); |
| + |
| + if (err) { |
| + wpa_printf(MSG_ERROR, |
| + "DFS failed to calculate CSA freq params"); |
| + hostapd_disable_iface(iface); |
| + return err; |
| + } |
| + |
| + for (i = 0; i < iface->num_bss; i++) { |
| + err = hostapd_switch_channel(iface->bss[i], &csa_settings); |
| + if (err) |
| + break; |
| + } |
| + |
| + if (err) { |
| + wpa_printf(MSG_WARNING, |
| + "DFS failed to schedule CSA (%d) - trying fallback", |
| + err); |
| + iface->freq = freq; |
| + iface->conf->channel = channel; |
| + iface->conf->secondary_channel = secondary_channel; |
| + hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth); |
| + hostapd_set_oper_centr_freq_seg0_idx(iface->conf, |
| + oper_centr_freq_seg0_idx); |
| + hostapd_set_oper_centr_freq_seg1_idx(iface->conf, |
| + oper_centr_freq_seg1_idx); |
| + |
| + hostapd_disable_iface(iface); |
| + hostapd_enable_iface(iface); |
| + |
| + return 0; |
| + } |
| + |
| + /* Channel configuration will be updated once CSA completes and |
| + * ch_switch_notify event is received */ |
| + wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); |
| + |
| + return 0; |
| +} |
| + |
| + |
| static void hostpad_dfs_update_background_chain(struct hostapd_iface *iface) |
| { |
| int sec = 0; |
| @@ -1213,14 +1297,8 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) |
| int secondary_channel; |
| u8 oper_centr_freq_seg0_idx; |
| u8 oper_centr_freq_seg1_idx; |
| - u8 new_vht_oper_chwidth; |
| enum dfs_channel_type channel_type = DFS_AVAILABLE; |
| - struct csa_settings csa_settings; |
| - unsigned int i; |
| - int err = 1; |
| - struct hostapd_hw_modes *cmode = iface->current_mode; |
| u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); |
| - int ieee80211_mode = IEEE80211_MODE_AP; |
| |
| wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", |
| __func__, iface->cac_started ? "yes" : "no", |
| @@ -1283,73 +1361,12 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) |
| } |
| } |
| |
| - wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", |
| - channel->chan); |
| - wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_NEW_CHANNEL |
| - "freq=%d chan=%d sec_chan=%d", channel->freq, |
| - channel->chan, secondary_channel); |
| - |
| - new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); |
| - hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth); |
| - |
| - /* Setup CSA request */ |
| - os_memset(&csa_settings, 0, sizeof(csa_settings)); |
| - csa_settings.cs_count = 5; |
| - csa_settings.block_tx = 1; |
| -#ifdef CONFIG_MESH |
| - if (iface->mconf) |
| - ieee80211_mode = IEEE80211_MODE_MESH; |
| -#endif /* CONFIG_MESH */ |
| - err = hostapd_set_freq_params(&csa_settings.freq_params, |
| - iface->conf->hw_mode, |
| - channel->freq, |
| - channel->chan, |
| - iface->conf->enable_edmg, |
| - iface->conf->edmg_channel, |
| - iface->conf->ieee80211n, |
| - iface->conf->ieee80211ac, |
| - iface->conf->ieee80211ax, |
| - secondary_channel, |
| - new_vht_oper_chwidth, |
| - oper_centr_freq_seg0_idx, |
| - oper_centr_freq_seg1_idx, |
| - cmode->vht_capab, |
| - &cmode->he_capab[ieee80211_mode]); |
| - |
| - if (err) { |
| - wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); |
| - hostapd_disable_iface(iface); |
| - return err; |
| - } |
| - |
| - for (i = 0; i < iface->num_bss; i++) { |
| - err = hostapd_switch_channel(iface->bss[i], &csa_settings); |
| - if (err) |
| - break; |
| - } |
| - |
| - if (err) { |
| - wpa_printf(MSG_WARNING, "DFS failed to schedule CSA (%d) - trying fallback", |
| - err); |
| - iface->freq = channel->freq; |
| - iface->conf->channel = channel->chan; |
| - iface->conf->secondary_channel = secondary_channel; |
| - hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth); |
| - hostapd_set_oper_centr_freq_seg0_idx(iface->conf, |
| - oper_centr_freq_seg0_idx); |
| - hostapd_set_oper_centr_freq_seg1_idx(iface->conf, |
| - oper_centr_freq_seg1_idx); |
| - |
| - hostapd_disable_iface(iface); |
| - hostapd_enable_iface(iface); |
| - return 0; |
| - } |
| - |
| - /* Channel configuration will be updated once CSA completes and |
| - * ch_switch_notify event is received */ |
| - |
| - wpa_printf(MSG_DEBUG, "DFS waiting channel switch event"); |
| - return 0; |
| + return hostapd_dfs_request_channel_switch(iface, channel->chan, |
| + channel->freq, |
| + secondary_channel, |
| + current_vht_oper_chwidth, |
| + oper_centr_freq_seg0_idx, |
| + oper_centr_freq_seg1_idx); |
| } |
| |
| |
| -- |
| 2.29.2 |
| |