Skip to content

Commit a02e896

Browse files
wdebruijdavem330
authored andcommitted
virtio-net: ethtool configurable LRO
Virtio-net devices negotiate LRO support with the host. Display the initially negotiated state with ethtool -k. Also allow configuring it with ethtool -K, reusing the existing virtnet_set_guest_offloads helper that configures LRO for XDP. This is conditional on VIRTIO_NET_F_CTRL_GUEST_OFFLOADS. Virtio-net negotiates TSO4 and TSO6 separately, but ethtool does not distinguish between the two. Display LRO as on only if any offload is active. RTNL is held while calling virtnet_set_features, same as on the path from virtnet_xdp_set. Changes v1 -> v2 - allow ethtool config (-K) only if VIRTIO_NET_F_CTRL_GUEST_OFFLOADS - show LRO as enabled if any LRO variant is enabled - do not allow configuration while XDP is active - differentiate current features from the capable set, to restore on XDP down only those features that were active on XDP up - move test out of VIRTIO_NET_F_CSUM/TSO branch, which is tx only Signed-off-by: Willem de Bruijn <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c3e5336 commit a02e896

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

drivers/net/virtio_net.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ struct virtnet_info {
236236
u32 speed;
237237

238238
unsigned long guest_offloads;
239+
unsigned long guest_offloads_capable;
239240

240241
/* failover when STANDBY feature enabled */
241242
struct failover *failover;
@@ -2479,6 +2480,31 @@ static int virtnet_get_phys_port_name(struct net_device *dev, char *buf,
24792480
return 0;
24802481
}
24812482

2483+
static int virtnet_set_features(struct net_device *dev,
2484+
netdev_features_t features)
2485+
{
2486+
struct virtnet_info *vi = netdev_priv(dev);
2487+
u64 offloads;
2488+
int err;
2489+
2490+
if ((dev->features ^ features) & NETIF_F_LRO) {
2491+
if (vi->xdp_queue_pairs)
2492+
return -EBUSY;
2493+
2494+
if (features & NETIF_F_LRO)
2495+
offloads = vi->guest_offloads_capable;
2496+
else
2497+
offloads = 0;
2498+
2499+
err = virtnet_set_guest_offloads(vi, offloads);
2500+
if (err)
2501+
return err;
2502+
vi->guest_offloads = offloads;
2503+
}
2504+
2505+
return 0;
2506+
}
2507+
24822508
static const struct net_device_ops virtnet_netdev = {
24832509
.ndo_open = virtnet_open,
24842510
.ndo_stop = virtnet_close,
@@ -2493,6 +2519,7 @@ static const struct net_device_ops virtnet_netdev = {
24932519
.ndo_xdp_xmit = virtnet_xdp_xmit,
24942520
.ndo_features_check = passthru_features_check,
24952521
.ndo_get_phys_port_name = virtnet_get_phys_port_name,
2522+
.ndo_set_features = virtnet_set_features,
24962523
};
24972524

24982525
static void virtnet_config_changed_work(struct work_struct *work)
@@ -2951,6 +2978,11 @@ static int virtnet_probe(struct virtio_device *vdev)
29512978
}
29522979
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
29532980
dev->features |= NETIF_F_RXCSUM;
2981+
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
2982+
virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
2983+
dev->features |= NETIF_F_LRO;
2984+
if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))
2985+
dev->hw_features |= NETIF_F_LRO;
29542986

29552987
dev->vlan_features = dev->features;
29562988

@@ -3080,6 +3112,7 @@ static int virtnet_probe(struct virtio_device *vdev)
30803112
for (i = 0; i < ARRAY_SIZE(guest_offloads); i++)
30813113
if (virtio_has_feature(vi->vdev, guest_offloads[i]))
30823114
set_bit(guest_offloads[i], &vi->guest_offloads);
3115+
vi->guest_offloads_capable = vi->guest_offloads;
30833116

30843117
pr_debug("virtnet: registered device %s with %d RX and TX vq's\n",
30853118
dev->name, max_queue_pairs);

0 commit comments

Comments
 (0)