diff --git a/drivers/wifi/nxp/nxp_wifi_drv.c b/drivers/wifi/nxp/nxp_wifi_drv.c index 71041c3360e..48f440831b4 100644 --- a/drivers/wifi/nxp/nxp_wifi_drv.c +++ b/drivers/wifi/nxp/nxp_wifi_drv.c @@ -1055,6 +1055,17 @@ static void nxp_wifi_auto_connect(void) } #endif +static int nxp_wifi_11k_cfg(const struct device *dev, struct wifi_11k_params *params) +{ + if (params->oper == WIFI_MGMT_GET) { + params->enable_11k = wlan_get_host_11k_status(); + } else { + wlan_host_11k_cfg(params->enable_11k); + } + + return 0; +} + static int nxp_wifi_power_save(const struct device *dev, struct wifi_ps_params *params) { int status = NXP_WIFI_RET_SUCCESS; @@ -1640,6 +1651,7 @@ static const struct wifi_mgmt_ops nxp_wifi_sta_mgmt = { #if defined(CONFIG_NET_STATISTICS_WIFI) .get_stats = nxp_wifi_stats, #endif + .cfg_11k = nxp_wifi_11k_cfg, .set_power_save = nxp_wifi_power_save, .get_power_save_config = nxp_wifi_get_power_save, .set_twt = nxp_wifi_set_twt, diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index bdf3bab48bd..b4d230abfdb 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -71,6 +71,10 @@ enum net_request_wifi_cmd { NET_REQUEST_WIFI_CMD_AP_DISABLE, /** Get interface status */ NET_REQUEST_WIFI_CMD_IFACE_STATUS, + /** Set or get 11k status */ + NET_REQUEST_WIFI_CMD_11K_CONFIG, + /** Send 11k neighbor request */ + NET_REQUEST_WIFI_CMD_11K_NEIGHBOR_REQUEST, /** Set power save status */ NET_REQUEST_WIFI_CMD_PS, /** Setup or teardown TWT flow */ @@ -154,6 +158,16 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE); NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_IFACE_STATUS); +#define NET_REQUEST_WIFI_11K_CONFIG \ + (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_11K_CONFIG) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_11K_CONFIG); + +#define NET_REQUEST_WIFI_11K_NEIGHBOR_REQUEST \ + (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_11K_NEIGHBOR_REQUEST) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_11K_NEIGHBOR_REQUEST); + /** Request a Wi-Fi power save */ #define NET_REQUEST_WIFI_PS \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PS) @@ -769,6 +783,16 @@ enum wifi_mgmt_op { WIFI_MGMT_SET = 1, }; +/** Wi-Fi 11k parameters */ +struct wifi_11k_params { + /** 11k command operation */ + enum wifi_mgmt_op oper; + /** 11k enable/disable */ + bool enable_11k; + /** SSID */ + uint8_t ssid[WIFI_SSID_MAX_LEN + 1]; +}; + /** Max regulatory channel number */ #define MAX_REG_CHAN_NUM 42 @@ -1227,6 +1251,22 @@ struct wifi_mgmt_ops { */ int (*reset_stats)(const struct device *dev); #endif /* CONFIG_NET_STATISTICS_WIFI */ + /** Set or get 11K status + * + * @param dev Pointer to the device structure for the driver instance. + * @param params 11k parameters + * + * @return 0 if ok, < 0 if error + */ + int (*cfg_11k)(const struct device *dev, struct wifi_11k_params *params); + /** Send 11k neighbor request + * + * @param dev Pointer to the device structure for the driver instance. + * @param params 11k parameters + * + * @return 0 if ok, < 0 if error + */ + int (*send_11k_neighbor_request)(const struct device *dev, struct wifi_11k_params *params); /** Set power save status * * @param dev Pointer to the device structure for the driver instance. diff --git a/modules/hostap/src/supp_api.c b/modules/hostap/src/supp_api.c index 52772b4becf..c8674a02716 100644 --- a/modules/hostap/src/supp_api.c +++ b/modules/hostap/src/supp_api.c @@ -1384,6 +1384,48 @@ out: return ret; } +int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params) +{ + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev); + + if (!wifi_mgmt_api || !wifi_mgmt_api->cfg_11k) { + wpa_printf(MSG_ERROR, "cfg 11k not supported"); + return -ENOTSUP; + } + + return wifi_mgmt_api->cfg_11k(dev, params); +} + +int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params) +{ + int ssid_len = strlen(params->ssid); + + if (params != NULL && ssid_len > 0) { + if (ssid_len > WIFI_SSID_MAX_LEN) { + wpa_printf(MSG_ERROR, "%s: ssid too long %u", + __func__, ssid_len); + return -1; + } + + if (!wpa_cli_cmd_v("neighbor_rep_request ssid %s", + params->ssid)) { + wpa_printf(MSG_ERROR, + "%s: cli cmd fail", + __func__, params->ssid); + return -1; + } + } else { + if (!wpa_cli_cmd_v("neighbor_rep_request")) { + wpa_printf(MSG_ERROR, + "%s: cli cmd fail", + __func__); + return -1; + } + } + + return 0; +} + int supplicant_set_power_save(const struct device *dev, struct wifi_ps_params *params) { const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev); diff --git a/modules/hostap/src/supp_api.h b/modules/hostap/src/supp_api.h index f6584d86126..b04824c3d5e 100644 --- a/modules/hostap/src/supp_api.h +++ b/modules/hostap/src/supp_api.h @@ -100,6 +100,24 @@ int supplicant_reset_stats(const struct device *dev); */ int supplicant_pmksa_flush(const struct device *dev); +/** Set or get 11K status + * + * @param dev Pointer to the device structure for the driver instance. + * @param params 11k parameters + * + * @return 0 if ok, < 0 if error + */ +int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params); + +/** Send 11k neighbor request + * + * @param dev Pointer to the device structure for the driver instance. + * @param params 11k parameters + * + * @return 0 if ok, < 0 if error + */ +int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params); + /** * @brief Set Wi-Fi power save configuration * diff --git a/modules/hostap/src/supp_main.c b/modules/hostap/src/supp_main.c index 826e15e9d8d..aa1530a1099 100644 --- a/modules/hostap/src/supp_main.c +++ b/modules/hostap/src/supp_main.c @@ -62,6 +62,8 @@ static const struct wifi_mgmt_ops mgmt_ops = { .get_stats = supplicant_get_stats, .reset_stats = supplicant_reset_stats, #endif + .cfg_11k = supplicant_11k_cfg, + .send_11k_neighbor_request = supplicant_11k_neighbor_request, .set_power_save = supplicant_set_power_save, .set_twt = supplicant_set_twt, .get_power_save_config = supplicant_get_power_save_config, diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index a1a84f9dcbb..7439f7d6338 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -555,6 +555,39 @@ static int wifi_iface_stats_reset(uint32_t mgmt_request, struct net_if *iface, NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_RESET_WIFI, wifi_iface_stats_reset); #endif /* CONFIG_NET_STATISTICS_WIFI */ +static int wifi_11k_cfg(uint32_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); + struct wifi_11k_params *params = data; + + if (wifi_mgmt_api == NULL || wifi_mgmt_api->cfg_11k == NULL) { + return -ENOTSUP; + } + + return wifi_mgmt_api->cfg_11k(dev, params); +} + +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_11K_CONFIG, wifi_11k_cfg); + +static int wifi_11k_neighbor_request(uint32_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); + struct wifi_11k_params *params = data; + + if (wifi_mgmt_api == NULL || wifi_mgmt_api->send_11k_neighbor_request == NULL) { + return -ENOTSUP; + } + + return wifi_mgmt_api->send_11k_neighbor_request(dev, params); +} + +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_11K_NEIGHBOR_REQUEST, + wifi_11k_neighbor_request); + static int wifi_set_power_save(uint32_t mgmt_request, struct net_if *iface, void *data, size_t len) { diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 75fec48b0bd..6696dd9c147 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -1172,6 +1172,84 @@ static int cmd_wifi_stats(const struct shell *sh, size_t argc, char *argv[]) return 0; } +static int cmd_wifi_11k(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface = net_if_get_first_wifi(); + struct wifi_11k_params params = { 0 }; + + context.sh = sh; + + if (argc > 2) { + PR_WARNING("Invalid number of arguments\n"); + return -ENOEXEC; + } + + if (argc == 1) { + params.oper = WIFI_MGMT_GET; + } else { + params.oper = WIFI_MGMT_SET; + if (!strncasecmp(argv[1], "enable", 2)) { + params.enable_11k = true; + } else if (!strncasecmp(argv[1], "disable", 3)) { + params.enable_11k = false; + } else { + PR_WARNING("Invalid argument\n"); + return -ENOEXEC; + } + } + + if (net_mgmt(NET_REQUEST_WIFI_11K_CONFIG, iface, ¶ms, sizeof(params))) { + PR_WARNING("11k enable/disable failed\n"); + return -ENOEXEC; + } + + if (params.oper == WIFI_MGMT_GET) { + PR("11k is %s\n", params.enable_11k ? "disabled" : "enabled"); + } else { + PR("%s %s requested\n", argv[0], argv[1]); + } + + return 0; +} + + +static int cmd_wifi_11k_neighbor_request(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface = net_if_get_first_wifi(); + struct wifi_11k_params params = { 0 }; + + context.sh = sh; + + if ((argc != 1 && argc != 3) || (argc == 3 && !strncasecmp("ssid", argv[1], 4))) { + PR_WARNING("Invalid input arguments\n"); + PR_WARNING("Usage: %s\n", argv[0]); + PR_WARNING("or %s ssid \n", argv[0]); + return -ENOEXEC; + } + + if (argc == 3) { + if (strlen(argv[2]) > (sizeof(params.ssid) - 1)) { + PR_WARNING("Error: ssid too long\n"); + return -ENOEXEC; + } + (void)memcpy((void *)params.ssid, (const void *)argv[2], + (size_t)strlen(argv[2])); + } + + if (net_mgmt(NET_REQUEST_WIFI_11K_NEIGHBOR_REQUEST, iface, ¶ms, sizeof(params))) { + PR_WARNING("11k neighbor request failed\n"); + return -ENOEXEC; + } + + if (argc == 3) { + PR("%s %s %s requested\n", argv[0], argv[1], argv[2]); + } else { + PR("%s requested\n", argv[0]); + } + + return 0; +} + static int cmd_wifi_ps(const struct shell *sh, size_t argc, char *argv[]) { struct net_if *iface = net_if_get_first_wifi(); @@ -3057,6 +3135,18 @@ SHELL_SUBCMD_ADD((wifi), dpp, &wifi_cmd_dpp, SHELL_SUBCMD_SET_CREATE(wifi_commands, (wifi)); +SHELL_SUBCMD_ADD((wifi), 11k, &wifi_commands, + "Configure 11k or get 11k status.\n" + "[enable/disable]\n", + cmd_wifi_11k, + 1, 1); + +SHELL_SUBCMD_ADD((wifi), 11k_neighbor_request, &wifi_commands, + "Send Neighbor Report Request frame.\n" + "[ssid ]\n", + cmd_wifi_11k_neighbor_request, + 1, 2); + #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM SHELL_SUBCMD_ADD((wifi), 11v_btm_query, &wifi_commands, ".\n",