FreeRTOS-Plus_TCP

jeronimo479 wrote on Monday, February 26, 2018:

Good Morning!

I’m trying to figure out an easy way to ping LOCALHOST (127.0.0.1), or even my own IP Address.

rtel wrote on Monday, February 26, 2018:

FreeRTOS+TCP does not have a loopback capability - although that could
be introduced in “FreeRTOS+TCP Multi”, as we are calling it, which
support multiple network interfaces.

heinbali01 wrote on Monday, February 26, 2018:

Hi Wayne, pinging to 127.0.0.x has indeed not been implemented yet. Neither it is possible to connect to the loop-back address.

heinbali01 wrote on Monday, February 26, 2018:

Richard wrote:

although that could be introduced in “FreeRTOS+TCP Multi”

That could indeed be the best place to introduce the loop-back device. It could have its own NetworkInterface.c
The FreeRTOS+TCP /multi release is still in the Labs, meaning that it is under development.
Although some people have been testing and using it for two years already, and they report that it works well for them.
The latest version can be downloaded from FreeRTOS Labs.

heinbali01 wrote on Thursday, March 01, 2018:

I added a “loop-back interface” to the normal ( non-multi ) FreeRTOS+TCP library, and it works nicely.

With this change, you can ping to the device’s IP-address, connect to your own TCP-services, and exchange UDP messages.

A small change is needed to the NetworkInterface.c that you are using, e.g. :


 BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t bReleaseAfterSend )
 {
 /* Do not wait too long for a free TX DMA buffer. */
 const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
 
     do {
+        if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )
+        {
+            /* The packet has been sent back to the IP-task.
+            The IP-task will further handle it.
+            Do not release the descriptor. */
+            bReleaseAfterSend = pdFALSE;
+            break;
+        }
         if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
         {
             /* Do not attempt to send packets as long as the Link Status is low. */
             break;
         }

The new function xCheckLoopback() will compare the target MAC-address of the IP-message ( ICMP, UDP, or TCP ) with the MAC-address of the device. If they are the same, the packet is forwarded to, and answered by the IP-stack.

It is literally a loop-back interface!

I put the new function xCheckLoopback() in FreeRTOS_ARP.c and declared it in FreeRTOS_ARP.h, so it can be used by any NetworkInterface.c.

FreeRTOS_ARP.c has a change in eARPGetCacheEntry(): In case the devices’s IP-address is looked-up, the proper MAC-address will be returned as a eARPCacheHit.

 eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * const pxMACAddress )
 {
 eARPLookupResult_t eReturn;
 uint32_t ulAddressToLookup;
 
 #if( ipconfigUSE_LLMNR == 1 )
     if( *pulIPAddress == ipLLMNR_IP_ADDR )    /* Is in network byte order. */
     {
         /* The LLMNR IP-address has a fixed virtual MAC address. */
         memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );
         eReturn = eARPCacheHit;
     }
     else
 #endif
+    if( *pulIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
+    {
+        /* Targeted at this device? Make sure that xNetworkInterfaceOutput()
+        in NetworkInterface.c calls xCheckLoopback(). */
+        memcpy( pxMACAddress->ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES );
+        eReturn = eARPCacheHit;
+    }
+    else
     if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) ||    /* Is it the general broadcast address 255.255.255.255? */
         ( *pulIPAddress == xNetworkAddressing.ulBroadcastAddress ) )/* Or a local broadcast address, eg 192.168.1.255? */
     {

I tested the changes on a SAME70 with ping and TCP.

Please find attached the code in the form of a patch.
The patch is based on the current AWS release of FreeRTOS+TCP.
In case you don’t like patches, there is also the raw code in xCheckLoopback.c.
Please let me know if it works for you, thanks.

jeronimo479 wrote on Tuesday, July 17, 2018:

Thanks! I have been using this for a long time, I just now got back around to reviewing forum stuff and realized I never thanked you.

hi htibosch,
I’m interested to apply your solution of the loopback interface, but i can’t get the xCheckLoopback.cattached file in your answer, thanks.

but i can’t get the xCheckLoopback.cattached file in your answer

That is because the FreeRTOS moved from SourceForge to it’s new site freertos.org. All attachments have gone lost since then.

You can find an implementation of xCheckLoopback() in here.

And this is how you can call it from your NetworkInterface.c, from the function xNetworkInterfaceOutput():

BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer,
									BaseType_t bReleaseAfterSend )
{
	if( xCheckLoopback( pxBuffer, bReleaseAfterSend ) != 0 )
	{
		/* The packet has been sent back to the IP-task.
		 * The IP-task will further handle it.
		 * Do not release the descriptor. */
		return pdTRUE;
	}

Please report how it works for you.
I tested it with ICMP/ping and with some TCP connections.