From f4670cb1846ac7ebed827607cbee0c1b75ce27f4 Mon Sep 17 00:00:00 2001 From: Mohan Kumar G Date: Tue, 6 Feb 2024 20:56:44 +0530 Subject: [PATCH] hostapd: Fix CU beacon delay in channel switch Currently, when channel switch is triggered in AP, critical update flag in the new channel beacon is set after a delay. This is because, the CUF for elements modified after channel switch is not set immediately after the channel switch completes. Instead, this flag is set after beaconing starts in new channel. - First, CUF for elements added is set during the Channel Switch - Channel Switch completes and beaconing starts immediately. - Next, CUF for elements modified is received when set beacon is called. So after CS is finished, beaconing starts immediately and the CU modified flag is received later. Fix this issue by adding a CUF after csa completes and unsetting critical update during set beacon. Signed-off-by: Mohan Kumar G --- src/ap/beacon.c | 1 + src/ap/drv_callbacks.c | 1 + src/ap/hostapd.c | 5 +++++ src/ap/hostapd.h | 1 + src/drivers/driver.h | 8 ++++++++ src/drivers/driver_nl80211.c | 9 +++++++-- 6 files changed, 23 insertions(+), 2 deletions(-) --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -2712,6 +2712,8 @@ static int __ieee802_11_set_beacon(struc #ifdef CONFIG_IEEE80211BE params.punct_bitmap = iconf->punct_bitmap; #endif /* CONFIG_IEEE80211BE */ + params.disable_cu = hapd->disable_cu; + hapd->disable_cu = 0; if (cmode && hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq, --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -1101,6 +1101,7 @@ void hostapd_event_ch_switch(struct host if (hapd->csa_in_progress && freq == hapd->cs_freq_params.freq) { hostapd_cleanup_cs_params(hapd); + hapd->disable_cu = 1; ieee802_11_set_beacon(hapd); hostapd_start_device_cac_background(hapd->iface); --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -4310,6 +4310,9 @@ static int hostapd_build_beacon_data(str beacon->assocresp_ies_len = wpabuf_len(assocresp_extra); } + beacon->elemid_added = params.elemid_added; + beacon->elemid_modified = params.elemid_modified; + ret = 0; free_beacon: /* if the function fails, the caller should not free beacon data */ @@ -4522,6 +4525,8 @@ static int hostapd_fill_csa_settings(str iface->conf->punct_bitmap = settings->punct_bitmap; #endif /* CONFIG_IEEE80211BE */ ret = hostapd_build_beacon_data(hapd, &settings->beacon_after); + if (settings->beacon_after.elemid_modified) + settings->beacon_after_cu = 1; /* change back the configuration */ #ifdef CONFIG_IEEE80211BE --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -541,6 +541,7 @@ struct hostapd_data { u8 session_cnt; #endif /* CONFIG_IEEE80211BE */ + bool disable_cu; }; --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -1917,6 +1917,7 @@ struct wpa_driver_ap_params { /* critical_update_flag - critical update flag*/ bool elemid_added; bool elemid_modified; + bool disable_cu; /** * allowed_freqs - List of allowed 20 MHz channel center frequencies in @@ -2807,6 +2808,10 @@ struct beacon_data { size_t proberesp_ies_len; size_t assocresp_ies_len; size_t probe_resp_len; + + /* critical_update_flag - critical update flag*/ + bool elemid_added; + bool elemid_modified; }; /** @@ -2834,6 +2839,9 @@ struct csa_settings { u16 punct_bitmap; bool handle_dfs; struct unsol_bcast_probe_resp ubpr; + + /* critical_update_flag - critical update flag*/ + bool beacon_after_cu; }; /** --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -5462,7 +5462,7 @@ static int wpa_driver_nl80211_set_ap(voi goto fail; #endif /* CONFIG_FILS */ - if (bss->n_links && (params->elemid_added || params->elemid_modified)) { + if (bss->n_links && (params->elemid_added || params->elemid_modified) && !params->disable_cu) { if (params->elemid_added) critical_update |= NL80211_CU_ELEMID_ADDED; if (params->elemid_modified) @@ -11414,6 +11414,11 @@ static int nl80211_switch_channel(void * settings->counter_offset_presp))) goto fail; + if (bss->n_links) { + critical_update |= NL80211_CU_ELEMID_ADDED; + if (nla_put_u8(msg, NL80211_ATTR_SET_CRITICAL_UPDATE, critical_update)) + goto fail; + } nla_nest_end(msg, beacon_csa); if (settings->handle_dfs && nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS)) @@ -11436,8 +11441,7 @@ static int nl80211_switch_channel(void * #endif /* CONFIG_IEEE80211AX */ if (bss->n_links) { - critical_update |= NL80211_CU_ELEMID_ADDED; - if (nla_put_u8(msg, NL80211_ATTR_SET_CRITICAL_UPDATE, critical_update)) + if (nla_put_u8(msg, NL80211_ATTR_SET_CRITICAL_UPDATE, NL80211_CU_ELEMID_MODIFIED)) goto fail; }