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/AM3354: NDK receive issue

Part Number: AM3354

Tool/software: TI-RTOS

Hello

I use CCS Version: 8.3.0, TIRTOS 2.00.01.23, NDK 2.25.00.09

I create the raw socket and receive a packets, a lot of packets, 4000 per second or more.

For receiving a packets, I use NDK_recvnc(...)

After getting a packet, and using it, I call recvncfree(...). But, if I call it after using a buffer with my packet, I usually receive two or three per second, but I am sure that there are no less than 4000 per second.

When I call recvncfree(...) after a call NDK_recvnc(...) I get all 4000 packets, but I know it is wrong, not like describe in the Guideline, because I have to release buffer after using, not before, it is a potential point when I could have a problems.

Why doesn't it work properly?

  • Hi,

    Can you elaborate >>>> not like describe in the Guideline, >>>>? Is that NDK reference guide (SPRU524), section 3.4 Raw Ethernet Sockets Programming Interface?

    And please attach a code snippet for working and failure cases to understand the issue? What code example you refer to develop your own code? Did you use Processor SDK RTOS on AM335x? What release is it? Is your application based on the NIMU example?

    Regards, Eric
  • Can you elaborate >>>> not like describe in the Guideline, >>>>? Is that NDK reference guide (SPRU524), section 3.4 Raw Ethernet Sockets Programming Interface?

    Yes, I read NDK reference guide (SPRU524), section 3.4 about raw sockets. There are a couple mistakes:

    >>NDK_recvnc()             Free buffer obtained from NDK_recvnc() API

    >>NDK_recvncfree()     Return a data buffer obtained from a no-copy receive operation

    {

        HANDLE  hBuffer = 0;

        buffer = Ethernet_receivePacket(self->ethSocket, &self->packet_sz, hBuffer);

    if (0 != self->buffer && 0 != self->packet_sz)
    {
        parse_message(self, &self->packet_sz);
    // TODO: it doesn't work like wrote in the manual, ask TI

    // when I try call this, I receive only couple packets per second, but I know exactly there are no less than 4000 per second
    // NDK_recvncfree(hBuffer);
        return true;
    }
    else
    {
        pckt_err_cntr++;
        Thread_sleep(1);
        return false;
    }

    }

    uint8_t* Ethernet_receivePacket(EthernetSocket self, int32_t *const packet_sz, HANDLE hBuffer)
    {
    uint8_t *loc_buffer = 0;

    *packet_sz = recvnc(self->rawSocket, (void **)&loc_buffer, MSG_DONTWAIT, &hBuffer);
    if (*packet_sz < 0)

    {
    // printf("receive packet is err = %d\n", fdError());
    recvncfree(hBuffer);
    Thread_sleep(1);
    return 0;
    }
    // it works properly only if I call it here, but my buffer can be used again and I can have a rubbish

    NDK_recvncfree(hBuffer);
    return loc_buffer;
    }

  • Hello Sergei,

    You should be calling NDK_recvnc, then perform work on the buffer it acquires, then freeing the buffer with NDK_recvncfree. It will not work if you free the buffer before using the data.

    You can run into performance limitations at higher speeds, but at that speed you shouldn't be seeing only a couple packets per second. Do you have a wireshark log for the case where you only get a couple of packets per second? 

    Regards,

    Dalton 

  • >>You should be calling NDK_recvnc, then perform work on the buffer it acquires, then freeing the buffer with NDK_recvncfree. It will not work if >>you free the buffer before using the data.

    Yes, I understand it and wonder why it doesn't work properly.

    File with 20000 packets per second: https://e2e.ti.com/cfs-file/__key/communityserver-discussions-components-files/791/20190424_5F00_20000_5F00_pckts_5F00_per_5F00_sec.7z

  • Sergei,

    Thanks for uploading that wireshark log, but I took another look at your code and actually noticed a bug that is likely causing the behavior you see.

    You pass hBuffer into the Ethernet_receivePacket() function and call the recv functions on it, but that is causing a scoping issue since the pointer is being passed by value. The hBuffer in Ethernet_receivePacket will be different than the one outside of it.

    Regards,

    Dalton

  • Yes, you are right.
    Childish mistake.

    In this code:
    uint8_t* Ethernet_receivePacket(EthernetSocket self, int32_t *const packet_sz, HANDLE hBuffer)
    {
    uint8_t *loc_buffer = 0;

    *packet_sz = recvnc(self->rawSocket, (void **)&loc_buffer, MSG_DONTWAIT, &hBuffer);
    if (*packet_sz < 0)

    {
    // printf("receive packet is err = %d\n", fdError());
    recvncfree(hBuffer);
    Thread_sleep(1);
    return 0;
    }
    // it works properly only if I call it here, but my buffer can be used again and I can have a rubbish

    NDK_recvncfree(hBuffer);
    return loc_buffer;
    }

    Do I have to call recvncfree(hBuffer) after recvnc(....); when *packet_sz < 0?
    In this part of code:
    if (*packet_sz < 0)
    {
    // printf("receive packet is err = %d\n", fdError());
    recvncfree(hBuffer); << here?
    Thread_sleep(1);
    return 0;
    }
  • Sergei,

    You don't need to NDK_recvncfree in this event as memory would not have been allocated to hBuffer if the return code is less than 0.

    Regards,

    Dalton