@@ -352,6 +352,8 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
}
}
+ vhost_user_set_master_dev(ncs[0].peer, dev);
+
return 0;
err_start:
@@ -12,6 +12,7 @@
#include "qapi/error.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-backend.h"
+#include "hw/virtio/virtio-pci.h"
#include "hw/virtio/vhost-user.h"
#include "hw/virtio/virtio-net.h"
#include "net/vhost-user.h"
@@ -75,6 +76,26 @@ fail:
return -1;
}
+static void handle_slave_acked_features(const char *name, VhostUserMsg *msg)
+{
+ CharBackend *chr_be = net_name_to_chr_be(name);
+ VhostUserState *s = container_of(chr_be, VhostUserState, chr);
+ VirtIODevice *vdev = s->vdev;
+ uint64_t master_features, slave_features;
+
+ master_features = vhost_net_get_acked_features(s->vhost_net) &
+ ~(1 << VHOST_USER_F_PROTOCOL_FEATURES);
+ slave_features = msg->payload.u64;
+
+ /*
+ * It is a rare case: vhost-pci driver only accepted a subset of the
+ * feature bits. In this case, reset the virtio device.
+ */
+ if (master_features != slave_features) {
+ master_reset_virtio_net(vdev);
+ }
+}
+
int vhost_user_can_read(void *opaque)
{
return VHOST_USER_HDR_SIZE;
@@ -109,6 +130,9 @@ void vhost_user_asyn_read(void *opaque, const uint8_t *buf, int size)
}
switch (msg.request) {
+ case VHOST_USER_SET_FEATURES:
+ handle_slave_acked_features(name, &msg);
+ break;
default:
error_report("%s: does not support msg %d", __func__, msg.request);
break;
@@ -37,6 +37,7 @@
#include "qemu/range.h"
#include "hw/virtio/virtio-bus.h"
#include "qapi/visitor.h"
+#include "monitor/qdev.h"
#define VIRTIO_PCI_REGION_SIZE(dev) VIRTIO_PCI_CONFIG_OFF(msix_present(dev))
@@ -2327,6 +2328,25 @@ static const TypeInfo virtio_serial_pci_info = {
/* virtio-net-pci */
+void master_reset_virtio_net(VirtIODevice *vdev)
+{
+ VirtIONet *net = VIRTIO_NET(vdev);
+ VirtIONetPCI *net_pci = container_of(net, VirtIONetPCI, vdev);
+ VirtIOPCIProxy *proxy = &net_pci->parent_obj;
+ DeviceState *qdev = DEVICE(proxy);
+ DeviceState *qdev_new;
+ Error *err = NULL;
+
+ virtio_pci_reset(qdev);
+ qdev_unplug(qdev, &err);
+ qdev->realized = false;
+ qdev_new = qdev_device_add(qdev->opts, &err);
+ if (!qdev_new) {
+ qemu_opts_del(qdev->opts);
+ }
+ object_unref(OBJECT(qdev));
+}
+
static Property virtio_net_properties[] = {
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
@@ -399,4 +399,6 @@ struct VirtIOCryptoPCI {
/* Virtio ABI version, if we increment this, we break the guest driver. */
#define VIRTIO_PCI_ABI_VERSION 0
+void master_reset_virtio_net(VirtIODevice *vdev);
+
#endif
@@ -12,6 +12,18 @@
#define NET_VHOST_USER_H
#include "sysemu/char.h"
+#include "net/vhost_net.h"
+
+typedef struct VhostUserState {
+ NetClientState nc;
+ CharBackend chr; /* only queue index 0 */
+ VHostNetState *vhost_net;
+ guint watch;
+ uint64_t acked_features;
+ bool started;
+ /* Pointer to the master device */
+ VirtIODevice *vdev;
+} VhostUserState;
struct vhost_net;
struct vhost_net *vhost_user_get_vhost_net(NetClientState *nc);
@@ -19,4 +31,6 @@ uint64_t vhost_user_get_acked_features(NetClientState *nc);
CharBackend *net_name_to_chr_be(const char *name);
+void vhost_user_set_master_dev(NetClientState *nc, VirtIODevice *vdev);
+
#endif /* VHOST_USER_H */
@@ -10,7 +10,6 @@
#include "qemu/osdep.h"
#include "clients.h"
-#include "net/vhost_net.h"
#include "net/vhost-user.h"
#include "hw/virtio/vhost-user.h"
#include "qemu/config-file.h"
@@ -18,14 +17,11 @@
#include "qmp-commands.h"
#include "trace.h"
-typedef struct VhostUserState {
- NetClientState nc;
- CharBackend chr; /* only queue index 0 */
- VHostNetState *vhost_net;
- guint watch;
- uint64_t acked_features;
- bool started;
-} VhostUserState;
+void vhost_user_set_master_dev(NetClientState *nc, VirtIODevice *vdev)
+{
+ VhostUserState *s = DO_UPCAST(VhostUserState, nc, nc);
+ s->vdev = vdev;
+}
VHostNetState *vhost_user_get_vhost_net(NetClientState *nc)
{
If the featuer bits sent by the slave are not equal to the ones that were sent by the master, perform a reset of the master device. Signed-off-by: Wei Wang <wei.w.wang@intel.com> --- hw/net/vhost_net.c | 2 ++ hw/virtio/vhost-user.c | 24 ++++++++++++++++++++++++ hw/virtio/virtio-pci.c | 20 ++++++++++++++++++++ hw/virtio/virtio-pci.h | 2 ++ include/net/vhost-user.h | 14 ++++++++++++++ net/vhost-user.c | 14 +++++--------- 6 files changed, 67 insertions(+), 9 deletions(-)