BSS coloring: Handling of collision events and triggering CCA

Add the core code for handling BSS color collision events and triggering
CCA inside the kernel. The caller of hostapd_switch_color() will be
added in the following commits.

Tested-by: Peter Chiu <chui-hao.chiu@mediatek.com>
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
This commit is contained in:
John Crispin 2022-03-21 12:10:30 +01:00 committed by Jouni Malinen
parent 2f336ca580
commit 654d2395dd
5 changed files with 205 additions and 0 deletions

View file

@ -66,6 +66,10 @@ static int setup_interface2(struct hostapd_iface *iface);
static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx);
static void hostapd_interface_setup_failure_handler(void *eloop_ctx,
void *timeout_ctx);
#ifdef CONFIG_IEEE80211AX
static void hostapd_switch_color_timeout_handler(void *eloop_data,
void *user_ctx);
#endif /* CONFIG_IEEE80211AX */
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
@ -462,6 +466,10 @@ void hostapd_free_hapd_data(struct hostapd_data *hapd)
}
eloop_cancel_timeout(auth_sae_process_commit, hapd, NULL);
#endif /* CONFIG_SAE */
#ifdef CONFIG_IEEE80211AX
eloop_cancel_timeout(hostapd_switch_color_timeout_handler, hapd, NULL);
#endif /* CONFIG_IEEE80211AX */
}
@ -3707,6 +3715,139 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
hostapd_enable_iface(iface);
}
#ifdef CONFIG_IEEE80211AX
void hostapd_cleanup_cca_params(struct hostapd_data *hapd)
{
hapd->cca_count = 0;
hapd->cca_color = 0;
hapd->cca_c_off_beacon = 0;
hapd->cca_c_off_proberesp = 0;
hapd->cca_in_progress = false;
}
static int hostapd_fill_cca_settings(struct hostapd_data *hapd,
struct cca_settings *settings)
{
struct hostapd_iface *iface = hapd->iface;
u8 old_color;
int ret;
if (!iface || iface->conf->he_op.he_bss_color_disabled)
return -1;
old_color = iface->conf->he_op.he_bss_color;
iface->conf->he_op.he_bss_color = hapd->cca_color;
ret = hostapd_build_beacon_data(hapd, &settings->beacon_after);
if (ret)
return ret;
iface->conf->he_op.he_bss_color = old_color;
settings->cca_count = hapd->cca_count;
settings->cca_color = hapd->cca_color,
hapd->cca_in_progress = true;
ret = hostapd_build_beacon_data(hapd, &settings->beacon_cca);
if (ret) {
free_beacon_data(&settings->beacon_after);
return ret;
}
settings->counter_offset_beacon = hapd->cca_c_off_beacon;
settings->counter_offset_presp = hapd->cca_c_off_proberesp;
return 0;
}
static void hostapd_switch_color_timeout_handler(void *eloop_data,
void *user_ctx)
{
struct hostapd_data *hapd = (struct hostapd_data *) eloop_data;
os_time_t delta_t;
unsigned int b;
int i, r;
/* CCA can be triggered once the handler constantly receives
* color collision events to for at least
* DOT11BSS_COLOR_COLLISION_AP_PERIOD (50 s by default). */
delta_t = hapd->last_color_collision.sec -
hapd->first_color_collision.sec;
if (delta_t < DOT11BSS_COLOR_COLLISION_AP_PERIOD)
return;
r = os_random() % HE_OPERATION_BSS_COLOR_MAX;
for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) {
if (r && !(hapd->color_collision_bitmap & BIT(r)))
break;
r = (r + 1) % HE_OPERATION_BSS_COLOR_MAX;
}
if (i == HE_OPERATION_BSS_COLOR_MAX) {
/* There are no free colors so turn BSS coloring off */
wpa_printf(MSG_INFO,
"No free colors left, turning off BSS coloring");
hapd->iface->conf->he_op.he_bss_color_disabled = 1;
hapd->iface->conf->he_op.he_bss_color = os_random() % 63 + 1;
for (b = 0; b < hapd->iface->num_bss; b++)
ieee802_11_set_beacon(hapd->iface->bss[b]);
return;
}
for (b = 0; b < hapd->iface->num_bss; b++) {
struct hostapd_data *bss = hapd->iface->bss[b];
struct cca_settings settings;
int ret;
hostapd_cleanup_cca_params(bss);
bss->cca_color = r;
bss->cca_count = 10;
if (hostapd_fill_cca_settings(bss, &settings)) {
hostapd_cleanup_cca_params(bss);
continue;
}
ret = hostapd_drv_switch_color(bss, &settings);
if (ret)
hostapd_cleanup_cca_params(bss);
free_beacon_data(&settings.beacon_cca);
free_beacon_data(&settings.beacon_after);
}
}
void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap)
{
struct os_reltime now;
if (hapd->cca_in_progress)
return;
if (os_get_reltime(&now))
return;
hapd->color_collision_bitmap = bitmap;
hapd->last_color_collision = now;
if (eloop_is_timeout_registered(hostapd_switch_color_timeout_handler,
hapd, NULL))
return;
hapd->first_color_collision = now;
/* 10 s window as margin for persistent color collision reporting */
eloop_register_timeout(DOT11BSS_COLOR_COLLISION_AP_PERIOD + 10, 0,
hostapd_switch_color_timeout_handler,
hapd, NULL);
}
#endif /* CONFIG_IEEE80211AX */
#endif /* NEED_AP_MLME */