mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-28 21:03:54 -06:00
virtio-net: vhost-user: Implement internal migration
Add support of VHOST_USER_PROTOCOL_F_DEVICE_STATE in virtio-net with vhost-user backend. Cc: Hanna Czenczek <hreitz@redhat.com> Signed-off-by: Laurent Vivier <lvivier@redhat.com> Message-Id: <20250115135044.799698-3-lvivier@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
3f65357313
commit
60f543ad91
1 changed files with 112 additions and 23 deletions
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue