|
@@ -3337,6 +3337,117 @@ static const VMStateDescription vmstate_virtio_net_rss = {
|
|
},
|
|
},
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static struct vhost_dev *virtio_net_get_vhost(VirtIODevice *vdev)
|
|
|
|
+{
|
|
|
|
+ VirtIONet *n = VIRTIO_NET(vdev);
|
|
|
|
+ NetClientState *nc;
|
|
|
|
+ struct vhost_net *net;
|
|
|
|
+
|
|
|
|
+ if (!n->nic) {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ nc = qemu_get_queue(n->nic);
|
|
|
|
+ if (!nc) {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ net = get_vhost_net(nc->peer);
|
|
|
|
+ if (!net) {
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return &net->dev;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vhost_user_net_save_state(QEMUFile *f, void *pv, size_t size,
|
|
|
|
+ const VMStateField *field,
|
|
|
|
+ JSONWriter *vmdesc)
|
|
|
|
+{
|
|
|
|
+ VirtIONet *n = pv;
|
|
|
|
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
|
|
|
+ struct vhost_dev *vhdev;
|
|
|
|
+ Error *local_error = NULL;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ vhdev = virtio_net_get_vhost(vdev);
|
|
|
|
+ if (vhdev == NULL) {
|
|
|
|
+ error_reportf_err(local_error,
|
|
|
|
+ "Error getting vhost back-end of %s device %s: ",
|
|
|
|
+ vdev->name, vdev->parent_obj.canonical_path);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = vhost_save_backend_state(vhdev, f, &local_error);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ error_reportf_err(local_error,
|
|
|
|
+ "Error saving back-end state of %s device %s: ",
|
|
|
|
+ vdev->name, vdev->parent_obj.canonical_path);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vhost_user_net_load_state(QEMUFile *f, void *pv, size_t size,
|
|
|
|
+ const VMStateField *field)
|
|
|
|
+{
|
|
|
|
+ VirtIONet *n = pv;
|
|
|
|
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
|
|
|
+ struct vhost_dev *vhdev;
|
|
|
|
+ Error *local_error = NULL;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ vhdev = virtio_net_get_vhost(vdev);
|
|
|
|
+ if (vhdev == NULL) {
|
|
|
|
+ error_reportf_err(local_error,
|
|
|
|
+ "Error getting vhost back-end of %s device %s: ",
|
|
|
|
+ vdev->name, vdev->parent_obj.canonical_path);
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = vhost_load_backend_state(vhdev, f, &local_error);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ error_reportf_err(local_error,
|
|
|
|
+ "Error loading back-end state of %s device %s: ",
|
|
|
|
+ vdev->name, vdev->parent_obj.canonical_path);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static bool vhost_user_net_is_internal_migration(void *opaque)
|
|
|
|
+{
|
|
|
|
+ VirtIONet *n = opaque;
|
|
|
|
+ VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
|
|
|
+ struct vhost_dev *vhdev;
|
|
|
|
+
|
|
|
|
+ vhdev = virtio_net_get_vhost(vdev);
|
|
|
|
+ if (vhdev == NULL) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return vhost_supports_device_state(vhdev);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const VMStateDescription vhost_user_net_backend_state = {
|
|
|
|
+ .name = "virtio-net-device/backend",
|
|
|
|
+ .version_id = 0,
|
|
|
|
+ .needed = vhost_user_net_is_internal_migration,
|
|
|
|
+ .fields = (const VMStateField[]) {
|
|
|
|
+ {
|
|
|
|
+ .name = "backend",
|
|
|
|
+ .info = &(const VMStateInfo) {
|
|
|
|
+ .name = "virtio-net vhost-user backend state",
|
|
|
|
+ .get = vhost_user_net_load_state,
|
|
|
|
+ .put = vhost_user_net_save_state,
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ VMSTATE_END_OF_LIST()
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
static const VMStateDescription vmstate_virtio_net_device = {
|
|
static const VMStateDescription vmstate_virtio_net_device = {
|
|
.name = "virtio-net-device",
|
|
.name = "virtio-net-device",
|
|
.version_id = VIRTIO_NET_VM_VERSION,
|
|
.version_id = VIRTIO_NET_VM_VERSION,
|
|
@@ -3389,6 +3500,7 @@ static const VMStateDescription vmstate_virtio_net_device = {
|
|
},
|
|
},
|
|
.subsections = (const VMStateDescription * const []) {
|
|
.subsections = (const VMStateDescription * const []) {
|
|
&vmstate_virtio_net_rss,
|
|
&vmstate_virtio_net_rss,
|
|
|
|
+ &vhost_user_net_backend_state,
|
|
NULL
|
|
NULL
|
|
}
|
|
}
|
|
};
|
|
};
|
|
@@ -3950,29 +4062,6 @@ static bool dev_unplug_pending(void *opaque)
|
|
return vdc->primary_unplug_pending(dev);
|
|
return vdc->primary_unplug_pending(dev);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct vhost_dev *virtio_net_get_vhost(VirtIODevice *vdev)
|
|
|
|
-{
|
|
|
|
- VirtIONet *n = VIRTIO_NET(vdev);
|
|
|
|
- NetClientState *nc;
|
|
|
|
- struct vhost_net *net;
|
|
|
|
-
|
|
|
|
- if (!n->nic) {
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- nc = qemu_get_queue(n->nic);
|
|
|
|
- if (!nc) {
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- net = get_vhost_net(nc->peer);
|
|
|
|
- if (!net) {
|
|
|
|
- return NULL;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return &net->dev;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static const VMStateDescription vmstate_virtio_net = {
|
|
static const VMStateDescription vmstate_virtio_net = {
|
|
.name = "virtio-net",
|
|
.name = "virtio-net",
|
|
.minimum_version_id = VIRTIO_NET_VM_VERSION,
|
|
.minimum_version_id = VIRTIO_NET_VM_VERSION,
|