mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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 <willemb@google.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									c3e5336925
								
							
						
					
					
						commit
						a02e8964ea
					
				
					 1 changed files with 33 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -236,6 +236,7 @@ struct virtnet_info {
 | 
			
		|||
	u32 speed;
 | 
			
		||||
 | 
			
		||||
	unsigned long guest_offloads;
 | 
			
		||||
	unsigned long guest_offloads_capable;
 | 
			
		||||
 | 
			
		||||
	/* failover when STANDBY feature enabled */
 | 
			
		||||
	struct failover *failover;
 | 
			
		||||
| 
						 | 
				
			
			@ -2479,6 +2480,31 @@ static int virtnet_get_phys_port_name(struct net_device *dev, char *buf,
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int virtnet_set_features(struct net_device *dev,
 | 
			
		||||
				netdev_features_t features)
 | 
			
		||||
{
 | 
			
		||||
	struct virtnet_info *vi = netdev_priv(dev);
 | 
			
		||||
	u64 offloads;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((dev->features ^ features) & NETIF_F_LRO) {
 | 
			
		||||
		if (vi->xdp_queue_pairs)
 | 
			
		||||
			return -EBUSY;
 | 
			
		||||
 | 
			
		||||
		if (features & NETIF_F_LRO)
 | 
			
		||||
			offloads = vi->guest_offloads_capable;
 | 
			
		||||
		else
 | 
			
		||||
			offloads = 0;
 | 
			
		||||
 | 
			
		||||
		err = virtnet_set_guest_offloads(vi, offloads);
 | 
			
		||||
		if (err)
 | 
			
		||||
			return err;
 | 
			
		||||
		vi->guest_offloads = offloads;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct net_device_ops virtnet_netdev = {
 | 
			
		||||
	.ndo_open            = virtnet_open,
 | 
			
		||||
	.ndo_stop   	     = virtnet_close,
 | 
			
		||||
| 
						 | 
				
			
			@ -2493,6 +2519,7 @@ static const struct net_device_ops virtnet_netdev = {
 | 
			
		|||
	.ndo_xdp_xmit		= virtnet_xdp_xmit,
 | 
			
		||||
	.ndo_features_check	= passthru_features_check,
 | 
			
		||||
	.ndo_get_phys_port_name	= virtnet_get_phys_port_name,
 | 
			
		||||
	.ndo_set_features	= virtnet_set_features,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void virtnet_config_changed_work(struct work_struct *work)
 | 
			
		||||
| 
						 | 
				
			
			@ -2951,6 +2978,11 @@ static int virtnet_probe(struct virtio_device *vdev)
 | 
			
		|||
	}
 | 
			
		||||
	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
 | 
			
		||||
		dev->features |= NETIF_F_RXCSUM;
 | 
			
		||||
	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
 | 
			
		||||
	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
 | 
			
		||||
		dev->features |= NETIF_F_LRO;
 | 
			
		||||
	if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))
 | 
			
		||||
		dev->hw_features |= NETIF_F_LRO;
 | 
			
		||||
 | 
			
		||||
	dev->vlan_features = dev->features;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3080,6 +3112,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 | 
			
		|||
	for (i = 0; i < ARRAY_SIZE(guest_offloads); i++)
 | 
			
		||||
		if (virtio_has_feature(vi->vdev, guest_offloads[i]))
 | 
			
		||||
			set_bit(guest_offloads[i], &vi->guest_offloads);
 | 
			
		||||
	vi->guest_offloads_capable = vi->guest_offloads;
 | 
			
		||||
 | 
			
		||||
	pr_debug("virtnet: registered device %s with %d RX and TX vq's\n",
 | 
			
		||||
		 dev->name, max_queue_pairs);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue