From d69aa50cc1da54200db61b797e782f2a158f2a2e Mon Sep 17 00:00:00 2001
Message-Id: <d69aa50cc1da54200db61b797e782f2a158f2a2e.1334064600.git.minovotn@redhat.com>
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Thu, 29 Mar 2012 14:09:47 +0200
Subject: [PATCH 1/2] macvtap: rhel6.2 compatibility

RH-Author: Michael S. Tsirkin <mst@redhat.com>
Message-id: <20120329140947.GB14070@redhat.com>
Patchwork-id: 39028
O-Subject: [PATCHv2 RHEL6.3] macvtap: rhel6.2 compatibility
Bugzilla: 806975
RH-Acked-by: Xiao Wang <jasowang@redhat.com>
RH-Acked-by: Amos Kong <akong@redhat.com>
RH-Acked-by: Amit Shah <amit.shah@redhat.com>

It turns out that because of
https://bugzilla.redhat.com/show_bug.cgi?id=789362
rhel6.2 kernel macvtap does not support rx mergeable
buffers when used with vhost-net.
Since this is a guest visible feature we can not
change it. Also, we don't currently know whether
a device has macvtap backend.

As a solution, add a rhel specific property that signals a macvtap
backend. When that is detected + rhel6.2 mode + vhost-net,
disable mergeable buffers.

Note: by convention x-* marks internal features which
should never be changed by management or users.

Brew build: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=4225359
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=806975
Tested: developer testing

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

---

Reposting with 6.3 tag. Sorry about the noise.

Changes from v1:
	- Typo fixes for typos reported by Jason on IRC
	- Add some more comments

 hw/pc.c         |   12 +++++++++++-
 hw/virtio-net.c |    9 +++++++++
 hw/virtio-net.h |    1 +
 hw/virtio-pci.c |   18 ++++++++++++++++++
 4 files changed, 39 insertions(+), 1 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 hw/pc.c         |   12 +++++++++++-
 hw/virtio-net.c |    9 +++++++++
 hw/virtio-net.h |    1 +
 hw/virtio-pci.c |   18 ++++++++++++++++++
 4 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/hw/pc.c b/hw/pc.c
index d17acc5..60e289b 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1561,6 +1561,12 @@ static void rhel_common_init(const char *type1_version,
                      strlen(buf) + 1, buf);
 }
 
+#define PC_RHEL6_2_COMPAT \
+        {\
+            .driver   = "virtio-net-pci",\
+            .property = "x-__com_redhat_rhel620_compat",\
+            .value    = "on",\
+        }
 #define PC_RHEL6_1_COMPAT \
         {\
             .driver   = "usb-tablet",\
@@ -1590,7 +1596,7 @@ static void rhel_common_init(const char *type1_version,
             .driver   = "virtio-balloon",\
             .property = "event_idx",\
             .value    = "off",\
-        }
+        }, PC_RHEL6_2_COMPAT
 
 #define PC_RHEL6_0_COMPAT \
         {\
@@ -1638,6 +1644,10 @@ static QEMUMachine pc_machine_rhel620 = {
     .desc = "RHEL 6.2.0 PC",
     .init = pc_init_rhel620,
     .max_cpus = 255,
+    .compat_props = (GlobalProperty[]) {
+        PC_RHEL6_2_COMPAT,
+        { /* end of list */ }
+    },
 };
 
 static void pc_init_rhel610(ram_addr_t ram_size,
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 01d9467..0926cf6 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -54,6 +54,7 @@ typedef struct VirtIONet
     uint8_t nouni;
     uint8_t nobcast;
     uint8_t vhost_started;
+    bool macvtap_rhel620_compat;
     struct {
         int in_use;
         int first_multi;
@@ -226,6 +227,13 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
     if (!tap_get_vhost_net(n->nic->nc.peer)) {
         return features;
     }
+    /*
+     * In rhel 6.1 and 6.2 macvtap does not support rx mergeable
+     * buffers when used with vhost-net.
+     */
+    if (n->macvtap_rhel620_compat) {
+        features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+    }
     return vhost_net_get_features(tap_get_vhost_net(n->nic->nc.peer), features);
 }
 
@@ -992,6 +1000,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
         n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx_bh);
         n->tx_bh = qemu_bh_new(virtio_net_tx_bh, n);
     }
+    n->macvtap_rhel620_compat = net->macvtap_rhel620_compat;
     n->ctrl_vq = virtio_add_queue(&n->vdev, 64, virtio_net_handle_ctrl);
     qemu_macaddr_default_if_unset(&conf->macaddr);
     memcpy(&n->mac[0], &conf->macaddr, sizeof(n->mac));
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 5eacda6..fde3697 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -61,6 +61,7 @@ typedef struct virtio_net_conf
     uint32_t txtimer;
     int32_t txburst;
     char *tx;
+    bool macvtap_rhel620_compat;
 } virtio_net_conf;
 
 /* Maximum packet size we can receive from tap device: header + 64k */
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index b2a558d..e8c08bf 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -89,6 +89,15 @@
 #define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1
 #define VIRTIO_PCI_FLAG_USE_IOEVENTFD   (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
 
+/* Enabled work-arounds for migration with macvtap backend */
+#define VIRTIO_PCI_FLAG_MACVTAP_BIT 2
+#define VIRTIO_PCI_FLAG_MACVTAP (1 << VIRTIO_PCI_FLAG_MACVTAP_BIT)
+
+/* Enabled compatibility for migration for rhel6.2.0 and older */
+#define VIRTIO_PCI_FLAG_RHEL620_BIT 3
+#define VIRTIO_PCI_FLAG_RHEL620 (1 << VIRTIO_PCI_FLAG_RHEL620_BIT)
+
+
 /* QEMU doesn't strictly need write barriers since everything runs in
  * lock-step.  We'll leave the calls to wmb() in though to make it obvious for
  * KVM or if kqemu gets SMP support.
@@ -884,6 +893,11 @@ static int virtio_net_init_pci(PCIDevice *pci_dev)
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
     VirtIODevice *vdev;
 
+    /* Set rhel6.2 or older compatibility mode for macvtap. */
+    proxy->net.macvtap_rhel620_compat =
+        (proxy->flags & VIRTIO_PCI_FLAG_RHEL620) &&
+        (proxy->flags & VIRTIO_PCI_FLAG_MACVTAP);
+
     vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net);
 
     vdev->nvectors = proxy->nvectors;
@@ -989,6 +1003,10 @@ static PCIDeviceInfo virtio_info[] = {
         .qdev.props = (Property[]) {
             DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
                             VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
+            DEFINE_PROP_BIT("__com_redhat_macvtap_compat", VirtIOPCIProxy,
+                            flags, VIRTIO_PCI_FLAG_MACVTAP_BIT, false),
+            DEFINE_PROP_BIT("x-__com_redhat_rhel620_compat", VirtIOPCIProxy,
+                            flags, VIRTIO_PCI_FLAG_RHEL620_BIT, false),
             DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
             DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
             DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
-- 
1.7.7.6

