Skip to content

wifi: Add support for runtime BSS max idle support configuration #91904

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/wifi/nrf_wifi/inc/fmac_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct nrf_wifi_vif_ctx_zep {
struct k_work_delayable nrf_wifi_rpu_recovery_bringup_work;
#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */
int rts_threshold_value;
unsigned short bss_max_idle_period;
};

struct nrf_wifi_vif_ctx_map {
Expand Down
3 changes: 3 additions & 0 deletions drivers/wifi/nrf_wifi/inc/wifi_mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,7 @@ int nrf_wifi_set_rts_threshold(const struct device *dev,

int nrf_wifi_get_rts_threshold(const struct device *dev,
unsigned int *rts_threshold);

int nrf_wifi_set_bss_max_idle_period(const struct device *dev,
unsigned short bss_max_idle_period);
#endif /* __ZEPHYR_WIFI_MGMT_H__ */
4 changes: 4 additions & 0 deletions drivers/wifi/nrf_wifi/src/fmac_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,9 @@ static int nrf_wifi_drv_main_zep(const struct device *dev)
#endif /* CONFIG_NRF70_RADIO_TEST */

k_mutex_init(&rpu_drv_priv_zep.rpu_ctx_zep.rpu_lock);
#ifndef CONFIG_NRF70_RADIO_TEST
vif_ctx_zep->bss_max_idle_period = USHRT_MAX;
#endif /* !CONFIG_NRF70_RADIO_TEST */
return 0;
#ifdef CONFIG_NRF70_RADIO_TEST
fmac_deinit:
Expand All @@ -865,6 +868,7 @@ static const struct wifi_mgmt_ops nrf_wifi_mgmt_ops = {
.get_power_save_config = nrf_wifi_get_power_save_config,
.set_rts_threshold = nrf_wifi_set_rts_threshold,
.get_rts_threshold = nrf_wifi_get_rts_threshold,
.set_bss_max_idle_period = nrf_wifi_set_bss_max_idle_period,
#endif
#ifdef CONFIG_NRF70_SYSTEM_WITH_RAW_MODES
.mode = nrf_wifi_mode,
Expand Down
53 changes: 53 additions & 0 deletions drivers/wifi/nrf_wifi/src/wifi_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1080,3 +1080,56 @@ int nrf_wifi_get_rts_threshold(const struct device *dev,

return ret;
}

int nrf_wifi_set_bss_max_idle_period(const struct device *dev,
unsigned short bss_max_idle_period)
{
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
int ret = -1;

if (!dev) {
LOG_ERR("%s: dev is NULL", __func__);
return ret;
}

vif_ctx_zep = dev->data;

if (!vif_ctx_zep) {
LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
return ret;
}

rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;

if (!rpu_ctx_zep) {
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
return ret;
}


if (!rpu_ctx_zep->rpu_ctx) {
LOG_ERR("%s: RPU context not initialized", __func__);
return ret;
}

if (((int)bss_max_idle_period < 0) ||
(bss_max_idle_period > 64000)) {
/* 0 or value less than 64000 is passed to f/w.
* All other values considered as invalid.
*/
LOG_ERR("%s: Invalid max_idle_period value : %d",
__func__, (int)bss_max_idle_period);
return ret;
}

k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);

vif_ctx_zep->bss_max_idle_period = bss_max_idle_period;

ret = 0;

k_mutex_unlock(&vif_ctx_zep->vif_lock);

return ret;
}
6 changes: 4 additions & 2 deletions drivers/wifi/nrf_wifi/src/wpa_supp_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,8 +931,10 @@ int nrf_wifi_wpa_supp_associate(void *if_priv, struct wpa_driver_associate_param
assoc_info.use_mfp = NRF_WIFI_MFP_REQUIRED;
}

if (params->bss_max_idle_period) {
assoc_info.bss_max_idle_time = params->bss_max_idle_period;
if (vif_ctx_zep->bss_max_idle_period == USHRT_MAX) {
assoc_info.bss_max_idle_time = CONFIG_WIFI_MGMT_BSS_MAX_IDLE_TIME;
} else {
assoc_info.bss_max_idle_time = vif_ctx_zep->bss_max_idle_period;
}

status = nrf_wifi_sys_fmac_assoc(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx, &assoc_info);
Expand Down
16 changes: 16 additions & 0 deletions include/zephyr/net/wifi_mgmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ enum net_request_wifi_cmd {
NET_REQUEST_WIFI_CMD_CANDIDATE_SCAN,
/** AP WPS config */
NET_REQUEST_WIFI_CMD_AP_WPS_CONFIG,
/** Configure BSS maximum idle period */
NET_REQUEST_WIFI_CMD_BSS_MAX_IDLE_PERIOD,
/** @cond INTERNAL_HIDDEN */
NET_REQUEST_WIFI_CMD_MAX
/** @endcond */
Expand Down Expand Up @@ -317,6 +319,11 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_START_ROAMING);

NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_NEIGHBOR_REP_COMPLETE);

#define NET_REQUEST_WIFI_BSS_MAX_IDLE_PERIOD \
(NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_BSS_MAX_IDLE_PERIOD)

NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_BSS_MAX_IDLE_PERIOD);

/** @cond INTERNAL_HIDDEN */

enum {
Expand Down Expand Up @@ -1598,6 +1605,15 @@ struct wifi_mgmt_ops {
* @return 0 if ok, < 0 if error
*/
int (*start_11r_roaming)(const struct device *dev);
/** Set BSS max idle period
*
* @param dev Pointer to the device structure for the driver instance.
* @param BSS max idle period value
*
* @return 0 if ok, < 0 if error
*/
int (*set_bss_max_idle_period)(const struct device *dev,
unsigned short bss_max_idle_period);
};

/** Wi-Fi management offload API */
Expand Down
13 changes: 13 additions & 0 deletions modules/hostap/src/supp_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1772,6 +1772,19 @@ int supplicant_legacy_roam(const struct device *dev)
return ret;
}

int supplicant_set_bss_max_idle_period(const struct device *dev,
unsigned short bss_max_idle_period)
{
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev);

if (!wifi_mgmt_api || !wifi_mgmt_api->set_bss_max_idle_period) {
wpa_printf(MSG_ERROR, "set_bss_max_idle_period is not supported");
return -ENOTSUP;
}

return wifi_mgmt_api->set_bss_max_idle_period(dev, bss_max_idle_period);
}

