Using TCP Checksum Offload from lwf based driver
When a NIC does TCP checksum offload, the OS has precalculated the pseudo header
checksum and stored it in the TCP checksum field. The pseudo header is derived
from the IP address and the TCP segment length. The OS calculates this pseudo
header checksum to avoid requiring the checksum hardware needing to parse the IP
header, which might have options, so is variable length. By supplying the
hardware with the precalculated pseudo header, the hardware only needs to know
the location of the TCP header, which is passed from the OS to the driver as
metadata. Note that in the case of TCP segmentation offload, the parts of the
pseudo header that depend on the IP address don’t change, although the segment
length after segmentation is needed to finish calculating the pseudo header
checksum. As I remember, the pseudo header checksum for large segment offload
packets is only a partial pseudo header checksum, as the segmentation determines
the individual packet size.
If you filter driver modifies certain fields in the IP header, it will need to
recalculate the TCP pseudo header. There are a number of subtle variations,
which you will need to correctly handle. Like IPv4 UDP packets can use a null
checksum of zero, but IPv6 packets can’t. You might see if you can filter things
at a layer before the checksums are calculated, modifying the packets after they
are built will be painful.
If you’re modifying IP headers, you will also likely need to handle cases other
than TCP checksums. Many server NIC’s can handle tunneled packets in hardware,
which can have for example TCP packets inside a wrapper TCP stream, so there are
two TCP checksums, the inner and outer streams. Your filter should not disable
any hardware offloads, so you may need to handle all the cases that hardware
might do. IPSEC packets might also be a serious problem, because the TCP header
will be encrypted, regenerating the TCP checksum for a changed IP header would
require knowing the encryption keys.
There are docs on how the pseudo header is calculated, like at
I may be useful to use the WHQL NIC checksum tests to verify you are correctly
fixing up the pseudo header in your filter, with a test NIC that does many
advanced hardware offloads. I’m assuming your filter should work with every NIC.
Perhaps there are explicit tests for filters than fool with the checksums, so
there is a way to verify all cases are handled.
From: firstname.lastname@example.org [mailto:email@example.com] On Behalf Of
Sent: Tuesday, January 2, 2018 7:06 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Using TCP Checksum Offload from lwf based driver
I know that this has probably been asked before but I have written a Driver
based on the lwf sample that modifies the outgoing packets and recalculates the
tcp checksum. This works fine if I disable the tcp checksum offload on the nic
card, but I cannot seem to get it to work with tcp checksum enabled. I cannot
find much doc on how this all works.Or if I can control the tcp checksum offload
from the driver or how to manipulate the ndis packet descriptor information to
include my changes. Any pointers would be deeply appreciated. Thanks.
--- NTDEV is sponsored by OSR Visit the list online at: MONTHLY seminars on
crash dump analysis, WDF, Windows internals and software drivers! Details at To
unsubscribe, visit the List Server section of OSR Online at