Freertos stack not able to bind same udp port to different ip

Hi,

This looks odd, yet has this been observed with the FreeRTOS Stack,

I have 2x EMAC on my Zynq
I allocate 192.168.2.200 and port 5001 for UDP send and receive on MAC1
I allocate 192.168.3.220 and port 5001 for UDP send and receive on MAC2

The bind fails on MAC2, if I change the Port to 5002 it works

I thought each IP should be able to have 2^16 ports by themselves, yet this not working
for me.

I also made sure the link is up before a bind.

Any Hints, where to look for - if I may have touched any code that I shouldn’t have

Regards
Anand

I presume you are using this version of the TCP/IP stack: https://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/freertostcp-multiple-interfaces.html. Most likely this is an “unintended limitation” in the code.

You can bind the server socket, e.g. port 23 and address 0.0.0.0
This socket will serve both EMAC’s
In fact the IP address is ignored by bind().
In Linux or Windows you can do the same: bind to 0.0.0.0 and servd all interfaces.
Can you try that?
PS. it works the same for TCP and for UDP sockets.

@rtel Yes that’s correct, I am using the multinode stack - and it is pretty good and stable,
I did put some debug code in my stack for loopbacks etc, and thought I may have injected a bug in my code.

Yes this seems to be a limitation as to the bound socket list

List_t xBoundUDPSocketsList;
considers only port numbers and not a pair <ipAddress,portNum>.

It is ok for us, yet it’s important to know vs Linux Sockets that the other team uses on a simulation.

The code below and the highlighted extract below which shows this limitation

( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port )!= NULL ) )

/**
 * @brief : Bind a socket to a port number.
 * @param[in] pxSocket : The socket to be bound.
 * @param[in] pxAddress : The socket will be bound to this address.
 * @param[in] pxSocketList : will either point to xBoundUDPSocketsList or
 *                           xBoundTCPSocketsList.
 * @param[in] xInternal : pdTRUE if this function is called 'internally', i.e.
 *                        by the IP-task.
 */
static BaseType_t prvSocketBindAdd( FreeRTOS_Socket_t * pxSocket,
                                    struct freertos_sockaddr * pxAddress,
                                    List_t * pxSocketList,
                                    BaseType_t xInternal )
{
    BaseType_t xReturn = 0;

    /* Check to ensure the port is not already in use.  If the bind is
     * called internally, a port MAY be used by more than one socket. */
    if( ( ( xInternal == pdFALSE ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_TCP ) ) &&
        ( pxListFindListItemWithValue( pxSocketList, ( TickType_t ) pxAddress->sin_port )!= NULL ) )
    {
        FreeRTOS_debug_printf( ( "vSocketBind: %sP port %d in use\n",
                                 ( pxSocket->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ) ? "TC" : "UD",
                                 FreeRTOS_ntohs( pxAddress->sin_port ) ) );
        xReturn = -pdFREERTOS_ERRNO_EADDRINUSE;
    }

Thanks for this info, this will be useful for some performance tests yet not for our applications

Both under Linux and under Windows it should be possible to bind a server socket to 0.0.0.0 the ANY address.
A socket option REUSE determines werher the port number may be bound (re-used) a second time.

I found this single binding simpler and more economic.

You can still check the address of the peer and
reply differently depending on which EMAC the message was received.
See FreeRTOS_GetRemoteAddress()

EDIT The above function only works for TCP sockets.
For UDP sockets you can inspect the address set by FreeRTOS_recvfrom()