Skip to content

Commit

Permalink
WIP: drivers: wifi: native_sim: Driver update
Browse files Browse the repository at this point in the history
Still WIP. The driver starts ok and can pass supplicant
API calls from Zephyr to Linux (nl80211 driver) but does not
really "work" properly yet.

Signed-off-by: Jukka Rissanen <[email protected]>
  • Loading branch information
jukkar committed Nov 10, 2023
1 parent bdaca76 commit 4c8afa7
Show file tree
Hide file tree
Showing 9 changed files with 744 additions and 32 deletions.
93 changes: 92 additions & 1 deletion drivers/wifi/native_sim/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,101 @@
# SPDX-License-Identifier: Apache-2.0

# Use 32-bit version of pkg-config
set(PKG_CONFIG_EXECUTABLE i686-pc-linux-gnu-pkg-config)
find_package(PkgConfig)
pkg_check_modules(LIBNL REQUIRED libnl-3.0 libnl-genl-3.0)

zephyr_library_sources_ifdef(CONFIG_WIFI_NATIVE_SIM
wifi_drv.c
mgmt_api.c
iface_api.c
wifi_drv_api.c
)

target_sources(native_simulator INTERFACE wifi_drv_adapt.c)
set(HOSTAP_BASE ${ZEPHYR_HOSTAP_MODULE_DIR})
set(WIFI_NM_WPA_SUPPLICANT_BASE ${HOSTAP_BASE}/wpa_supplicant)
set(HOSTAP_SRC_BASE ${HOSTAP_BASE}/src)

target_sources(native_simulator INTERFACE
wifi_drv_adapt.c
wifi_drv_supplicant_adapt.c

${HOSTAP_SRC_BASE}/common/wpa_common.c
${HOSTAP_SRC_BASE}/common/ieee802_11_common.c
${HOSTAP_SRC_BASE}/common/hw_features_common.c
${HOSTAP_SRC_BASE}/common/wpa_ctrl.c
${HOSTAP_SRC_BASE}/common/cli.c
${HOSTAP_SRC_BASE}/common/ctrl_iface_common.c

${HOSTAP_SRC_BASE}/drivers/driver_common.c
${HOSTAP_SRC_BASE}/drivers/drivers.c
${HOSTAP_SRC_BASE}/drivers/netlink.c
${HOSTAP_SRC_BASE}/drivers/linux_ioctl.c
${HOSTAP_SRC_BASE}/drivers/rfkill.c
${HOSTAP_SRC_BASE}/drivers/driver_nl80211.c
${HOSTAP_SRC_BASE}/drivers/driver_nl80211_capa.c
${HOSTAP_SRC_BASE}/drivers/driver_nl80211_scan.c
${HOSTAP_SRC_BASE}/drivers/driver_nl80211_event.c
${HOSTAP_SRC_BASE}/drivers/driver_nl80211_monitor.c
${HOSTAP_SRC_BASE}/utils/radiotap.c
${HOSTAP_SRC_BASE}/utils/base64.c
${HOSTAP_SRC_BASE}/utils/common.c
${HOSTAP_SRC_BASE}/utils/wpabuf.c
${HOSTAP_SRC_BASE}/utils/bitfield.c
${HOSTAP_SRC_BASE}/utils/eloop.c
${HOSTAP_SRC_BASE}/utils/os_unix.c
${HOSTAP_SRC_BASE}/crypto/crypto_linux.c
${HOSTAP_SRC_BASE}/crypto/tls_none.c
${HOSTAP_SRC_BASE}/l2_packet/l2_packet_linux.c
${HOSTAP_SRC_BASE}/utils/wpa_debug.c

${WIFI_NM_WPA_SUPPLICANT_BASE}/config.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/notify.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/eap_register.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/op_classes.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/rrm.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/wmm_ac.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/config_none.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/bssid_ignore.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/wpas_glue.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/scan.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/ctrl_iface.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/ctrl_iface_unix.c

${WIFI_NM_WPA_SUPPLICANT_BASE}/bss.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/sme.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/wpa_supplicant.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/events.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/robust_av.c
# ${WIFI_NM_WPA_SUPPLICANT_BASE}/mbo.c
# ${WIFI_NM_WPA_SUPPLICANT_BASE}/wnm_sta.c
${WIFI_NM_WPA_SUPPLICANT_BASE}/wpa_cli_cmds.c
)

