net device drivers need to set if_hw_tsomaxsegcount and friends
Rick Macklem
rmacklem at uoguelph.ca
Wed Feb 4 00:16:47 UTC 2015
Hi,
If you are an author/maintainer of a network device driver that
supports TSO, please add a few lines to your driver to set these
TSO related parameters in "struct ifnet", before you call
ether_ifattach(). Thanks go to hselasky@ for committing the patch
for these.
if_hw_tsomax - Maximum size of a TSO segment in bytes, excluding
any link level header(s).
Many devices expect this value to be in the 16bit
length in the IP header part of the TSO segment,
but not all.
--> If it must fit in the 16bit IP length field,
then I think IP_MAXPACKET (65535) would be
the correct value.
*** See below w.r.t. weird default for this, which
is probably incorrect/suboptimal for your hardware.
if_hw_tsomaxsegcount - The maximum number of discontiguous transmit
buffers that a TSO segment can live in, typically referred
to as transmit segments.
(This is essentially the upper bound on the number of data
mbufs that tcp_output() can use for the TSO segment.)
--> If your hardware allows it, please make this at least
35. (35 is sufficient for a 64K data payload + assorted
headers for NFS/iSCSI, TCP/IP etc.)
if_hw_tsomaxsegsize - The maximum size in bytes of each of these
transmit segments.
--> If this is less than MCLBYTES, you may need to
reduce if_hw_tsomaxsegcount by one, if the link
level header needs to be in one of these transmit
segments. (Again, see below for this case.)
*** The weird default value for if_hw_tsomax is a workaround for a
problem where devices with a transmit segment limit of 32 would
fail for a TSO segment of just under 64K.
- When a TSO segment was less than 64K by less than the size of
the link level header, the driver couldn't fit the TSO segment
into 32 * MCLBYTES when the size of the link level (MAC) header
was included.
--> Since the device only supported 32 transmit segments, even
m_defrag() couldn't get a > than 64K TSO segment
(including link header) to work.
Therefore, the default for if_hw_tsomax was set to:
32 * MCLBYTES - (max size of ethernet link level header)
as a hack/workaround for the problem. (It is only slightly smaller
than IP_MAXPACKET, which was the previous default.)
--> If the driver sets if_hw_tsomaxsegcount correctly, this hack should
not be needed.
For the weird case of if_hw_tsomaxsegsize < MCLBYTES, you might need to
set if_hw_tsomaxsegcount to 1 less than the hardware limit so that you
have a transmit segment available for the link level (ethernet) header.
If you don't set these values in your driver, the default value of
if_hw_tsomax will probably make things work, but your driver will
end up calling m_defrag() over and over and over again for TSO
segments, if your hardware supports less than 35 transmit segments.
If your hardware supports >= 35 transmit segments, then you might
still be using TSO suboptimally.
So, please set these...Thanks, rick
ps: Here's the comment from if_var.h, in case it does a better
job of describing these.
/*
237 * Network adapter TSO limits:
238 * ===========================
239 *
240 * If the "if_hw_tsomax" field is zero the maximum segment
241 * length limit does not apply. If the "if_hw_tsomaxsegcount"
242 * or the "if_hw_tsomaxsegsize" field is zero the TSO segment
243 * count limit does not apply. If all three fields are zero,
244 * there is no TSO limit.
245 *
246 * NOTE: The TSO limits only apply to the data payload part of
247 * a TCP/IP packet. That means there is no need to subtract
248 * space for ethernet-, vlan-, IP- or TCP- headers from the
249 * TSO limits unless the hardware driver in question requires
250 * so.
251 */
More information about the freebsd-net
mailing list