#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM
int supplicant_btm_query(const struct device *dev, uint8_t reason)
{
Expand Down
8 changes: 8 additions & 0 deletions modules/hostap/src/supp_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,14 @@ int supplicant_get_wifi_conn_params(const struct device *dev,
*/
int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_params *params);

/** @ Set Wi-Fi max idle period
*
* @param dev Wi-Fi interface handle to use
* @param bss_max_idle_period Maximum idle period to set
* @return 0 for OK; -1 for ERROR
*/
int supplicant_set_bss_max_idle_period(const struct device *dev,
unsigned short bss_max_idle_period);
#ifdef CONFIG_AP
int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth);

Expand Down
1 change: 1 addition & 0 deletions modules/hostap/src/supp_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static const struct wifi_mgmt_ops mgmt_ops = {
#endif
.get_conn_params = supplicant_get_wifi_conn_params,
.wps_config = supplicant_wps_config,
.set_bss_max_idle_period = supplicant_set_bss_max_idle_period,
#ifdef CONFIG_AP
.ap_enable = supplicant_ap_enable,
.ap_disable = supplicant_ap_disable,
Expand Down
16 changes: 16 additions & 0 deletions subsys/net/l2/wifi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,19 @@ config HEAP_MEM_POOL_ADD_SIZE_WIFI_CERT
endif # WIFI_SHELL_RUNTIME_CERTIFICATES

endif # WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE

config WIFI_MGMT_BSS_MAX_IDLE_TIME
int "BSS max idle timeout in seconds"
range 0 64000
default 300
help
As per 802.11-2020: 11.21.13 BSS max idle period management
If dot11WirelessManagementImplemented is true, dot11BSSMaxIdlePeriod is
nonzero and dot11BSSMaxIdlePeriodIndicationByNonAPSTA is true, then a
non-S1G non-AP STA shall include a BSS Max Idle Period element
in the (Re)Association Request frame. If the BSS Max Idle Period
element is present in the (Re)Association Request frame received
by a non-S1G AP that has dot11BSSMaxIdlePeriodIndicationByNonAPSTA
equal to true, then the non-S1G AP may choose the non-AP STA’s
preferred maximum idle period. The non-S1G AP indicates its chosen
value to the non-S1G STA in the (Re)Association Response frame.
25 changes: 25 additions & 0 deletions subsys/net/l2/wifi/wifi_mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,31 @@ static int wifi_set_enterprise_creds(uint64_t mgmt_request, struct net_if *iface
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_ENTERPRISE_CREDS, wifi_set_enterprise_creds);
#endif

static int wifi_set_bss_max_idle_period(uint64_t mgmt_request, struct net_if *iface,
void *data, size_t len)
{
const struct device *dev = net_if_get_device(iface);
const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface);
unsigned short *bss_max_idle_period = data;

if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_bss_max_idle_period == NULL) {
return -ENOTSUP;
}

