svn commit: r242739 - stable/9/sys/dev/ti

Andre Oppermann andre at freebsd.org
Thu Nov 8 11:13:22 UTC 2012


On 08.11.2012 03:38, YongHyeon PYUN wrote:
> On Wed, Nov 07, 2012 at 06:15:30PM -0800, Adrian Chadd wrote:
>> If so, may I suggest we perhaps accelerate discussing if_transmit() of
>> multiple frames per call?
>
> Hmm, actually I'm still not a fan of if_transmit() at this moment.
> Honestly I don't have good queuing code in driver to handle queue
> full condition. Interactions with altq(9) is also one of my
> concern as well as packet reordering issue of drbr(9) interface.

The whole interface packet handoff needs some serious reconsideration.

These days we have two queues/buffers at the interfaces.  One is the
DMA ring which can take a considerable number of packets and the second
one is the ifq (if enabled).  The DMA ring already adds significant
depth and latency so that a packet scheduler like altq(9) become almost
useless.  Also modern queue management algorithms like CoDel don't work
with the current framework.  Also bufferbloat is a major concern.  See
ACM queue article by Jim Gettys.

What we need to take make this functionality available again is a well
specified and reasonably simple interface handoff.  It should include
information on the maximum tx DMA ring depth and the current depth.
There should also be a function to limit the current depth to a certain
value.

What I'd like to see is this (names are not fixed):

  if_send() as the main entry point for the stack.  It's a function
   pointer within struct ifnet.  In normal operation it is the same
   as if_transmit() and directly adds a packet to the tx DMA ring.
   Locking of the DMA ring is done in this function and a property
   of the driver.  The stack always calls unlocked.  Obviously the
   tx DMA ring lock must not be a sleep lock.
   When altq(9) or equivalent is active this function pointer is
   replaced with a call to the alternative queuing function that
   does it's magic.  Again locking of the queuing mechanism is the
   property of that mechanism.  When a NIC has multiple queues that
   it can bind to CPU's locking may not be necessary.  We gain this
   flexibility in the driver to do that.

  if_transmit() is a function pointer for a function that directly
   adds a packet to the tx DMA ring (if a free slot is available).
   It is never called by the stack directly except in special
   circumstances.  The altq(9), if active, uses if_transmit() to
   add packets to the tx DMA ring.  If not active, if_send() is
   this function pointer.

  if_txeof() is a function pointer for a callback from the driver
   to an altq(9) dequeue function, if active.  It is called when
   when new free slots on the tx DMA ring are available.

When a driver needs a software interface queue because the tx DMA
is too small, then the stack should provide a generic queuing
implementation the driver can use.

I've begun to explore this area while hacking on bge(4) and em(4)
in tcp_workqueue branch.

It's a very interesting path and we going to have a couple more
discussions before we arrive at the optimal solution. :)

-- 
Andre



More information about the freebsd-net mailing list