Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

igb/igbvf: Don't use lco_csum to compute IPv4 checksum

In the case of IPIP and SIT tunnel frames the outer transport header
offset is actually set to the same offset as the inner transport header.
This results in the lco_csum call not doing any checksum computation over
the inner IPv4/v6 header data.

In order to account for that I am updating the code so that we determine
the location to start the checksum ourselves based on the location of the
IPv4 header and the length.

Fixes: e10715d3e961 ("igb/igbvf: Add support for GSO partial")
Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Alexander Duyck and committed by
David S. Miller
516165a1 fadf3a28

+12 -4
+6 -2
drivers/net/ethernet/intel/igb/igb_main.c
··· 4931 4931 4932 4932 /* initialize outer IP header fields */ 4933 4933 if (ip.v4->version == 4) { 4934 + unsigned char *csum_start = skb_checksum_start(skb); 4935 + unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); 4936 + 4934 4937 /* IP header will have to cancel out any data that 4935 4938 * is not a part of the outer IP header 4936 4939 */ 4937 - ip.v4->check = csum_fold(csum_add(lco_csum(skb), 4938 - csum_unfold(l4.tcp->check))); 4940 + ip.v4->check = csum_fold(csum_partial(trans_start, 4941 + csum_start - trans_start, 4942 + 0)); 4939 4943 type_tucmd |= E1000_ADVTXD_TUCMD_IPV4; 4940 4944 4941 4945 ip.v4->tot_len = 0;
+6 -2
drivers/net/ethernet/intel/igbvf/netdev.c
··· 1965 1965 1966 1966 /* initialize outer IP header fields */ 1967 1967 if (ip.v4->version == 4) { 1968 + unsigned char *csum_start = skb_checksum_start(skb); 1969 + unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); 1970 + 1968 1971 /* IP header will have to cancel out any data that 1969 1972 * is not a part of the outer IP header 1970 1973 */ 1971 - ip.v4->check = csum_fold(csum_add(lco_csum(skb), 1972 - csum_unfold(l4.tcp->check))); 1974 + ip.v4->check = csum_fold(csum_partial(trans_start, 1975 + csum_start - trans_start, 1976 + 0)); 1973 1977 type_tucmd |= E1000_ADVTXD_TUCMD_IPV4; 1974 1978 1975 1979 ip.v4->tot_len = 0;