FREERTOS TCP/IP buffer fetch issue when using arp GRATUITOUS

HI,

While sending or receiving packets at a very fast rate say 1ms, the arp GRATUITOUS which triggers when an ARP timer expires

  case eARPTimerEvent:
                /* The ARP timer has expired, process the ARP cache. */
				#if (arpGRATUITOUS_ARP_PERIOD == pdTRUE)
            		vARPAgeCache();
                	SafeRTOSNet_debug_printf( ( "prvIPTask running: Event Type =  ARP timer has expired \r\n" ) );
				#endif
                break;

caused the stack to crash, i.e the send/receive was not able
to get network buffers

i.e. you will eventually hit in bufferAllocaion_1.c


            if( xInvalid == pdTRUE )
            {
                /* _RB_ Can printf() be called from an interrupt?  (comment
                 * above says this can be called from an interrupt too) */
                configASSERT(xInvalid);

                /* _HT_ The function shall not be called from an ISR. Comment
                 * was indeed misleading. Hopefully clear now?
                 * So the printf()is OK here. */
                SafeRTOSNet_debug_printf( ( "pxGetNetworkBufferWithDescriptor: INVALID BUFFER: %p (valid %lu)\n",
                                         pxReturn, bIsValidNetworkDescriptor( pxReturn ) ) );
                pxReturn = NULL;
            }

I think this is due to task starvation of the IP_STACK, where a small glitch due to ARP has occurred. Probably having static Net configs than ARP-based caching will be the best.

Is this a known issue

Regards
Anand

It is not a known issue - however it looks like you are using SafeRTOS rather than FreeRTOS - what are the steps to replicate using FreeRTOS?

When data is sent from a task say at 1ms using send to or receive from Socket APIs, the ARP timeout sends an ARP eARPTimerEvent to refresh the ARP cache, When this event occurs it causes some delay between the ongoing sending/receiving data and the ARP event that occurs in between.
After I commented this event from occuring the send/receive were much better.
I initially tested with FreeRTOS and yes now Trying to get moving for SafeRTOS for a prototype . Also Probably I will have to drop ARP and go fully static configs to make things more deterministic

How have you set task priorities? Recommend any MAC related tasks (for example, a task that is woken by a MAC interrupt) be highest, then the TCP task, finally the application task lowest.

1 Like

When I compare the code fragment that you show with the FreeRTOS+TCP code, I see these changes:

     case eARPTimerEvent:
     /* The ARP timer has expired, process the ARP cache. */
+    #if (arpGRATUITOUS_ARP_PERIOD == pdTRUE)
         vARPAgeCache();
+        SafeRTOSNet_debug_printf( ( "prvIPTask running: Event Type =  ARP timer has expired \r\n" ) );
+    #endif
     break;

That is a bit unexpected: vARPAgeCache() must be called unconditionally, and should not depend on any macro.
vARPAgeCache() will work on the ARP cache table, refresh old entries and remove dead entries.

The macro arpGRATUITOUS_ARP_PERIOD is only defined in FreeRTOR_ARP.c as a number, not a boolean pdTRUE or pdFALSE:

/** @brief The time between gratuitous ARPs. */
#ifndef arpGRATUITOUS_ARP_PERIOD
    #define arpGRATUITOUS_ARP_PERIOD    ( pdMS_TO_TICKS( 20000U ) )
#endif

So by default, a gratuitous ARP request will be send every 20 seconds. That is frequently.
You can overwrite that value in your FreeRTOSIPConfig.h:

Send a gratuitous ARP request every 2 minutes.
#define arpGRATUITOUS_ARP_PERIOD    ( pdMS_TO_TICKS( 120000U ) )

You wrote:

caused the stack to crash, i.e the send/receive was not able to get network buffers

Does the IP-stack crash, get an exception? Or does it run out of network buffers?
What value have you assigned to the macro ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS?
How much is it now? Have you tried increasing it?

What platform are you using? Are you on a busy LAN?

Is the application receiving many UDP packets? And does receiving task get enough CPU time?
Are the UDP packets queueing up in the socket?

If there is a risk of receiving too many UDP packets, you can define ipconfigUDP_MAX_RX_PACKETS, described here. Or you can use the socket option FREERTOS_SO_UDP_MAX_RX_PACKETS.

1 Like

Hi,
I think I am mixing my Deterministic Requirements that I am prototyping , with this question

  1. As @rtel said fixing task priorities will make things work and it does - no issues with the stack as-is.
  2. However ARP causes non-determinism (agreed it’s for me w.r.t my req - special case), as it causes a glitch in the normal Tx/RX flow - through its periodic the system is not expecting it.
    e.g. (scenario only) I get an alert and at the same time the 20sec ARP kicks in , the system goes to the emergency backup (Say CAN bus).
  3. Better option for me is to have a separate socket as a heartbeat socket and then I have things in control. Or Make a pact with system guys for ARP however its very unlikely with
    a broadcast packet.

Many Thanks Again,
Anand