FreeRTOS+TCP creating unnecessary fragments

exile_10 wrote on Thursday, August 01, 2019:

When sending data over TCP FreeRTOS TCP will fragment the message unnecessarily. This pcap shows and example of the problem. I have a windows PC (10.10.0.1) that connects to my embedded device (10.10.0.5) and requests information. The device responds with 2 segments, the total data in the response is 26 bytes which should easily fit into my MSS of 552 bytes.

If its helpful, the full IP Config can be read here. Its running on an NXP LPC1857. FreeRTOS version 10.2.0 with FreeRTOS+TCP version 2.0.11.

The result of this extra fragmentation is that Windows needs to acknowledge each one, after the acknowledgement it forces a 200msec delay before making the next request which really reduces the transfer speed.

rtel wrote on Thursday, August 01, 2019:

Thanks for the logs - will look through but won’t be able to do it
immediately.

heinbali01 wrote on Friday, August 02, 2019:

Jason, in the PCAP you see that two packets are sent: 24 bytes and 3 bytes.
I assume that you have called send() twice, once with 24 and once with 3 bytes? Can you confirm that?

FreeRTOS+TCP is developed for speed, it has no Nagle algorithm that avoids sending small packets, by delaying delivery.

About your FreeRTOSIPConfig.h

#define ipconfigTCP_MSS (512 + ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER)

It is unusual to define ipconfigTCP_MSS your self: the library gives it a proper default value:

    #define ipconfigTCP_MSS		( ipconfigNETWORK_MTU - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_TCP_HEADER )

Maximum DNP message size is 1162 bytes, need at least that much
(1271 in UDP? 1182 in TCP)
#define ipconfigNETWORK_MTU 1500

If you want a maximum TCP payload of PAYLOAD_SIZE, indeed you need to define:

#define ipconfigNETWORK_MTU  ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER + PAYLOAD_SIZE )

normally with a maximum of 1500 ( when MSS equals 1460 ).

exile_10 wrote on Friday, August 02, 2019:

Thanks Hein Tibosch, I think you’ve nailed it. I had a loop around my send checking to make sure all of the data was transfered. I had botched some of that logic which caused multiple sends to happen. I didn’t realize that Wireshark was reassembling those packets and that the transfer was being segmented. Now that I’ve corrected the logic this is now working.

As to the MSS setting, the application is RAM limited the setting channge was an attempt to minimize its usage but still allowing TCP windowing to be enabled. As the comment there says we occasionally need packets over 1K, so full size MTU allows UDP to support this. Its certainly not ideal, but until we can get enough RAM freed for Ethernet use we’re resigned to such measures.