Skip to content

Remove socketpair in hostap to save memory #90317

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 4 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 lib/os/zvfs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ if ZVFS_EVENTFD

config ZVFS_EVENTFD_MAX
int "Maximum number of ZVFS eventfd's"
default 8 if WIFI_NM_WPA_SUPPLICANT
default 1
range 1 4096
help
Expand Down
3 changes: 2 additions & 1 deletion modules/hostap/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ config WIFI_NM_WPA_SUPPLICANT
select XSI_SINGLE_PROCESS
select NET_SOCKETS
select NET_SOCKETS_PACKET
select NET_SOCKETPAIR
select NET_L2_WIFI_MGMT
select WIFI_NM
select EXPERIMENTAL
select COMMON_LIBC_MALLOC
select ZVFS
select ZVFS_EVENTFD
help
WPA supplicant as a network management backend for WIFI_NM.

Expand Down
171 changes: 90 additions & 81 deletions modules/hostap/src/supp_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ LOG_MODULE_REGISTER(wifi_supplicant, CONFIG_WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL);
#include <zephyr/kernel.h>
#include <zephyr/init.h>
#include <poll.h>
#include <zephyr/zvfs/eventfd.h>

#if !defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE) && !defined(CONFIG_MBEDTLS_ENABLE_HEAP)
#include <mbedtls/platform.h>
Expand Down Expand Up @@ -44,6 +45,7 @@ static K_THREAD_STACK_DEFINE(iface_wq_stack, CONFIG_WIFI_NM_WPA_SUPPLICANT_WQ_ST
#include "fst/fst.h"
#include "includes.h"
#include "wpa_cli_zephyr.h"
#include "ctrl_iface_zephyr.h"
#ifdef CONFIG_WIFI_NM_HOSTAPD_AP
#include "hostapd.h"
#include "hapd_main.h"
Expand Down Expand Up @@ -109,7 +111,8 @@ struct supplicant_context {
struct net_mgmt_event_callback cb;
struct net_if *iface;
char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1];
int event_socketpair[2];
struct k_fifo fifo;
int sock;
struct k_work iface_work;
struct k_work_q iface_wq;
int (*iface_handler)(struct supplicant_context *ctx, struct net_if *iface);
Expand Down Expand Up @@ -139,39 +142,25 @@ struct k_work_q *get_workq(void)
return &get_default_context()->iface_wq;
}

/* found in hostap/wpa_supplicant/ctrl_iface_zephyr.c */
extern int send_data(struct k_fifo *fifo, int sock, const char *buf, size_t len, int flags);

