0

I'm trying to set up host-only networking between my Linux host (running Fedora 33) and a QEMU instance (a fork for Xilinx devices), more specifically between a bridge interface (host) and a tap interface (QEMU).

When trying to connect from the host TCP client to QEMU TCP server, the host seems to ignore the SYN/ACK packet from QEMU, or at least that's what I can gather from sniffing packets on the bridge interface.

Here's what I'm doing:

  1. I'm creating a bridge interface br0, a tap interface tap0, connecting tap0 to br0, and assigning a static address 192.168.2.210/24 to the bridge.

    ip link add name br0 type bridge
    ip tuntap add name tap0 mode tap
    ip link set tap0 master br0
    ip link set br0 up
    ip link set tap0 up
    ip addr add 192.168.2.210/24 dev br0
    
  2. I'm spinning up the QEMU guest with all the relevant arguments for my target platform, plus the argument to make QEMU attach to the tap interface I have created. The interface on the guest OS has a static IP as well, in the subnet of the host's address: 192.168.2.215/24.

    ./qemu/build-v2020.1/arm-softmmu/qemu-system-arm \
            -nic tap,ifname=tap0,script=no,downscript=no \
            [PLATFORM_SPECIFIC_ARGUMENTS]
    
  3. On the host, I'm launching a Python script to connect to an open TCP port on the guest.

    import socket
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect(('192.168.2.215', 1275))
    

What happens: on the guest/TCP server, I can see the first SYN packet coming in, and the SYN/ACK packet going out. On the host/TCP client, sniffing on br0, I can see the first SYN packet going out, and the SYN/ACK packet coming in, but it looks like that SYN/ACK packet is ignored, or does not reach the Python process (I've tried with a C++ program as well, same thing). The client is stuck in sock.connect(), and a packet capture shows the client retransmitting SYN packets, as well as the server reacting to these retransmissions with more SYN/ACK packets.

No.     Time           Source                    Destination           Protocol Length Info
      1 0.000000000    fe80::e083:d7ff:fe6e:5ce2 ff02::16              ICMPv6   150    Multicast Listener Report Message v2
      2 0.000024907    192.168.2.210             224.0.0.22            IGMPv3   54     Membership Report / Join group 224.0.0.252 for any sources
      3 0.331992771    192.168.2.210             224.0.0.22            IGMPv3   54     Membership Report / Join group 224.0.0.252 for any sources
      4 0.707989061    fe80::e083:d7ff:fe6e:5ce2 ff02::16              ICMPv6   150    Multicast Listener Report Message v2
      5 5.960512301    e2:83:d7:6e:5c:e2         Broadcast             ARP      42     Who has 192.168.2.215? Tell 192.168.2.210
      6 5.967187240    02:00:00:00:00:01         e2:83:d7:6e:5c:e2     ARP      60     192.168.2.215 is at 02:00:00:00:00:01
      7 5.967225848    192.168.2.210             192.168.2.215         TCP      74     59130 → 1275 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1376754999 TSecr=0 WS=128
      8 6.002308149    192.168.2.215             192.168.2.210         TCP      66     1275 → 59130 [SYN, ACK] Seq=0 Ack=1 Win=7300 Len=0 MSS=1460 WS=1 SACK_PERM=1
      9 6.980032443    192.168.2.210             192.168.2.215         TCP      74     [TCP Retransmission] 59130 → 1275 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1376756019 TSecr=0 WS=128
     10 6.981422696    192.168.2.215             192.168.2.210         TCP      66     [TCP Retransmission] 1275 → 59130 [SYN, ACK] Seq=0 Ack=1 Win=7300 Len=0 MSS=1460 WS=1 SACK_PERM=1
     11 9.027996685    192.168.2.210             192.168.2.215         TCP      74     [TCP Retransmission] 59130 → 1275 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1376758067 TSecr=0 WS=128
     12 9.029198423    192.168.2.215             192.168.2.210         TCP      66     [TCP Retransmission] 1275 → 59130 [SYN, ACK] Seq=0 Ack=1 Win=7300 Len=0 MSS=1460 WS=1 SACK_PERM=1

Why is it that I see these SYN/ACK packets coming into br0, but somehow not reaching the socket?

Some thoughts:

  • I don't think it is a TCP checksum error: enabling checksum verification in Wireshark confirms that checksums of incoming packets is correct.
  • I don't think it is a missing ARP table entry either: in the packet capture, I can see ARP request and reply as expected. Plus, looking into the sniffed packets, MAC-layer source and destination addresses of the SYN and SYN/ACK packets look correct.
  • Can it be a firewall issue? I've tried systemctl stop firewalld.service, but I still get the same behaviour.

Details of my set-up:

0

After a little more digging into the packet capture, I realised that the SYN/ACK packets were coming in to br0 with a wrong IP checksum, which I hadn't bothered checking. The reason for this wrong checksum is that the TCP/IP stack on the guest OS was configured to offload IP checksum calculations, which the default QEMU emulated NIC does not seem to support.

Disabling IP checksum offload on the guest OS fixed the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.