TX Checksum Offloading and ICMP

The processor I am using can offload all the checksums including ICMP. However code in prvProcessICMPEchoRequestcauses this not to work as the CRC at this point should be set to zero. Is there a way around this without modifying the stack?

Is this the problematic code?

        usRequest = ( uint16_t ) ( ( uint16_t ) ipICMP_ECHO_REQUEST << 8 );

        if( pxICMPHeader->usChecksum >= FreeRTOS_htons( 0xFFFFU - usRequest ) )
        {
            pxICMPHeader->usChecksum = pxICMPHeader->usChecksum + FreeRTOS_htons( usRequest + 1U );
        }
        else
        {
            pxICMPHeader->usChecksum = pxICMPHeader->usChecksum + FreeRTOS_htons( usRequest );
        }

Would replacing that with a complete checksum calculation fix the issue for you?

Yes that is the code. I have temporarily replaced it with the following and it works fine. However I don’t want to have to change the stack for forwards compatibility issues. Not sure if a complete checksum calculation would fix it.

pxICMPHeader->usChecksum = 0;

There are several configuration file options that describe the offloading configuration (for example ipconfigHAS_TX_CRC_OFFLOADING) - so it looks like we need to add some #ifdefs into that function to do the right thing depending on their setting. Will need Hein or one of the TCP team to advise.

1 Like

These two macro’s determine if the driver is responsible for checksum calculations:

#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM    1
#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM    1

And if the driver is responsible, the following macro’s:

#define ipconfigHAS_TX_CRC_OFFLOADING    1
#define ipconfigHAS_RX_CRC_OFFLOADING    1

determine if the hardware will do the job, or the checksum routines.

Of course the hardware calculations are preferable, the ‘OFFLOADING’ macro is only used in testing situations.

I was hesitating about PR #87, and PR #92, because I don’t want to break existing projects.
Maybe some developers use ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM for both IP, UDP, and TCP, while making an exception for ICMP: they trust that it is calculated in prvProcessICMPEchoRequest().
Now if we set it to zero, their projects will be broken. Ping will be replied with an invalid checksum.

The ICMP checksum will be set to zero in the STM32Fx driver, and also in the Zynq driver, before it is passed to the EMAC for sending.

Strange enough the IP- and the protocol-checksums do not require to set the checksum field to zero. Some EMAC’s do expect the ICMP field to be zero.

So to Rik: your proposal is correct, but I am not sure how many existing projects would get broken. A work-around can easily be made in the NetworkInterface.c in xNetworkInterfaceOutput().