Julian Elischer julian at
Wed Jul 26 19:03:22 UTC 2006

Murat Balaban wrote:

>Hello hackers,
>I have a special-purpose setting where I have a ng_hub like kernel module (ng_lb)
>which I've been coding. The box I'm using has two em(4) adapters, and I've
>hooked em0's lower with my ng_lb's link0, and em1's lower with ng_lb's link1.
>Situation looks like this:
>        lower            link0                 link1              lower
>em0 ---------------> -------------> ng_lb --------------> ---------------> em1
>Every packet that is received by em0 is handed over to my netgraph module and
>after very little modification in the packet ethernet header (changing destination
>mac addresss) I NG_FWD_ITEM() the packet to em1.

somewhat similar to what ng_bridge does.

>I'm generating traffic with a packet generator, and em0 seems to be ok with around
>910 Mbit/s traffic.
>However if I write the packets into em1, em1 seems to drop 40-60 Mbit/s (of 910 Mbit/s)
>data. I digged the problem a bit, and found out that, IFQ_HANDOFF, called deep inside
>from NG_FWD_ITEM was returning ENOBUFS.
>A little more investigation proved me that the source of ENOBUFS error was that
>the em1 was running out of Tx descriptors. The relative logic in dev/em/if_em.c
>(em_encap) was that if # of Tx descriptors falls below a threshold, the driver
>tries to clean transmit interrupts once. # of available Tx desc. is again checked
>and if the number is still not incresed ENOBUFS error is returned.
>What I'd like to ask is, instead of cleaning the transmit interrupts only once,
>why not do it many times till the number of available tx descriptors increases 
>to a moderate level?
>The following patch solved my problem, though I wanted to get your opinions about
>PS: Both cards are plugged into a 64-bit 66 Mhz PCI-X bus. I've polling enabled
>in both interfaces, and HZ set to 10000.
>--- if_em_murat.c       Wed Jul 26 13:59:22 2006
>+++ if_em.c     Wed Jul 26 14:01:11 2006
>@@ -1177,11 +1177,9 @@
>          * available hits the threshold
>          */
>         if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
>-                em_clean_transmit_interrupts(adapter);
>-                if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
>-                        adapter->no_tx_desc_avail1++;
>-                        return(ENOBUFS);
>-                }
>+               do {
>+                       em_clean_transmit_interrupts(adapter);
>+               while (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD);
>         }

please have some limit to the number of times that the loop can be run.. 
maybe 20 or something.
(and maybe something  to note that it has hit that limit).

>         /*
>freebsd-hackers at mailing list
>To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at"

More information about the freebsd-hackers mailing list