On Wed, Dec 19, 2018 at 05:32:27PM -0500, Willem de Bruijn wrote: > From: Willem de Bruijn <will...@google.com> > > 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 disables LRO for XDP. > > Virtio-net negotiates TSO4 and TSO6 separately, but ethtool does not > distinguish between the two. In the unlikely legacy case where the > host only supports one of the two, maintain the current state. > > RTNL is held while calling virtnet_set_features, same as on the path > from virtnet_xdp_set. > > Tested: > Verified that large-receive-offload is "off [fixed]" when not > negotiated during initial probe and "on" otherwise. > > Measured packet size when scp-ing a large file to the guest with > nstat (IpExtInOctets / IpInDelivers). Verified that packet size > exceeds MTU only if ethtool -k shows LRO and/or GRO as enabled. > > Signed-off-by: Willem de Bruijn <will...@google.com>
So I see a bug here: virtnet_send_command calls: /* Caller should know better */ BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)); works fine for XDP because that checks VIRTIO_NET_F_CTRL_GUEST_OFFLOADS in virtnet_xdp_set. > --- > drivers/net/virtio_net.c | 22 ++++++++++++++++++++++ > 1 file changed, 22 insertions(+) > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > index ea672145f6a66..9890ef30ef32e 100644 > --- a/drivers/net/virtio_net.c > +++ b/drivers/net/virtio_net.c > @@ -2479,6 +2479,22 @@ 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); > + int ret = 0; > + > + if ((dev->features ^ features) & NETIF_F_LRO) { > + if (features & NETIF_F_LRO) > + ret = virtnet_restore_guest_offloads(vi); > + else > + ret = virtnet_clear_guest_offloads(vi); > + } > + > + return ret; > +} > + > static const struct net_device_ops virtnet_netdev = { > .ndo_open = virtnet_open, > .ndo_stop = virtnet_close, > @@ -2493,6 +2509,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) > @@ -2942,6 +2959,11 @@ static int virtnet_probe(struct virtio_device *vdev) > dev->hw_features |= NETIF_F_TSO6; > if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) > dev->hw_features |= NETIF_F_TSO_ECN; > + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) && > + virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6)) { > + dev->hw_features |= NETIF_F_LRO; > + dev->features |= NETIF_F_LRO; > + } > > dev->features |= NETIF_F_GSO_ROBUST; > > -- > 2.20.1.415.g653613c723-goog