Networking with QEMU¶
- Basic Setup
- Setting up Zephyr and NAT/masquerading on host to access Internet
- Network connection between two QEMU VMs
- Running multiple QEMU VMs of the same sample
This page describes how to set up a virtual network between a (Linux) host and a Zephyr application running in a QEMU virtual machine (built for Zephyr targets such as qemu_x86 and qemu_cortex_m3).
In this example, the Socket Echo Server sample application from the Zephyr source distribution is run in QEMU. The QEMU instance is connected to a Linux host using a serial port, and SLIP is used to transfer data between the Zephyr application and Linux (over a chain of virtual connections).
On the Linux Host, fetch the Zephyr
net-tools project, which is located
in a separate Git repository:
git clone https://github.com/zephyrproject-rtos/net-tools cd net-tools make
If you get an error about AX_CHECK_COMPILE_FLAG, install package
autoconf-archive package on Debian/Ubuntu.
For the steps below, you will need at least 4 terminal windows:
- Terminal #1 is your usual Zephyr development terminal, with the Zephyr environment initialized.
- Terminals #2, #3, and #4 are terminal windows with net-tools being the current
Before starting QEMU with network emulation, a Unix socket for the emulation should be created.
In terminal #2, type:
In terminal #3, type:
For applications requiring DNS, you may need to restart the host’s DNS server at this point, as described in Setting up Zephyr and NAT/masquerading on host to access Internet.
Build and start the
echo_server sample application.
In terminal #1, type:
west build -t run
Using CMake and ninja:
cmake -B build -GNinja -DBOARD=qemu_x86 samples/net/sockets/echo_server ninja -C build run
If you see an error from QEMU about unix:/tmp/slip.sock, it means you missed Step 1 above.
Now in terminal #4, you can run various tools to communicate with the application running in QEMU.
You can start with pings:
ping 192.0.2.1 ping6 2001:db8::1
You can use the netcat (“nc”) utility, connecting using UDP:
echo foobar | nc -6 -u 2001:db8::1 4242 foobar
echo foobar | nc -u 192.0.2.1 4242 foobar
If echo_server is compiled with TCP support (now enabled by default for the echo_server sample, CONFIG_NET_TCP=y):
echo foobar | nc -6 -q2 2001:db8::1 4242 foobar
Use Ctrl+C to exit.
You can also use the telnet command to achieve the above.
When you are finished with network testing using QEMU, you should stop any daemons or helpers started in the initial steps, to avoid possible networking or routing problems such as address conflicts in local network interfaces. For example, stop them if you switch from testing networking with QEMU to using real hardware, or to return your host laptop to normal Wi-Fi use.
To stop the daemons, press Ctrl+C in the corresponding terminal windows
(you need to stop both
To access the internet from a Zephyr application, some additional setup on the host may be required. This setup is common for both application running in QEMU and on real hardware, assuming that a development board is connected to the development host. If a board is connected to a dedicated router, it should not be needed.
To access the internet from a Zephyr application using IPv4,
a gateway should be set via DHCP or configured manually.
For applications using the “Settings” facility (with the config option
CONFIG_NET_CONFIG_MY_IPV4_GW option to the IP address
of the gateway. For apps not using the “Settings” facility, set up the
gateway by calling the
net_if_ipv4_set_gw() at runtime.
To access the internet from a custom application running in QEMU, NAT (masquerading) should be set up for QEMU’s source address. Assuming 192.0.2.1 is used, the following command should be run as root:
iptables -t nat -A POSTROUTING -j MASQUERADE -s 192.0.2.1
Additionally, IPv4 forwarding should be enabled on the host, and you may need to check that other firewall (iptables) rules don’t interfere with masquerading. To enable IPv4 forwarding the following command should be run as root:
sysctl -w net.ipv4.ip_forward=1
Some applications may also require a DNS server. A number of Zephyr-provided samples assume by default that the DNS server is available on the host (IP 192.0.2.2), which, in modern Linux distributions, usually runs at least a DNS proxy. When running with QEMU, it may be required to restart the host’s DNS, so it can serve requests on the newly created TAP interface. For example, on Debian-based systems:
service dnsmasq restart
An alternative to relying on the host’s DNS server is to use one in the
network. For example, 18.104.22.168 is a publicly available DNS server. You can
configure it using
Unlike the VM-to-Host setup described above, VM-to-VM setup is automatic. For sample applications that support this mode (such as the echo_server and echo_client samples), you will need two terminal windows, set up for Zephyr development.
west build -b qemu_x86 samples/net/sockets/echo_server
Using CMake and ninja:
cmake -B build -GNinja -DBOARD=qemu_x86 samples/net/sockets/echo_server ninja -C build server
This will start QEMU, waiting for a connection from a client QEMU.
If you find yourself wanting to run multiple instances of the same Zephyr
sample application, which do not need to talk to each other, use the
tunslip6 manually (instead of using the
loop-xxx.sh scripts) for as many instances as you want. Use the
following as a guide, replacing MAIN or OTHER.
socat PTY,link=/tmp/slip.devMAIN UNIX-LISTEN:/tmp/slip.sockMAIN $ZEPHYR_BASE/../net-tools/tunslip6 -t tapMAIN -T -s /tmp/slip.devMAIN \ 2001:db8::1/64 # Now run Zephyr make -Cbuild run QEMU_INSTANCE=MAIN