Add a description for the hardware-assisted checksumming
facilities based on http://people.freebsd.org/~jlemon/csum.txt and my own observations.
This commit is contained in:
parent
34be712a35
commit
c939cff388
@ -238,6 +238,12 @@ the packet has been received from
|
||||
.Pq Vt struct ifnet Va *rcvif ,
|
||||
and the total packet length
|
||||
.Pq Vt int Va len .
|
||||
Fields used in offloading checksum calculation to the hardware are kept in
|
||||
.Va m_pkthdr
|
||||
as well.
|
||||
See
|
||||
.Sx HARDWARE-ASSISTED CHECKSUM CALCULATION
|
||||
for details.
|
||||
.Pp
|
||||
If small enough, data is stored in the internal data buffer of an
|
||||
.Vt mbuf .
|
||||
@ -760,6 +766,164 @@ and attempts to restore the
|
||||
.Vt mbuf chain
|
||||
to its original state.
|
||||
.El
|
||||
.Sh HARDWARE-ASSISTED CHECKSUM CALCULATION
|
||||
This section currently applies to TCP/IP only.
|
||||
In order to save the host CPU resources, computing checksums is
|
||||
offloaded to the network interface hardware if possible.
|
||||
The
|
||||
.Va m_pkthdr
|
||||
member of the leading
|
||||
.Vt mbuf
|
||||
of a packet contains two fields used for that purpose,
|
||||
.Vt int Va csum_flags
|
||||
and
|
||||
.Vt int Va csum_data .
|
||||
The meaning of those fields depends on the direction a packet flows in,
|
||||
and on whether the packet is fragmented.
|
||||
Henceforth,
|
||||
.Va csum_flags
|
||||
or
|
||||
.Va csum_data
|
||||
of a packet
|
||||
will denote the corresponding field of the
|
||||
.Va m_pkthdr
|
||||
member of the leading
|
||||
.Vt mbuf
|
||||
in the
|
||||
.Vt mbuf chain
|
||||
containing the packet.
|
||||
.Pp
|
||||
On output, checksum offloading is attempted after the outgoing
|
||||
interface has been determined for a packet.
|
||||
The interface-specific field
|
||||
.Va ifnet.if_data.ifi_hwassist
|
||||
(see
|
||||
.Xr ifnet 9 )
|
||||
is consulted for the capabilities of the interface to assist in
|
||||
computing checksums.
|
||||
The
|
||||
.Va csum_flags
|
||||
field of the packet is set to indicate which actions the interface
|
||||
is supposed to perform on it.
|
||||
The actions unsupported by the network interface are done in the
|
||||
software prior to passing the packet down to the interface driver;
|
||||
such actions will never be requested through
|
||||
.Va csum_flags .
|
||||
.Pp
|
||||
The flags demanding a particular action from an interface are as follows:
|
||||
.Bl -tag -width ".Dv CSUM_TCP" -offset indent
|
||||
.It Dv CSUM_IP
|
||||
The IP header checksum is to be computed and stored in the
|
||||
corresponding field of the packet.
|
||||
The hardware is expected to know the format of an IP header
|
||||
to determine the offset of the IP checksum field.
|
||||
.It Dv CSUM_TCP
|
||||
The TCP checksum is to be computed. (See below.)
|
||||
.It Dv CSUM_UDP
|
||||
The UDP checksum is to be computed. (See below.)
|
||||
.El
|
||||
.Pp
|
||||
Should the TCP or UDP checksum be calculated in the hardware,
|
||||
the field
|
||||
.Va csum_data
|
||||
will contain the byte offset of the checksum field relative to the
|
||||
end of the IP header.
|
||||
In this case, the checksum field will be initially
|
||||
set by the TCP/IP module to the checksum of the pseudo header
|
||||
defined by the protocol specification.
|
||||
.Pp
|
||||
For outbound packets which have been fragmented
|
||||
by the host CPU, the following will also be true,
|
||||
regardless of the checksum flag settings:
|
||||
.Bl -bullet -offset indent
|
||||
.It
|
||||
all fragments will have the flag
|
||||
.Dv M_FRAG
|
||||
set in their
|
||||
.Va m_flags
|
||||
field;
|
||||
.It
|
||||
the first and the last fragments in the chain will have
|
||||
.Dv M_FIRSTFRAG
|
||||
or
|
||||
.Dv M_LASTFRAG
|
||||
set in their
|
||||
.Va m_flags ,
|
||||
correspondingly;
|
||||
.It
|
||||
the first fragment in the chain will have the total number
|
||||
of fragments contained in its
|
||||
.Va csum_data
|
||||
field.
|
||||
.El
|
||||
.Pp
|
||||
It is obvious that computing the TCP or UDP checksum cannot
|
||||
be offloaded for a packet fragmented by the host CPU.
|
||||
Consequently, there is no ambiguity in the meaning of
|
||||
.Va csum_data
|
||||
for an outgoing packet.
|
||||
.Pp
|
||||
On input, an interface indicates the actions it has performed
|
||||
on a packet by setting one or more of the following flags in
|
||||
.Va csum_flags
|
||||
associated with the packet:
|
||||
.Bl -tag -width ".Dv CSUM_IP_CHECKED" -offset indent
|
||||
.It Dv CSUM_IP_CHECKED
|
||||
The IP header checksum has been computed.
|
||||
.It Dv CSUM_IP_VALID
|
||||
The IP header has a valid checksum.
|
||||
This flag can appear only in combination with
|
||||
.Dv CSUM_IP_CHECKED .
|
||||
.It Dv CSUM_DATA_VALID
|
||||
The checksum of the data portion of the IP packet has been computed
|
||||
and stored in the field
|
||||
.Va csum_data
|
||||
in network byte order.
|
||||
.It Dv CSUM_PSEUDO_HDR
|
||||
Can be set only along with
|
||||
.Dv CSUM_DATA_VALID
|
||||
to indicate that the IP data checksum found in
|
||||
.Va csum_data
|
||||
allows for the pseudo header.
|
||||
Otherwise the checksum of the pseudo header must be calculated by
|
||||
the host CPU and added to
|
||||
.Va csum_data
|
||||
to obtain the final checksum to be used for validation purposes.
|
||||
.El
|
||||
.Pp
|
||||
If a particular network interface just indicates success or
|
||||
failure of TCP or UDP checksum validation without returning
|
||||
the exact value of the checksum to the host CPU, its driver can mark
|
||||
.Dv CSUM_DATA_VALID
|
||||
and
|
||||
.Dv CSUM_PSEUDO_HDR
|
||||
in
|
||||
.Va csum_flags ,
|
||||
and set
|
||||
.Va csum_data
|
||||
to
|
||||
.Li 0xFFFF
|
||||
hexadecimal to indicate a valid checksum.
|
||||
It's a peculiarity of the algorithm used that the Internet checksum
|
||||
calculated over any valid packet will be
|
||||
.Li 0xFFFF
|
||||
as long as the original checksum field is included.
|
||||
.Pp
|
||||
For inbound packets which are IP fragments, all
|
||||
.Va csum_data
|
||||
fields will be summed during reassembly to obtain the final checksum
|
||||
value passed to an upper layer in the
|
||||
.Va csum_data
|
||||
field of the reassembled packet.
|
||||
The
|
||||
.Va csum_flags
|
||||
fields of all fragments will be consolidated using logical AND
|
||||
to obtain the final value for
|
||||
.Va csum_flags .
|
||||
Thus, in order to successfully
|
||||
offload checksum computation for fragmented data,
|
||||
all fragments should have the same value of
|
||||
.Va csum_flags .
|
||||
.Sh STRESS TESTING
|
||||
When running a kernel compiled with the option
|
||||
.Dv MBUF_STRESS_TEST ,
|
||||
@ -791,6 +955,8 @@ should be tested with this feature.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
See above.
|
||||
.Sh SEE ALSO
|
||||
.Xr ifnet 9 .
|
||||
.Sh HISTORY
|
||||
.\" Please correct me if I'm wrong
|
||||
.Vt Mbufs
|
||||
|
Loading…
Reference in New Issue
Block a user