From a93e599d4a04c3cf7edcf5a24f3397e27431c027 Mon Sep 17 00:00:00 2001 From: Maxime Coquelin Date: Sat, 10 Dec 2016 16:30:38 +0100 Subject: [PATCH] virtio-net: Add MTU feature support This patch allows advising guest with host MTU's by setting host_mtu parameter. If VIRTIO_NET_F_MTU has been successfully negotiated, MTU value is passed to the backend. Cc: Michael S. Tsirkin Cc: Aaron Conole Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/net/virtio-net.c | 19 +++++++++++++++++++ include/hw/virtio/virtio-net.h | 1 + 2 files changed, 20 insertions(+) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 6f98eab2ba..7b3ad4a9f0 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -55,6 +55,8 @@ static VirtIOFeature feature_sizes[] = { .end = endof(struct virtio_net_config, status)}, {.flags = 1 << VIRTIO_NET_F_MQ, .end = endof(struct virtio_net_config, max_virtqueue_pairs)}, + {.flags = 1 << VIRTIO_NET_F_MTU, + .end = endof(struct virtio_net_config, mtu)}, {} }; @@ -81,6 +83,7 @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config) virtio_stw_p(vdev, &netcfg.status, n->status); virtio_stw_p(vdev, &netcfg.max_virtqueue_pairs, n->max_queues); + virtio_stw_p(vdev, &netcfg.mtu, n->net_conf.mtu); memcpy(netcfg.mac, n->mac, ETH_ALEN); memcpy(config, &netcfg, n->config_size); } @@ -152,6 +155,16 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status) qemu_net_queue_purge(qnc->incoming_queue, qnc->peer); } + if (virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_MTU)) { + r = vhost_net_set_mtu(get_vhost_net(nc->peer), n->net_conf.mtu); + if (r < 0) { + error_report("%uBytes MTU not supported by the backend", + n->net_conf.mtu); + + return; + } + } + n->vhost_started = 1; r = vhost_net_start(vdev, n->nic->ncs, queues); if (r < 0) { @@ -1721,6 +1734,7 @@ static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features) { int i, config_size = 0; virtio_add_feature(&host_features, VIRTIO_NET_F_MAC); + for (i = 0; feature_sizes[i].flags != 0; i++) { if (host_features & feature_sizes[i].flags) { config_size = MAX(feature_sizes[i].end, config_size); @@ -1750,6 +1764,10 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) NetClientState *nc; int i; + if (n->net_conf.mtu) { + n->host_features |= (0x1 << VIRTIO_NET_F_MTU); + } + virtio_net_set_config_size(n, n->host_features); virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size); @@ -1948,6 +1966,7 @@ static Property virtio_net_properties[] = { DEFINE_PROP_STRING("tx", VirtIONet, net_conf.tx), DEFINE_PROP_UINT16("rx_queue_size", VirtIONet, net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE), + DEFINE_PROP_UINT16("host_mtu", VirtIONet, net_conf.mtu, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 0ced975c57..8ea56a8f60 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -36,6 +36,7 @@ typedef struct virtio_net_conf int32_t txburst; char *tx; uint16_t rx_queue_size; + uint16_t mtu; } virtio_net_conf; /* Maximum packet size we can receive from tap device: header + 64k */