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>
This commit is contained in:
Lorenzo Bianconi 2022-03-06 20:34:12 +01:00 committed by Jouni Malinen
parent 316a9dc63b
commit 25663241c5

View file

@ -943,6 +943,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;
@ -1195,14 +1279,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",
@ -1265,73 +1343,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,
return hostapd_dfs_request_channel_switch(iface, channel->chan,
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,
current_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;
}