Skip to content

Commit 1a52828

Browse files
Make virtio-net backends configurable
Add Kconfig options for the virtio-net device, Linux TAP backend, and user-mode SLIRP backend. Exclude unused network objects at build time, build minislirp only when the user backend is enabled, and guard the related CLI, runtime, MMIO, DTB, and interrupt integration. Also list only compiled backends in the CLI help and consolidate backend initialization through a shared helper (netdev_setup in src/devices/netdev.c).
1 parent 103be25 commit 1a52828

14 files changed

Lines changed: 261 additions & 100 deletions

File tree

Makefile

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ deps :=
5858
# Feature Flags (Kconfig -> RV32_FEATURE_*)
5959
$(call set-features, ELF_LOADER MOP_FUSION BLOCK_CHAINING LOG_COLOR)
6060
$(call set-features, SYSTEM GOLDFISH_RTC ARCH_TEST)
61+
$(call set-features, VIRTIO_NET VIRTIO_NET_TAP VIRTIO_NET_USER)
6162
$(call set-features, EXT_M EXT_A EXT_F EXT_C EXT_V RV32E)
6263
$(call set-features, Zicsr Zifencei Zba Zbb Zbc Zbs)
6364
$(call set-features, SDL SDL_MIXER GDBSTUB JIT)
@@ -222,13 +223,35 @@ $(OUT)/emulate.o: CFLAGS += -foptimize-sibling-calls -fomit-frame-pointer -fno-s
222223
# HTTP Utilities (shared by external.mk and artifact.mk)
223224
include mk/http.mk
224225

226+
# VirtIO networking is available only for kernel system emulation and requires
227+
# at least one host backend. CONFIG_* values may be overridden by legacy
228+
# ENABLE_* flags after loading .config, so derive the effective build state here
229+
# instead of relying only on the Kconfig dependency graph.
230+
VIRTIO_NET_BUILD_ENABLED := n
231+
ifeq ($(CONFIG_SYSTEM),y)
232+
ifneq ($(CONFIG_ELF_LOADER),y)
233+
ifeq ($(CONFIG_VIRTIO_NET),y)
234+
ifneq ($(filter y,$(CONFIG_VIRTIO_NET_TAP) $(CONFIG_VIRTIO_NET_USER)),)
235+
VIRTIO_NET_BUILD_ENABLED := y
236+
endif
237+
endif
238+
endif
239+
endif
240+
241+
VIRTIO_NET_USER_BUILD_ENABLED := n
242+
ifeq ($(VIRTIO_NET_BUILD_ENABLED),y)
243+
ifeq ($(CONFIG_VIRTIO_NET_USER),y)
244+
VIRTIO_NET_USER_BUILD_ENABLED := y
245+
endif
246+
endif
247+
225248
# External Dependencies & System Emulation
226249
include mk/external.mk
227250
include mk/artifact.mk
228251
include mk/system.mk
229252
include mk/wasm.mk
230253

231-
ifeq ($(CONFIG_SYSTEM),y)
254+
ifeq ($(VIRTIO_NET_USER_BUILD_ENABLED),y)
232255
ifneq ($(CC_IS_EMCC),1)
233256
MINISLIRP_DIR := src/minislirp
234257
MINISLIRP_LIB := $(MINISLIRP_DIR)/src/libslirp.a
@@ -248,6 +271,7 @@ $(MINISLIRP_DIR)/src/Makefile:
248271
$(MINISLIRP_LIB): $(MINISLIRP_DIR)/src/Makefile
249272
$(Q)$(MAKE) -C $(dir $<) CC="$(CC)" $(MINISLIRP_CFLAGS)
250273

274+
$(OUT)/devices/slirp.o: $(MINISLIRP_LIB)
251275
$(BIN): $(MINISLIRP_LIB)
252276
endif
253277
endif
@@ -271,6 +295,7 @@ deps += $(OBJS:%.o=%.o.d)
271295
EFFECTIVE_CONFIG_STAMP := $(OUT)/.effective-config
272296
EFFECTIVE_CONFIG_VARS := \
273297
CONFIG_BUILD_WASM CONFIG_SYSTEM CONFIG_GOLDFISH_RTC CONFIG_ELF_LOADER \
298+
CONFIG_VIRTIO_NET CONFIG_VIRTIO_NET_TAP CONFIG_VIRTIO_NET_USER \
274299
CONFIG_EXT_M CONFIG_EXT_A CONFIG_EXT_F CONFIG_EXT_C CONFIG_EXT_V CONFIG_RV32E \
275300
CONFIG_Zicsr CONFIG_Zifencei CONFIG_Zba CONFIG_Zbb CONFIG_Zbc CONFIG_Zbs \
276301
CONFIG_MOP_FUSION CONFIG_BLOCK_CHAINING CONFIG_LOG_COLOR CONFIG_ARCH_TEST \

