Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 Mar 2011 09:51:00 -0400
From:      Arnaud Lacombe <lacombar@gmail.com>
To:        Jack Vogel <jfvogel@gmail.com>
Cc:        freebsd-net@freebsd.org
Subject:   em(4) hang [Was: Re: igb(4) won't start with "igb0: Could not setup receive structures"]
Message-ID:  <AANLkTin64gGxRituE2B%2BsfVpRXt2QetdNLaV7HCf0uNE@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Hi

[let's start a new thread :)]

On Wed, Mar 30, 2011 at 2:22 PM, Jack Vogel <jfvogel@gmail.com> wrote:
> Read the code in HEAD, em_local_timer() has a test of ALL the rx queues and
> will schedule a task that refreshes mbufs if they are empty. This has
> exactly the
> same effect as checking for some interrupt cause, a cause that is not
> available
> when using MSIX on 82574, but this approach works for everything.
>
ok, it took me a long time to reproduce the issue with em(4) version
7.1.9, about 3h rather than a few minutes a month ago and only got
~875 allocations failure vs. several thousand before, here are some
stats:

# sysctl -a | grep missed
dev.em.0.mac_stats.missed_packets: 1917112
dev.em.1.mac_stats.missed_packets: 0
dev.em.2.mac_stats.missed_packets: 0
dev.em.3.mac_stats.missed_packets: 0
dev.em.4.mac_stats.missed_packets: 0
dev.em.5.mac_stats.missed_packets: 0

# sysctl dev.em.0.debug=1
dev.em.0.debug: I-1nterface is RUNNING and INACTIVE
em0: hw tdh = 861, hw tdt = 861
em0: hw rdh = 929, hw rdt = 929
em0: Tx Queue Status = 0
em0: TX descriptors avail = 1024
em0: Tx Descriptors avail failure = 0
em0: RX discarded packets = 0
em0: RX Next to Check = 929
em0: RX Next to Refresh = 930
 -> -1

I backported the -current driver to 7.1 and re-ran the test overnight.
Now, the box is running 7.2.2. The box was hung this morning:

dev.em.0.mac_stats.missed_packets: 25513991
dev.em.1.mac_stats.missed_packets: 0
dev.em.2.mac_stats.missed_packets: 0
dev.em.3.mac_stats.missed_packets: 0
dev.em.4.mac_stats.missed_packets: 0
dev.em.5.mac_stats.missed_packets: 0

There has been about 1000 mbuf allocation denial. I changed some
relevant field of the RX soft stat in the sysctl output of the device
[Of course, the only field of interest, `next_to_check' is invalid
because of a typo... I should not change code past a certain hour :)],
here it is:

# sysctl dev.em.0
dev.em.0.%desc: Intel(R) PRO/1000 Network Connection 7.2.2
dev.em.0.%driver: em
dev.em.0.%location: slot=0 function=0
dev.em.0.%pnpinfo: vendor=0x8086 device=0x10d3 subvendor=0x8086
subdevice=0x0000 class=0x020000
dev.em.0.%parent: pci1
dev.em.0.nvm: -1
dev.em.0.debug: -1
dev.em.0.rx_int_delay: 0
dev.em.0.tx_int_delay: 66
dev.em.0.rx_abs_int_delay: 66
dev.em.0.tx_abs_int_delay: 66
dev.em.0.rx_processing_limit: 100
dev.em.0.flow_control: 3
dev.em.0.eee_control: 0
dev.em.0.link_irq: 11621474
dev.em.0.mbuf_alloc_fail: 0
dev.em.0.cluster_alloc_fail: 0
dev.em.0.dropped: 0
dev.em.0.tx_dma_fail: 0
dev.em.0.rx_overruns: 0
dev.em.0.watchdog_timeouts: 0
dev.em.0.device_control: 1477444168
dev.em.0.rx_control: 67141634
dev.em.0.fc_high_water: 18432
dev.em.0.fc_low_water: 16932
dev.em.0.queue0.txd_head: 904
dev.em.0.queue0.txd_tail: 904
dev.em.0.queue0.tx_irq: 10291170
dev.em.0.queue0.no_desc_avail: 0
dev.em.0.queue0.rxd_head: 766
dev.em.0.queue0.rxd_tail: 767
dev.em.0.queue0.rx_irq: 6937760
dev.em.0.queue0.rx_discarded: 0
dev.em.0.queue0.rx_forced_refill: 0
dev.em.0.queue0.next_to_check: 6937760
^^^ this field is invalid... bad code... :(
dev.em.0.queue0.next_to_refresh: 767
dev.em.0.mac_stats.excess_coll: 0
dev.em.0.mac_stats.single_coll: 0
dev.em.0.mac_stats.multiple_coll: 0
dev.em.0.mac_stats.late_coll: 0
dev.em.0.mac_stats.collision_count: 0
dev.em.0.mac_stats.symbol_errors: 0
dev.em.0.mac_stats.sequence_errors: 0
dev.em.0.mac_stats.defer_count: 0
dev.em.0.mac_stats.missed_packets: 25752895
dev.em.0.mac_stats.recv_no_buff: 3
dev.em.0.mac_stats.recv_undersize: 0
dev.em.0.mac_stats.recv_fragmented: 0
dev.em.0.mac_stats.recv_oversize: 0
dev.em.0.mac_stats.recv_jabber: 0
dev.em.0.mac_stats.recv_errs: 0
dev.em.0.mac_stats.crc_errs: 0
dev.em.0.mac_stats.alignment_errs: 0
dev.em.0.mac_stats.coll_ext_errs: 0
dev.em.0.mac_stats.xon_recvd: 0
dev.em.0.mac_stats.xon_txd: 0
dev.em.0.mac_stats.xoff_recvd: 0
dev.em.0.mac_stats.xoff_txd: 25752073
dev.em.0.mac_stats.total_pkts_recvd: 39996734
dev.em.0.mac_stats.good_pkts_recvd: 14243839
dev.em.0.mac_stats.bcast_pkts_recvd: 5
dev.em.0.mac_stats.mcast_pkts_recvd: 0
dev.em.0.mac_stats.rx_frames_64: 13878627
dev.em.0.mac_stats.rx_frames_65_127: 365212
dev.em.0.mac_stats.rx_frames_128_255: 0
dev.em.0.mac_stats.rx_frames_256_511: 0
dev.em.0.mac_stats.rx_frames_512_1023: 0
dev.em.0.mac_stats.rx_frames_1024_1522: 0
dev.em.0.mac_stats.good_octets_recvd: 916346006
dev.em.0.mac_stats.good_octets_txd: 21377046229
dev.em.0.mac_stats.total_pkts_txd: 44415008
dev.em.0.mac_stats.good_pkts_txd: 18661905
dev.em.0.mac_stats.bcast_pkts_txd: 24822815
dev.em.0.mac_stats.mcast_pkts_txd: 0
dev.em.0.mac_stats.tx_frames_64: 1278447
dev.em.0.mac_stats.tx_frames_65_127: 1221602
dev.em.0.mac_stats.tx_frames_128_255: 503121
dev.em.0.mac_stats.tx_frames_256_511: 770073
dev.em.0.mac_stats.tx_frames_512_1023: 1921953
dev.em.0.mac_stats.tx_frames_1024_1522: 12966709
dev.em.0.mac_stats.tso_txd: 0
dev.em.0.mac_stats.tso_ctx_fail: 0
dev.em.0.interrupts.asserts: 5297765
dev.em.0.interrupts.rx_pkt_timer: 0
dev.em.0.interrupts.rx_abs_timer: 0
dev.em.0.interrupts.tx_pkt_timer: 1
dev.em.0.interrupts.tx_abs_timer: 1
dev.em.0.interrupts.tx_queue_empty: 0
dev.em.0.interrupts.tx_queue_min_thresh: 0
dev.em.0.interrupts.rx_desc_min_thresh: 0
dev.em.0.interrupts.rx_overrun: 3186

I added `rx_forced_refill', which account the number of time the RX
taskqueue is scheduled from em_local_timer().

Now, if I read the patched em_local_timer() correctly, the relevant code being:

        /* trigger tq to refill rx ring queue if it is empty */
        for (int i = 0; i < adapter->num_queues; i++, rxr++) {
                if (rxr->next_to_check == rxr->next_to_refresh) {
                        rxr->rx_forced_refill++;
                        taskqueue_enqueue(rxr->tq, &rxr->rx_task);
                }
        }

and assuming that we have the same pattern between `next_to_check' and
`next_to_refresh' as we did with 7.1.9, it is understandable the
driver hang.

I'll remove part of the changes I made to keep only `rx_forced_refill'
and the associated sysctl, re-run the tests and come back with correct
value, hopefully in a few hours.

 - Arnaud



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTin64gGxRituE2B%2BsfVpRXt2QetdNLaV7HCf0uNE>