if (!net_if_is_admin_up(iface)) {
return -ENETDOWN;
}

if (!data || len != sizeof(*bss_max_idle_period)) {
return -EINVAL;
}

return wifi_mgmt_api->set_bss_max_idle_period(dev, *bss_max_idle_period);
}

NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_BSS_MAX_IDLE_PERIOD,
wifi_set_bss_max_idle_period);

#ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface,
struct wifi_raw_scan_result *raw_scan_result)
Expand Down
32 changes: 32 additions & 0 deletions subsys/net/l2/wifi/wifi_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -3807,6 +3807,32 @@ static int cmd_wifi_pmksa_flush(const struct shell *sh, size_t argc, char *argv[

return 0;
}

static int cmd_wifi_set_bss_max_idle_period(const struct shell *sh, size_t argc, char *argv[])
{
struct net_if *iface = get_iface(IFACE_TYPE_STA, argc, argv);
unsigned short bss_max_idle_period = 0;
int idx = 1;
unsigned long val = 0;

if (!parse_number(sh, &val, argv[idx++], "bss_max_idle_period", 0, USHRT_MAX)) {
return -EINVAL;
}

bss_max_idle_period = (unsigned short)val;

if (net_mgmt(NET_REQUEST_WIFI_BSS_MAX_IDLE_PERIOD, iface,
&bss_max_idle_period, sizeof(bss_max_idle_period))) {
shell_fprintf(sh, SHELL_WARNING,
"Setting BSS maximum idle period failed.\n");
return -ENOEXEC;
}

shell_fprintf(sh, SHELL_NORMAL, "BSS max idle period: %hu\n", bss_max_idle_period);

return 0;
}

SHELL_STATIC_SUBCMD_SET_CREATE(
wifi_cmd_ap,
SHELL_CMD_ARG(disable, NULL, "Disable Access Point mode.\n"
Expand Down Expand Up @@ -4285,6 +4311,12 @@ SHELL_SUBCMD_ADD((wifi), ps_exit_strategy, NULL,
cmd_wifi_ps_exit_strategy,
2, 2);

SHELL_SUBCMD_ADD((wifi), bss_max_idle_period, NULL,
"<BSS max idle period preference: timeout(in seconds)>.\n"
"[-i, --iface=<interface index>] : Interface index.\n",
cmd_wifi_set_bss_max_idle_period,
2, 2);

SHELL_CMD_REGISTER(wifi, &wifi_commands, "Wi-Fi commands", NULL);

static int wifi_shell_init(void)
Expand Down
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ manifest:
- hal
- name: hostap
path: modules/lib/hostap
revision: cf270006050cf944af699301c7f4de2b427cd862
revision: pull/89/head
- name: liblc3
revision: 48bbd3eacd36e99a57317a0a4867002e0b09e183
path: modules/lib/liblc3
Expand Down
Loading