Delayed checksums: In a system which sees a lot of network traffic, computing the checksums of all network packets can take a significant amount of cpu time. This interface provides a way to offload the computation of the checksum to the NIC, if it supports it. The NIC will set the following bits in the interface field if_hwassist to what the hardware is willing to support: #define CSUM_IP 0x0001 /* will csum IP */ #define CSUM_TCP 0x0002 /* will csum TCP */ #define CSUM_UDP 0x0004 /* will csum UDP */ #define CSUM_IP_FRAGS 0x0008 /* will csum IP fragments */ #define CSUM_FRAGMENT 0x0010 /* will do IP fragmentation */ An mbuf that is passed to the driver may have some of these bits set in the m_pkthdr->csum_flags to indicate what actions the hardware is supposed to perform. Only the flags corresponding to actions which the hardware has indicated it's support for should be set. A driver which does not support any checksum offloading should always receive a mbuf with the m_pkthdr->csum_flags field set to 0. For packets which are supposed to have their TCP/UDP checksums computed by the hardware, the checksum field of the TCP/UDP protocol will contain the checksum of the pseudo header. For packets which have been fragemnted by the host cpu, the following will also be true, regardless of the checksum flag settings: - all fragmented packets will have M_FRAG set in m_flags - the last fragment in the chain will have M_LASTFRAG set in the m_flags field. - the first fragment in the chain will have M_FIRSTFRAG set in the m_flags field. - the first fragment in the chain will have the fragment count contained in m_pkthdr.csum_data field. In order to offload incoming checksums, the driver must set the following bits in the m_pkthdr.csum_flag field in the mbuf passed back to the cpu to indicate which actions the hardware has performed: #define CSUM_IP_CHECKED 0x0100 /* did csum IP */ #define CSUM_IP_VALID 0x0200 /* ... the csum is valid */ #define CSUM_DATA_VALID 0x0400 /* csum_data field is valid */ #define CSUM_PSEUDO_HDR 0x0800 /* csum_data has pseudo hdr */ The checksum of the data portion of the packet is placed into the csum_data field of the mbuf (in network-byte order) by the driver, and the CSUM_DATA_VALID flag is set. If the checksum contains the pseudoheader for the packet, CSUM_PSEUDO_HDR should also be set, otherwise the host will compute the pseudo header. For packets which are IP fragments, all csum_data fields will be summed during reassembly to obtain a final checksum. The csum_flags for all fragments will be logical-anded together to obtain the final csum_flags used for protocol checksum offloading. Thus, in order to successfully offload the checksum computation for fragmented data, all fragments should have the same csum_flags.