Skip to content

Fix TCP IPv4 tx checksum length for padded RX frames#1332

Open
marcusb wants to merge 1 commit intoFreeRTOS:mainfrom
marcusb:fix/tcp-ipv4-tx-checksum-length
Open

Fix TCP IPv4 tx checksum length for padded RX frames#1332
marcusb wants to merge 1 commit intoFreeRTOS:mainfrom
marcusb:fix/tcp-ipv4-tx-checksum-length

Conversation

@marcusb
Copy link
Copy Markdown
Contributor

@marcusb marcusb commented Apr 13, 2026

Summary

prvTCPReturnPacket_IPV4() called usGenerateProtocolChecksum() with pxNetworkBuffer->xDataLength as the buffer length. At that point xDataLength still holds the length of the incoming frame — for example, 60 bytes for a SYN that was padded up to the Ethernet minimum. The reply (e.g. a SYNACK with TCP options) is typically longer, so the checksum ended up being computed over the wrong byte range. xDataLength is only updated to the outgoing length a few lines later, at pxNetworkBuffer->xDataLength = ( size_t ) ulLen; pxNetworkBuffer->xDataLength += ipSIZE_OF_ETH_HEADER;.

The IPv6 path (prvTCPReturnPacket_IPV6()) was already correct — it uses ulLen + ipSIZE_OF_ETH_HEADER directly. This change mirrors that in the IPv4 path.

@marcusb marcusb marked this pull request as ready for review April 13, 2026 03:22
Copy link
Copy Markdown
Member

@AniruddhaKanhere AniruddhaKanhere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution, @marcusb. Good catch — confirmed the bug by comparing the IPv4 and IPv6 paths. The checksum was indeed being computed over the stale incoming xDataLength rather than the outgoing packet length.
The fix correctly mirrors prvTCPReturnPacket_IPV6() and the unit test is solid.

Tagging @htibosch for review.

LGTM — approving.

@marcusb marcusb force-pushed the fix/tcp-ipv4-tx-checksum-length branch from 70312bd to 79f4693 Compare April 22, 2026 02:28
@marcusb marcusb force-pushed the fix/tcp-ipv4-tx-checksum-length branch from 79f4693 to 402c35a Compare April 22, 2026 02:29
@htibosch
Copy link
Copy Markdown
Contributor

It looks correct to me, but I want to make sure that things went really wrong with the existing release. One moment please.

@htibosch
Copy link
Copy Markdown
Contributor

I found that the patch doesn't make much a difference: the protocol checksum doesn't change if you add more zeros to the packet.
In the code we are referring to pxNetworkBuffer->xDataLength, but it hasn't been trimmed yet. Sometimes it is 1522 because I use BufferAllocation.1.

Why not move the following 2 lines to above:

    /* Important: tell NIC driver how many bytes must be sent. */
    pxNetworkBuffer->xDataLength = ( size_t ) ulLen;
    pxNetworkBuffer->xDataLength += ipSIZE_OF_ETH_HEADER;

Or if you prefer, here in a patch:
hein_proposal.patch

@htibosch
Copy link
Copy Markdown
Contributor

PS my patch applies to your branch
I tested all on real hardware (a telnet server) using the main release.

prvTCPReturnPacket_IPV4() passed pxNetworkBuffer->xDataLength to
usGenerateProtocolChecksum(), but at that point xDataLength still
holds the length of the incoming frame (e.g. 60 bytes for a SYN
padded to the Ethernet minimum) rather than the outgoing reply
(typically 66 bytes for a SYNACK with options).  The checksum was
computed over the wrong byte range, yielding a bogus value.

Add a unit test that installs a content-dependent stub for
usGenerateProtocolChecksum and asserts the written checksum matches
the sum over the outgoing packet length.  Verified the test fails
against the unfixed source and passes after the fix.
@marcusb marcusb force-pushed the fix/tcp-ipv4-tx-checksum-length branch from 402c35a to ecd52d1 Compare April 22, 2026 11:32
@marcusb
Copy link
Copy Markdown
Contributor Author

marcusb commented Apr 22, 2026

@htibosch I applied your patch.

The issue is that the received packet is still in the buffer under some circumstances, so it's not only zeros. This caused connections to fail in my project.

@htibosch
Copy link
Copy Markdown
Contributor

The issue is that the received packet is still in the buffer under some circumstances, so it's not only zeros.

As you may have seen, the driver sometimes allocates a new large buffer ( for sending data ), and it uses a static small buffer for simple messages like an ACK.

Were you also able to test the change?

@htibosch
Copy link
Copy Markdown
Contributor

@archigup @AniruddhaKanhere Can you please check this PR #1332?
I tested and checked it and it looks good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants