Setting up a tap device for QEMU using Yocto in Docker container

Typically it should just work but there are some catches when using a docker container environment.

NOTE: You don’t need to create a bridge between the host NIC and the TAP device.

When you run runqemu the tap device is automatically created to match the subnet of the network interface in the guest OS. See the troubleshooting section if you get errors as this point.

Below is shown the host/guest network interaces when functioning correctly.

Note, the host tap0 is set to 192.168.7.1 and the guest eth0 is set to 192.168.7.2.

Host:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 54:e1:ad:4a:57:24 brd ff:ff:ff:ff:ff:ff
    inet6 2a00:23c4:4abd:9c01:2a33:7dfb:eef1:b0e0/64 scope global temporary dynamic 
       valid_lft 292sec preferred_lft 112sec
    inet6 2a00:23c4:4abd:9c01:962:6199:2c57:594c/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 292sec preferred_lft 112sec
    inet6 fe80::ba5a:5975:9885:6770/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:97:23:f9:f6 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:97ff:fe23:f9f6/64 scope link 
       valid_lft forever preferred_lft forever
4: tap0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether e2:3e:f0:ad:5d:82 brd ff:ff:ff:ff:ff:ff
    inet 192.168.7.1/32 brd 192.168.7.255 scope global tap0
       valid_lft forever preferred_lft forever
    inet6 fe80::e03e:f0ff:fead:5d82/64 scope link 
       valid_lft forever preferred_lft forever

Guest

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 52:54:00:12:34:02 brd ff:ff:ff:ff:ff:ff
    inet 192.168.7.2/24 brd 192.168.7.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe12:3402/64 scope link 
       valid_lft forever preferred_lft forever
3: sit0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0

Prerequisites

  • Yocto build using a machine configuration that supports QEMU

Requirments

  1. The dockerfile needs the following:
  • You need to install iptables
  • You need to add password-les sudo permissions to your user: RUN echo "myuser ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers
  1. The container must be run using the host network. This is because you need access to the underlying /dev/net/tun device. So add the --network=host option to your docker run args. If you’re using VSCode this can go in your .devcontainers file.

Troubleshooting

  • If you get asked for a password after running runqemu you haven’t setup the password-less sudo permissions correctly.

  • If you get an unspecified error during runqemu you can run the command given in the output to get a clearer error message.

Leave a Reply

Your email address will not be published. Required fields are marked *