target_compile_options(native_simulator INTERFACE
"-I${WIFI_NM_WPA_SUPPLICANT_BASE}"
"-I${HOSTAP_BASE}"
"-I${HOSTAP_SRC_BASE}"
"-I${HOSTAP_SRC_BASE}/utils"
"-I${HOSTAP_SRC_BASE}/drivers"
"${LIBNL_CFLAGS}"
"-D_DEFAULT_SOURCE"
"-DCONFIG_CTRL_IFACE"
"-DCONFIG_SME"
# "-DCONFIG_WNM"
"-DCONFIG_NO_CONFIG_WRITE"
"-DCONFIG_NO_CONFIG_BLOBS"
"-DCONFIG_NO_RANDOM_POOL"
"-DCONFIG_NO_WPA"
"-DCONFIG_NO_PBKDF2"
"-DCONFIG_SHA256"
"-DCONFIG_SUITEB192"
"-DTLS_DEFAULT_CIPHERS=\"DEFAULT:!EXP:!LOW\""
"-DCONFIG_DRIVER_NL80211"
"-DCONFIG_DEBUG_FILE"
# "-DCONFIG_TESTING_OPTIONS"
)

target_link_options(native_simulator INTERFACE
"${LIBNL_LDFLAGS}"
)
17 changes: 11 additions & 6 deletions drivers/wifi/native_sim/Kconfig.native_sim
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ config WIFI_NATIVE_SIM_DRV_NAME
then this value is used as a prefix and the interface names will be
like zwifi0, zwifi1, etc.

config WIFI_NATIVE_SIM_DEV_NAME
string "Host ethernet TUN/TAP device name"
default "/dev/net/tun"
help
This option sets the TUN/TAP device name in your host system.

config WIFI_NATIVE_SIM_RANDOM_MAC
bool "Random MAC address"
depends on ENTROPY_GENERATOR
Expand Down Expand Up @@ -68,4 +62,15 @@ config WIFI_NATIVE_SIM_RX_TIMEOUT
Specify how long the thread sleeps between these checks if no new data
available.

config WIFI_NATIVE_SIM_SUPPLICANT_CONF_FILE
string ""
help
wpa_supplicant configuration file that is used to connect
to Linux mac80211_hwsim based network.

config WIFI_NATIVE_SIM_SUPPLICANT_LOG_FILE
string "/var/log/zephyr-host-wpa_supplicant.log"
help
wpa_supplicant log file for host side output.

endif # WIFI_NATIVE_SIM
11 changes: 8 additions & 3 deletions drivers/wifi/native_sim/iface_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ LOG_MODULE_DECLARE(wifi_native_sim, CONFIG_WIFI_LOG_LEVEL);

#define NET_BUF_TIMEOUT K_MSEC(100)

static bool extra_debug; /* set to true to hex dump the sent pkt */

