QEMU:在具有 tap 接口的仅主机网络中,主机上忽略 SYN/ACK

QEMU:在具有 tap 接口的仅主机网络中,主机上忽略 SYN/ACK

我正在尝试在我的 Linux 主机(运行 Fedora 33)和 QEMU 实例(Xilinx 设备的分支)之间建立仅主机网络,更具体地说是在桥接接口(主机)和 tap 接口(QEMU)之间建立。

当尝试从主机 TCP 客户端连接到 QEMU TCP 服务器时,主机似乎忽略了来自 QEMU 的 SYN/ACK 数据包,或者至少这是我从桥接接口上的嗅探数据包中可以收集到的信息。

以下是我正在做的事情:

  1. 我正在创建一个桥接接口br0、一个分接接口tap0、连接tap0br0192.168.2.210/24为桥接接口分配一个静态地址。

    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. 我正在使用目标平台的所有相关参数以及使 QEMU 连接到我创建的 tap 接口的参数来启动 QEMU 客户机。客户机操作系统上的接口也有一个静态 IP,位于主机地址的子网中: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. 在主机上,我启动一个 Python 脚本来连接到客户机上的开放 TCP 端口。

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

发生了什么:在客户机/TCP 服务器上,我可以看到第一个 SYN 数据包进来,SYN/ACK 数据包出去。在主机/TCP 客户端上,嗅探时br0,我可以看到第一个 SYN 数据包出去,SYN/ACK 数据包进来,但看起来 SYN/ACK 数据包被忽略了,或者没有到达 Python 进程(我也尝试过使用 C++ 程序,结果相同)。客户端卡在了 中sock.connect(),数据包捕获显示客户端正在重新传输 SYN 数据包,而服务器正在用更多 SYN/ACK 数据包对这些重新传输做出反应。

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

为什么我看到这些 SYN/ACK 数据包进入br0,但却无法到达套接字?

一些想法:

  • 我不认为这是一个 TCP 校验和错误:在 Wireshark 中启用校验和验证可确认传入数据包的校验和是正确的。
  • 我也不认为这是由于缺少 ARP 表条目造成的:在数据包捕获中,我可以看到 ARP 请求和回复符合预期。此外,查看嗅探到的数据包,SYN 和 SYN/ACK 数据包的 MAC 层源地址和目标地址看起来是正确的。
  • 这可能是防火墙问题吗?我试过了systemctl stop firewalld.service,但仍然出现同样的情况。

我的设置细节:

  • 主机操作系统:Fedora 33
  • 客户操作系统:带有 TCP 堆栈的裸机 FreeRTOS
  • 适用于 Xilinx 设备的 QEMU 分支(https://github.com/Xilinx/qemu

答案1

在对数据包捕获进行进一步分析后,我意识到 SYN/ACK 数据包br0是以错误的 IP 校验和,我没费心去检查。这个错误校验和的原因是客户操作系统上的 TCP/IP 堆栈配置为卸载 IP 校验和计算,而默认的 QEMU 模拟 NIC 似乎不支持该计算。

在客户操作系统上禁用 IP 校验和卸载可解决该问题。

相关内容