BUG: some drivers return ENOBUFS when the mbuf is actually queued

Luigi Rizzo rizzo at iet.unipi.it
Wed Jun 4 13:45:03 UTC 2014


Hi,
if I read correctly the code, there are a few network device drivers
(igb, ixgbe, i40e, vtnet, vmxnet) where ifp->if_transmit(ifp, m)
can return ENOBUFS even when 'm' has _not_ been dropped:

    e1000/if_igb.c :: igb_mq_start()
            can return ENOBUFS from igb_xmit()

    ixgbe/ixgbe_main.c :: ixgbe_mq_start_locked()
            can return ENOBUFS from ixgbe_xmit()
       (similar for i40)

    virtio/network/if_vtnet.c :: vtnet_txq_mq_start
            can return ENOBUFS if virtqueue_full()

In all these cases, the error comes from a later attempt to transfer
mbufs from the buf_ring to the NIC ring.

All drivers using if_transmit() seem correct, as well as a bunch
of others (cxgbe, sfxge, mxge ...) that reassign if_transmit and I
checked for correctness.

I think that when the current buffer has been queued, returning
ENOBUFS is extremely confusing and should not be done.

I would also argue that the return from ifp->if_transmit(ifp, m)
should only tell what happened to 'm', not other things
such as the status of the queue.

Any objections if i fix the above drivers ?

	cheers
	luigi

(For those curious: i found this issue when using emulated
netmap mode on top of a standard driver. The netmap emulation
code assumes that ENOBUFS indicates that the driver has
m_free()'d the mbuf, same as it happens on linux, and the
bug was causing panics in my system).



More information about the freebsd-current mailing list