short packets dropped by some network cards when using certain network backends

Host environment

  • QEMU flavor: qemu-system-XXX
  • QEMU version: 9.0.0
  • QEMU command line: script below

Emulated/Virtualized environment

  • Operating system: various

Description of problem

Effectively a duplicate of #2058 (closed) -- short ethernet packets (such as ARP packets) are discarded by various networking devices now.

QEMU previously padded ethernet frames to 64 bytes when some network cards received them, but this was removed in various commits (140eae9c, c445f200, c58da33f, 05db4476, 6d0d261d, 63b901bf, aee87b43).

969e50b6 fixed SLIRP and TAP support, however the other various network backends (socket, dgram, vde, others) all have the same issue that some network cards will reject short packets.

This does not fail on older versions of QEMU.

Steps to reproduce

I have a python script that shows connecting two VMs of your choice using a socketpair connected to one of the affected NIC types (pcnet). If you start your OS (I used alpine linux as my test), and give each VM a unique IP address (eg, ip addr add 192.168.0.1/24 dev eth0), ping will fail to work. When you run tcpdump, you can see that the OS is sending out short ARP packets, but the other VM cannot see them.

Using an older version of QEMU allows the ping to succeed.

#!/usr/bin/env python3

import argparse
import shlex
import socket
import subprocess


QEMU_PATH = "bin/qemu-system-x86_64"
NIC = "pcnet"
vnc = True

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("qcow")
    args = parser.parse_args()

    p1, p2 = socket.socketpair()

    qargs1 = [
        QEMU_PATH, "-snapshot",
        "-m", "2G",
        "-drive", f"file={args.qcow}",
        "-device", f"{NIC},netdev=n,mac=52:54:00:00:00:01",
        "-netdev", f"socket,id=n,fd={p1.fileno()}"
    ]
    if vnc:
        qargs1 += ["-display", "vnc=:2"]

    print("+", shlex.join(qargs1))
    proc1 = subprocess.Popen(qargs1, pass_fds=[p1.fileno()])

    qargs2 = [
        QEMU_PATH, "-snapshot",
        "-m", "2G",
        "-drive", f"file={args.qcow}",
        "-device", f"{NIC},netdev=n,mac=52:54:00:00:00:02",
        "-netdev", f"socket,id=n,fd={p2.fileno()}"
    ]
    if vnc:
        qargs2 += ["-display", "vnc=:3"]

    print("+", shlex.join(qargs2))
    proc2 = subprocess.Popen(qargs2, pass_fds=[p2.fileno()])

    proc1.wait()
    proc2.wait()
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information