-
Notifications
You must be signed in to change notification settings - Fork 1
HOWTO: Bridged Qemu Networking
By default, cheribuild runs qemu with its so-called "user-mode networking" stack (i.e., SLiRP). This allows the emulated (CHERI) guest to make outbound TCP connections, additional command line options allow for bridging host TCP ports to in-guest listeners, and cheribuild even has qemu run smbd for the guest, but it's still a pretty restrictive networking setup. As such, we've had some requests for a bridged setup, where the emulated guest is on equal network footing with the machine running it. This not something cheribuild can completely automate away (one might speculate as to how firmly UNIX network stacks remain stuck in 1990, but that's another matter) and so will require some work if you wish to adopt this kind of setup, but we can hope to make the process as painless as possible.
In broad strokes, we're going to:
- Create a network bridge device on the host
- Move the host's current network interface under that bridge
- Move the host's network setup to configure the bridge instead
- Create a persistent TAP device under the bridge for qemu's use
- Run qemu with modified network flags
Please note that this is only very lightly tested at the moment; some experimentation is doubtless required.
-
Steps 1 through 3 can all be accomplished by changing
/etc/rc.confand rebooting. Useifconfigto determine which network interface is the default (on many VM images it'sem0orhn0). Assuming that'sem0(and that you're using DHCP to get your network configuration) add torc.confthese lines (or adjust appropriately):cloned_interfaces="bridge0" ifconfig_bridge0="addm em0 SYNCDHCP" ifconfig_em0="up"I suggest you verify that networking continues to function on the host before proceeding.
ifconfig bridge0should show a sensible address, at least. -
Creating a persistent TAP device for user use requires several steps...
-
setting some sysctls. Add to
/etc/sysctl.confthese lines:net.link.tap_user_open=1 net.link.tap.up_on_open=1 -
add a devd rule to
/etc/devd.confto control ownership of the TAP device. Replaceuserwith your username on the host. If you routinely run everything as root (which we cannot recommend), you can skip this step.attach 100 { match "system" "ETHERNET"; match "type" "IFATTACH"; match "subsystem" "tap0"; action "chown user /dev/tap0"; }; -
run
ifconfigper boot; add to/etc/rc.local(or create it with just these lines):ifconfig tap0 create ifconfig bridge0 addm tap0
Again I suggest rebooting to verify that everything is still functional and iterating until that's so. (
ls -l /dev/tap*should show a/dev/tap0owned by your user.) -
Now skip to Step 5: Running qemu guests with TAP networking
It's possible to dynamically reconfigure Linux's networking stack on the fly to have the requisite bridge device by running a series of commands as root. (Though note that this will likely play poorly with anything other than manually configured or static networking setups. That is, if you're using DHCP, perhaps change the configuration of the mechanism that starts DHCP.) You'll need ip (possibly packaged as iproute2), brctl (bridge-utils), and tunctl (uml-utilities) for this option.
Note that if your "generic Linux host" is a WSL2 VM, these instructions will allow your Linux host and qemu guest to communicate if you additionally manually assign an in-subnet address in the guest, but the guest will not be able to reach the WSL default gateway for reasons not yet understood (but likely something to do with ethernet addresses).
-
Create the bridge:
brctl addbr br0 ip link set dev br0 up -
Move the existing interface (presumed to be
eth0) underneath the bridge. We're going to extract the current addresses and remove them from the raw device, too:ADDR4=$(ip -4 -o addr show dev eth0 | awk '{ print $4 }') ADDR6=$(ip -6 -o addr show dev eth0 | awk '{ print $4 }') GW4=$(ip -4 -o route show default | awk '{ print $3 }') ip -4 route del default dev eth0 ip -4 addr del dev eth0 ${ADDR4} ip -6 addr del dev eth0 ${ADDR6} brctl addif br0 eth0 -
Put the addresses back on the bridge:
ip -4 addr add dev br0 ${ADDR4} ip -6 addr add dev br0 ${ADDR6} ip -4 route add default via ${GW4} dev br0 -
Create the TUN device and join it to the bridge. Replace
userwith your username on the host.tunctl -u user -t tap0 brctl addif br0 tap0 ip link set dev tap0 up
Now that the host OS is ready, we can run the guest with networking via this new TAP device. The simplest way to do this, so far, is to add a second network device to the qemu guests spawned by cheribuild, by using the --run/extra-options setting (if you're already using this, e.g., to pass -snapshot as well, then merely add the quoted bit here).
.../cheribuild.py run-riscv64-purecap --run/extra-options="-netdev tap,id=tapnet,ifname=tap0,script=no,downscript=no -device virtio-net-pci,netdev=tapnet,mac=52:54:AA:BB:CC:DD"
The guest should automatically bring up DHCP on vtnet0 and vtnet1 both (that is, on the qemu SLiRP network and the TAP network). If your host network is not configured by DHCP, it may be necessary to edit /etc/rc.conf in the guest disk image (perhaps by using the extra-files feature of cheribuild).