FreeRTOS+TCP data loss

Hi guys, I’ve recently finished developing a STM32F zero-copy driver port and have been doing some performance tests but are hitting an issue with TCP transfers. I’ve been using the iperf (tested ver 2 & 3) for first loop-back bandwidth tests. In UDP loop-back tests it comfortably achieves 100mb/s full duplex with zero packet loss running for minutes on end. I’m having problems with TCP transfers though. In basic text (eg CLI) TCP connections it all works fine, but when I try an iperf loop-back Wireshark shows it connects ok, but after several PSH transfers it stops. After a few seconds iperf (or more likely Windows’ IP stack) retries again but after a few SYN & RST ping-pongs it stops again for a few seconds before the next retry. Given the lack of packet loss with UDP transfers it suggests a TCP handshaking sensitivity. That above explanation may not be enough for you to go by, but would it be possible for you to test a very simple iperf TCP loopback on your known working ports? I ask mainly because it’s actually quite a good standard example that you could use. Also, if people are interested in the driver port I could package it up and post it. FYI, on a side note, a heads up on a few tiny website API documentation discrepancies: – FreeRTOScreatesocketset is now FreeRTOSCreateSocketSet in the code – FreeRTOSshutdown links to “FreeRTOSrevc()” (sic) typo. The href itself is correct though. – The code example in FreeRTOS_recvfrom doesn’t pass pxSourceAddressLength as a pointer. Thanks for the support guys. Rob

FreeRTOS+TCP data loss

Hi Rob, I am preparing a small iperf module that should work for both TCP and UDP. Does your IPerf code echo the data? If so, that might cause troubles. The example will soon be ready. Regards.

FreeRTOS+TCP data loss

I’ve tried both. UDP echo is straight forward: ~~~~~~ int lReturned = FreeRTOSrecvfrom(xSocket, (void *)&pucUDPPayloadBuffer, 0, FREERTOSZEROCOPY, &xEchoServerAddress, &xAddressLength); if (lReturned > 0) { int lSent = FreeRTOSsendto(xSocket, (void *)pucUDPPayloadBuffer, lReturned, FREERTOS_ZERO_COPY, &xEchoServerAddress, sizeof(xEchoServerAddress)); if (lSent <= 0) { FreeRTOS_ReleaseUDPPayloadBuffer(pucUDPPayloadBuffer); } } ~~~~~~ Both TCP sink-only and TCP echo (separate server & client connections) are causing the iperf client to stop. Echo (server & client connections) example: ~~~~~~ for (;;) { int rxLen = FreeRTOSrecv(xServerSocket, tcpEchoBuff, sizeof(tcpEchoBuff), 0); if (rxLen >= 0) { if (rxLen > 0) { int num = 0; do { int numSent = FreeRTOSsend(xConnectionBackSocket, tcpEchoBuff, rxLen, 0); if (numSent <= 0) break; num += numSent; } while (num < rxLen); } } else break; } FreeRTOSshutdown(xConnectionBackSocket, FREERTOSSHUTRDWR); while (FreeRTOSrecv(xConnectionBackSocket, tcpEchoBuff, sizeof(tcpEchoBuff), 0) >= 0) { } FreeRTOS_closesocket(xConnectionBackSocket); FreeRTOSshutdown(xServerSocket, FREERTOSSHUTRDWR); while (FreeRTOSrecv(xServerSocket, tcpEchoBuff, sizeof(tcpEchoBuff), 0) >= 0) { } FreeRTOS_closesocket(xServerSocket); ~~~~~~ Regards

FreeRTOS+TCP data loss

Thanks for the documentation corrections – they have been made and will get uploaded to the website shortly. Regards.

FreeRTOS+TCP data loss

Hi Robert, Thanks for testing the iperf module that I sent you last week. I attach it here (see “iperftaskv1_0.c”), so that other users can also have a look at it. “iperftaskv1_0.c” is a module that can be used on any platform with +TCP. It implements a simple iperf server for both TCP and UDP. When using TCP, it is also able to actively connect to its iperf client and echo back all data received. When using this double connection, there is no flow control yet. The iperf client may be sending aggressively and thus preventing +TCP from forwarding all data back to the remote client. Why is that possible? That happens because the reception of data always has priority above transmission. Now suppose that the RX stream already uses 60% of the bandwidth and also a high percentage of the CPU time, the TX stream buffer may run full and data will get dropped. With a bit of extra code this can be prevented. The loss of data can be seen in the following logging. 32MB was sent and 21.8 MB was received back: C:temp>iperf -c 192.168.2.106 –dualtest –port 5001 –num 32M
Server listening on TCP port 5001 TCP window size: 64.0 KByte (default)

Client connecting to 192.168.2.106, TCP port 5001 TCP window size: 64.0 KByte (default)
[ 4] local 192.168.2.3 port 2411 connected with 192.168.2.106 port 5001 [ 5] local 192.168.2.3 port 5001 connected with 192.168.2.106 port 55328 [ ID] Interval Transfer Bandwidth [ 4] 0.0- 4.6 sec 32.0 MBytes 58.8 Mbits/sec [ 5] 0.0- 4.6 sec 21.8 MBytes 40.1 Mbits/sec Note that TCP flow control is fully automatic: if you stop to call FreeRTOSrecv() on a receiving socket, the TCP sliding window will run full, and the remote instance of iperf will temporarily stop sending data. As soon as RX data are popped (by calling FreeRTOSrecv()), a window-change message is sent and the communication will resume. Regards.