AM5726: NDK 2.26.00.08 on AM572x — Broadcast Flood Issue

Part Number: AM5726

Tool/software:

Hello,

I am using NDK 2.26.00.08 on AM572x. It is on RTOS environment

The issue: Broadcast replies exhaust network buffers, and seems to have the entire network stuck. not sure how to increase pktNumFrameBufs (or alternative tuning method)

The goal is to receive a broadcast and send one in return.

I will share a snippet of how I init and how I send.

As long as the send function is commented - everything works fine. Once I send over 9k worth of data (in 1024x9 or 512x18 or 1400x7...). It seems like the network stack (tcp / ip or other wise) crashed. Accessing the network from another thread will crash the app.

I think this is a configuration issue - but I haven't found the "magic bullet" so far...

static int initBroadcastSocket(SOCKET* sock_out) {
struct sockaddr_in addr;
int optval = 1;

SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == INVALID_SOCKET) {
IP_PRINT("IP scanner - socket failed\n");
return -1;
}

setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(MULTICASTPORT_S);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (OSAL_SOCKET_UDP_bind(sock, &addr, sizeof(addr)) < 0) {
IP_PRINT("IP scanner - bind failed\n");
OSAL_SOCKET_close(sock);
return -1;
}

*sock_out = sock;
return 0;
}

struct in_addr ip_addr = client_addr->sin_addr;
struct in_addr subnet_mask;
subnet_mask.s_addr = htonl(0xFFFFFF00);

struct in_addr broadcast_addr;
broadcast_addr.s_addr = ip_addr.s_addr | ~subnet_mask.s_addr;

struct sockaddr_in reply_addr = {0};
reply_addr.sin_family = AF_INET;
reply_addr.sin_port = htons(request->response_port);
reply_addr.sin_addr = broadcast_addr;

int sent = sendto(sock, json_buffer, sizeof(json_buffer), 0, &reply_addr, sizeof(reply_addr));

As you can see the json_buffer is just a random json that works, and there is a client that receives it.

On the same system I also had a Linux running with the same version of code (adapted to Linux) and that didn't happen.