configs/Kconfig

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ config HAVE_RISCV_TOOLCHAIN
9999
bool
100100
default $(python,assert run(sys.executable, 'tools/detect-env.py', '--have-riscv-toolchain'))
101101

102+
# Host platform detection used by platform-specific system devices.
103+
config HOST_LINUX
104+
def_bool $(python,assert sys.platform.startswith('linux'))
105+
106+
config HOST_MACOS
107+
def_bool $(python,assert sys.platform == 'darwin')
108+
102109
# RISC-V ISA Extensions
103110

104111
menu "RISC-V ISA Configuration"
@@ -282,6 +289,37 @@ config ELF_LOADER
282289
Enable this for running 'make check' tests in system mode.
283290
Disable this for booting Linux kernel images.
284291

292+
config VIRTIO_NET
293+
bool "Enable VirtIO network device"
294+
default y
295+
depends on SYSTEM && !ELF_LOADER && !CC_IS_EMCC
296+
depends on HOST_LINUX || HOST_MACOS
297+
help
298+
Enable VirtIO network device emulation.
299+
300+
Disable this option to exclude virtio-net, its host backends,
301+
and their dependencies from the rv32emu executable.
302+
303+
config VIRTIO_NET_TAP
304+
bool "Enable Linux TAP backend"
305+
default y
306+
depends on VIRTIO_NET && HOST_LINUX
307+
help
308+
Enable the Linux TAP backend for VirtIO networking.
309+
310+
This backend uses /dev/net/tun and normally requires root
311+
privileges or CAP_NET_ADMIN.
312+
313+
config VIRTIO_NET_USER
314+
bool "Enable user-mode SLIRP backend"
315+
default y
316+
depends on VIRTIO_NET && (HOST_LINUX || HOST_MACOS)
317+
help
318+
Enable user-mode networking through minislirp.
319+
320+
This backend does not require a TAP interface or root privileges,
321+
but it adds minislirp to the final executable.
322+
285323
endmenu
286324

287325
# Performance Optimizations

configs/system_defconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
# System emulation for Linux kernel
22
CONFIG_SYSTEM=y
33
CONFIG_GOLDFISH_RTC=y
4+
CONFIG_VIRTIO_NET=y
5+
CONFIG_VIRTIO_NET_TAP=y
6+
CONFIG_VIRTIO_NET_USER=y

mk/system.mk

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ $(DEV_OUT)/%.o: $(DEV_SRC)/%.c $(EFFECTIVE_CONFIG_STAMP) | $(DEV_OUT)
5252
$(Q)$(CC) -o $@ $(CFLAGS) $(CFLAGS_emcc) -c -MMD -MF $@.d $<
5353

