FreeRTOS - TCP/IP: UDP socket buffer size?

kenchang1 wrote on Monday, May 28, 2018:

For TCP sockets I can find “ipconfigTCP_RX_BUFFER_LENGTH” for the receive buffer size.

Is there a similar parameter for UDP sockets? Or is it only this one: ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ?

regards,

Ken

heinbali01 wrote on Monday, May 28, 2018:

Interesting question!

The number of UDP messages that you can receive without reading them, is indeed
limited by ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS.

For TCP a circular “stream buffer” is created for each direction. TCP data must be
buffered, and kept in a buffer until the transmission has been acknowledged by the
peer.
This TCP housekeeping of data is complicated. I tried to make clear how it works in 2
pictures ( attached to this post ).

The implementation of UDP sockets is a lot simpler. It has a list ( List_t ) of Network Buffers that were received. Note that FreeRTOS_recvfrom() has a zero-copy possibility, so that you can peek directly into a Network Buffer.

There is an important setting for UDP sockets, limiting the maximum number of received packets:

#ifndef ipconfigUDP_MAX_RX_PACKETS
    /* Make positive to define the maximum number of packets
     * which will be buffered for each UDP socket. Can be
     * overridden with the socket option FREERTOS_SO_UDP_MAX_RX_PACKETS
     */
    #define ipconfigUDP_MAX_RX_PACKETS        0u
#endif

Suppose that you get a UDP attack: thousands of packets are fired to your UDP
port, the attack will not disturb the device because at most ipconfigUDP_MAX_RX_PACKETS
network buffers will be stored.

kenchang1 wrote on Monday, May 28, 2018:

Hi Hein,

Thanks for the answer. I have an additional question. How are these 2 parameters related, ipconfigUDP_MAX_RX_PACKETS and ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS?

When I increase ipconfigUDP_MAX_RX_PACKETS from (3) to (10), I get an Assertion fail:
“Assertion failed in file …/src/FreeRTOS-Plus-TCP-multi/FreeRTOS_IP.c, line 1610”.

Line 1610 of FreeRTOS_IP.c is this part of the code:

static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
EthernetHeader_t *pxEthernetHeader;
volatile eFrameProcessingResult_t eReturned; /* Volatile to prevent complier warnings when ipCONSIDER_FRAME_FOR_PROCESSING just sets it to eProcessBuffer. */

	configASSERT( pxNetworkBuffer );

regards,
Ken

kenchang1 wrote on Tuesday, June 05, 2018:

The Assert fail was caused by 2 globally declared network pointer buffers in x_emacpsif_dma.c:

static NetworkBufferDescriptor_t *ethMsg = NULL;
static NetworkBufferDescriptor_t *ethLast = NULL;

Fixed by making them local.

heinbali01 wrote on Thursday, June 07, 2018:

Ken, thanks a lot for your big effort to find the cause of this problem.

The driver x_emacpsif_dma.c worked fine as long as it handled a single NIC. You found that when it serves two EMAC’s, corruption may occur. So the problem was only present in the /multi version.

My stupid: two tasks were storing temporary data in common variables.

These simple changes were made to avoid mentioned problem:

Around line 320:

-static NetworkBufferDescriptor_t *ethMsg = NULL;
-static NetworkBufferDescriptor_t *ethLast = NULL;
-
-static void passEthMessages( )
+static void passEthMessages( NetworkBufferDescriptor_t *ethMsg )

Around line 346:

 int emacps_check_rx( xemacpsif_s *xemacpsif )
 {
 NetworkBufferDescriptor_t *pxBuffer, *pxNewBuffer;
 int rx_bytes;
 volatile int msgCount = 0;
 int head = xemacpsif->rxHead;
 BaseType_t bHasDataPacket = pdFALSE;
+NetworkBufferDescriptor_t *ethMsg = NULL;
+NetworkBufferDescriptor_t *ethLast = NULL;
    <snip>
-        passEthMessages( );
+        passEthMessages( ethMsg );