About the transmission rate of TCP

Hello, I want to know how to improve the tcp transmit rate.
I’m running FreeRTOS-TCP with STM32F407VET6, and i can send data to a tcp server.However, after I sent about 1024 bytes of data, I must wait about 50ms that can ensure the next 1024 bytes of data are sent successfully.
And the tcp tx buffer length I set it to (8*mss).
so can someone help me?

@slhuan

Are you willing to share the code you use to send the TCP data?
Also please share the priorities at which you have configured your application, IP task and the ethernet RX tasks.

You can take a look at the TCP echo client demo here, if not already: FreeRTOS/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/TCPEchoClient_SingleTasks.c at main · FreeRTOS/FreeRTOS · GitHub

Also, TCP/IP Stack Configuration to Maximise Throughput

ok

unsigned char socket_buf[1028] = {0xFF, 0xFF, 0xFF, 0xFF};

void net_task(void* param)
{
    while(xTasksAlreadyCreated == pdFALSE)
    {
        vTaskDelay(1);
    }
    xTasksAlreadyCreated = pdFALSE;
    
    Socket_t xSocket;

    /* Set the IP address (192.168.0.200) and port (1500) of the remote socket
       to which this client socket will transmit. */
    struct freertos_sockaddr xRemoteAddress;
    memset( &xRemoteAddress, 0, sizeof(xRemoteAddress) );
    xRemoteAddress.sin_port = FreeRTOS_htons( 9000 );
    xRemoteAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( 192, 168, 50, 13 );
    xRemoteAddress.sin_family = FREERTOS_AF_INET4;
    
    struct freertos_sockaddr xLocalAddress;
    memset( &xLocalAddress, 0, sizeof(xLocalAddress) );
    xLocalAddress.sin_port = FreeRTOS_htons( 9999 );
    xLocalAddress.sin_address.ulIP_IPv4 = FreeRTOS_inet_addr_quick( 192, 168, 50, 121 );
    xLocalAddress.sin_family = FREERTOS_AF_INET4;
    
    static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 20000 );
    static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 20000 );
    /* Create a socket. */
    xSocket = FreeRTOS_socket( FREERTOS_AF_INET,
                               FREERTOS_SOCK_STREAM,/* FREERTOS_SOCK_STREAM for TCP. */
                               FREERTOS_IPPROTO_TCP );
    configASSERT( xSocket != FREERTOS_INVALID_SOCKET );
    /* Set a time out so a missing reply does not cause the task to block indefinitely. */
    FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
    FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );
    
    FreeRTOS_bind(xSocket, &xLocalAddress, sizeof(xLocalAddress));
    
    while(FreeRTOS_issocketconnected(xSocket) != pdTRUE)
    {
        FreeRTOS_connect( xSocket, &xRemoteAddress, sizeof( xRemoteAddress ));
        vTaskDelay(150);
    }
    
    unsigned short offset = 0;
    for(unsigned int i = 4; i<sizeof(socket_buf); i++)
    {
        socket_buf[i] = i - 4;
    }
    while(1)
    {
        BaseType_t xAvlSpace = 0;
        uint8_t *pucTCPZeroCopyStrmBuffer = FreeRTOS_get_tx_head( xSocket, &xAvlSpace );
        memcpy( pucTCPZeroCopyStrmBuffer, 
              ( void * ) (( (uint8_t *) socket_buf )),  
                sizeof(socket_buf));
        unsigned char xByteSent = FreeRTOS_send( /* The socket being sent to. */
                                xSocket,
                                /* The data being sent. */
                                NULL,
                                /* The remaining length of data to send. */
                                sizeof(socket_buf), /* ulFlags. */
                                FREERTOS_MSG_DONTWAIT );
        taskYIELD();
    }

    /* The socket has shut down and is safe to close. */
    FreeRTOS_closesocket( xSocket );
}


void network(void)
{
    FreeRTOS_printf( ( "FreeRTOS_IPInit\n" ) );
    FreeRTOS_IPInit(
        ucIPAddress,
        ucNetMask,
        ucGatewayAddress,
        ucDNSServerAddress,
        ucMACAddress );
    xTaskCreate(net_task, "net", 1024, NULL, configMAX_PRIORITIES - 3, NULL);
}

I just need to send data to the server, so now only created a send task. My rtos’s max task priority I defined to 8.
The ip task’s priority has set to the max priority-2

#define ipconfigIP_TASK_PRIORITY                   ( configMAX_PRIORITIES - 2 )

Dis you mean to send no data? How do you think you can measure performance that way? Also, what is the peer you run against?

This is the way that called zero copy. The data of sent have been copy to a pointer pucTCPZeroCopyStrmBuffer.

oh i see, apologies.

So what is the peer you run against? Do you have a wireshark trace of the communication?

Do you mean who I’m communicating with?
yes i trace of the communication, it shows some tcp retransmission.

