[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251125100655-mutt-send-email-mst@kernel.org>
Date: Tue, 25 Nov 2025 11:54:39 -0500
From: "Michael S. Tsirkin" <mst@...hat.com>
To: Simon Schippers <simon.schippers@...dortmund.de>
Cc: willemdebruijn.kernel@...il.com, jasowang@...hat.com,
andrew+netdev@...n.ch, davem@...emloft.net, edumazet@...gle.com,
kuba@...nel.org, pabeni@...hat.com, eperezma@...hat.com,
jon@...anix.com, tim.gebauer@...dortmund.de, netdev@...r.kernel.org,
linux-kernel@...r.kernel.org, kvm@...r.kernel.org,
virtualization@...ts.linux.dev
Subject: Re: [PATCH net-next v6 3/8] tun/tap: add synchronized ring
produce/consume with queue management
On Thu, Nov 20, 2025 at 04:29:08PM +0100, Simon Schippers wrote:
> Implement new ring buffer produce and consume functions for tun and tap
> drivers that provide lockless producer-consumer synchronization and
> netdev queue management to prevent ptr_ring tail drop and permanent
> starvation.
>
> - tun_ring_produce(): Produces packets to the ptr_ring with proper memory
> barriers and proactively stops the netdev queue when the ring is about
> to become full.
>
> - __tun_ring_consume() / __tap_ring_consume(): Internal consume functions
> that check if the netdev queue was stopped due to a full ring, and wake
> it when space becomes available. Uses memory barriers to ensure proper
> ordering between producer and consumer.
>
> - tun_ring_consume() / tap_ring_consume(): Wrapper functions that acquire
> the consumer lock before calling the internal consume functions.
>
> Key features:
> - Proactive queue stopping using __ptr_ring_full_next() to stop the queue
> before it becomes completely full.
> - Not stopping the queue when the ptr_ring is full already, because if
> the consumer empties all entries in the meantime, stopping the queue
> would cause permanent starvation.
what is permanent starvation? this comment seems to answer this
question:
/* Do not stop the netdev queue if the ptr_ring is full already.
* The consumer could empty out the ptr_ring in the meantime
* without noticing the stopped netdev queue, resulting in a
* stopped netdev queue and an empty ptr_ring. In this case the
* netdev queue would stay stopped forever.
*/
why having a single entry in
the ring we never use helpful to address this?
In fact, all your patch does to solve it, is check
netif_tx_queue_stopped on every consumed packet.
I already proposed:
static inline int __ptr_ring_peek_producer(struct ptr_ring *r)
{
if (unlikely(!r->size) || r->queue[r->producer])
return -ENOSPC;
return 0;
}
And with that, why isn't avoiding the race as simple as
just rechecking after stopping the queue?
__ptr_ring_produce();
if (__ptr_ring_peek_producer())
netif_tx_stop_queue
if (!__ptr_ring_peek_producer())
netif_tx_wake_queue(txq);
--
MST
Powered by blists - more mailing lists