virtio-net: enable NETIF_F_GRO_HW only if GRO-related offloads are supported

Negotiating VIRTIO_NET_F_CTRL_GUEST_OFFLOADS indicates the device
allows control over offload support, but the offloads that can be
controlled may have nothing to do with GRO (e.g., if neither GUEST_TSO4
nor GUEST_TSO6 is supported).

In such a setup, reporting NETIF_F_GRO_HW as available for the device
is too optimistic and misleading to the user.

Improve the situation by masking off NETIF_F_GRO_HW unless the device
possesses actual GRO-related offload capabilities. Out of an abundance
of caution, this does not change the current behaviour for hardware with
just v6 or just v4 GRO: current interfaces do not allow distinguishing
between v6/v4 GRO, so we can't expose them to userspace precisely.

Signed-off-by: Di Zhu <zhud@hygon.cn>
Acked-by: Jason Wang <jasowang@redhat.com>
Link: https://patch.msgid.link/20260323041730.986351-1-zhud@hygon.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Di Zhu 2026-03-23 12:17:30 +08:00 committed by Jakub Kicinski
parent 6a539eee85
commit f8844dfeea

View File

@ -6800,8 +6800,6 @@ static int virtnet_probe(struct virtio_device *vdev)
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
dev->features |= NETIF_F_GRO_HW;
if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))
dev->hw_features |= NETIF_F_GRO_HW;
dev->vlan_features = dev->features;
dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
@ -6994,6 +6992,19 @@ static int virtnet_probe(struct virtio_device *vdev)
enable_rx_mode_work(vi);
for (i = 0; i < ARRAY_SIZE(guest_offloads); i++) {
unsigned int fbit;
fbit = virtio_offload_to_feature(guest_offloads[i]);
if (virtio_has_feature(vi->vdev, fbit))
set_bit(guest_offloads[i], &vi->guest_offloads);
}
vi->guest_offloads_capable = vi->guest_offloads;
if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) &&
(vi->guest_offloads_capable & GUEST_OFFLOAD_GRO_HW_MASK))
dev->hw_features |= NETIF_F_GRO_HW;
/* serialize netdev register + virtio_device_ready() with ndo_open() */
rtnl_lock();
@ -7076,15 +7087,6 @@ static int virtnet_probe(struct virtio_device *vdev)
netif_carrier_on(dev);
}
for (i = 0; i < ARRAY_SIZE(guest_offloads); i++) {
unsigned int fbit;
fbit = virtio_offload_to_feature(guest_offloads[i]);
if (virtio_has_feature(vi->vdev, fbit))
set_bit(guest_offloads[i], &vi->guest_offloads);
}
vi->guest_offloads_capable = vi->guest_offloads;
rtnl_unlock();
err = virtnet_cpu_notif_add(vi);