5454
DEV_OBJS := $(patsubst $(DEV_SRC)/%.c, $(DEV_OUT)/%.o, $(wildcard $(DEV_SRC)/*.c))
55+
# VirtIO networking is optional. Exclude all network-related objects unless
56+
# kernel system emulation is active and at least one host backend is enabled.
57+
# The SLIRP object is only needed by the user-mode backend.
58+
ifneq ($(VIRTIO_NET_BUILD_ENABLED),y)
59+
DEV_OBJS := $(filter-out \
60+
$(DEV_OUT)/virtio-net.o \
61+
$(DEV_OUT)/netdev.o \
62+
$(DEV_OUT)/slirp.o, \
63+
$(DEV_OBJS))
64+
else
65+
ifneq ($(VIRTIO_NET_USER_BUILD_ENABLED),y)
66+
DEV_OBJS := $(filter-out $(DEV_OUT)/slirp.o, $(DEV_OBJS))
67+
endif
68+
endif
69+
5570
# Enable Goldfish RTC peripheral
5671
ifneq ($(CONFIG_GOLDFISH_RTC),y)
5772
DEV_OBJS := $(filter-out $(DEV_OUT)/rtc.o, $(DEV_OBJS))

src/devices/netdev.c

Lines changed: 52 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,52 @@
1919
#include <sys/ioctl.h>
2020
#endif
2121

22+
#if RV32EMU_NET_HAS_TAP || RV32EMU_NET_HAS_SLIRP
23+
typedef int (*netdev_init_fn_t)(netdev_t *netdev);
24+
#endif
25+
2226
static void netdev_reset(netdev_t *netdev)
2327
{
2428
if (!netdev)
2529
return;
2630

2731
netdev->name = NULL;
28-
netdev->type = NETDEV_IMPL_none;
32+
netdev->type = NETDEV_IMPL_NONE;
2933
netdev->op = NULL;
3034
}
3135

36+
#if RV32EMU_NET_HAS_TAP || RV32EMU_NET_HAS_SLIRP
37+
static bool netdev_setup(netdev_t *netdev,
38+
const char *name,
39+
netdev_impl_t type,
40+
size_t options_size,
41+
netdev_init_fn_t init_fn)
42+
{
43+
netdev->name = name;
44+
netdev->type = type;
45+
netdev->op = calloc(1, options_size);
46+
47+
if (!netdev->op) {
48+
netdev_reset(netdev);
49+
return false;
50+
}
51+
52+
if (init_fn(netdev) < 0) {
53+
free(netdev->op);
54+
netdev_reset(netdev);
55+
return false;
56+
}
57+
58+
return true;
59+
}
60+
#endif
61+
3262
#if RV32EMU_NET_HAS_TAP
3363
static int net_init_tap(netdev_t *netdev)
3464
{
3565
net_tap_options_t *tap = (net_tap_options_t *) netdev->op;
3666

67+
tap->tap_fd = -1;
3768
tap->tap_fd = open("/dev/net/tun", O_RDWR);
3869
if (tap->tap_fd < 0) {
3970
rv_log_error("failed to open TAP device: %s", strerror(errno));
@@ -84,19 +115,16 @@ static int net_init_user(netdev_t *netdev)
84115
}
85116
#endif
86117

87-
#if RV32EMU_NET_HAS_TAP
88-
static const char *netdev_linux_default(void)
118+
static const char *netdev_default_backend(void)
89119
{
120+
#if RV32EMU_NET_HAS_TAP
90121
return "tap";
91-
}
92-
#endif
93-
94-
#if defined(__APPLE__) && RV32EMU_NET_HAS_SLIRP
95-
static const char *netdev_macos_default(void)
96-
{
122+
#elif RV32EMU_NET_HAS_SLIRP
97123
return "user";
98-
}
124+
#else
125+
return NULL;
99126
#endif
127+
}
100128

101129
bool netdev_init(netdev_t *netdev, const char *net_type)
102130
{
@@ -105,73 +133,28 @@ bool netdev_init(netdev_t *netdev, const char *net_type)
105133

106134
netdev_reset(netdev);
107135

108-
#if defined(__APPLE__) && RV32EMU_NET_HAS_SLIRP
109-
const char *requested = net_type ? net_type : netdev_macos_default();
110-
111-
if (!strcmp(requested, "user")) {
112-
netdev->name = "user";
113-
netdev->type = NETDEV_IMPL_user;
114-
netdev->op = calloc(1, sizeof(net_user_options_t));
115-
if (!netdev->op)
116-
return false;
117-
118-
if (net_init_user(netdev) < 0) {
119-
free(netdev->op);
120-
netdev->op = NULL;
121-
return false;
122-
}
123-
124-
return true;
136+
const char *requested = net_type ? net_type : netdev_default_backend();
137+
if (!requested) {
138+
rv_log_error("no virtio-net backend was compiled");
139+
return false;
125140
}
126141

127-
rv_log_error("unsupported virtio-net backend on macOS: %s", requested);
128-
return false;
129-
130-
#elif RV32EMU_NET_HAS_TAP
131-
const char *requested = net_type ? net_type : netdev_linux_default();
132-
142+
#if RV32EMU_NET_HAS_TAP
133143
if (!strcmp(requested, "tap")) {
134-
netdev->name = "tap";
135-
netdev->type = NETDEV_IMPL_tap;
136-
netdev->op = calloc(1, sizeof(net_tap_options_t));
137-
if (!netdev->op)
138-
return false;
139-
140-
if (net_init_tap(netdev) < 0) {
141-
free(netdev->op);
142-
netdev->op = NULL;
143-
return false;
144-
}
145-
146-
return true;
144+
return netdev_setup(netdev, "tap", NETDEV_IMPL_TAP,
145+
sizeof(net_tap_options_t), net_init_tap);
147146
}
147+
#endif
148148

149149
#if RV32EMU_NET_HAS_SLIRP
150150
if (!strcmp(requested, "user")) {
151-
netdev->name = "user";
152-
netdev->type = NETDEV_IMPL_user;
153-
netdev->op = calloc(1, sizeof(net_user_options_t));
154-
if (!netdev->op)
155-
return false;
156-
157-
if (net_init_user(netdev) < 0) {
158-
free(netdev->op);
159-
netdev->op = NULL;
160-
return false;
161-
}
162-
163-
return true;
151+
return netdev_setup(netdev, "user", NETDEV_IMPL_USER,
152+
sizeof(net_user_options_t), net_init_user);
164153
}
165154
#endif
166155

167-
rv_log_error("unsupported virtio-net backend on Linux: %s", requested);
156+
rv_log_error("unsupported virtio-net backend: %s", requested);
168157
return false;
169-
170-
#else
171-
(void) net_type;
172-
rv_log_error("virtio-net networking is disabled on this host");
173-
return false;
174-
#endif
175158
}
176159

177160
void netdev_delete(netdev_t *netdev)
@@ -181,7 +164,7 @@ void netdev_delete(netdev_t *netdev)
181164

182165
switch (netdev->type) {
183166
#if RV32EMU_NET_HAS_TAP
184-
case NETDEV_IMPL_tap: {
167+
case NETDEV_IMPL_TAP: {
185168
net_tap_options_t *tap = (net_tap_options_t *) netdev->op;
186169
if (tap->tap_fd >= 0)
187170
close(tap->tap_fd);
@@ -190,11 +173,12 @@ void netdev_delete(netdev_t *netdev)
190173
#endif
191174

192175
#if RV32EMU_NET_HAS_SLIRP
193-
case NETDEV_IMPL_user:
176+
case NETDEV_IMPL_USER:
194177
net_slirp_cleanup((net_user_options_t *) netdev->op);
195178
break;
196179
#endif
197180

181+
case NETDEV_IMPL_NONE:
198182
default:
199183
break;
200184
}

src/devices/netdev.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <sys/types.h>
1212
#include <sys/uio.h>
1313

14+
#include "feature.h"
15+
1416
/*
1517
* Networking backends:
1618
*
@@ -22,18 +24,15 @@
2224
* - user : user-mode SLIRP
2325
*
2426
* Emscripten:
25-
* * Networking backends:
26-
*
27-
*
2827
* - virtio-net networking backends are disabled
2928
*/
30-
#if defined(__linux__) && !defined(__EMSCRIPTEN__)
29+
#if RV32_HAS(VIRTIO_NET_TAP) && defined(__linux__) && !defined(__EMSCRIPTEN__)
3130
#define RV32EMU_NET_HAS_TAP 1
3231
#else
3332
#define RV32EMU_NET_HAS_TAP 0
3433
#endif
3534

36-
#if !defined(__EMSCRIPTEN__)
35+
#if RV32_HAS(VIRTIO_NET_USER) && !defined(__EMSCRIPTEN__)
3736
#define RV32EMU_NET_HAS_SLIRP 1
3837
#else
3938
#define RV32EMU_NET_HAS_SLIRP 0
@@ -44,12 +43,12 @@
4443
typedef struct netdev netdev_t;
4544

4645
typedef enum {
47-
NETDEV_IMPL_none = 0,
46+
NETDEV_IMPL_NONE = 0,
4847
#if RV32EMU_NET_HAS_TAP
49-
NETDEV_IMPL_tap,
48+
NETDEV_IMPL_TAP,
5049
#endif
5150
#if RV32EMU_NET_HAS_SLIRP
52-
NETDEV_IMPL_user,
51+
NETDEV_IMPL_USER,
5352
#endif
5453
} netdev_impl_t;
5554

0 commit comments

Comments
 (0)