This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 45025e2d2119d0273e6aac475ec6bdb094a7bec7 Author: dengwenqi <[email protected]> AuthorDate: Thu Aug 27 19:17:03 2026 +0800 drivers/virtio-net: free RX buffers on ifdown virtio_net_ifdown() only disabled the callbacks and left the RX buffers filled by virtio_net_rxfill() queued in the virtqueue, so they stayed allocated while the interface was down. Drain the RX and TX virtqueues on ifdown. Also free the netpkt when virtio_net_rxfill() fails to add it to the virtqueue; it was lost before. Signed-off-by: dengwenqi <[email protected]> --- drivers/virtio/virtio-net.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio-net.c b/drivers/virtio/virtio-net.c index d40a0932dfd..be2225ce42c 100644 --- a/drivers/virtio/virtio-net.c +++ b/drivers/virtio/virtio-net.c @@ -313,7 +313,12 @@ static void virtio_net_rxfill(FAR struct netdev_lowerhalf_s *dev) /* Add buffer to RX virtqueue */ - virtio_net_addbuffer(dev, vq, pkt, VIRTIO_NET_RX); + if (virtio_net_addbuffer(dev, vq, pkt, VIRTIO_NET_RX) < 0) + { + vrterr("Failed to add buffer to RX virtqueue, i=%d\n", i); + netpkt_free(dev, pkt, NETPKT_RX); + break; + } } if (i > 0) @@ -392,6 +397,8 @@ static int virtio_net_ifup(FAR struct netdev_lowerhalf_s *dev) static int virtio_net_ifdown(FAR struct netdev_lowerhalf_s *dev) { FAR struct virtio_net_priv_s *priv = (FAR struct virtio_net_priv_s *)dev; + FAR struct virtqueue *vq = priv->vdev->vrings_info[VIRTIO_NET_RX].vq; + FAR struct virtio_net_llhdr_s *hdr; int i; /* Disable the Ethernet interrupt */ @@ -402,6 +409,26 @@ static int virtio_net_ifdown(FAR struct netdev_lowerhalf_s *dev) &priv->lock[i]); } + /* Drain RX virtqueue to free netpkt buffers that are still queued + * but not yet consumed. + */ + + while (1) + { + hdr = virtqueue_get_buffer_lock(vq, NULL, NULL, + &priv->lock[VIRTIO_NET_RX]); + if (hdr == NULL) + { + break; + } + + netpkt_free(dev, hdr->pkt, NETPKT_RX); + } + + /* Drain TX virtqueue as well */ + + virtio_net_txfree(dev); + #ifdef CONFIG_DRIVERS_WIFI_SIM if (priv->lower.wifi) {
