Part 1
요약·해설
Helper socket과 routing daemon의 수명주기부터 IPv4/IPv6 test, masquerading·DNS와 QEMU_INSTANCE 분리까지 설명합니다.
socat · tunslip6 · TAP
Gateway · NAT · DNS
Server/client · Instances
Part 2
접을 수 있는 영어 원문 전체
영어 원문 전체 펼치기
A2B32D91158E16DBD3133FAAEF82DD21AE760BDDC79BE782194E5EE9210AF296
.. _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, fetch the Zephyr ``net-tools`` project, which is located
in a separate Git repository:
.. code-block:: console
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
$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
Terminal #2:
============
.. code-block:: console
socat PTY,link=/tmp/slip.devOTHER UNIX-LISTEN:/tmp/slip.sockOTHER
$ZEPHYR_BASE/../net-tools/tunslip6 -t tapOTHER -T -s /tmp/slip.devOTHER \
2001:db8::1/64
make -Cbuild run QEMU_INSTANCE=OTHER
Part 3
한국어 전문 번역
QEMU Networking
이 문서는 Linux host와 qemu_x86·qemu_cortex_m3 같은 Zephyr target용 QEMU virtual machine에서 실행하는 Zephyr application 사이에 virtual network를 설정하는 방법을 설명합니다.
qemu_cortex_a53처럼 UART 하나만 지원하는 virtual ARM board에서는 QEMU Ethernet 방식이 더 적합합니다.
예제는 QEMU에서 sockets echo server sample을 실행합니다. QEMU instance를 serial port로 Linux host에 연결하고 여러 virtual connection을 거쳐 SLIP으로 Zephyr application과 Linux 사이에 data를 전달합니다.
사전 준비
Linux host에서 별도 Git repository의 Zephyr net-tools project를 내려받아 build합니다.
git clone https://github.com/zephyrproject-rtos/net-tools
cd net-tools
make기본 설정
아래 절차에는 terminal window가 최소 네 개 필요합니다.
Terminal #1: Zephyr environment를 초기화한 development terminalTerminal #2,#3,#4: net-tools를 현재 directory로 둔 terminal(cd net-tools)
1단계: Helper socket 생성
Network emulation을 사용하는 QEMU를 시작하기 전에 emulation용 Unix socket을 만듭니다. Terminal #2에서 실행합니다.
./loop-socat.sh2단계: TAP routing daemon 시작
Terminal #3에서 다음 명령을 실행합니다.
sudo ./loop-slip-tap.shDNS가 필요한 application이라면 이 시점에 host DNS server를 다시 시작해야 할 수 있습니다.
3단계: QEMU에서 application 시작
Terminal #1에서 samples/net/sockets/echo_server를 qemu_x86 board용으로 build하고 run target을 실행합니다.
unix:/tmp/slip.sock 관련 QEMU error가 나타나면 1단계 helper socket을 만들지 않은 것입니다.
4단계: Host application 실행
Terminal #4에서 QEMU application과 통신할 여러 host tool을 실행할 수 있습니다. 먼저 IPv4와 IPv6 ping을 확인합니다.
ping 192.0.2.1
ping6 2001:db8::1Netcat(nc)으로 IPv6 UDP를 확인합니다.
echo foobar | nc -6 -u 2001:db8::1 4242
foobarIPv4 UDP도 확인합니다.
echo foobar | nc -u 192.0.2.1 4242
foobarCONFIG_NET_TCP=y로 echo server의 TCP 지원을 켰다면 현재 기본값으로 활성화된 TCP를 다음처럼 시험합니다.
echo foobar | nc -6 -q2 2001:db8::1 4242
foobar5단계: 지원 daemon 종료
QEMU network test가 끝나면 초기 단계에서 시작한 daemon과 helper를 중지해야 합니다. 그대로 두면 local interface address conflict 같은 networking·routing 문제가 생길 수 있습니다.
loop-slip-tap.sh와 loop-socat.sh를 실행한 terminal에서 각각 Ctrl+C를 눌러 둘 다 중지합니다. 실제 hardware test로 전환하거나 host laptop의 일반 Wi-Fi 사용 상태를 복원할 때도 필요합니다.
CTRL+A를 누른 뒤 x를 눌러 QEMU를 종료합니다.
Zephyr의 Internet 접근을 위한 host NAT·masquerading
Zephyr application에서 Internet에 접근하려면 host 추가 설정이 필요할 수 있습니다. QEMU application과 development host에 직접 연결한 실제 board 모두에 공통이며, board가 전용 router에 연결돼 있다면 필요하지 않습니다.
IPv4 Internet 접근에는 DHCP 또는 수동 설정으로 gateway를 지정해야 합니다. Settings facility에서 CONFIG_NET_CONFIG_SETTINGS를 켠 application은 CONFIG_NET_CONFIG_MY_IPV4_GW에 gateway IP를 설정합니다.
Settings facility를 쓰지 않으면 runtime에 net_if_ipv4_set_gw()를 호출합니다. 예제 gateway는 CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"입니다.
QEMU의 custom application에는 source address NAT(masquerading)를 설정합니다. QEMU address가 192.0.2.1, Zephyr interface가 zeth라고 가정하면 root로 다음을 실행합니다.
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 ACCEPTHost에서 IPv4 forwarding도 활성화하고 다른 firewall(iptables) rule이 masquerading을 방해하지 않는지 확인합니다.
sysctl -w net.ipv4.ip_forward=1여러 Zephyr sample은 host 192.0.2.2에서 DNS server 또는 proxy를 사용할 수 있다고 가정합니다. QEMU 실행 시 새 TAP interface의 request를 처리하도록 Debian 계열 host DNS를 다시 시작해야 할 수 있습니다.
service dnsmasq restartHost DNS 대신 public DNS 8.8.8.8 같은 network server를 CONFIG_DNS_SERVER1로 지정할 수도 있습니다.
두 QEMU VM 사이 network 연결
앞의 VM-to-host 설정과 달리 VM-to-VM 설정은 자동입니다. 이 mode를 지원하는 echo server와 echo client에는 Zephyr development terminal 두 개가 필요합니다.
Terminal #1: Server
qemu_x86용 sockets echo server를 server build argument로 build합니다. QEMU가 시작돼 client QEMU connection을 기다립니다.
Terminal #2: Client
qemu_x86용 sockets echo client를 client build argument로 build합니다. 두 번째 QEMU가 시작되고 양쪽에서 송수신 log를 볼 수 있습니다.
같은 sample의 QEMU VM 여러 개 실행
서로 통신할 필요가 없는 동일 Zephyr sample instance를 여러 개 실행하려면 QEMU_INSTANCE argument를 사용합니다.
loop-xxx.sh 대신 instance 수만큼 socat과 tunslip6를 수동으로 시작하고 MAIN 또는 OTHER를 각 instance 이름으로 사용합니다.
Terminal #1: MAIN instance
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=MAINTerminal #2: OTHER instance
socat PTY,link=/tmp/slip.devOTHER UNIX-LISTEN:/tmp/slip.sockOTHER
$ZEPHYR_BASE/../net-tools/tunslip6 -t tapOTHER -T -s /tmp/slip.devOTHER \
2001:db8::1/64
make -Cbuild run QEMU_INSTANCE=OTHER
Source
출처
영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.