SKB CHECKSUMS(9)
π skb checksums π
okay so bestie, this is the skb checksums(9) page from the Kernel API Manual β part 1 of 2, and we are doing a full vibe check on every flag, value, and caveat. No skipping, no cap. The whole interface for checksum offload between the stack and networking drivers is as follows...
β¨ IP checksum related features β¨
Drivers advertise checksum offload capabilities in the features of a device. From the stack's point of view these are capabilities offered by the driver. A driver typically only advertises features that it is capable of offloading to its device.
the feature table is named Checksum related device features and has :widths: 1 10, so here are the rows:
NETIF_F_HW_CSUMβ The driver (or its device) is able to compute one IP (one's complement) checksum for any combination of protocols or protocol layering. The checksum is computed and set in a packet per theCHECKSUM_PARTIALinterface (see below). main character energy, honestly.NETIF_F_IP_CSUMβ Driver (device) is only able to checksum plain TCP or UDP packets over IPv4. These are specifically unencapsulated packets of the formIPv4|TCPorIPv4|UDPwhere theProtocolfield in the IPv4 header is TCP or UDP. The IPv4 header may contain IP options. This feature cannot be set in features for a device withNETIF_F_HW_CSUMalso set. This feature is being DEPRECATED (see below). lowkey old school.NETIF_F_IPV6_CSUMβ Driver (device) is only able to checksum plain TCP or UDP packets over IPv6. These are specifically unencapsulated packets of the formIPv6|TCPorIPv6|UDPwhere theNext Headerfield in the IPv6 header is either TCP or UDP. IPv6 extension headers are not supported with this feature. This feature cannot be set in features for a device withNETIF_F_HW_CSUMalso set. This feature is being DEPRECATED (see below). also lowkey old school.NETIF_F_RXCSUMβ Driver (device) performs receive checksum offload. This flag is only used to disable the RX checksum feature for a device. The stack will accept receive checksum indication in packets received on a device regardless of whetherNETIF_F_RXCSUMis set. not me thinking it's a full on/off switch β it's specifically the disable knob, bestie.
π«Ά Checksumming of received packets by device π«Ά
Indication of checksum verification is set in sk_buff.ip_summed. Possible values are:
CHECKSUM_NONEβ Device did not checksum this packet e.g. due to lack of capabilities. The packet contains full (though not verified) checksum in packet but not inskb->csum. Thus,skb->csumis undefined in this case. so do not trust that field, fr fr.CHECKSUM_UNNECESSARYβ The hardware you're dealing with doesn't calculate the full checksum (as inCHECKSUM_COMPLETE), but it does parse headers and verify checksums for specific protocols. For such packets it will setCHECKSUM_UNNECESSARYif their checksums are okay.sk_buff.csumis still undefined in this case though. A driver or device must never modify the checksum field in the packet even if checksum is verified. iconic boundary, honestly.- TCP: IPv6 and IPv4.
- UDP: IPv4 and IPv6. A device may apply
CHECKSUM_UNNECESSARYto a zero UDP checksum for either IPv4 or IPv6, the networking stack may perform further validation in this case. - GRE: only if the checksum is present in the header.
- SCTP: indicates the CRC in SCTP header has been validated.
- FCOE: indicates the CRC in FC frame has been validated.
sk_buff.csum_level indicates the number of consecutive checksums found in the packet minus one that have been verified as CHECKSUM_UNNECESSARY. For instance if a device receives an IPv6->UDP->GRE->IPv4->TCP packet and a device is able to verify the checksums for UDP (possibly zero), GRE (checksum flag is set) and TCP, sk_buff.csum_level would be set to two. If the device were only able to verify the UDP checksum and not GRE, either because it doesn't support GRE checksum or because GRE checksum is bad, skb->csum_level would be set to zero (TCP checksum is not considered in this case). the way that math works is so specific and I respect it.
CHECKSUM_COMPLETEβ This is the most generic way. The device supplied checksum of the _whole_ packet as seen bynetif_rxand fills insk_buff.csum. This means the hardware doesn't need to parse L3/L4 headers to implement this. Notes:- Even if device supports only some protocols, but is able to produce
skb->csum, it MUST useCHECKSUM_COMPLETE, notCHECKSUM_UNNECESSARY. CHECKSUM_COMPLETEis not applicable to SCTP and FCoE protocols.
- Even if device supports only some protocols, but is able to produce
CHECKSUM_PARTIALβ A checksum is set up to be offloaded to a device as described in the output description forCHECKSUM_PARTIAL. This may occur on a packet received directly from another Linux OS, e.g., a virtualized Linux kernel on the same host, or it may be set in the input path in GRO or remote checksum offload. For the purposes of checksum verification, the checksum referred to byskb->csum_start + skb->csum_offsetand any preceding checksums in the packet are considered verified. Any checksums in the packet that are after the checksum being offloaded are not considered to be verified. so if it's after, do not count it verified β periodt.
π Checksumming on transmit for non-GSO π
The stack requests checksum offload in the sk_buff.ip_summed for a packet. Values are:
CHECKSUM_PARTIALβ The driver is required to checksum the packet as seen byhard_start_xmitfromsk_buff.csum_startup to the end, and to record/write the checksum at offsetsk_buff.csum_start + sk_buff.csum_offset. A driver may verify that thecsum_startandcsum_offsetvalues are valid values given the length and offset of the packet, but it should not attempt to validate that the checksum refers to a legitimate transport layer checksum -- it is the purview of the stack to validate thatcsum_startandcsum_offsetare set correctly.
When the stack requests checksum offload for a packet, the driver MUST ensure that the checksum is set correctly. A driver can either offload the checksum calculation to the device, or call skb_checksum_help (in the case that the device does not support offload for a particular checksum).
NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM are being deprecated in favor of NETIF_F_HW_CSUM. New devices should use NETIF_F_HW_CSUM to indicate checksum offload capability. skb_csum_hwoffload_help can be called to resolve CHECKSUM_PARTIAL based on network device checksumming capabilities: if a packet does not match them, skb_checksum_help or skb_crc32c_help (depending on the value of sk_buff.csum_not_inet, see the crc reference) is called to resolve the checksum.
the driver MUST ensure the checksum is set correctly. not "should", not "maybe", MUST. fr fr. π
CHECKSUM_NONEβ The skb was already checksummed by the protocol, or a checksum is not required. chill.CHECKSUM_UNNECESSARYβ This has the same meaning asCHECKSUM_NONEfor checksum offload on output. same vibe, different name.CHECKSUM_COMPLETEβ Not used in checksum output. If a driver observes a packet with this value set in skbuff, it should treat the packet as ifCHECKSUM_NONEwere set. do not invent new behavior, bestie.
tiny anchor checkpoint:.. _crc:goes right here in the original, so thecrcreference above has somewhere to land. iykyk.
π§ Non-IP checksum (CRC) offloads π§
the original has a FLAT-TABLE: with :widths: 1 10, and the rows are:
NETIF_F_SCTP_CRCβ This feature indicates that a device is capable of offloading the SCTP CRC in a packet. To perform this offload the stack will setcsum_startandcsum_offsetaccordingly, setip_summedtoCHECKSUM_PARTIALand setcsum_not_inetto1, to provide an indication in the skbuff that theCHECKSUM_PARTIALrefers to CRC32c. A driver that supports both IP checksum offload and SCTP CRC32c offload must verify which offload is configured for a packet by testing the value ofsk_buff.csum_not_inet;skb_crc32c_csum_helpis provided to resolveCHECKSUM_PARTIALon skbs wherecsum_not_inetis set to1. ate.NETIF_F_FCOE_CRCβ This feature indicates that a device is capable of offloading the FCOE CRC in a packet. To perform this offload the stack will setip_summedtoCHECKSUM_PARTIALand setcsum_startandcsum_offsetaccordingly. Note that there is no indication in the skbuff that theCHECKSUM_PARTIALrefers to an FCOE checksum, so a driver that supports both IP checksum offload and FCOE CRC offload must verify which offload is configured for a packet, presumably by inspecting packet headers. so you gotta look at headers β slay.
π Checksumming on output with GSO π
In the case of a GSO packet (skb_is_gso is true), checksum offload is implied by the SKB_GSO_* flags in gso_type. Most obviously, if the gso_type is SKB_GSO_TCPV4 or SKB_GSO_TCPV6, TCP checksum offload as part of the GSO operation is implied. If a checksum is being offloaded with GSO then ip_summed is CHECKSUM_PARTIAL, and both csum_start and csum_offset are set to refer to the outermost checksum being offloaded (two offloaded checksums are possible with UDP encapsulation). iconic, honestly.
and that's where part 1 stops, bestie β part 2 is next and there's more page to go π
π the deep-lore reading list, aka the SEE ALSO section
okay bestie, you made it to the end and now you get the bonus round β¨ β every single cross-reference on this page, in order, no skipping, because some of these are lowkey the whole personality of the skb code. Go click around, iykyk π«Ά
First up, the mothership itself β Kernel file ./include/linux/skbuff.h β and then the frag girlies, who handle all the fragment size math:
skb_frag_size(9)skb_frag_size_set(9)skb_frag_size_add(9)skb_frag_size_sub(9)skb_frag_must_loop(9)skb_frag_foreach_page(9)
Then the β¨conceptβ¨ pages β timestamp structs, datarefs, geometry, and the main character herself, struct sk_buff:
struct skb_shared_hwtstamps(9)dataref and headerless skbs(9)Basic sk_buff geometry(9)struct sk_buff(9)
π dst land + napi + the refcount/free squad:
skb_pfmemalloc(9)skb_dst(9)skb_dstref_steal(9)skb_dstref_restore(9)skb_dst_set(9)skb_dst_set_noref(9)skb_dst_is_noref(9)skb_napi_id(9)skb_unref(9)kfree_skb(9)
Allocation, padding, queue vibes, and the clone/share/unshare trio (they're a package deal, fr fr):
alloc_skb(9)skb_fclone_busy(9)alloc_skb_fclone(9)skb_pad(9)skb_queue_empty(9)skb_queue_empty_lockless(9)skb_queue_is_last(9)skb_queue_is_first(9)skb_queue_next(9)skb_queue_prev(9)skb_get(9)skb_cloned(9)skb_header_cloned(9)__skb_header_release(9)skb_shared(9)skb_share_check(9)skb_unshare(9)
π· peek at the queue, check the length, splice it, init it, dequeue it β the whole queue choreography:
skb_peek(9)__skb_peek(9)skb_peek_next(9)skb_peek_tail(9)skb_queue_len(9)skb_queue_len_lockless(9)__skb_queue_head_init(9)skb_queue_splice(9)skb_queue_splice_init(9)skb_queue_splice_tail(9)skb_queue_splice_tail_init(9)__skb_queue_after(9)__skb_queue_head(9)__skb_queue_tail(9)__skb_dequeue(9)__skb_dequeue_tail(9)skb_len_add(9)
Filling page descs, headroom/tailroom math, and the carefully-named header setters (yes they're careful, that's the whole point π):
__skb_fill_netmem_desc(9)skb_fill_page_desc(9)skb_fill_page_desc_noacc(9)skb_headroom(9)skb_tailroom(9)skb_availroom(9)skb_reserve(9)skb_tailroom_reserve(9)skb_reset_transport_header_careful(9)skb_set_transport_header_careful(9)pskb_trim_unique(9)skb_orphan(9)skb_orphan_frags(9)__skb_queue_purge_reason(9)
π¦ the alloc family expands β frags, skbs, and dev pages:
netdev_alloc_frag(9)netdev_alloc_skb(9)__dev_alloc_pages(9)__dev_alloc_page(9)dev_page_is_reusable(9)skb_propagate_pfmemalloc(9)
Frag offsets, net iovs, pages, netmems, addresses, phys, copies and the DMA map β the frag extended universe π«:
skb_frag_off(9)skb_frag_off_add(9)skb_frag_off_set(9)skb_frag_off_copy(9)skb_frag_net_iov(9)skb_frag_page(9)skb_frag_netmem(9)skb_frag_address(9)skb_frag_address_safe(9)skb_frag_phys(9)skb_frag_page_copy(9)__skb_frag_dma_map(9)
Copy-on-write era π β clone_writable, cow, cow_head, the padto trio, and the linearize squad:
skb_clone_writable(9)skb_cow(9)skb_cow_head(9)skb_padto(9)__skb_put_padto(9)skb_put_padto(9)skb_linearize(9)skb_has_shared_frag(9)skb_linearize_cow(9)
rcsum fixups, the linearize check, and every timestamp/data-move entry you could ever want β°:
skb_postpull_rcsum(9)skb_postpush_rcsum(9)skb_push_rcsum(9)pskb_trim_rcsum(9)skb_needs_linearize(9)skb_get_timestamp(9)skb_data_move(9)skb_postpull_data_move(9)skb_postpush_data_move(9)skb_complete_tx_timestamp(9)skb_tstamp_tx(9)skb_tx_timestamp(9)skb_complete_wifi_ack(9)
and the final four, saving the checksum completion for last because of course π:
skb_checksum_complete(9)struct skb_ext(9)skb_checksum_none_assert(9)skb_head_is_locked(9)
and that's the whole page, bestie β you're officially an skb checksum girlie now ππ
This one comes to you from the kernel source at ./include/linux, dated October 2026, and it's the skb checksums(9) page β go forth and checksum responsibly β¨π«Άπ
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms