(This is the fourth in a series of five posts. See
part 1,
part 2,
part 3,
part 5.)
The checksum problem is happening in the call to vlan_check_reorder_header() on
line 203 of net/8021q/vlan_dev.c. The checksum field is 0xffffffff before the call and 0x001fffff after it [1]. The only difference between the packets I can see so far is that the ones at or below RX_COPY_THRESHOLD, from the non-buggy code path of the sunhme driver, have 52 bytes of headroom and the problematic ones have only 20 bytes.
[1] Checksums in IP and related protocols are 16-bit one's-complement sums, but the kernel uses 32-bit unsigned integers to store them and perform all operations in unsigned arithmetic for efficiency, and then folds down to the real checksums by repeatedly adding to the upper 16 bits to the lower 16 bits to count all the overflows, and then complementing them. These values thus fold to 0x0000 (correct checksum for a valid packet) and 0xffe0 (incorrect checksum).