.. _networking_with_qemu:

Networking with QEMU
####################

.. contents::
    :local:
    :depth: 2

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). Some virtual ARM boards (such as
qemu_cortex_a53) only support a single UART, in this case QEMU Ethernet is
preferred, see :ref:`networking_with_eth_qemu` for details.

In this example, the :zephyr:code-sample:`sockets-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).

Prerequisites
*************

On the Linux Host, find the Zephyr `net-tools`_ project, which can either be
found in a Zephyr standard installation under the ``tools/net-tools`` directory
or installed stand alone from its own git repository:

.. code-block:: console

   sudo apt install -y socat libpcap-dev
   git clone https://github.com/zephyrproject-rtos/net-tools
   cd net-tools
   make

.. note::

   If you get an error about AX_CHECK_COMPILE_FLAG, install package
   ``autoconf-archive`` package on Debian/Ubuntu.

Basic Setup
***********

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
  directory (``cd net-tools``)

Step 1 - Create helper socket
=============================

Before starting QEMU with network emulation, a Unix socket for the emulation
should be created.

In terminal #2, type:

.. code-block:: console

   ./loop-socat.sh

Step 2 - Start TAP device routing daemon
========================================

In terminal #3, type:


.. code-block:: console

   sudo ./loop-slip-tap.sh

For applications requiring DNS, you may need to restart the host's DNS server
at this point, as described in :ref:`networking_internet`.

Step 3 - Start app in QEMU
==========================

Build and start the ``echo_server`` sample application.

In terminal #1, type:

.. zephyr-app-commands::
   :zephyr-app: samples/net/sockets/echo_server
   :host-os: unix
   :board: qemu_x86
   :goals: run
   :compact:

If you see an error from QEMU about unix:/tmp/slip.sock, it means you missed Step 1
above.

Step 4 - Run apps on host
=========================

Now in terminal #4, you can run various tools to communicate with the
application running in QEMU.

You can start with pings:

.. code-block:: console

   ping 192.0.2.1
   ping6 2001:db8::1

You can use the netcat ("nc") utility, connecting using UDP:

.. code-block:: console

   echo foobar | nc -6 -u 2001:db8::1 4242
   foobar

.. code-block:: console

   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):

.. code-block:: console

   echo foobar | nc -6 -q2 2001:db8::1 4242
   foobar

.. note::

   Use Ctrl+C to exit.

You can also use the telnet command to achieve the above.

Step 5 - Stop supporting daemons
================================

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 ``loop-slip-tap.sh`` and ``loop-socat.sh``).

Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`.

.. _networking_internet:

Setting up Zephyr and NAT/masquerading on host to access Internet
*****************************************************************

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
:kconfig:option:`CONFIG_NET_CONFIG_SETTINGS` enabled),
set the :kconfig: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 :c:func:`net_if_ipv4_set_gw` at runtime.
For example: ``CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"``

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 and the Zephyr network interface is ``zeth``, the following command should be run as root:

.. code-block:: console

   iptables -t nat -A POSTROUTING -j MASQUERADE -s 192.0.2.1/24
   iptables -I FORWARD 1 -i zeth -j ACCEPT
   iptables -I FORWARD 1 -o zeth -m state --state RELATED,ESTABLISHED -j ACCEPT

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:

.. code-block:: console

   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:

.. code-block:: console

   service dnsmasq restart

An alternative to relying on the host's DNS server is to use one in the
network. For example, ``8.8.8.8`` is a publicly available DNS server. You can
configure it using :kconfig:option:`CONFIG_DNS_SERVER1` option.


Network connection between two QEMU VMs
***************************************

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.

Terminal #1:
============

.. zephyr-app-commands::
   :zephyr-app: samples/net/sockets/echo_server
   :host-os: unix
   :board: qemu_x86
   :goals: build
   :build-args: server
   :compact:

This will start QEMU, waiting for a connection from a client QEMU.

Terminal #2:
============

.. zephyr-app-commands::
   :zephyr-app: samples/net/sockets/echo_client
   :host-os: unix
   :board: qemu_x86
   :goals: build
   :build-args: client
   :compact:

This will start a second QEMU instance, where you should see logging of data sent and
received in both.

Running multiple QEMU VMs of the same sample
********************************************

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
``QEMU_INSTANCE`` argument.

Start ``socat`` and ``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.

Terminal #1:
============

.. code-block:: console

   socat PTY,link=/tmp/slip.devMAIN UNIX-LISTEN:/tmp/slip.sockMAIN &
   sudo $ZEPHYR_BASE/../tools/net-tools/tunslip6 -t tapMAIN -T -s /tmp/slip.devMAIN 2001:db8::1/64 &
   # Now run Zephyr
   make -Cbuild run QEMU_INSTANCE=MAIN

Terminal #2:
============

.. code-block:: console

   socat PTY,link=/tmp/slip.devOTHER UNIX-LISTEN:/tmp/slip.sockOTHER &
   sudo $ZEPHYR_BASE/../tools/net-tools/tunslip6 -t tapOTHER -T -s /tmp/slip.devOTHER 2001:db8::1/64 &
   make -Cbuild run QEMU_INSTANCE=OTHER

.. _`net-tools`: https://github.com/zephyrproject-rtos/net-tools