I will also mention that the app is running a tcp stack without any problems.

  • Hello Itzhak,

    I will be re-assigning your query to one of our networking engineers.

    -Josue

  • I would like to add something I've learned.

    HW/SW context:

    • SoC: AM572x (A15 only on a custom board)

    • Project: NIMU_BasicHelloWorldExample_idkAM572x_armExampleproject (no app changes except board layer)

    • Reproduced on two SDK lines:

      1. Processor SDK RTOS 04.03.00.05

        • PDK am57xx 1.0.10, NDK 2.26.00.08, SYS/BIOS 6.52.00.12, GCC 6-2017q1, CCS 8

      2. processor_sdk_rtos_am57xx_09_03_00_00

        • PDK am57xx 1.0.21, SYS/BIOS 6.76.03.01, XDC 3.55.02.22, GCC 7-2018q2, CCS 9.3

    I am using a costume board, and the only change I made was to the board lib.

    For both SDKs, I confirmed the project could communicate by pinging 192.168.57.100. - Sanity checks

    The following works and runs indefinitely:

    void runBroadcastServerTask()
    {
    #define IP_PRINT UART_printf

    fdOpenSession(Task_self());
    Task_sleep(5000);

    int optval = 1;
    SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock == INVALID_SOCKET) {
    IP_PRINT("socket failed\n");
    return;
    }

    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

    // 1) BIND to the local IP of the interface you want to use (adjust if different)
    struct sockaddr_in src = {0};
    src.sin_family = AF_INET;
    src.sin_port = htons(0); // ephemeral local port
    src.sin_addr.s_addr = inet_addr("192.168.57.100"); // <-- your NIC's IP on that subnet
    if (bind(sock, (struct sockaddr*)&src, sizeof(src)) < 0) {
    int err = fdError();
    IP_PRINT("IP scanner - bind failed with err = %d\n", err);
    fdClose(sock); // or OSAL_SOCKET_close(sock) if that's correct in your stack
    return;
    }

    // 2) CONNECT to the peer so routing/ARP errors are reported
    struct sockaddr_in dst = {0};
    dst.sin_family = AF_INET;
    dst.sin_port = htons(6667);
    dst.sin_addr.s_addr = inet_addr("192.168.57.105");

    if (connect(sock, (struct sockaddr*)&dst, sizeof(dst)) < 0) {
    int err = fdError();
    IP_PRINT("connect failed err=%d (route/ARP issue?)\n", err);
    fdClose(sock);
    return;
    }

    char json_buffer[1024] = "Hello world";
    while (1) {

    int sent = sendto(sock, (void*)json_buffer, 1400 + 1, 0,
    (struct sockaddr*)&dst, sizeof(dst));
    if (sent < 0) {
    int err = fdError();
    IP_PRINT("send failed err=%d\n", err);
    } else {
    IP_PRINT("[SERVER] Sent %d\n", sent);
    }

    Task_sleep(500);
    }
    }

    The following DOES NOT work correctly.

    void runBroadcastServerTask_B()
    {
    #define IP_PRINT UART_printf

    fdOpenSession(Task_self());
    Task_sleep(5000);

    int optval = 1;
    SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock == INVALID_SOCKET) {
    IP_PRINT("socket failed\n");
    return;
    }

    // Allow rebinding and broadcast
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
    setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)); // <-- required for broadcast

    // Bind to the interface you want to send from (kept as in your code)
    struct sockaddr_in src = {0};
    src.sin_family = AF_INET;
    src.sin_port = htons(0); // ephemeral local port
    src.sin_addr.s_addr = inet_addr("192.168.57.100");// your NIC's IP on that subnet
    if (bind(sock, (struct sockaddr*)&src, sizeof(src)) < 0) {
    int err = fdError();
    IP_PRINT("IP scanner - bind failed with err = %d\n", err);
    fdClose(sock);
    return;
    }

    // BROADCAST destination: /24 directed broadcast (or use 255.255.255.255)
    struct sockaddr_in bcast = {0};
    bcast.sin_family = AF_INET;
    bcast.sin_port = htons(6667);
    bcast.sin_addr.s_addr = inet_addr("192.168.57.255"); // or "255.255.255.255"

    // Payload (unchanged)
    char json_buffer[1024] = "Hello world";

    while (1) {

    int sent = sendto(sock, (void*)json_buffer, 1400 + 1, 0,(struct sockaddr*)&bcast, sizeof(bcast));

    if (sent < 0) {
    int err = fdError();
    IP_PRINT("send failed err=%d\n", err);
    } else {
    IP_PRINT("[SERVER] Sent %d\n", sent);
    }

    Task_sleep(500);
    }
    }

    On both SDK:

    • Wireshark sees only the first ~6 broadcast frames (total ~8.5–9 KB sent, exact count depends on payload length).

    • After that, network traffic stalls from the board side: can’t ping, ARP stops responding. CPU is still running (no exception), but the stack appears stuck.

    • The same test with unicast runs forever. - the working version.

    I also tried varying the payload length (100–1024 bytes); the total bytes before stall are consistently around 8.5–9 KB. The stall reproduces.

    Questions / request

    • Is there a known issue in AM572x CPSW/NDK with broadcast TX buffer reclamation (PBM/Tx descriptors not returned)?

    • Are there required socket options for broadcast on this stack or recommended Cfg tuning ?

    • Any patches or example code that exercises broadcast reliably on AM572x CPSW?

  • Adding a short clip with Wireshark on the broadcasting version

  • Hi,

    Apologies for the delay.

    The issue does seem to be related to the number of buffers you have on hand and it seems that they are not getting freed soon enough. Is it possible to test this with larger sleep duration. This will confirm if this is related to freeing of buffers.

    As this is with a much older stack (NDK), I need some time to check on this. I will get back to you by end of next week.

    Regards,
    Tanmay

  • Hey,

    Thanks for the reply. I want to note 2 things:

    1. I have re-created it with the newest stack (the clip and the code as mentioned above were on 2 SDK)

    2. I have tried with a larger sleep - I sent 3, waited for 10 minutes, and then got stuck in the same place.