-
Notifications
You must be signed in to change notification settings - Fork 86
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
tinyemu: Slirp Socket support on WAMR #64
base: main
Are you sure you want to change the base?
Conversation
So as far as I can tell enabling SLIRP would result in the guest using VIRTIO_NET for networking. The module is actually loaded on my custom-built image but not used, at least it doesn't expose a networking interface. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
EMU_OBJS+=$(addprefix slirp/, bootp.o ip_icmp.o mbuf.o slirp.o tcp_output.o cksum.o ip_input.o misc.o socket.o tcp_subr.o udp.o if.o ip_output.o sbuf.o tcp_input.o tcp_timer.o) | ||
EMU_OBJS+=$(addprefix slirp/, bootp.o ip_icmp.o mbuf.o slirp.o tcp_output.o cksum.o ip_input.o misc.o socket.o tcp_subr.o udp.o if.o ip_output.o sbuf.o tcp_input.o tcp_timer.o wasi_socket_ext.o) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might also need to specify CONFIG_SLIRP=y
to make
command in Dockerfile.
Lines 271 to 273 in bc5b068
RUN make -j $(nproc) -f Makefile \ | |
CONFIG_FS_NET= CONFIG_SDL= CONFIG_INT128= CONFIG_X86EMU= CONFIG_SLIRP= OUTPUT_NAME=$JS_OUTPUT_NAME \ | |
CC="emcc --preload-file /pack -s WASM=1 -s ASYNCIFY=1 -s ALLOW_MEMORY_GROWTH=1 -UEMSCRIPTEN -DON_BROWSER -sNO_EXIT_RUNTIME=1 -sFORCE_FILESYSTEM=1" && \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
#else | ||
#include "wasi_socket_ext.h" | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these socket-related WASM APIs wamr-specific? If so, it would be great if we can enable this slirp feature only when the user specify -net=wamr
to the runtime flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose it's c2w's .go that should generate a Dockerfile argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done a boolean flag for now since CONFIG_SLIRP also is just a boolean.
EMU_OBJS+=$(addprefix slirp/, bootp.o ip_icmp.o mbuf.o slirp.o tcp_output.o cksum.o ip_input.o misc.o socket.o tcp_subr.o udp.o if.o ip_output.o sbuf.o tcp_input.o tcp_timer.o) | ||
EMU_OBJS+=$(addprefix slirp/, bootp.o ip_icmp.o mbuf.o slirp.o tcp_output.o cksum.o ip_input.o misc.o socket.o tcp_subr.o udp.o if.o ip_output.o sbuf.o tcp_input.o tcp_timer.o wasi_socket_ext.o) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As of now, it's fine that the guest VM and the container share the network namespace to make the network interface visible to the container. You can change the runc spec to do so:
container2wasm/cmd/create-spec/main.go
Line 247 in bc5b068
s, err := ctdoci.GenerateSpecWithPlatform(ctdCtx, nil, p, &ctdcontainers.Container{}) |
- s, err := ctdoci.GenerateSpecWithPlatform(ctdCtx, nil, "linux/riscv64", &ctdcontainers.Container{})
+ s, err := ctdoci.GenerateSpecWithPlatform(ctdCtx, nil, "linux/riscv64", &ctdcontainers.Container{},
+ ctdoci.WithHostNamespace(specs.NetworkNamespace),
+ )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handled.
Thanks! container2wasm/patches/tinyemu/tinyemu/temu.c Lines 550 to 554 in bc5b068
In the guest VM, https://github.com/ktock/container2wasm/blob/main/cmd/init/main.go is executed before launching runc container so we can invoke some commands there for the interface configuration. |
Thanks, I'll set it up there and remove the capabilities as soon as it works properly. Attempting the QEMU-preferred way of using DHCP (using dhclient), it seems as if only the first UDP packet gets forwarded through Virtio, then discarded because the checksum doesn't match, and no further UDP packets get forwarded afterwards. I wonder what's up here. |
Maybe we need some compile-time configurations for slirp? https://github.com/ktock/container2wasm/blob/main/patches/tinyemu/tinyemu/slirp/slirp_config.h (e.g. |
Tried that but those values already were accurate. I assume the device's virtio queue to not getting processed properly. Taking a deeper look now. |
Seems as if writing Now I wonder why that is, since other virtio devices seem to be increasing the Note that right now I'm setting up networking like this:
|
I haven't dig this deeply but IIRC napi_tx didn't work well on the emulator. Maybe |
That indeed was it! Will add the ip configuration commands and remove capabilities in a short moment. |
I hit a roadblock, apparently the host (10.0.2.2) can be pinged now, but setting a nameserver or even using a known public IP address doesn't result in curl fetching any valid data. |
What error is curl reporting? |
Sorry for the late response, I was busy. curl itself just times out, this is what I currently have:
Changing iwasm's address pool to something like 0.0.0.0/0 doesn't help either. |
Super interested in this!, ie. networking support from a c2w wasm binary running in my browser. I have a websocket to "network" service ready to go for something like this. Once ready for testing, feel free to ping me, happy to help testing, or help however i can. |
This bridges the gap between TinyEMU and the WASI runtime to allow for networking.
The capabilities are required to enable the container to mess with IP address configuration.
60e2434
to
1c3ddb9
Compare
For those that want to make use of SLIRP without a networking proxy, tested on WebAssembly Micro Runtime, I finally figured it out! Turns out Out-Of-Band communication doesn't seem to be a concept the current socket APIs understand. Working around this issue and treating connect()s synchronously does the job. Right now the way to enable an image with networking support is by using the RISCV/TinyEMU backend and building the image with the Though the Go side probably needs some adjustments to fully be upstream-worthy, I guess those count as finishing touches only. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This is very cool!
if (ret == 0) { | ||
soisfconnected(so); | ||
} else | ||
{ | ||
/* | ||
* If it's not in progress, it failed, so we just return 0, | ||
* without clearing SS_NOFDREF | ||
*/ | ||
soisfconnecting(so); | ||
soisfconnecting(so); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this change related to OOB? If this doesn't work, it rather feels like the socket doesn't support non-blocking connect
(e.g. select
on the socket doesn't set the writefd on ready).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a combination of both as far as I can tell, OOB flags stopping WAMR from continuing connecting as well as non-blocking not working at all.
@@ -778,7 +811,12 @@ ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags) | |||
return len; | |||
} | |||
#endif | |||
|
|||
#ifdef WASI | |||
return send(so->s, buf, len, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we clear OOB flag on the caller of slirp_send rather than entirely remove the flags?
return buf; | ||
} | ||
|
||
int get_dns_addr(struct in_addr *pdns_addr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this used?
struct addrinfo *res; | ||
int count = 0; | ||
struct addrinfo hints; | ||
char *url = "google-public-dns-a.google.com"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make it a flag rather than hard-coding?
cli.BoolFlag{ | ||
Name: "net", | ||
Usage: "Build with networking capabilities (default: false)", | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to rely on wamr-specific codes so I think we should enable this with the flag-net=wamr
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will try to tackle this, keep in mind I'm not much of a Go developer.
if ((1 & (long) w) && (mlen > 0)) { | ||
if ((1 & (uintptr_t) w) && (mlen > 0)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add an explanation comment here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not my change, applied from an upstream libslirp change. The commit message is detailed enough.
#ifndef WASI | ||
opt = 1; | ||
setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem to be compiled by default.
patches/tinyemu/tinyemu/temu.c
Outdated
/*******************************************************/ | ||
/* socket */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do not remove the original networking logic because it's needed for non-wamr runtimes (e.g. wasmtime, wazero and browser). We can enable the networking logic for wamr when -net=wamr
is passed to the emulator flag during runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoopsies, no idea how that happened, must have been through the rebase. Will check and reapply customizations again.
Enables CONFIG_SLIRP based on user preference.
…nditionally - Rather than setting CONFIG_SLIRP=y, just undefine it to keep the Makefile simple. - Only build WASI part if requested to do so by defining that one as well.
Casting a pointer to an integer value must use uintptr_t or intptr_t (not long) for portable code. MinGW-w64 requires this because sizeof(long) != sizeof(void *) for w64 hosts, so casting to long raises a compiler warning. I use uintptr_t instead of intptr_t because changing the sign does not matter here and casting pointers to unsigned values seems more reasonable (the unsigned value is a non negative offset. Cc: Jan Kiszka <[email protected]> Signed-off-by: Stefan Weil <[email protected]> Signed-off-by: Jan Kiszka <[email protected]>
Fixes checksum calculation for UDP/DHCP.
Not necessary anymore.
Hardcoded enablement for now. Enabling withNet itself results in stuck communications (probably due to the missing networking proxy).
Also remove assumption that OOB communication is supported right now.
- Implement get_dns_addr for DNS lookups - Avoid calling send() with flags since those are not supported universally, at least not in WebAssembly Micro Runtime
Instead of assuming OOB to be supported, just jump to connected-state after a successful connect() and leave it at that.
1c3ddb9
to
c93d7e5
Compare
The Wasm Micro Runtime ships with an Apache 2.0 (with LLVM Exception) library which enables use of sockets in Wasm binaries. Integrating this library and fixing fallout issues enables networking support at least on WAMR.