This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C1294NCPDT: Bypass or selectively disable the ICMP checksum offload engine

Part Number: TM4C1294NCPDT

I am working on a device with the aforementioned MCU that uses lwIP for network functions. One function of the device to respond to pings (ICMP echo requests), and print out the data about them (think length,  source, etc.) It works fine with normal-sized ping packets, but when presented with an oversized (>1500) packet, the ping utility does not see a response. Snooping around with Wireshark reveals that the response arrives and looks good (neatly split into 2 frames), but the checksum is wrong. Digging into the tm4c-lwip code revealed that generating ICMP checksums is relegated to the MCU's checksum offload engine. Per datasheet, the ".. checksum for TCP, UDP, or ICMP is calculated over a complete frame, and then inserted into its corresponding header field." (p. 1452). My guess is that the fragmentation has already been handled by lwIP, and the wrong checksum is calculated from only one of the frames. Is there a way to temporarily disable the checksum engine in order to calculate the checksum in software for this particular packet before it gets fragged? 

  • Hi Janis,

      Sorry the late response as e2e was taken down for maintenance the last two days. 

    My guess is that the fragmentation has already been handled by lwIP, and the wrong checksum is calculated from only one of the frames. Is there a way to temporarily disable the checksum engine in order to calculate the checksum in software for this particular packet before it gets fragged? 

    lwIP has the below checksum options that you can enable/disable in the lwipopts.h file. If you have already tried to disable checksum but I think this is a permanent means to disable the checksum. I'm not aware of an option to temporarily disable the checksum as we are not experts of 3rd party lwIP. Please consult with lwIP at https://savannah.nongnu.org/projects/lwip/ and I hope experts can guide you on what is feasible and not. 

    //*****************************************************************************
    //
    // ---------- checksum options ----------
    //
    //*****************************************************************************
    //#define CHECKSUM_GEN_IP 1
    //#define CHECKSUM_GEN_UDP 1
    //#define CHECKSUM_GEN_TCP 1
    //#define CHECKSUM_CHECK_IP 1
    //#define CHECKSUM_CHECK_UDP 1
    //#define CHECKSUM_CHECK_TCP 1

  • Digging into the tm4c-lwip code revealed that generating ICMP checksums is relegated to the MCU's checksum offload engine. Per datasheet, the ".. checksum for TCP, UDP, or ICMP is calculated over a complete frame, and then inserted into its corresponding header field." (p. 1452).

    This sounds similar to the issue reported in MSP432E401Y: NDK in simplelink_msp432e4_sdk_4_20_00_12 can't send fragmented UDP packets, but can receive them, albeit on a MSP432E (which uses the same Ethernet controller as a TM4C129) and the TI NDK rather than LwIP.

    Not sure if the modifications described in Add modified EMACMSP432E4.c driver which only enables hardware checksum offload for IP headers helps for how to make the equivalent changes to the LwIP driver. 

  • They're all disabled (the defines you listed are set to 0) - the checksum generation is not handled by lwIP, but by the controller's built-in checksum offload engine.  LWIP's checksum functions are never called during execution.

  • Looks like the same problem indeed. "The MSP432E EMAC Checksum Offload is therefore unable to generate or check the payload of a packet which is fragmented into multiple Ethernet frames" - sounds like exactly what I'm dealing with. I'll check the links, they seem interesting. By the way, I found that in the EMACCFG register there's a bit called IPC, which supposedly en-/disables the checksum engine, but as far as I could gather, it only works on received packets, and remains always on for transmitting.

     By the way, we also tried pinging the device with a 2048 B packet with a payload of all 0s, where the checksum should be valid even if the packet gets truncated. There was a response, the checksum was indeed valid, Wireshark recognized it as such, but the ping utility still doesn't pick it up, so the question might as well be moot. For now we figured to just not respond to oversized ping packets. 

    I suppose that if it was a matter of life and death, the checksum engine might be tricked into providing the correct checksum. If you pass it a packet where the checksum fields are not zeroed out, it will provide an invalid checksum - so I guess it uses them in the calculations. I suppose it would not be too hard to work out the math for a value that you could put into the checksum field before handing it off to the offload engine, so that the end result matches the correct checksum for the whole, unfragmented packet - but that's on whichever poor soul next stumbles onto this topic, without the option of proclaiming it's not his job. 

    EDIT: okay, I can't seem to let this go. I have a suspicion it might be enough to just calculate the (ICMP) checksum over the part of data that's stashed in the second frame, and put that it in the ICMP checksum field in the first frame. Not enough time or motivation to test it, though.