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.

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 https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Checksum_computation

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.

Jan

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
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