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.

RTOS/AM4376: TCP/IP performance

Part Number: AM4376

Tool/software: TI-RTOS

Hi,

We are working on a product based on the AM4376 processor. For our product, network transfer rate is critical.
We did some tests with Linux OS on the processor, and we reached rates of 340 Mbps (bits per sec) out of the 1G. (TCP Connection)
Then we tried to use TI RTOS to hopefully get better rates, however, the max TCP rate we could achieve after tweaking buffer sizes is 170Mbps (half then linux)
We most booster the transfer rate because high traffic of frame transfer in this  gigaethernet channel.
Is this a reasonable rate to expect for RTOS? What to do  in order to make the TCPIP driver more efficiency ?
thanks 
  • The RTOS team have been notified. They will respond here.
  • Hi pascal,

    Can you please elaborate the procedure you benchmark the TCP throughput? Which software (emac driver, application) are you using? And
    Do you get the same performance on TI AM437x platforms (IDK or Starterkit)?

    Regards,
    Garrett
  • Hi Garrett,

    All the tests are done on StarterKit.
    Basically, I used NIMU_BasicExample_skAM437x_armExampleproject, and on top of it I add my benchmark application - similar to the Linux one.
    I used the built in Daemon to listen to tcp connections. A PC program connects to the SK, then requests data.
    The data I return is a ~1Mbyte buffer. I do that about 100 times in a row, then calculate the time it took.
    Thanks!
    Here is the source:

    /*
    * FGComm.c
    *
    * Created on: Jan 31, 2018
    * Author: shaise
    */

    #include <netmain.h>
    #include <_stack.h>

    /* UART Header files */
    #include <ti/drv/uart/UART.h>
    #include <ti/drv/uart/UART_stdio.h>


    #define FGCOMM_PORT 9999
    #define FG_log UART_printf
    #define ETH_PORT 1

    static HANDLE hFgComm;
    int FgCommProcess( SOCKET s, SOCKET (*cbfn)(PSA) );

    int StartComm(void)
    {
    IPN IpAddr;

    if( !NtIfIdx2Ip( ETH_PORT, &IpAddr ) )
    return(-1);
    hFgComm = DaemonNew( SOCK_STREAM, IpAddr, FGCOMM_PORT, (int(*)(SOCKET,UINT32))FgCommProcess,
    OS_TASKPRIHIGH, OS_TASKSTKNORM, 0, 2);
    FG_log("\nFG Communication protocol started.\n");
    return 0;
    }

    void NetPrintIPN( IPN IPAddr )
    {
    IPAddr = htonl( IPAddr );
    FG_log( "%d.%d.%d.%d",
    (UINT8)((IPAddr>>24)&0xFF), (UINT8)((IPAddr>>16)&0xFF),
    (UINT8)((IPAddr>>8)&0xFF), (UINT8)(IPAddr&0xFF) );
    }


    int FgCommProcess( SOCKET s, SOCKET (*cbfn)(PSA) )
    {
    int optval = 1;
    int frame_size = 1280*128;
    char *frame = (char *)mmBulkAlloc(frame_size);
    struct sockaddr_in peer_addr;
    int cmd32, len32;

    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(optval)) < 0)
    FG_log("setsockopt(SO_REUSEADDR) failed");
    if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&optval, sizeof(optval)) < 0)
    FG_log("setsockopt(TCP_NODELAY) failed");

    FG_log("FGComm connection established. Client:");
    getpeername(s,(struct sockaddr *)&peer_addr, &len32 );
    NetPrintIPN(peer_addr.sin_addr.s_addr);
    FG_log("\n");


    for (;;)
    {
    if (recv(s, (char *)&cmd32, 4, 0) < 0)
    {
    break;
    }
    if (recv(s, (char *)&len32, 4, 0) < 0)
    {
    break;
    }

    //FG_log("received command:%d, length:%d\n", cmd32, len32);

    len32 = frame_size;
    if (send(s, (char *)&cmd32, 4, 0) < 0)
    break;

    if (send(s, (char *)&len32, 4, 0) < 0)
    break;

    // if (len > 0) {
    if (send(s, frame, len32, 0) < 0)
    break;

    }
    return 1;
    }
  • Hi Pascal,

    I noticed similar TCP throughput using the FTP example from PDK, have submitted a JIRA to track the item. Do you have any hard requirement on the benchmark in your project?

    Regards,
    Garrett
  • Hi Garrett

    We would like to reach at least 500Mbps if possible.

    Regards,
    pascal

  • Hi Pascal,

    Sorry for the late update. The TCP throughput issue has been planed to be fixed in next PROCESSOR-SDK_05.00.00 release. We are trying to get the JIRA prioritized, and checking if it's possible to provide you a fix through git repository earlier once the fix is available.

    Regards,
    Garrett
  • Hi Garrett

    The proto board should go to production as soon as possible .

    Please do the maximum to get an earlier version.

    Best regards

    pascal

  • Pascal,

    We are actively working on the issue. We have compared the TCP throughput result on AM437x IDK and GP EVM, and benchmarked the raw packet throughput and CPU load with EMAC driver to check if NDK/NIMU level tuning is needed.

    Regards, Garrett

  • Garrett

    I understand that the issue is not easy.

    Thanks again .

    pascal

  • Hi Pascal,

    Can you please try the followings to see if the throughput also increases in your setup?
    1) using enhanced no-copy socket, please refer to section F.2 in spru524j.pdf, essentially you need update the TCP socket stream type from SOCK_STREAM to SOCK_STREAMNC, recv() to recvnc() and send() to sendnc().

    2) update number of descriptors in pdk transport\ndk\nimu\src\v4\cpsw_nimu_eth.c. (you can either rebuild the nimu library or add the file in your ccs project)
    open_cfg.num_of_rx_pkt_desc = 256;
    open_cfg.num_of_tx_pkt_desc = 256;

    3) Does your 'tweaking buffer sizes' look like below?
    Global.pktNumFrameBufs=384;
    Tcp.transmitBufSize = 65536;
    Tcp.receiveBufSize = 65536;
    Tcp.receiveBufLimit = 65536;

    Regards,
    Garrett
  • Hi Garrett

    I tried to test your solution to speed up the network, but I could not get it to work for the following reasons:
    To use 'sendnc' I need to preallocate a buffer using 'getsendncbuff'. This function accepts a socket and a buffer length. But this function always return with an error for 2 reasons:
    1. the buffer is larger then MTU (and we use 1Mbyte send buffer)
    2. the function works only on raw ethernet sockets, but the 'accept' function returns a standard socket. (even though the listen socket is SOCK_STREAMNC)
    Perhaps I do something wrong so if there is a simple code example that works with SOCK_STREAMNC, please let us know.
    best regards
    pascal

  • Hi Pascal,

    We were focusing on Rx benchmarking, do you see throughput improvement while using recvnc() and keeping send()?

    The following code sample is based on PDK ftp server code and updated with no copy APIs.

    static int32_t func_port (io_handler_t *ioh) {
    ioh->data_socket = socket(AF_INET, SOCK_STREAMNC, IPPROTO_TCP);

    int32_t ftp_filerout_write(io_handler_t *ioh, char *path) {
    //bytesRead = recv(ioh->data_socket, ioh->DataBuf, DATA_BUFFER_SIZE, 0);
    bytesRead = (int)recvnc(ioh->data_socket, (void**)&pBuf, 0, &hBuffer);
    //UART_printf("bytesRead: %d\n", bytesRead);

    if (bytesRead > 0)
    {
    recvncfree(hBuffer);
    //Task_yield();
    }

    Regards,
    Garrett
  • Hi Garrett
    thank for your reply.
    we are more interested in improving transmit speed( sending big frame from TI arm to computer).
    We will continue doing test and report if find something.
    regards
    pascal