Message ID | 20220914042055.61939-12-xuanzhuo@linux.alibaba.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Support VIRTIO_F_RING_RESET for virtio-net, vhost-net kernel in virtio pci-modern | expand |
On Wed, Sep 14, 2022 at 12:21 PM Xuan Zhuo <xuanzhuo@linux.alibaba.com> wrote: > > From: Kangjie Xu <kangjie.xu@linux.alibaba.com> > > 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> Acked-by: Jason Wang <jasowang@redhat.com> > --- > hw/net/vhost_net.c | 53 +++++++++++++++++++++++++++++++++++++++++ > include/net/vhost_net.h | 2 ++ > 2 files changed, 55 insertions(+) > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c > index 8beecb4d22..d2926e2ed6 100644 > --- a/hw/net/vhost_net.c > +++ b/hw/net/vhost_net.c > @@ -34,6 +34,7 @@ > #include "standard-headers/linux/virtio_ring.h" > #include "hw/virtio/vhost.h" > #include "hw/virtio/virtio-bus.h" > +#include "linux-headers/linux/vhost.h" > > > /* Features supported by host kernel. */ > @@ -556,3 +557,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 -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 = VHOST_FILE_UNBIND; > + 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 > -- > 2.32.0.3.g01195cf9f >
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 8beecb4d22..d2926e2ed6 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -34,6 +34,7 @@ #include "standard-headers/linux/virtio_ring.h" #include "hw/virtio/vhost.h" #include "hw/virtio/virtio-bus.h" +#include "linux-headers/linux/vhost.h" /* Features supported by host kernel. */ @@ -556,3 +557,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 -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 = VHOST_FILE_UNBIND; + 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