Commit 592bb52d87 for qemu.org

commit 592bb52d87a1a07172656a91cf5c38f63b5f6c60
Author: Nariman Sayed <narimansayed28@gmail.com>
Date:   Wed Oct 7 08:07:18 2026 +0300

    virtio-net: add mtu-from-tap property for automatic MTU detection

    Currently, exposing the host tap device's MTU to the guest via
    VIRTIO_NET_F_MTU requires manually specifying host_mtu= on the
    virtio-net-pci device, duplicating the MTU already configured on
    the host's tap interface.

    Add a new mtu-from-tap boolean property (default off, preserving
    existing behavior). When enabled, the netdev peer's MTU is queried
    via the generic qemu_get_mtu() and used to set net_conf.mtu and
    enable VIRTIO_NET_F_MTU, regardless of the backend's type.

    This detection must happen in virtio_net_device_realize(), before
    virtio_net_set_config_size() computes the virtio config space
    size from host_features. Performing the detection later (e.g. in
    the get_features_ex() callback, which runs after the NIC and its
    config space are already sized) results in the mtu config field
    falling outside the sized config space, and the guest reading
    back an unmapped garbage value (0xffff) instead of the intended
    MTU.

    Since qemu_new_nic() has not yet been called at this point in
    realize(), the peer is accessed via n->nic_conf.peers.ncs[0]
    (populated during property parsing, before realize() runs, via
    the netdev= property) rather than through n->nic.

    Signed-off-by: Nariman Sayed <narimansayed28@gmail.com>
    Tested-by: Aniket Sahu <asahu1x@linux.ibm.com>
    Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
    Acked-by: Eugenio Pérez <eperezma@redhat.com>
    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
    Message-ID: <20261007050718.926-4-narimansayed28@gmail.com>

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 4794496b96..54e42cfec9 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -4006,6 +4006,15 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
         n->host_features |= (1ULL << VIRTIO_NET_F_MTU);
     }

+    if (n->net_conf.mtu_from_tap) {
+        NetClientState *peer = n->nic_conf.peers.ncs[0];
+        int mtu = qemu_get_mtu(peer);
+        if (mtu > 0) {
+            n->net_conf.mtu = mtu;
+            n->host_features |= (1ULL << VIRTIO_NET_F_MTU);
+        }
+    }
+
     if (n->net_conf.duplex_str) {
         if (strncmp(n->net_conf.duplex_str, "half", 5) == 0) {
             n->net_conf.duplex = DUPLEX_HALF;
@@ -4386,6 +4395,7 @@ static const Property virtio_net_properties[] = {
     DEFINE_PROP_UINT16("tx_queue_size", VirtIONet, net_conf.tx_queue_size,
                        VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE),
     DEFINE_PROP_UINT16("host_mtu", VirtIONet, net_conf.mtu, 0),
+    DEFINE_PROP_BOOL("mtu-from-tap", VirtIONet, net_conf.mtu_from_tap, false),
     DEFINE_PROP_INT32("speed", VirtIONet, net_conf.speed, SPEED_UNKNOWN),
     DEFINE_PROP_STRING("duplex", VirtIONet, net_conf.duplex_str),
     DEFINE_PROP_BOOL("failover", VirtIONet, failover, false),
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index 8c967760c2..fed37245be 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -52,6 +52,7 @@ typedef struct virtio_net_conf
     uint16_t rx_queue_size;
     uint16_t tx_queue_size;
     uint16_t mtu;
+    bool mtu_from_tap;
     int32_t speed;
     char *duplex_str;
     uint8_t duplex;