Gleb,

On 20/11/2012 6:18 AM, Gleb Smirnoff wrote:
   Karim,

On Mon, Nov 19, 2012 at 02:57:24PM -0500, Karim Fodil-Lemelin wrote:
K> While testing the latest igb driver in CURRENT I came across an issue
K> with igb_mq_start(). More specifically this code:
K>
K> ...
K>
K>          struct mbuf *pm = NULL;
K>          /*
K>          ** Try to queue first to avoid
K>          ** out-of-order delivery, but
K>          ** settle for it if that fails
K>          */
K>          if (m && drbr_enqueue(ifp, txr->br, m))
K>              pm = m;
K>          err = igb_mq_start_locked(ifp, txr, pm);
K>
K> ...
K>
K>
K> The problem comes from the fact that drbr_enqueue() can return an error
K> and delete the mbuf as seen in drbr_enqueue():
K>
K> ...
K> error = buf_ring_enqueue(br, m);
K>      if (error)
K>          m_freem(m);
K> ...

Good catch!

K> diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
K> index 1318910..be1719a 100644
K> --- a/sys/dev/e1000/if_igb.c
K> +++ b/sys/dev/e1000/if_igb.c
K> @@ -961,15 +961,7 @@ igb_mq_start(struct ifnet *ifp, struct mbuf *m)
K>   que = &adapter->queues[i];
K>   if (((txr->queue_status & IGB_QUEUE_DEPLETED) == 0) &&
K>       IGB_TX_TRYLOCK(txr)) {
K> -         struct mbuf *pm = NULL;
K> -         /*
K> -         ** Try to queue first to avoid
K> -         ** out-of-order delivery, but
K> -         ** settle for it if that fails
K> -         */
K> -         if (m && drbr_enqueue(ifp, txr->br, m))
K> -                 pm = m;
K> -         err = igb_mq_start_locked(ifp, txr, pm);
K> +         err = igb_mq_start_locked(ifp, txr, m);
K>           IGB_TX_UNLOCK(txr);
K>   } else {
K>           err = drbr_enqueue(ifp, txr->br, m);

Well, the idea to prevent out-of-order delivery is important. TCP
suffers a lot when this happens.

I'd suggest the following code:

                if (m)
                        drbr_enqueue(ifp, txr->br, m);
                err = igb_mq_start_locked(ifp, txr, NULL);

Which eventually leads us to all invocations of igb_mq_start_locked() called
with third argument as NULL. This allows us to simplify this function.

Patch for review attached.


In my case I use ALTQ and in igb_mq_start_locked() it calls drbr_needs_enqueue() which always return 1 with ALTQ. So I did not see the out of order issue. I do think your patch makes sense though and I'm also thinking that em_mq_start() could also benefit from the same logic.

Regards,

Karim.

_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"

Reply via email to