When you are using TCP zero copy, you receive a pointer to the TCP stream where you can write the data directly, but how much data you can write depends on the available stream buffer space left, which is set in the xAvlSpace variable. Writing more than xAvlSpace will lead to buffer overflow. If you are planning to use TCP zero copy, take a look at this page: Sending Data Using a TCP Socket (zero copy interface) - FreeRTOS™

Also, have you compared the results without using zero copy?
Make sure you have enabled TCP windowing (ipconfigUSE_TCP_WIN) [enabled by default]. You can configure the window properties as shown here: FreeRTOS/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/DemoTasks/TCPEchoClient_SingleTasks.c at main · FreeRTOS/FreeRTOS · GitHub

the retransmissons do not look right. yes, the question is what platform the server runs on, but from the trace it looks as if your unit (the .13) fails to low level acknowledge the peer packets in time, so there may simply be a bug in your system. As @tony-josi-aws suggested, you may want to start with a sample known to work.

Thanks. Now I change my code as zero copy as sample.

    while(1)
    {
        BaseType_t xAlreadyTransmitted = 0;
        BaseType_t xTotalLengthToSend  = sizeof(socket_buf);
        while(xAlreadyTransmitted <  xTotalLengthToSend)
        {
            BaseType_t xAvlSpace = 0;
            BaseType_t xBytesToSend = 0;
            uint8_t *pucTCPZeroCopyStrmBuffer = FreeRTOS_get_tx_head( xSocket, &xAvlSpace );
            if(pucTCPZeroCopyStrmBuffer == NULL)    break;
            if((xTotalLengthToSend - xAlreadyTransmitted) > xAvlSpace)
            {
                xBytesToSend = xAvlSpace;
            }
            else
            {
                xBytesToSend = (xTotalLengthToSend - xAlreadyTransmitted);
            }
            memcpy( pucTCPZeroCopyStrmBuffer, 
                    ( void * ) (( (uint8_t *) socket_buf ) + xAlreadyTransmitted),  
                    xBytesToSend);
            unsigned char xByteSent = FreeRTOS_send( /* The socket being sent to. */
                                    xSocket,
                                    /* The data being sent. */
                                    NULL,
                                    /* The remaining length of data to send. */
                                    xBytesToSend, /* ulFlags. */
                                    0 );
            if( xByteSent >= 0 )
            {
                /* Data was sent successfully. */
                xAlreadyTransmitted += xByteSent;
            }
            else
            {
                break;
            }
        }
        taskYIELD();
    }

And I use the wireshark traced, the result as follow:


It seems that my system runs for a while, and then miss ack from server.

I also run the code without zero copy, but get the same result:

    while(1)
    {
        BaseType_t xAlreadyTransmitted = 0;
        BaseType_t xTotalLengthToSend  = sizeof(socket_buf);
        while( xAlreadyTransmitted < xTotalLengthToSend )
        {
            /* How many bytes are left to send? */
            size_t  xLenToSend = xTotalLengthToSend - xAlreadyTransmitted;
            BaseType_t xBytesSent = FreeRTOS_send( /* The socket being sent to. */
                                        xSocket,
                                        /* The data being sent. */
                                        &( socket_buf[ xAlreadyTransmitted ] ),
                                        /* The remaining length of data to send. */
                                        xLenToSend,
                                        /* ulFlags. */
                                        0 );

            if( xBytesSent >= 0 )
            {
                /* Data was sent successfully. */
                xAlreadyTransmitted += xBytesSent;
            }
            else
            {
                /* Error - break out of the loop for graceful socket close. */
                break;
            }
        }
        taskYIELD();
    }

Or there is some filewall our misfunctioning router in between that does not relay the packets correctly.

Once more (from my point of view for the last time): What OS and software are you running against? And what is the network infrastructure in between, ie are the two units peer-to-peer connected, or is there a switch or a router in between? Or possibly even more sophisticated infra structure such as a dial-up connection?

my tcp server was running on windows10, and it is a software that called serial-helper downloaded in Microsoft app store
my board and computer are connected to a switcher.

Hi @slhuan,
Could you help check if the very last data that keep retransmitted is received even once on the app layer?
Likely the device is waiting the ACK for that packet but it’s never sent from the server.

Thank you.

@slhuan

Can you upload the wireshark capture from start to stall here?

ok. later i will capture some data with wireshark and share here.

ok, wait a minute.Theoretically, is it possible to run at full speed using freertos-tcp?

@slhuan

What do you mean by full speed? The speed you can get depends on the how much your MAC/PHY supports, your RAM available for buffers, your network capacity, compiler configuration, etc. You can always tweek these to get the optimal speed.

net.zip (81.8 KB)
here is my capture data. And my board’s ip is 192.168.50.121
@tony-josi-aws @ActoryOu

ok, let me think about it that what rate should I achieve in my current scenario