static struct net_linkaddr *eth_get_mac(struct wifi_context *ctx)
{
ctx->ll_addr.addr = ctx->mac_addr;
Expand Down Expand Up @@ -286,10 +288,9 @@ void wifi_if_init(struct net_if *iface)
net_if_set_link_addr(iface, ll_addr->addr, ll_addr->len,
NET_LINK_ETHERNET);

ctx->dev_fd = eth_iface_create(CONFIG_WIFI_NATIVE_SIM_DEV_NAME,
ctx->if_name_host, false);
ctx->dev_fd = eth_iface_create(ctx->if_name_host);
if (ctx->dev_fd < 0) {
LOG_ERR("Cannot create %s (%d)", ctx->if_name_host, -errno);
LOG_ERR("Cannot create %s (%d)", ctx->if_name_host, ctx->dev_fd);
} else {
/* Create a thread that will handle incoming data from host */
create_rx_handler(ctx);
Expand Down Expand Up @@ -385,6 +386,10 @@ int wifi_if_send(const struct device *dev, struct net_pkt *pkt)

LOG_DBG("Send pkt %p len %d", pkt, count);

if (extra_debug) {
LOG_HEXDUMP_DBG(ctx->send, count, "pkt");
}

ret = eth_write_data(ctx->dev_fd, ctx->send, count);
if (ret < 0) {
LOG_DBG("Cannot send pkt %p (%d)", pkt, ret);
Expand Down
3 changes: 3 additions & 0 deletions drivers/wifi/native_sim/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ struct wifi_context {
struct net_linkaddr ll_addr;
struct net_if *iface;
const char *if_name_host; /* Interface name in host side */
void *host_context;
scan_result_cb_t scan_cb;
struct k_work_delayable scan_work;
k_tid_t rx_thread;
struct z_thread_stack_element *rx_stack;
size_t rx_stack_size;
Expand Down
47 changes: 45 additions & 2 deletions drivers/wifi/native_sim/mgmt_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,44 @@
#include "mgmt_api.h"
#include "internal.h"

#include "drivers/driver_zephyr.h"
#include "drivers/driver.h"
#include "wpa_supplicant/driver_i.h"
#include "wifi_drv_priv.h"

LOG_MODULE_DECLARE(wifi_native_sim, CONFIG_WIFI_LOG_LEVEL);

#define SCAN_TIMEOUT 10

static struct zep_wpa_supp_dev_ops *get_api(const struct device *dev)
{
return ((struct net_wifi_mgmt_offload *)dev->api)->wifi_drv_ops;
}

/* FIXME: We should not need to call this directly */
struct wpa_scan_results *wpa_drv_zep_get_scan_results2(void *priv);

static void scan_handler(struct k_work *work)
{
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
struct wifi_context *ctx = CONTAINER_OF(dwork,
struct wifi_context,
scan_work);

/* FIXME: We cannot call the host side result function directly as then
* the zephyr side memory would not get allocated.
*/
(void)wpa_drv_zep_get_scan_results2(ctx->supplicant_drv_ctx);

ctx->scan_in_progress = false;
}

int wifi_scan(const struct device *dev, struct wifi_scan_params *params,
scan_result_cb_t cb)
{
struct wifi_context *ctx = dev->data;
struct zep_wpa_supp_dev_ops *drv = get_api(dev);
struct wpa_driver_scan_params scan_params = {0};
int ret;

if (ctx->scan_in_progress) {
Expand All @@ -28,10 +60,21 @@ int wifi_scan(const struct device *dev, struct wifi_scan_params *params,

LOG_DBG("iface %s [%d] dev %s (%p)", ctx->name, ctx->if_index, dev->name, dev);

/* Do the scan */
/* TODO: fill in the params */
scan_params.num_ssids = 0;

/* TODO: add code here */
/* We could get the results pretty quick and call the scan result
* function here but simulate a way that a normal wifi driver
* would get the results.
*/
k_work_init_delayable(&ctx->scan_work, scan_handler);
k_work_reschedule(&ctx->scan_work, K_SECONDS(SCAN_TIMEOUT));

ctx->supplicant_callbacks.scan_start(ctx->supplicant_drv_ctx);

(void)drv->scan2(ctx, &scan_params);

ctx->scan_cb = cb;
ctx->scan_in_progress = true;

ret = 0;
Expand Down
72 changes: 60 additions & 12 deletions drivers/wifi/native_sim/wifi_drv_adapt.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <net/if.h>
#include <time.h>
Expand All @@ -35,33 +37,57 @@

#include "wifi_drv_priv.h"

/* Note that we cannot create the TUN/TAP device from the setup script
* as we need to get a file descriptor to communicate with the interface.
/* We are attaching here to the wireless network interface created
* by mac80211_hwsim. In order to send data to the network interface,
* we create a packet socket that is used to send and receive data.
*/
int eth_iface_create(const char *dev_name, const char *if_name, bool tun_only)
int eth_iface_create(const char *if_name)
{
struct ifreq ifr;
struct sockaddr_ll ll;
int fd, ret = -EINVAL;

fd = open(dev_name, O_RDWR);
fd = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL);
if (fd < 0) {
return -errno;
ret = -errno;
nsi_print_trace("%s: %s: %s (%d)\n", __func__,
"socket[AF_PACKET]",
strerror(errno), ret);
return ret;
}

(void)memset(&ifr, 0, sizeof(ifr));

#ifdef __linux
ifr.ifr_flags = (tun_only ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));

strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
ret = ioctl(fd, SIOCGIFINDEX, &ifr);
if (ret < 0) {
ret = -errno;
nsi_print_trace("%s: %s: %s (%d)\n", __func__,
"ioctl[SIOCGIFINDEX]",
strerror(errno), ret);
close(fd);
return ret;
}

memset(&ll, 0, sizeof(ll));

ret = ioctl(fd, TUNSETIFF, (void *)&ifr);
ll.sll_family = AF_PACKET;
ll.sll_ifindex = ifr.ifr_ifindex;
ll.sll_protocol = htons(ETH_P_ALL);

nsi_print_trace("%s: Connecting to %s (%d)\n", __func__,
if_name, ifr.ifr_ifindex);

ret = bind(fd, (struct sockaddr *)&ll, sizeof(ll));
if (ret < 0) {
ret = -errno;
nsi_print_trace("%s: %s: %s (%d)\n", __func__,
"bind[AF_PACKET]",
strerror(errno), ret);
close(fd);
return ret;
}
#endif

return fd;
}
Expand Down Expand Up @@ -118,12 +144,34 @@ int eth_wait_data(int fd)

ssize_t eth_read_data(int fd, void *buf, size_t buf_len)
{
return read(fd, buf, buf_len);
int ret;

ret = recv(fd, buf, buf_len, 0);
if (ret < 0) {
ret = -errno;
nsi_print_trace("%s: %s: %s (%d)\n", __func__,
"recv",
strerror(errno), ret);
return -1;
}

return ret;
}

ssize_t eth_write_data(int fd, void *buf, size_t buf_len)
{
return write(fd, buf, buf_len);
int ret;

ret = send(fd, buf, buf_len, 0);
if (ret < 0) {
ret = -errno;
nsi_print_trace("%s: %s: %s (%d)\n", __func__,
"send",
strerror(errno), ret);
return -1;
}

return ret;
}

int eth_promisc_mode(const char *if_name, bool enable)
Expand Down
Loading

0 comments on commit 4c8afa7

Please sign in to comment.