Index | Thread | Search

From:
Vitaliy Makkoveev <mvs@openbsd.org>
Subject:
Re: bse: mp-safe genet_qstart()
To:
Jonathan Matthew <jonathan@d14n.org>
Cc:
tech@openbsd.org, bluhm@openbsd.org
Date:
Thu, 15 Jan 2026 02:59:53 +0000

Download raw body.

Thread
On Thu, Jan 15, 2026 at 11:53:36AM +1000, Jonathan Matthew wrote:
> On Wed, Jan 14, 2026 at 11:01:49PM +0000, Vitaliy Makkoveev wrote:
> > On Tue, Jan 13, 2026 at 09:20:24AM +0000, Vitaliy Makkoveev wrote:
> > > On Mon, Jan 12, 2026 at 11:40:47AM +1000, Jonathan Matthew wrote:
> > > > On Sun, Jan 11, 2026 at 01:18:47PM +0300, Vitaliy Makkoveev wrote:
> > > > > On Tue, Jan 06, 2026 at 12:21:28PM +0300, Vitaliy Makkoveev wrote:
> > > > > > On Tue, Jan 06, 2026 at 01:04:11AM +0300, Vitaliy Makkoveev wrote:
> > > > > > > This diff follows the instructions from net/ifq.h The interface queues
> > > > > > > layer takes care about serialization. To keep qenet_qstart() path
> > > > > > > lockless I do atomic operations on sc_tx.queued shared between
> > > > > > > genet_qstart() and genet_intr() to avoid mutex(9). It also rely on
> > > > > > > atomic operations, but exclude parallel run of these handlers.
> > > > > > > 
> > > > > > > I do re-lock dances around barriers within genet_stop(). In one hand
> > > > > > > they are not necessary because the netlock will not be taken in both
> > > > > > > genet_qstart() and genet_intr() paths. In other hand, barriers under
> > > > > > > exclusive netlock completely stop packets processing. Some mp-safe
> > > > > > > drivers follow the first way, some follow the second.
> > > > > > > 
> > > > > > > Tested for two days on couple RPI4 under load and continuous interface
> > > > > > > up/down sequence.
> > > > > > > 
> > > > > > 
> > > > > > Al little update. Against previous I pushed sc_tx.queued decrement back
> > > > > > to the loop. Previous one looks too fragile to me. If we want to
> > > > > > optimise this path, is better to do subtraction after loop.
> > > > > > 
> > > > > 
> > > > > bluhm@ doesn't like re-locking in the ioctl path. So this diff follows
> > > > > the ixgbe(4) way and avoids re-locking. This is not the problem, because
> > > > > concurrent genet_qstart() thread never acquire netlock.
> > > > > 
> > > > > Diff is stable more than 36 hours.
> > > > > 
> > > > > ok?
> > > > 
> > > > In most mpsafe drivers we avoid using atomic operations by
> > > > calculating the number of free tx slots from the producer and
> > > > consumer indexes, where the producer is only updated by qstart
> > > > and the consumer is only updated by the interrupt handler, rather
> > > > than having a field storing the difference between them that has
> > > > to be updated in both. It looks like that approach should work here
> > > > too, using the cidx and pidx fields in sc->sc_tx.
> > > > 
> > > 
> > > Thanks for feedback. The diff was reworked to follow this way.
> > > 
> > 
> > No issues for more than two days.
> 
> I don't have hardware to test this, but it looks good to me.
> One suggestion for a future change below, but ok jmatthew@ as is.
>

Thanks!

> 
> Instead of checking if there's space on the ring here, after loading
> the mbuf into a DMA map, what we typically do is check if there's
> space for the largest possible packet in *_start before dequeuing,
> so we don't have to then roll back if the packet we got won't fit.
> The big comment towards the top of src/sys/net/ifq.h shows what
> this should look like.
> 
> In this driver, the largest possible packet is apparently 128
> segments, and the ring only has 256 slots, so this would leave half
> the ring unused. 128 segments is 'a lot' for a gigabit interface
> that only supports 1500 byte packets, so maybe reducing this to 8 or
> so would be better? I think we only get up to 30 segments on 10GbE+
> nics with TSO, so we won't get anywhere near that here.
> 
> 

Will do with the next diff.