Re: [PATCH 12/16] vhost-net: introduce restart and stop for vhost_net's vqs
在 2022/7/26 12:16, Jason Wang 写道: 在 2022/7/18 19:17, Kangjie Xu 写道: Introduce vhost_virtqueue_restart(), which can restart the virtqueue when the vhost net started running before. Introduce vhost_virtqueue_stop(), which can disable the vq and unmap vrings and the desc of the vq. When disabling the vq, the function is blocked and waits for a reply. Combining the two functions, we can reset a virtqueue with a started vhost net. Signed-off-by: Kangjie Xu Signed-off-by: Xuan Zhuo --- hw/net/vhost_net.c | 55 + include/net/vhost_net.h | 5 2 files changed, 60 insertions(+) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index ccac5b7a64..4f5f034c11 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -514,3 +514,58 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu) return vhost_ops->vhost_net_set_mtu(>dev, mtu); } + +void vhost_virtqueue_stop(VirtIODevice *vdev, NetClientState *nc, + int vq_index) Let's rename this as vhost_net_virtqueue_stop() Yeah, I agree. Thanks +{ + VHostNetState *net = get_vhost_net(nc->peer); + const VhostOps *vhost_ops = net->dev.vhost_ops; + int r; + + assert(vhost_ops); + + r = vhost_ops->vhost_set_single_vring_enable(>dev, vq_index, 0, true); + if (r < 0) { + goto err_queue_disable; + } + + vhost_dev_virtqueue_release(>dev, vdev, vq_index); + + return; + +err_queue_disable: + error_report("Error when releasing the qeuue."); +} + +int vhost_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, + int vq_index) +{ + VHostNetState *net = get_vhost_net(nc->peer); + const VhostOps *vhost_ops = net->dev.vhost_ops; + int r; + + if (!net->dev.started) { + return 0; + } + + assert(vhost_ops); + + r = vhost_dev_virtqueue_restart(>dev, vdev, vq_index); + if (r < 0) { + goto err_start; + } + + r = vhost_ops->vhost_set_single_vring_enable(>dev, vq_index, 1, + false); So it looks nothing vhost_net specific but vhost. And why not do set_single_vring_enable in vhost_dev_virtqueue_restart() (btw, the name of this function looks confusing). Thanks I thought it was a convention that virtio-net will call vhost_net first, and cannot call vhost directly. So I implement it in this way. It's no probem to move it to vhost. I'll fix it. Thanks + if (r < 0) { + goto err_start; + } + + return 0; + +err_start: + error_report("Error when restarting the queue."); + vhost_dev_stop(>dev, vdev); + + return r; +} diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 387e913e4e..fcb09e36ef 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -48,4 +48,9 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net); int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu); +void vhost_virtqueue_stop(VirtIODevice *vdev, NetClientState *nc, + int vq_index); +int vhost_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, + int vq_index); + #endif
Re: [PATCH 12/16] vhost-net: introduce restart and stop for vhost_net's vqs
在 2022/7/18 19:17, Kangjie Xu 写道: Introduce vhost_virtqueue_restart(), which can restart the virtqueue when the vhost net started running before. Introduce vhost_virtqueue_stop(), which can disable the vq and unmap vrings and the desc of the vq. When disabling the vq, the function is blocked and waits for a reply. Combining the two functions, we can reset a virtqueue with a started vhost net. Signed-off-by: Kangjie Xu Signed-off-by: Xuan Zhuo --- hw/net/vhost_net.c | 55 + include/net/vhost_net.h | 5 2 files changed, 60 insertions(+) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index ccac5b7a64..4f5f034c11 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -514,3 +514,58 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu) return vhost_ops->vhost_net_set_mtu(>dev, mtu); } + +void vhost_virtqueue_stop(VirtIODevice *vdev, NetClientState *nc, + int vq_index) Let's rename this as vhost_net_virtqueue_stop() +{ +VHostNetState *net = get_vhost_net(nc->peer); +const VhostOps *vhost_ops = net->dev.vhost_ops; +int r; + +assert(vhost_ops); + +r = vhost_ops->vhost_set_single_vring_enable(>dev, vq_index, 0, true); +if (r < 0) { +goto err_queue_disable; +} + +vhost_dev_virtqueue_release(>dev, vdev, vq_index); + +return; + +err_queue_disable: +error_report("Error when releasing the qeuue."); +} + +int vhost_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, +int vq_index) +{ +VHostNetState *net = get_vhost_net(nc->peer); +const VhostOps *vhost_ops = net->dev.vhost_ops; +int r; + +if (!net->dev.started) { +return 0; +} + +assert(vhost_ops); + +r = vhost_dev_virtqueue_restart(>dev, vdev, vq_index); +if (r < 0) { +goto err_start; +} + +r = vhost_ops->vhost_set_single_vring_enable(>dev, vq_index, 1, + false); So it looks nothing vhost_net specific but vhost. And why not do set_single_vring_enable in vhost_dev_virtqueue_restart() (btw, the name of this function looks confusing). Thanks +if (r < 0) { +goto err_start; +} + +return 0; + +err_start: +error_report("Error when restarting the queue."); +vhost_dev_stop(>dev, vdev); + +return r; +} diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 387e913e4e..fcb09e36ef 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -48,4 +48,9 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net); int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu); +void vhost_virtqueue_stop(VirtIODevice *vdev, NetClientState *nc, + int vq_index); +int vhost_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, +int vq_index); + #endif
[PATCH 12/16] vhost-net: introduce restart and stop for vhost_net's vqs
Introduce vhost_virtqueue_restart(), which can restart the virtqueue when the vhost net started running before. Introduce vhost_virtqueue_stop(), which can disable the vq and unmap vrings and the desc of the vq. When disabling the vq, the function is blocked and waits for a reply. Combining the two functions, we can reset a virtqueue with a started vhost net. Signed-off-by: Kangjie Xu Signed-off-by: Xuan Zhuo --- hw/net/vhost_net.c | 55 + include/net/vhost_net.h | 5 2 files changed, 60 insertions(+) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index ccac5b7a64..4f5f034c11 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -514,3 +514,58 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu) return vhost_ops->vhost_net_set_mtu(>dev, mtu); } + +void vhost_virtqueue_stop(VirtIODevice *vdev, NetClientState *nc, + int vq_index) +{ +VHostNetState *net = get_vhost_net(nc->peer); +const VhostOps *vhost_ops = net->dev.vhost_ops; +int r; + +assert(vhost_ops); + +r = vhost_ops->vhost_set_single_vring_enable(>dev, vq_index, 0, true); +if (r < 0) { +goto err_queue_disable; +} + +vhost_dev_virtqueue_release(>dev, vdev, vq_index); + +return; + +err_queue_disable: +error_report("Error when releasing the qeuue."); +} + +int vhost_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, +int vq_index) +{ +VHostNetState *net = get_vhost_net(nc->peer); +const VhostOps *vhost_ops = net->dev.vhost_ops; +int r; + +if (!net->dev.started) { +return 0; +} + +assert(vhost_ops); + +r = vhost_dev_virtqueue_restart(>dev, vdev, vq_index); +if (r < 0) { +goto err_start; +} + +r = vhost_ops->vhost_set_single_vring_enable(>dev, vq_index, 1, + false); +if (r < 0) { +goto err_start; +} + +return 0; + +err_start: +error_report("Error when restarting the queue."); +vhost_dev_stop(>dev, vdev); + +return r; +} diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index 387e913e4e..fcb09e36ef 100644 --- a/include/net/vhost_net.h +++ b/include/net/vhost_net.h @@ -48,4 +48,9 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net); int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu); +void vhost_virtqueue_stop(VirtIODevice *vdev, NetClientState *nc, + int vq_index); +int vhost_virtqueue_restart(VirtIODevice *vdev, NetClientState *nc, +int vq_index); + #endif -- 2.32.0