diff --git a/boards/nordic/nrf7002dk/nrf70_common.dtsi b/boards/nordic/nrf7002dk/nrf70_common.dtsi index cd9cd23bb892e..721826c88553f 100644 --- a/boards/nordic/nrf7002dk/nrf70_common.dtsi +++ b/boards/nordic/nrf7002dk/nrf70_common.dtsi @@ -13,6 +13,10 @@ wifi-max-tx-pwr-2g-dsss = <21>; wifi-max-tx-pwr-2g-mcs0 = <16>; wifi-max-tx-pwr-2g-mcs7 = <16>; -wlan0: wlan { +wlan0: wlan0 { + compatible = "nordic,wlan"; +}; + +wlan1: wlan1 { compatible = "nordic,wlan"; }; diff --git a/boards/shields/nrf7002eb/nrf7002eb.overlay b/boards/shields/nrf7002eb/nrf7002eb.overlay index 7f9074da9d0c8..3a09ef8158d99 100644 --- a/boards/shields/nrf7002eb/nrf7002eb.overlay +++ b/boards/shields/nrf7002eb/nrf7002eb.overlay @@ -30,6 +30,10 @@ compatible = "nordic,wlan"; }; + wlan1: wlan1 { + compatible = "nordic,wlan"; + }; + wifi-max-tx-pwr-2g-dsss = <21>; wifi-max-tx-pwr-2g-mcs0 = <16>; wifi-max-tx-pwr-2g-mcs7 = <16>; diff --git a/boards/shields/nrf7002ek/nrf7002ek_common.dtsi b/boards/shields/nrf7002ek/nrf7002ek_common.dtsi index c9bbbde4b9269..6c3d4ede81ed8 100644 --- a/boards/shields/nrf7002ek/nrf7002ek_common.dtsi +++ b/boards/shields/nrf7002ek/nrf7002ek_common.dtsi @@ -26,3 +26,7 @@ wifi-max-tx-pwr-2g-mcs7 = <16>; wlan0: wlan0 { compatible = "nordic,wlan"; }; + +wlan1: wlan1 { + compatible = "nordic,wlan"; +}; diff --git a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi index e0a39f2123e1b..271984be27bf3 100644 --- a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi +++ b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi @@ -108,6 +108,15 @@ config NRF70_AP_MODE depends on WIFI_NM_WPA_SUPPLICANT_AP default y if WIFI_USAGE_MODE_AP || WIFI_USAGE_MODE_STA_AP +config NRF70_ENABLE_DUAL_VIF + bool "Dual virtual Wi-Fi interfaces" + default y if WIFI_NM_MAX_MANAGED_INTERFACES = 2 + depends on (WIFI_NRF7002 || WIFI_NRF7001) && NET_L2_ETHERNET + help + Enable support for two virtual Wi-Fi interfaces (VIFs). + When enabled, the driver can operate two VIFs simultaneously, + allowing use cases such as one interface in AP mode and another in STA mode. + config NRF70_P2P_MODE bool "P2P support in driver" diff --git a/drivers/wifi/nrf_wifi/src/fmac_main.c b/drivers/wifi/nrf_wifi/src/fmac_main.c index 72055fb02993b..49564b89f4e83 100644 --- a/drivers/wifi/nrf_wifi/src/fmac_main.c +++ b/drivers/wifi/nrf_wifi/src/fmac_main.c @@ -725,7 +725,19 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) struct nrf_wifi_data_config_params data_config = { 0 }; struct rx_buf_pool_params rx_buf_pools[MAX_NUM_OF_RX_QUEUES]; struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = dev->data; + static unsigned int vif_ctx_cnt; + if (vif_ctx_cnt >= MAX_NUM_VIFS) { + LOG_ERR("%s: Max number of VIFs reached", __func__); + return -ENOMEM; + } + + if (vif_ctx_cnt >= 1) { + /* FMAC is already initialized for VIF-0 */ + return 0; + } + + ++vif_ctx_cnt; vif_ctx_zep->rpu_ctx_zep = &rpu_drv_priv_zep.rpu_ctx_zep; #ifdef CONFIG_NRF70_DATA_TX @@ -953,6 +965,21 @@ ETH_NET_DEVICE_DT_INST_DEFINE(0, CONFIG_WIFI_INIT_PRIORITY, /* prio */ &wifi_offload_ops, /* api */ CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */ +#ifdef CONFIG_NRF70_ENABLE_DUAL_VIF +/* Register second interface */ +ETH_NET_DEVICE_DT_INST_DEFINE(1, + nrf_wifi_drv_main_zep, /* init_fn */ + NULL, /* pm_action_cb */ + &rpu_drv_priv_zep.rpu_ctx_zep.vif_ctx_zep[1], /* data */ +#ifdef CONFIG_NRF70_STA_MODE + &wpa_supp_ops, /* cfg */ +#else /* CONFIG_NRF70_STA_MODE */ + NULL, /* cfg */ +#endif /* !CONFIG_NRF70_STA_MODE */ + CONFIG_WIFI_INIT_PRIORITY, /* prio */ + &wifi_offload_ops, /* api */ + CONFIG_NRF_WIFI_IFACE_MTU); /*mtu */ +#endif /* NRF70_ENABLE_DUAL_VIF */ #else DEVICE_DT_INST_DEFINE(0, nrf_wifi_drv_main_zep, /* init_fn */ diff --git a/drivers/wifi/nrf_wifi/src/net_if.c b/drivers/wifi/nrf_wifi/src/net_if.c index 19101fab442ef..8f1a44a9f7748 100644 --- a/drivers/wifi/nrf_wifi/src/net_if.c +++ b/drivers/wifi/nrf_wifi/src/net_if.c @@ -794,8 +794,7 @@ int nrf_wifi_if_start_zep(const struct device *dev) } k_mutex_init(&vif_ctx_zep->vif_lock); - rpu_ctx_zep->vif_ctx_zep[vif_ctx_zep->vif_idx].if_type = - add_vif_info.iftype; + vif_ctx_zep->if_type = add_vif_info.iftype; /* Check if user has provided a valid MAC address, if not * fetch it from OTP. diff --git a/drivers/wifi/nrf_wifi/src/wpa_supp_if.c b/drivers/wifi/nrf_wifi/src/wpa_supp_if.c index d06f0792fa28e..43664da204b74 100644 --- a/drivers/wifi/nrf_wifi/src/wpa_supp_if.c +++ b/drivers/wifi/nrf_wifi/src/wpa_supp_if.c @@ -447,7 +447,10 @@ void *nrf_wifi_wpa_supp_dev_init(void *supp_drv_if_ctx, const char *iface_name, struct zep_wpa_supp_dev_callbk_fns *supp_callbk_fns) { struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; - const struct device *device = DEVICE_DT_GET(DT_CHOSEN(zephyr_wifi)); + /* Get device for each interface */ + int if_idx = net_if_get_by_name(iface_name); + struct net_if *iface = net_if_get_by_index(if_idx); + const struct device *device = net_if_get_device(iface); if (!device) { LOG_ERR("%s: Interface %s not found", __func__, iface_name); diff --git a/lib/os/Kconfig b/lib/os/Kconfig index 004df87ccf390..bca940023c6e5 100644 --- a/lib/os/Kconfig +++ b/lib/os/Kconfig @@ -12,6 +12,7 @@ config FDTABLE config ZVFS_OPEN_MAX int "Maximum number of open file descriptors" + default 24 if NRF70_ENABLE_DUAL_VIF default 16 if WIFI_NM_WPA_SUPPLICANT default 16 if POSIX_API default 4 diff --git a/lib/os/zvfs/Kconfig b/lib/os/zvfs/Kconfig index 101e2cce08640..09192ddc30df8 100644 --- a/lib/os/zvfs/Kconfig +++ b/lib/os/zvfs/Kconfig @@ -44,6 +44,7 @@ if ZVFS_POLL config ZVFS_POLL_MAX int "Max number of supported zvfs_poll() entries" default NET_SOCKETS_POLL_MAX if NET_SOCKETS_POLL_MAX > 0 + default 8 if NRF70_ENABLE_DUAL_VIF default 6 if WIFI_NM_WPA_SUPPLICANT default 4 if SHELL_BACKEND_TELNET default 3 diff --git a/modules/hostap/src/supp_api.c b/modules/hostap/src/supp_api.c index 4f82068385cda..c6bab2ab4718d 100644 --- a/modules/hostap/src/supp_api.c +++ b/modules/hostap/src/supp_api.c @@ -80,20 +80,19 @@ static void supp_shell_connect_status(struct k_work *work); static K_WORK_DELAYABLE_DEFINE(wpa_supp_status_work, supp_shell_connect_status); -#define wpa_cli_cmd_v(cmd, ...) ({ \ - bool status; \ - \ - if (zephyr_wpa_cli_cmd_v(cmd, ##__VA_ARGS__) < 0) { \ - wpa_printf(MSG_ERROR, \ - "Failed to execute wpa_cli command: %s", \ - cmd); \ - status = false; \ - } else { \ - status = true; \ - } \ - \ - status; \ -}) +#define wpa_cli_cmd_v(cmd, ...) \ + ({ \ + bool status; \ + \ + if (zephyr_wpa_cli_cmd_v(wpa_s->ctrl_conn, cmd, ##__VA_ARGS__) < 0) { \ + wpa_printf(MSG_ERROR, "Failed to execute wpa_cli command: %s", cmd); \ + status = false; \ + } else { \ + status = true; \ + } \ + \ + status; \ + }) static struct wpa_supplicant *get_wpa_s_handle(const struct device *dev) { @@ -622,7 +621,7 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s, goto out; } - ret = z_wpa_ctrl_add_network(&resp); + ret = z_wpa_ctrl_add_network(wpa_s->ctrl_conn, &resp); if (ret) { wpa_printf(MSG_ERROR, "Failed to add network"); goto out; @@ -1313,7 +1312,7 @@ int supplicant_status(const struct device *dev, struct wifi_iface_status *status status->channel = channel; if (ssid_len == 0) { - int _res = z_wpa_ctrl_status(&cli_status); + int _res = z_wpa_ctrl_status(wpa_s->ctrl_conn, &cli_status); if (_res < 0) { ssid_len = 0; @@ -1342,7 +1341,7 @@ int supplicant_status(const struct device *dev, struct wifi_iface_status *status status->rssi = -WPA_INVALID_NOISE; if (status->iface_mode == WIFI_MODE_INFRA) { - ret = z_wpa_ctrl_signal_poll(&signal_poll); + ret = z_wpa_ctrl_signal_poll(wpa_s->ctrl_conn, &signal_poll); if (!ret) { status->rssi = signal_poll.rssi; status->current_phy_tx_rate = signal_poll.current_txrate; @@ -1492,6 +1491,7 @@ int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params) int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params) { int ssid_len = strlen(params->ssid); + struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev); if (params != NULL && ssid_len > 0) { if (ssid_len > WIFI_SSID_MAX_LEN) { @@ -1758,6 +1758,7 @@ int supplicant_bss_ext_capab(const struct device *dev, int capab) int supplicant_legacy_roam(const struct device *dev) { int ret = -1; + struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev); k_mutex_lock(&wpa_supplicant_mutex, K_FOREVER); if (!wpa_cli_cmd_v("scan")) { @@ -1866,7 +1867,7 @@ static int supplicant_wps_pin(const struct device *dev, struct wifi_wps_config_p } if (params->oper == WIFI_WPS_PIN_GET) { - if (zephyr_wpa_cli_cmd_resp(get_pin_cmd, params->pin)) { + if (zephyr_wpa_cli_cmd_resp(wpa_s->ctrl_conn, get_pin_cmd, params->pin)) { goto out; } } else if (params->oper == WIFI_WPS_PIN_SET) { @@ -2299,6 +2300,7 @@ int supplicant_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *pa { int ret; char *cmd = NULL; + struct wpa_supplicant *wpa_s = get_wpa_s_handle(dev); if (params == NULL) { return -EINVAL; @@ -2317,7 +2319,7 @@ int supplicant_dpp_dispatch(const struct device *dev, struct wifi_dpp_params *pa } wpa_printf(MSG_DEBUG, "wpa_cli %s", cmd); - if (zephyr_wpa_cli_cmd_resp(cmd, params->resp)) { + if (zephyr_wpa_cli_cmd_resp(wpa_s->ctrl_conn, cmd, params->resp)) { os_free(cmd); return -ENOEXEC; } diff --git a/modules/hostap/src/supp_main.h b/modules/hostap/src/supp_main.h index 60ac642f9c797..2b2d5fc61112a 100644 --- a/modules/hostap/src/supp_main.h +++ b/modules/hostap/src/supp_main.h @@ -58,8 +58,6 @@ struct wpa_supplicant *zephyr_get_handle_by_ifname(const char *ifname); struct hapd_interfaces *zephyr_get_default_hapd_context(void); #endif -struct wpa_supplicant *zephyr_get_handle_by_ifname(const char *ifname); - struct wpa_supplicant_event_msg { #ifdef CONFIG_WIFI_NM_HOSTAPD_AP int hostapd; diff --git a/modules/hostap/src/wpa_cli.c b/modules/hostap/src/wpa_cli.c index 406008da101aa..0e1b41728b749 100644 --- a/modules/hostap/src/wpa_cli.c +++ b/modules/hostap/src/wpa_cli.c @@ -8,10 +8,17 @@ * @brief wpa_cli implementation for Zephyr OS */ +#include #include #include +#include #include + +#include "supp_main.h" + +#include "common.h" +#include "wpa_supplicant_i.h" #include "wpa_cli_zephyr.h" #ifdef CONFIG_WIFI_NM_HOSTAPD_AP #include "hostapd_cli_zephyr.h" @@ -21,8 +28,20 @@ static int cmd_wpa_cli(const struct shell *sh, size_t argc, const char *argv[]) { + struct net_if *iface = net_if_get_first_wifi(); + char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; + struct wpa_supplicant *wpa_s = NULL; + ARG_UNUSED(sh); + if (iface == NULL) { + shell_error(sh, "No Wifi interface found"); + return -ENOENT; + } + + net_if_get_name(iface, if_name, sizeof(if_name)); + wpa_s = zephyr_get_handle_by_ifname(if_name); + if (argc == 1) { shell_error(sh, "Missing argument"); return -EINVAL; @@ -32,7 +51,7 @@ static int cmd_wpa_cli(const struct shell *sh, argc++; /* Remove wpa_cli from the argument list */ - return zephyr_wpa_ctrl_zephyr_cmd(argc - 1, &argv[1]); + return zephyr_wpa_ctrl_zephyr_cmd(wpa_s->ctrl_conn, argc - 1, &argv[1]); } #ifdef CONFIG_WIFI_NM_HOSTAPD_AP diff --git a/subsys/net/ip/Kconfig.ipv4 b/subsys/net/ip/Kconfig.ipv4 index 842a02edd7b5e..f4467db0aa05c 100644 --- a/subsys/net/ip/Kconfig.ipv4 +++ b/subsys/net/ip/Kconfig.ipv4 @@ -14,6 +14,7 @@ if NET_IPV4 config NET_IF_MAX_IPV4_COUNT int "Max number of IPv4 network interfaces in the system" default NET_VLAN_COUNT if NET_VLAN && NET_VLAN_COUNT > 0 + default 2 if NRF70_ENABLE_DUAL_VIF default 2 if NET_LOOPBACK default 1 help diff --git a/subsys/net/ip/Kconfig.ipv6 b/subsys/net/ip/Kconfig.ipv6 index 017061b974a27..02cd410e27a2a 100644 --- a/subsys/net/ip/Kconfig.ipv6 +++ b/subsys/net/ip/Kconfig.ipv6 @@ -16,6 +16,7 @@ if NET_IPV6 config NET_IF_MAX_IPV6_COUNT int "Max number of IPv6 network interfaces in the system" default NET_VLAN_COUNT if NET_VLAN && NET_VLAN_COUNT > 0 + default 2 if NRF70_ENABLE_DUAL_VIF default 2 if NET_LOOPBACK default 1 help diff --git a/west.yml b/west.yml index d1de5eea80281..4b322a20d3ce4 100644 --- a/west.yml +++ b/west.yml @@ -281,7 +281,7 @@ manifest: - hal - name: hostap path: modules/lib/hostap - revision: cf270006050cf944af699301c7f4de2b427cd862 + revision: pull/80/head - name: liblc3 revision: 48bbd3eacd36e99a57317a0a4867002e0b09e183 path: modules/lib/liblc3