brintos

brintos / linux-shallow public Read only

0
0
Text · 6.3 KiB · 69b23cf Raw
144 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3=================4Checksum Offloads5=================6 7 8Introduction9============10 11This document describes a set of techniques in the Linux networking stack to12take advantage of checksum offload capabilities of various NICs.13 14The following technologies are described:15 16* TX Checksum Offload17* LCO: Local Checksum Offload18* RCO: Remote Checksum Offload19 20Things that should be documented here but aren't yet:21 22* RX Checksum Offload23* CHECKSUM_UNNECESSARY conversion24 25 26TX Checksum Offload27===================28 29The interface for offloading a transmit checksum to a device is explained in30detail in comments near the top of include/linux/skbuff.h.31 32In brief, it allows to request the device fill in a single ones-complement33checksum defined by the sk_buff fields skb->csum_start and skb->csum_offset.34The device should compute the 16-bit ones-complement checksum (i.e. the35'IP-style' checksum) from csum_start to the end of the packet, and fill in the36result at (csum_start + csum_offset).37 38Because csum_offset cannot be negative, this ensures that the previous value of39the checksum field is included in the checksum computation, thus it can be used40to supply any needed corrections to the checksum (such as the sum of the41pseudo-header for UDP or TCP).42 43This interface only allows a single checksum to be offloaded.  Where44encapsulation is used, the packet may have multiple checksum fields in45different header layers, and the rest will have to be handled by another46mechanism such as LCO or RCO.47 48CRC32c can also be offloaded using this interface, by means of filling49skb->csum_start and skb->csum_offset as described above, and setting50skb->csum_not_inet: see skbuff.h comment (section 'D') for more details.51 52No offloading of the IP header checksum is performed; it is always done in53software.  This is OK because when we build the IP header, we obviously have it54in cache, so summing it isn't expensive.  It's also rather short.55 56The requirements for GSO are more complicated, because when segmenting an57encapsulated packet both the inner and outer checksums may need to be edited or58recomputed for each resulting segment.  See the skbuff.h comment (section 'E')59for more details.60 61A driver declares its offload capabilities in netdev->hw_features; see62Documentation/networking/netdev-features.rst for more.  Note that a device63which only advertises NETIF_F_IP[V6]_CSUM must still obey the csum_start and64csum_offset given in the SKB; if it tries to deduce these itself in hardware65(as some NICs do) the driver should check that the values in the SKB match66those which the hardware will deduce, and if not, fall back to checksumming in67software instead (with skb_csum_hwoffload_help() or one of the68skb_checksum_help() / skb_crc32c_csum_help functions, as mentioned in69include/linux/skbuff.h).70 71The stack should, for the most part, assume that checksum offload is supported72by the underlying device.  The only place that should check is73validate_xmit_skb(), and the functions it calls directly or indirectly.  That74function compares the offload features requested by the SKB (which may include75other offloads besides TX Checksum Offload) and, if they are not supported or76enabled on the device (determined by netdev->features), performs the77corresponding offload in software.  In the case of TX Checksum Offload, that78means calling skb_csum_hwoffload_help(skb, features).79 80 81LCO: Local Checksum Offload82===========================83 84LCO is a technique for efficiently computing the outer checksum of an85encapsulated datagram when the inner checksum is due to be offloaded.86 87The ones-complement sum of a correctly checksummed TCP or UDP packet is equal88to the complement of the sum of the pseudo header, because everything else gets89'cancelled out' by the checksum field.  This is because the sum was90complemented before being written to the checksum field.91 92More generally, this holds in any case where the 'IP-style' ones complement93checksum is used, and thus any checksum that TX Checksum Offload supports.94 95That is, if we have set up TX Checksum Offload with a start/offset pair, we96know that after the device has filled in that checksum, the ones complement sum97from csum_start to the end of the packet will be equal to the complement of98whatever value we put in the checksum field beforehand.  This allows us to99compute the outer checksum without looking at the payload: we simply stop100summing when we get to csum_start, then add the complement of the 16-bit word101at (csum_start + csum_offset).102 103Then, when the true inner checksum is filled in (either by hardware or by104skb_checksum_help()), the outer checksum will become correct by virtue of the105arithmetic.106 107LCO is performed by the stack when constructing an outer UDP header for an108encapsulation such as VXLAN or GENEVE, in udp_set_csum().  Similarly for the109IPv6 equivalents, in udp6_set_csum().110 111It is also performed when constructing an IPv4 GRE header, in112net/ipv4/ip_gre.c:build_header().  It is *not* currently performed when113constructing an IPv6 GRE header; the GRE checksum is computed over the whole114packet in net/ipv6/ip6_gre.c:ip6gre_xmit2(), but it should be possible to use115LCO here as IPv6 GRE still uses an IP-style checksum.116 117All of the LCO implementations use a helper function lco_csum(), in118include/linux/skbuff.h.119 120LCO can safely be used for nested encapsulations; in this case, the outer121encapsulation layer will sum over both its own header and the 'middle' header.122This does mean that the 'middle' header will get summed multiple times, but123there doesn't seem to be a way to avoid that without incurring bigger costs124(e.g. in SKB bloat).125 126 127RCO: Remote Checksum Offload128============================129 130RCO is a technique for eliding the inner checksum of an encapsulated datagram,131allowing the outer checksum to be offloaded.  It does, however, involve a132change to the encapsulation protocols, which the receiver must also support.133For this reason, it is disabled by default.134 135RCO is detailed in the following Internet-Drafts:136 137* https://tools.ietf.org/html/draft-herbert-remotecsumoffload-00138* https://tools.ietf.org/html/draft-herbert-vxlan-rco-00139 140In Linux, RCO is implemented individually in each encapsulation protocol, and141most tunnel types have flags controlling its use.  For instance, VXLAN has the142flag VXLAN_F_REMCSUM_TX (per struct vxlan_rdst) to indicate that RCO should be143used when transmitting to a given remote destination.144