tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
wm(4) and the maximum buffer length for TSO
wm(4) sets up its Tx DMA maps like this,
if ((error = bus_dmamap_create(sc->sc_dmat, WM_MAXTXDMA,
WM_NTXSEGS, WTX_MAX_LEN, 0, 0,
&sc->sc_txsoft[i].txs_dmamap)) != 0) {
WM_MAXTXDMA is round_page(IP_MAXPACKET) == round_page(65535) ==
65536. Thus wm(4) will fail to map for Tx any mbuf whose m_pkthdr.len
> 65536. That's ok if tcp_output() produces a buffer no longer
than 65536 bytes for the NIC to segment, but in practice it will
produce a longer buffer because first it clamps the length to
IP_MAXPACKET,
if (use_tso) {
/*
* Truncate TSO transfers to IP_MAXPACKET, and make
* sure that we send equal size transfers down the
* stack (rather than big-small-big-small-...).
*/
#ifdef INET6
CTASSERT(IPV6_MAXPACKET == IP_MAXPACKET);
#endif
len = (min(len, IP_MAXPACKET) / txsegsize) * txsegsize;
...
and then it adds in the combined length of the IP and TCP headers:
m->m_pkthdr.len = hdrlen + len;
In this way, wm(4) can see m->m_pkthdr.len greater than 65536 and fail
to map m. It will send no feedback to TCP to stop trying to send such
long un-segmented buffers. Also, it looks to me like it will retry
forever to map the same mbuf for DMA---that matches the misbehavior that
we're seeing at $DAYJOB, where the wm(4) ceases to transmit anything.
It seems to me that drivers should advertise the maximum unsegmented
buffer length that they support (at least some wm instances support
1MB), and tcp_output() should be very careful not to send a buffer any
longer than what is supported. What do you think?
Dave
--
David Young
dyoung%pobox.com@localhost Urbana, IL (217) 721-9981
Home |
Main Index |
Thread Index |
Old Index