FreeRTOS + TCP ARP only resolves when request is initiated from remote

Hello,

I am exploring integrating the TCP stack on a STM32F7 platform. So far it’s been great, clear instructions on how to setup. It’s compiling and I manage to open a udp socket to periodically send a “hello world” message.

ARP requests are being sent to my “remote” computer and I can see the traffic on wireshark. I’m under the impression the computer replies to the ARP requests. Yet the ARP table does not seem to ever get updated, in the end the “hello world” frame is never transmitted.

It is however sufficient to send a single UDP package from the remote to the STM to initiate an ARP request in the opposite direction, and here everything unlocks. ARP is resolved, and my hello world message is being transmitted.

I am quite novice at the TCP stack. Is this expected? Is this a known issue?

what kind of infra structure is between your DUT and the peer?

What exctly do you mean “you are under the impression that the computer replies to the ARP requests?” What makes you think that?

Do you have wireshark traces of the traffic?

I should’ve included some traces you are right.

The following are the debug traces from RTOs (printed over UART)

=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2025.04.24 14:15:08 =~=~=~=~=~=~=~=~=~=~=~=^M
FreeRTOS_AddEndPoint: MAC: 44-55 IPv4: c0a80145ip
prvIPTask started
PHY ID 7C130
xPhyReset: phyBMCR_RESET 0 ready
+TCP: advertise: 01E1 config 3100
Autonego ready: 00000004: full duplex 100 mbit high status
Opened socket!^M
ARP c0a80164ip miss using c0a80164ip
HAL_ETH_RxLinkCallback: Buffer Dropped
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
HAL_ETH_RxLinkCallback: Buffer Dropped
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip
HAL_ETH_RxLinkCallback: Buffer Dropped
ARP c0a80164ip miss using c0a80164ip
ARP c0a80164ip miss using c0a80164ip

The tcpdump traces (from the ‘remote’) are as follows:

> sudo tcpdump -i enp5s0 arp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp5s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
14:19:53.376760 ARP, Request who-has LL-PF3MRH7X-L.pc.goiba.net tell 192.168.1.69, length 46
14:19:53.376796 ARP, Reply LL-PF3MRH7X-L.pc.goiba.net is-at 6c:24:08:02:b8:49 (oui Unknown), length 28
14:19:59.678919 ARP, Request who-has 192.168.1.69 tell LL-PF3MRH7X-L.pc.goiba.net, length 28
14:19:59.688314 ARP, Reply 192.168.1.69 is-at 00:11:22:33:44:55 (oui Unknown), length 50
14:20:00.014921 ARP, Request who-has 192.168.1.69 tell 192.168.1.69, length 46
14:20:30.025393 ARP, Request who-has 192.168.1.69 tell 192.168.1.69, length 46
14:20:38.314691 ARP, Request who-has LL-PF3MRH7X-L.pc.goiba.net tell 192.168.1.69, length 46
14:20:38.314730 ARP, Reply LL-PF3MRH7X-L.pc.goiba.net is-at 6c:24:08:02:b8:49 (oui Unknown), length 28
14:20:44.953629 ARP, Request who-has LL-PF3MRH7X-L.pc.goiba.net tell 192.168.1.69, length 46
14:20:44.953648 ARP, Reply LL-PF3MRH7X-L.pc.goiba.net is-at 6c:24:08:02:b8:49 (oui Unknown), length 28
14:20:44.953659 ARP, Request who-has 192.168.1.69 tell 192.168.1.69, length 46
^C
11 packets captured
11 packets received by filter
0 packets dropped by kernel

I believe the HAL_ETH_RxLinkCallback: Buffer Dropped traces coincide with the ARP packet.

what kind of infra structure is between your DUT and the peer?

I’m not sure I understand your question. It’s a physical connection over ethernet port between “remote” and STM32.

it seems as if your dut is attempting to contact 192.168.1.100 which fails. Is that the ip address of your peer? Please elaborate on the configuration, what are the ip addresses of both your units as well as the configured default gateway and netmask? Source code of your dut conf sequence is most useful here.

There is an entry in the arp log which suggests that your dut is at 192.168.1.69, but that node also requests the arp resolution of a dns host name which seems strange.

I was really asking for a packet (wireshark or full tcpdump) trace of the network traffic.

The remote is configured with a static IPv4 address: 192.168.1.100/24

The dut (? I don’t know this abbreviation, google wasn’t helpful) is configured as follows:

IPv4: 192.168.1.69
netmask: 255.255.255.0
gatweay: 192.168.1.33

If I’m being honest, I just grabbed a random number in IP range for the gateway as to my understanding it shouldn’t come into play in this scenario. I might be wrong.

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

#include "FreeRTOS_IP.h"

//
static uint8_t ucMACAddress[ 6 ] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };

static const uint8_t ucIPAddress[ 4 ] = { 192, 168, 1, 69 };
static const uint8_t ucNetMask[ 4 ] = { 255, 255, 255, 0 };
static const uint8_t ucGatewayAddress[ 4 ] = { 192, 168, 1, 33 };
static const uint8_t ucDNSServerAddress[ 4 ] = { 208, 67, 222, 222 };

/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  FreeRTOS_IPInit(ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress);
}

#define DEST_IP_ADDR  "192.168.1.100"   // Destination IP
#define DEST_PORT     5005              // Destination port
#define LOCAL_PORT    5000              // Local port (can be 0 for auto)

// Data to send
static const char *messageToSend = "Hello from STM32 over UDP!\r\n";
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
    Socket_t xSocket;
    struct freertos_sockaddr xDestinationAddress;
    BaseType_t xSendResult;

    // wait for IP task to be ready  // TODO use semaphore
    osDelay(1000);

    // Create the UDP socket
    xSocket = FreeRTOS_socket(FREERTOS_AF_INET,
                              FREERTOS_SOCK_DGRAM,
                              FREERTOS_SOCK_DEPENDENT_PROTO );


    if (xSocket == FREERTOS_INVALID_SOCKET) {
        // Handle error
    	printf("Inavlid socket\r\n");
        vTaskDelete(NULL);
    }
    else
    {
    	printf("Opened socket!\r\n");
    }

    // Optional: bind to a local port
    struct freertos_sockaddr xBindAddress;
    xBindAddress.sin_port = FreeRTOS_htons(LOCAL_PORT);
    FreeRTOS_bind(xSocket, &xBindAddress, sizeof(xBindAddress));

    // Set destination address
    xDestinationAddress.sin_addr = FreeRTOS_inet_addr(DEST_IP_ADDR);
    xDestinationAddress.sin_port = FreeRTOS_htons(DEST_PORT);

    for(;;)
    {
		// Send the UDP message
		xSendResult = FreeRTOS_sendto(xSocket,
									  messageToSend,
									  strlen(messageToSend),
									  0,
									  &xDestinationAddress,
									  sizeof(xDestinationAddress));

		if (xSendResult < 0) {
			printf("Error\r\n");
		}

		osDelay(1000);
    }
}

I will update with a full tcpdump tomorrw, I don’t have access to my tools.

but if your dut (device under test) has the .69, the above arp request sounds odd, normally that is nothing a FreeRTOS unit would do. Could you have an IP address conflict in your net?