int zephyr_wifi_send_event(const struct wpa_supplicant_event_msg *msg)
{
struct supplicant_context *ctx;
struct pollfd fds[1];
int ret;

/* TODO: Fix this to get the correct container */
ctx = get_default_context();

if (ctx->event_socketpair[1] < 0) {
if (ctx->sock < 0) {
ret = -ENOENT;
goto out;
}

fds[0].fd = ctx->event_socketpair[0];
fds[0].events = POLLOUT;
fds[0].revents = 0;

ret = zsock_poll(fds, 1, WRITE_TIMEOUT);
if (ret < 0) {
ret = -errno;
LOG_ERR("Cannot write event (%d)", ret);
goto out;
}

ret = zsock_send(ctx->event_socketpair[1], msg, sizeof(*msg), 0);
if (ret < 0) {
ret = -errno;
LOG_WRN("Event send failed (%d)", ret);
goto out;
}

if (ret != sizeof(*msg)) {
ret = send_data(&ctx->fifo, ctx->sock,
(const char *)msg, sizeof(*msg), 0);
if (ret != 0) {
ret = -EMSGSIZE;
LOG_WRN("Event partial send (%d)", ret);
goto out;
Expand Down Expand Up @@ -562,84 +551,105 @@ static int setup_interface_monitoring(struct supplicant_context *ctx, struct net
static void event_socket_handler(int sock, void *eloop_ctx, void *user_data)
{
struct supplicant_context *ctx = user_data;
struct wpa_supplicant_event_msg msg;
int ret;
struct wpa_supplicant_event_msg event_msg;
struct zephyr_msg *msg;
zvfs_eventfd_t value;

ARG_UNUSED(eloop_ctx);
ARG_UNUSED(ctx);

ret = zsock_recv(sock, &msg, sizeof(msg), 0);
if (ret < 0) {
LOG_ERR("Failed to recv the message (%d)", -errno);
return;
}
do {
zvfs_eventfd_read(sock, &value);

if (ret != sizeof(msg)) {
LOG_ERR("Received incomplete message: got: %d, expected:%d",
ret, sizeof(msg));
return;
}
msg = k_fifo_get(&ctx->fifo, K_NO_WAIT);
if (msg == NULL) {
LOG_ERR("fifo(event): %s", "empty");
return;
}

LOG_DBG("Passing message %d to wpa_supplicant", msg.event);
if (msg->data == NULL) {
LOG_ERR("fifo(event): %s", "no data");
goto out;
}

if (msg.global) {
wpa_supplicant_event_global(msg.ctx, msg.event, msg.data);
if (msg->len != sizeof(event_msg)) {
LOG_ERR("Received incomplete message: got: %d, expected:%d",
msg->len, sizeof(event_msg));
goto out;
}

memcpy(&event_msg, msg->data, sizeof(event_msg));

LOG_DBG("Passing message %d to wpa_supplicant", event_msg.event);

if (event_msg.global) {
wpa_supplicant_event_global(event_msg.ctx, event_msg.event,
event_msg.data);
#ifdef CONFIG_WIFI_NM_HOSTAPD_AP
} else if (msg.hostapd) {
hostapd_event(msg.ctx, msg.event, msg.data);
} else if (event_msg.hostapd) {
hostapd_event(event_msg.ctx, event_msg.event, event_msg.data);
#endif
} else {
wpa_supplicant_event(msg.ctx, msg.event, msg.data);
}

if (msg.data) {
union wpa_event_data *data = msg.data;

/* Free up deep copied data */
if (msg.event == EVENT_AUTH) {
os_free((char *)data->auth.ies);
} else if (msg.event == EVENT_RX_MGMT) {
os_free((char *)data->rx_mgmt.frame);
} else if (msg.event == EVENT_TX_STATUS) {
os_free((char *)data->tx_status.data);
} else if (msg.event == EVENT_ASSOC) {
os_free((char *)data->assoc_info.addr);
os_free((char *)data->assoc_info.req_ies);
os_free((char *)data->assoc_info.resp_ies);
os_free((char *)data->assoc_info.resp_frame);
} else if (msg.event == EVENT_ASSOC_REJECT) {
os_free((char *)data->assoc_reject.bssid);
os_free((char *)data->assoc_reject.resp_ies);
} else if (msg.event == EVENT_DEAUTH) {
os_free((char *)data->deauth_info.addr);
os_free((char *)data->deauth_info.ie);
} else if (msg.event == EVENT_DISASSOC) {
os_free((char *)data->disassoc_info.addr);
os_free((char *)data->disassoc_info.ie);
} else if (msg.event == EVENT_UNPROT_DEAUTH) {
os_free((char *)data->unprot_deauth.sa);
os_free((char *)data->unprot_deauth.da);
} else if (msg.event == EVENT_UNPROT_DISASSOC) {
os_free((char *)data->unprot_disassoc.sa);
os_free((char *)data->unprot_disassoc.da);
} else {
wpa_supplicant_event(event_msg.ctx, event_msg.event, event_msg.data);
}

os_free(msg.data);
}
if (event_msg.data) {
union wpa_event_data *data = event_msg.data;

/* Free up deep copied data */
if (event_msg.event == EVENT_AUTH) {
os_free((char *)data->auth.ies);
} else if (event_msg.event == EVENT_RX_MGMT) {
os_free((char *)data->rx_mgmt.frame);
} else if (event_msg.event == EVENT_TX_STATUS) {
os_free((char *)data->tx_status.data);
} else if (event_msg.event == EVENT_ASSOC) {
os_free((char *)data->assoc_info.addr);
os_free((char *)data->assoc_info.req_ies);
os_free((char *)data->assoc_info.resp_ies);
os_free((char *)data->assoc_info.resp_frame);
} else if (event_msg.event == EVENT_ASSOC_REJECT) {
os_free((char *)data->assoc_reject.bssid);
os_free((char *)data->assoc_reject.resp_ies);
} else if (event_msg.event == EVENT_DEAUTH) {
os_free((char *)data->deauth_info.addr);
os_free((char *)data->deauth_info.ie);
} else if (event_msg.event == EVENT_DISASSOC) {
os_free((char *)data->disassoc_info.addr);
os_free((char *)data->disassoc_info.ie);
} else if (event_msg.event == EVENT_UNPROT_DEAUTH) {
os_free((char *)data->unprot_deauth.sa);
os_free((char *)data->unprot_deauth.da);
} else if (event_msg.event == EVENT_UNPROT_DISASSOC) {
os_free((char *)data->unprot_disassoc.sa);
os_free((char *)data->unprot_disassoc.da);
}

os_free(event_msg.data);
}

out:
os_free(msg->data);
os_free(msg);

} while (!k_fifo_is_empty(&ctx->fifo));
}

static int register_supplicant_event_socket(struct supplicant_context *ctx)
{
int ret;

ret = socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->event_socketpair);
ret = zvfs_eventfd(0, 0);
if (ret < 0) {
ret = -errno;
LOG_ERR("Failed to initialize socket (%d)", ret);
return ret;
}

eloop_register_read_sock(ctx->event_socketpair[0], event_socket_handler, NULL, ctx);
ctx->sock = ret;

k_fifo_init(&ctx->fifo);

eloop_register_read_sock(ctx->sock, event_socket_handler, NULL, ctx);

return 0;
}
Expand Down Expand Up @@ -707,7 +717,7 @@ static void handler(void)

supplicant_generate_state_event(ctx->if_name, NET_EVENT_SUPPLICANT_CMD_NOT_READY, 0);

eloop_unregister_read_sock(ctx->event_socketpair[0]);
eloop_unregister_read_sock(ctx->sock);

zephyr_global_wpa_ctrl_deinit();

Expand All @@ -716,8 +726,7 @@ static void handler(void)
out:
wpa_supplicant_deinit(ctx->supplicant);

zsock_close(ctx->event_socketpair[0]);
zsock_close(ctx->event_socketpair[1]);
close(ctx->sock);

err:
os_free(params.pid_file);
Expand Down
5 changes: 0 additions & 5 deletions subsys/net/lib/sockets/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ if NET_SOCKETPAIR

config NET_SOCKETPAIR_BUFFER_SIZE
int "Size of the intermediate buffer, in bytes"
default 1024 if WIFI_NM_WPA_SUPPLICANT
default 64
range 1 4096
help
Expand All @@ -372,8 +371,6 @@ if NET_SOCKETPAIR_STATIC

config NET_SOCKETPAIR_MAX
int "How many socketpairs to pre-allocate"
default 6 if WIFI_NM_HOSTAPD_AP
default 4 if WIFI_NM_WPA_SUPPLICANT
default 1

endif # NET_SOCKETPAIR_STATIC
Expand All @@ -382,8 +379,6 @@ if NET_SOCKETPAIR_HEAP

config HEAP_MEM_POOL_ADD_SIZE_SOCKETPAIR
int
default 9136 if WIFI_NM_HOSTAPD_AP
default 6852 if WIFI_NM_WPA_SUPPLICANT
default 296

endif # NET_SOCKETPAIR_HEAP
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/86/head
- name: liblc3
revision: 48bbd3eacd36e99a57317a0a4867002e0b09e183
path: modules/lib/liblc3
Expand Down
Loading