Move VHOST_GET_FEATURES to get_host_features() so the guest is aware of what will actually be supported. This removes the invalid guess about VIRTIO_NET_F_MRG_RXBUF (if vhost didn't support it, we shouldn't let the guest negotiate it). Note the masking of VHOST_NET_F_VIRTIO_NET_HDR when handing features to vhost. Unfortunately the vhost-net driver interprets VIRTIO_F_ANY_LAYOUT as VHOST_NET_F_VIRTIO_NET_HDR, which is specific to vhost and forces vhost-net to supply the vnet header. Since this is done by tap, we don't want to set the bit. Signed-off-by: Jean-Philippe Brucker <jean-philippe@xxxxxxxxxx> --- virtio/net.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/virtio/net.c b/virtio/net.c index 3e1aedf7..c4d20f22 100644 --- a/virtio/net.c +++ b/virtio/net.c @@ -505,21 +505,23 @@ static u64 get_host_features(struct kvm *kvm, void *dev) features |= (1UL << VIRTIO_NET_F_HOST_UFO | 1UL << VIRTIO_NET_F_GUEST_UFO); + if (ndev->vhost_fd) { + u64 vhost_features; + + if (ioctl(ndev->vhost_fd, VHOST_GET_FEATURES, &vhost_features) != 0) + die_perror("VHOST_GET_FEATURES failed"); + + features &= vhost_features; + } + return features; } static int virtio_net__vhost_set_features(struct net_dev *ndev) { - u64 features = 1UL << VIRTIO_RING_F_EVENT_IDX; - u64 vhost_features; - - if (ioctl(ndev->vhost_fd, VHOST_GET_FEATURES, &vhost_features) != 0) - die_perror("VHOST_GET_FEATURES failed"); - - /* make sure both side support mergable rx buffers */ - if (vhost_features & 1UL << VIRTIO_NET_F_MRG_RXBUF && - has_virtio_feature(ndev, VIRTIO_NET_F_MRG_RXBUF)) - features |= 1UL << VIRTIO_NET_F_MRG_RXBUF; + /* VHOST_NET_F_VIRTIO_NET_HDR clashes with VIRTIO_F_ANY_LAYOUT! */ + u64 features = ndev->vdev.features & + ~(1UL << VHOST_NET_F_VIRTIO_NET_HDR); return ioctl(ndev->vhost_fd, VHOST_SET_FEATURES, &features); } -- 2.40.1