Message ID | e95212a61687ae8df7be05af09e220d90160c9a3.1662916759.git.kangjie.xu@linux.alibaba.com |
---|---|
State | New |
Headers | show |
Series | Support VIRTIO_F_RING_RESET for virtio-net, vhost-net kernel in virtio pci-modern | expand |
在 2022/9/12 01:22, Kangjie Xu 写道: > Introduce vhost_net_virtqueue_restart(), which can restart the > specific virtqueue when the vhost net started running before. > If it fails to restart the virtqueue, the device will be stopped. > > Here we do not reuse vhost_net_start_one() or vhost_dev_start() > because they work at queue pair level. The mem table and features > do not change, so we can call the vhost_virtqueue_start() to > restart a specific queue. > > This patch only considers the case of vhost-kernel, when > NetClientDriver is NET_CLIENT_DRIVER_TAP. > > Signed-off-by: Kangjie Xu <kangjie.xu@linux.alibaba.com> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> > --- > hw/net/vhost_net.c | 52 +++++++++++++++++++++++++++++++++++++++++ > include/net/vhost_net.h | 2 ++ > 2 files changed, 54 insertions(+) > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c > index 8beecb4d22..1059aa45b4 100644 > --- a/hw/net/vhost_net.c > +++ b/hw/net/vhost_net.c > @@ -556,3 +556,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc, > net->dev.vqs + idx, > net->dev.vq_index + idx); > } > + > +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, > + int vq_index) > +{ > + VHostNetState *net = get_vhost_net(nc->peer); > + const VhostOps *vhost_ops = net->dev.vhost_ops; > + struct vhost_vring_file file = { }; > + int idx, r; > + > + if (!net->dev.started) { > + return -ENOTSUP; > + } -EBUSY? > + > + /* should only be called after backend is connected */ > + assert(vhost_ops); > + > + idx = vhost_ops->vhost_get_vq_index(&net->dev, vq_index); > + > + r = vhost_virtqueue_start(&net->dev, > + vdev, > + net->dev.vqs + idx, > + net->dev.vq_index + idx); > + if (r < 0) { > + goto err_start; > + } > + > + if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { > + file.index = idx; > + file.fd = net->backend; > + r = vhost_net_set_backend(&net->dev, &file); > + if (r < 0) { > + r = -errno; > + goto err_start; > + } > + } > + > + return 0; > + > +err_start: > + error_report("Error when restarting the queue."); > + > + if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { > + file.fd = -1; Let's try reuse VHOST_FILE_UNBIND. Other looks good. Thanks > + file.index = idx; > + int r = vhost_net_set_backend(&net->dev, &file); > + assert(r >= 0); > + } > + > + vhost_dev_stop(&net->dev, vdev); > + > + return r; > +} > diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h > index 85d85a4957..40b9a40074 100644 > --- a/include/net/vhost_net.h > +++ b/include/net/vhost_net.h > @@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu); > > void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc, > int vq_index); > +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, > + int vq_index); > #endif
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 8beecb4d22..1059aa45b4 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -556,3 +556,55 @@ void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc, net->dev.vqs + idx, net->dev.vq_index + idx); } + +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, + int vq_index) +{ + VHostNetState *net = get_vhost_net(nc->peer); + const VhostOps *vhost_ops = net->dev.vhost_ops; + struct vhost_vring_file file = { }; + int idx, r; + + if (!net->dev.started) { + return -ENOTSUP; + } + + /* should only be called after backend is connected */ + assert(vhost_ops); + + idx = vhost_ops->vhost_get_vq_index(&net->dev, vq_index); + + r = vhost_virtqueue_start(&net->dev, + vdev, + net->dev.vqs + idx, + net->dev.vq_index + idx); + if (r < 0) { + goto err_start; + } + + if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { + file.index = idx; + file.fd = net->backend; + r = vhost_net_set_backend(&net->dev, &file); + if (r < 0) { + r = -errno; + goto err_start; + } + } + + return 0; + +err_start: + error_report("Error when restarting the queue."); + + if (net->nc->info->type == NET_CLIENT_DRIVER_TAP) { + file.fd = -1; + file.index = idx; + int r = vhost_net_set_backend(&net->dev, &file); + assert(r >= 0); + } + + vhost_dev_stop(&net->dev, vdev); + + return r; +} diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 85d85a4957..40b9a40074 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -50,4 +50,6 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu); void vhost_net_virtqueue_reset(VirtIODevice *vdev, NetClientState *nc, int vq_index); +int vhost_net_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, + int vq_index); #endif