Skip to content

Commit

Permalink
virtio-net: enable mrg buf header in tap on linux
Browse files Browse the repository at this point in the history
Modern linux supports arbitrary header size,
which makes it possible to pass mrg buf header
to tap directly without iovec mangling.
Use this capability when it is there.

This removes the need to deal with it in
vhost-net as we do now.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
mstsirkin committed Oct 29, 2012
1 parent 6e371ab commit ff3a806
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 21 deletions.
13 changes: 0 additions & 13 deletions hw/vhost_net.c
Expand Up @@ -150,10 +150,6 @@ int vhost_net_start(struct vhost_net *net,
if (r < 0) {
goto fail_notifiers;
}
if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
tap_set_vnet_hdr_len(net->nc,
sizeof(struct virtio_net_hdr_mrg_rxbuf));
}

r = vhost_dev_start(&net->dev, dev);
if (r < 0) {
Expand All @@ -179,9 +175,6 @@ int vhost_net_start(struct vhost_net *net,
}
net->nc->info->poll(net->nc, true);
vhost_dev_stop(&net->dev, dev);
if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr));
}
fail_start:
vhost_dev_disable_notifiers(&net->dev, dev);
fail_notifiers:
Expand All @@ -199,18 +192,12 @@ void vhost_net_stop(struct vhost_net *net,
}
net->nc->info->poll(net->nc, true);
vhost_dev_stop(&net->dev, dev);
if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr));
}
vhost_dev_disable_notifiers(&net->dev, dev);
}

void vhost_net_cleanup(struct vhost_net *net)
{
vhost_dev_cleanup(&net->dev);
if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
tap_set_vnet_hdr_len(net->nc, sizeof(struct virtio_net_hdr));
}
g_free(net);
}
#else
Expand Down
26 changes: 18 additions & 8 deletions hw/virtio-net.c
Expand Up @@ -228,6 +228,20 @@ static int peer_has_ufo(VirtIONet *n)
return n->has_ufo;
}

static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs)
{
n->mergeable_rx_bufs = mergeable_rx_bufs;

n->guest_hdr_len = n->mergeable_rx_bufs ?
sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);

if (peer_has_vnet_hdr(n) &&
tap_has_vnet_hdr_len(n->nic->nc.peer, n->guest_hdr_len)) {
tap_set_vnet_hdr_len(n->nic->nc.peer, n->guest_hdr_len);
n->host_hdr_len = n->guest_hdr_len;
}
}

static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
{
VirtIONet *n = to_virtio_net(vdev);
Expand Down Expand Up @@ -280,9 +294,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
{
VirtIONet *n = to_virtio_net(vdev);

n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF));
n->guest_hdr_len = n->mergeable_rx_bufs ?
sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
virtio_net_set_mrg_rx_bufs(n, !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)));

if (n->has_vnet_hdr) {
tap_set_offload(n->nic->nc.peer,
Expand Down Expand Up @@ -898,9 +910,8 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)

qemu_get_buffer(f, n->mac, ETH_ALEN);
n->tx_waiting = qemu_get_be32(f);
n->mergeable_rx_bufs = qemu_get_be32(f);
n->guest_hdr_len = n->mergeable_rx_bufs ?
sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);

virtio_net_set_mrg_rx_bufs(n, qemu_get_be32(f));

if (version_id >= 3)
n->status = qemu_get_be16(f);
Expand Down Expand Up @@ -1050,8 +1061,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,

n->tx_waiting = 0;
n->tx_burst = net->txburst;
n->mergeable_rx_bufs = 0;
n->guest_hdr_len = sizeof(struct virtio_net_hdr);
virtio_net_set_mrg_rx_bufs(n, 0);
n->promisc = 1; /* for compatibility */

n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
Expand Down

0 comments on commit ff3a806

Please sign in to comment.