From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
To: Simon Schippers <simon.schippers@tu-dortmund.de>,
willemdebruijn.kernel@gmail.com, jasowang@redhat.com,
mst@redhat.com, eperezma@redhat.com,
stephen@networkplumber.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, virtualization@lists.linux.dev,
kvm@vger.kernel.org
Cc: Simon Schippers <simon.schippers@tu-dortmund.de>,
Tim Gebauer <tim.gebauer@tu-dortmund.de>
Subject: Re: [PATCH 2/4] netdev queue flow control for TUN
Date: Tue, 02 Sep 2025 17:20:58 -0400 [thread overview]
Message-ID: <willemdebruijn.kernel.243baccfedc16@gmail.com> (raw)
In-Reply-To: <20250902080957.47265-3-simon.schippers@tu-dortmund.de>
Simon Schippers wrote:
> The netdev queue is stopped in tun_net_xmit after inserting an SKB into
> the ring buffer if the ring buffer became full because of that. If the
> insertion into the ptr_ring fails, the netdev queue is also stopped and
> the SKB is dropped. However, this never happened in my testing.
Indeed, since the last successful insertion will always pause the
queue before this can happen. Since this cannot be reached, no need
to add the code defensively. If in doubt, maybe add a
NET_DEBUG_WARN_ON_ONCE.
> To ensure
> that the ptr_ring change is available to the consumer before the netdev
> queue stop, an smp_wmb() is used.
>
> Then in tun_ring_recv, the new helper wake_netdev_queue is called in the
> blocking wait queue and after consuming an SKB from the ptr_ring. This
> helper first checks if the netdev queue has stopped. Then with the paired
> smp_rmb() it is known that tun_net_xmit will not produce SKBs anymore.
> With that knowledge, the helper can then wake the netdev queue if there is
> at least a single spare slot in the ptr_ring by calling ptr_ring_spare
> with cnt=1.
>
> Co-developed-by: Tim Gebauer <tim.gebauer@tu-dortmund.de>
> Signed-off-by: Tim Gebauer <tim.gebauer@tu-dortmund.de>
> Signed-off-by: Simon Schippers <simon.schippers@tu-dortmund.de>
> ---
> drivers/net/tun.c | 33 ++++++++++++++++++++++++++++++---
> 1 file changed, 30 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index cc6c50180663..735498e221d8 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -1060,13 +1060,21 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
>
> nf_reset_ct(skb);
>
> - if (ptr_ring_produce(&tfile->tx_ring, skb)) {
> + queue = netdev_get_tx_queue(dev, txq);
> + if (unlikely(ptr_ring_produce(&tfile->tx_ring, skb))) {
> + /* Paired with smp_rmb() in wake_netdev_queue. */
> + smp_wmb();
> + netif_tx_stop_queue(queue);
> drop_reason = SKB_DROP_REASON_FULL_RING;
> goto drop;
> }
> + if (ptr_ring_full(&tfile->tx_ring)) {
> + /* Paired with smp_rmb() in wake_netdev_queue. */
> + smp_wmb();
> + netif_tx_stop_queue(queue);
> + }
>
> /* dev->lltx requires to do our own update of trans_start */
> - queue = netdev_get_tx_queue(dev, txq);
> txq_trans_cond_update(queue);
>
> /* Notify and wake up reader process */
> @@ -2110,6 +2118,24 @@ static ssize_t tun_put_user(struct tun_struct *tun,
> return total;
> }
>
> +static inline void wake_netdev_queue(struct tun_file *tfile)
> +{
> + struct netdev_queue *txq;
> + struct net_device *dev;
> +
> + rcu_read_lock();
> + dev = rcu_dereference(tfile->tun)->dev;
> + txq = netdev_get_tx_queue(dev, tfile->queue_index);
> +
> + if (netif_tx_queue_stopped(txq)) {
> + /* Paired with smp_wmb() in tun_net_xmit. */
> + smp_rmb();
> + if (ptr_ring_spare(&tfile->tx_ring, 1))
> + netif_tx_wake_queue(txq);
> + }
> + rcu_read_unlock();
> +}
> +
> static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
> {
> DECLARE_WAITQUEUE(wait, current);
> @@ -2139,7 +2165,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
> error = -EFAULT;
> break;
> }
> -
> + wake_netdev_queue(tfile);
Why wake when no entry was consumed?
Also keep the empty line.
> schedule();
> }
>
> @@ -2147,6 +2173,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
> remove_wait_queue(&tfile->socket.wq.wait, &wait);
>
> out:
> + wake_netdev_queue(tfile);
> *err = error;
> return ptr;
> }
> --
> 2.43.0
>
next prev parent reply other threads:[~2025-09-02 21:21 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-02 8:09 [PATCH net-next v4 0/4] TUN/TAP & vhost_net: netdev queue flow control to avoid ptr_ring tail drop Simon Schippers
2025-09-02 8:09 ` [PATCH 1/4] ptr_ring_spare: Helper to check if spare capacity of size cnt is available Simon Schippers
2025-09-02 21:13 ` Willem de Bruijn
2025-09-03 3:13 ` Jason Wang
2025-09-03 13:05 ` Michael S. Tsirkin
2025-09-03 18:29 ` Simon Schippers
2025-09-02 8:09 ` [PATCH 2/4] netdev queue flow control for TUN Simon Schippers
2025-09-02 21:20 ` Willem de Bruijn [this message]
2025-09-03 18:35 ` Simon Schippers
2025-09-02 21:31 ` Willem de Bruijn
2025-09-03 3:27 ` Jason Wang
2025-09-03 18:41 ` Simon Schippers
2025-09-03 13:10 ` Michael S. Tsirkin
2025-09-03 18:45 ` Simon Schippers
2025-09-03 13:13 ` Michael S. Tsirkin
2025-09-03 18:49 ` Simon Schippers
2025-09-02 8:09 ` [PATCH 3/4] netdev queue flow control for TAP Simon Schippers
2025-09-02 8:09 ` [PATCH 4/4] netdev queue flow control for vhost_net Simon Schippers
2025-09-02 21:31 ` Willem de Bruijn
2025-09-03 3:42 ` Jason Wang
2025-09-03 13:51 ` Willem de Bruijn
2025-09-04 2:47 ` Jason Wang
2025-09-03 4:00 ` [PATCH net-next v4 0/4] TUN/TAP & vhost_net: netdev queue flow control to avoid ptr_ring tail drop Jason Wang
2025-09-03 18:55 ` Simon Schippers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=willemdebruijn.kernel.243baccfedc16@gmail.com \
--to=willemdebruijn.kernel@gmail.com \
--cc=eperezma@redhat.com \
--cc=jasowang@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mst@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=simon.schippers@tu-dortmund.de \
--cc=stephen@networkplumber.org \
--cc=tim.gebauer@tu-dortmund.de \
--cc=virtualization@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).