1
0
mirror of https://github.com/FreeRTOS/FreeRTOS-Plus-TCP synced 2025-10-24 03:32:36 +08:00

ARP changes to support IPv6 (#608)

The changes includes generic ARP and ARP endpoint changes
to support IPv6.
This commit is contained in:
shubnil
2022-12-14 21:44:56 +05:30
committed by GitHub
parent f29870920d
commit dca79a1fce
2 changed files with 150 additions and 58 deletions

View File

@@ -43,7 +43,6 @@
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Timers.h"
#include "FreeRTOS_IP_Utils.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_ARP.h"
@@ -53,7 +52,6 @@
#include "FreeRTOS_DNS.h"
#endif /* ipconfigUSE_LLMNR */
#include "NetworkBufferManagement.h"
#include "FreeRTOS_Routing.h"
#include "NetworkInterface.h"
#include "FreeRTOS_Routing.h"
#include "FreeRTOS_ND.h"
@@ -87,11 +85,13 @@
* Lookup an MAC address in the ARP cache from the IP address.
*/
static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup,
MACAddress_t * const pxMACAddress );
MACAddress_t * const pxMACAddress,
NetworkEndPoint_t ** ppxEndPoint );
/*-----------------------------------------------------------*/
static void vProcessARPPacketReply( const ARPPacket_t * pxARPFrame,
NetworkEndPoint_t * pxTargetEndPoint,
uint32_t ulSenderProtocolAddress );
/*-----------------------------------------------------------*/
@@ -132,6 +132,11 @@ eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
/* memcpy() helper variables for MISRA Rule 21.15 compliance*/
const void * pvCopySource;
void * pvCopyDest;
NetworkEndPoint_t * pxTargetEndPoint = pxNetworkBuffer->pxEndPoint;
#if ( ipconfigARP_USE_CLASH_DETECTION != 0 )
NetworkEndPoint_t * pxSourceEndPoint;
#endif
/* Next defensive request must not be sent for arpIP_CLASH_RESET_TIMEOUT_MS
* period. */
@@ -186,6 +191,10 @@ eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
break;
}
#if ( ipconfigARP_USE_CLASH_DETECTION != 0 )
pxSourceEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( ulSenderProtocolAddress, 2 ); /* Clash detection. */
#endif
/* Check whether the lowest bit of the highest byte is 1 to check for
* multicast address or even a broadcast address (FF:FF:FF:FF:FF:FF). */
if( ( pxARPHeader->xSenderHardwareAddress.ucBytes[ 0 ] & 0x01U ) == 0x01U )
@@ -233,11 +242,14 @@ eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
/* Process received ARP frame to see if there is a clash. */
#if ( ipconfigARP_USE_CLASH_DETECTION != 0 )
{
if( pxSourceEndPoint != NULL )
{
xARPHadIPClash = pdTRUE;
/* Remember the MAC-address of the other device which has the same IP-address. */
( void ) memcpy( xARPClashMacAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) );
}
}
#endif /* ipconfigARP_USE_CLASH_DETECTION */
break;
@@ -247,7 +259,8 @@ eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
/* Don't do anything if the local IP address is zero because
* that means a DHCP request has not completed. */
if( *ipLOCAL_IP_ADDRESS_POINTER != 0U )
//if( *ipLOCAL_IP_ADDRESS_POINTER != 0U )
if( ( pxTargetEndPoint != NULL ) && ( pxTargetEndPoint->bits.bEndPointUp != pdFALSE_UNSIGNED ) )
{
switch( pxARPHeader->usOperation )
{
@@ -266,7 +279,7 @@ eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
/* The request is for the address of this node. Add the
* entry into the ARP cache, or refresh the entry if it
* already exists. */
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress, pxTargetEndPoint );
/* Generate a reply payload in the same buffer. */
pxARPHeader->usOperation = ( uint16_t ) ipARP_REPLY;
@@ -290,13 +303,27 @@ eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
pvCopyDest = pxARPHeader->ucSenderProtocolAddress;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
/*
* Use helper variables for memcpy() to remain
* compliant with MISRA Rule 21.15. These should be
* optimized away.
*/
pvCopySource = pxTargetEndPoint->xMACAddress.ucBytes;
pvCopyDest = pxARPHeader->xSenderHardwareAddress.ucBytes;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( MACAddress_t ) );
pvCopySource = &( pxTargetEndPoint->ipv4_settings.ulIPAddress );
pvCopyDest = pxARPHeader->ucSenderProtocolAddress;
( void ) memcpy( pvCopyDest, pvCopySource, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
eReturn = eReturnEthernetFrame;
}
break;
case ipARP_REPLY:
vProcessARPPacketReply( pxARPFrame, ulSenderProtocolAddress );
vProcessARPPacketReply( pxARPFrame, pxTargetEndPoint, ulSenderProtocolAddress );
break;
@@ -317,6 +344,7 @@ eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
* @param[in] ulSenderProtocolAddress: The IPv4 address involved.
*/
static void vProcessARPPacketReply( const ARPPacket_t * pxARPFrame,
NetworkEndPoint_t * pxTargetEndPoint,
uint32_t ulSenderProtocolAddress )
{
const ARPHeader_t * pxARPHeader = &( pxARPFrame->xARPHeader );
@@ -327,7 +355,7 @@ static void vProcessARPPacketReply( const ARPPacket_t * pxARPFrame,
( xIsIPInARPCache( ulSenderProtocolAddress ) == pdTRUE ) )
{
iptracePROCESSING_RECEIVED_ARP_REPLY( ulTargetProtocolAddress );
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress, pxTargetEndPoint );
}
if( pxARPWaitingNetworkBuffer != NULL )
@@ -474,7 +502,8 @@ BaseType_t xCheckRequiresARPResolution( const NetworkBufferDescriptor_t * pxNetw
* is being updated.
*/
void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress,
const uint32_t ulIPAddress )
const uint32_t ulIPAddress,
struct xNetworkEndPoint * pxEndPoint )
{
BaseType_t x = 0;
BaseType_t xIpEntry = -1;
@@ -542,6 +571,7 @@ void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress,
* function by setting 'xAllDone' to pdTRUE. */
xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
xARPCache[ x ].ucValid = ( uint8_t ) pdTRUE;
xARPCache[ x ].pxEndPoint = pxEndPoint;
xAllDone = pdTRUE;
break;
}
@@ -630,6 +660,7 @@ void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress,
/* And this entry does not need immediate attention */
xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdTRUE;
xARPCache[ xLocation.xUseEntry ].pxEndPoint = pxEndPoint;
}
else if( xIpEntry < 0 )
{
@@ -656,7 +687,8 @@ void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress,
* @return Either eARPCacheMiss or eARPCacheHit.
*/
eARPLookupResult_t eARPGetCacheEntryByMac( const MACAddress_t * const pxMACAddress,
uint32_t * pulIPAddress )
uint32_t * pulIPAddress,
struct xNetworkInterface ** ppxInterface )
{
BaseType_t x;
eARPLookupResult_t eReturn = eARPCacheMiss;
@@ -664,6 +696,11 @@ void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress,
configASSERT( pxMACAddress != NULL );
configASSERT( pulIPAddress != NULL );
if( ppxInterface != NULL )
{
*( ppxInterface ) = NULL;
}
/* Loop through each entry in the ARP cache. */
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
@@ -672,6 +709,13 @@ void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress,
if( memcmp( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
{
*pulIPAddress = xARPCache[ x ].ulIPAddress;
if( ( ppxInterface != NULL ) &&
( xARPCache[ x ].pxEndPoint != NULL ) )
{
*( ppxInterface ) = xARPCache[ x ].pxEndPoint->pxNetworkInterface;
}
eReturn = eARPCacheHit;
break;
}
@@ -733,7 +777,6 @@ eARPLookupResult_t eARPGetCacheEntry( uint32_t * pulIPAddress,
break;
}
}
}
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? */
@@ -843,12 +886,14 @@ eARPLookupResult_t eARPGetCacheEntry( uint32_t * pulIPAddress,
* @param[out] pxMACAddress: A pointer to MACAddress_t variable where, if there
* is an ARP cache hit, the MAC address corresponding to
* the IP address will be stored.
* @param[in,out] ppxEndPoint: a pointer to the end-point will be stored.
*
* @return When the IP-address is found: eARPCacheHit, when not found: eARPCacheMiss,
* and when waiting for a ARP reply: eCantSendPacket.
*/
static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup,
MACAddress_t * const pxMACAddress )
MACAddress_t * const pxMACAddress,
NetworkEndPoint_t ** ppxEndPoint )
{
BaseType_t x;
eARPLookupResult_t eReturn = eARPCacheMiss;
@@ -870,6 +915,8 @@ static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup,
{
/* A valid entry was found. */
( void ) memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );
/* ppxEndPoint != NULL was tested in the only caller eARPGetCacheEntry(). */
*( ppxEndPoint ) = xARPCache[ x ].pxEndPoint;
eReturn = eARPCacheHit;
}
@@ -987,7 +1034,22 @@ void vARPSendGratuitous( void )
void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )
{
NetworkBufferDescriptor_t * pxNetworkBuffer;
NetworkEndPoint_t * pxEndPoint;
NetworkInterface_t * pxInterface;
for( pxInterface = FreeRTOS_FirstNetworkInterface();
pxInterface != NULL;
pxInterface = FreeRTOS_NextNetworkInterface( pxInterface ) )
{
pxEndPoint = FreeRTOS_FindEndPointOnIP_IPv4( ulIPAddress, 25 );
if( pxEndPoint == NULL )
{
pxEndPoint = FreeRTOS_InterfaceEndPointOnNetMask( pxInterface, ulIPAddress, 26 );
}
if( pxEndPoint != NULL )
{
/* This is called from the context of the IP event task, so a block time
* must not be used. */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t ) 0U );
@@ -1035,6 +1097,8 @@ void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )
}
}
}
}
}
/*-----------------------------------------------------------*/
/**
@@ -1054,13 +1118,14 @@ BaseType_t xARPWaitResolution( uint32_t ulIPAddress,
TimeOut_t xTimeOut;
MACAddress_t xMACAddress;
eARPLookupResult_t xLookupResult;
NetworkEndPoint_t * pxEndPoint;
size_t uxSendCount = ipconfigMAX_ARP_RETRANSMISSIONS;
uint32_t ulIPAddressCopy = ulIPAddress;
/* The IP-task is not supposed to call this function. */
configASSERT( xIsCallingFromIPTask() == pdFALSE );
xLookupResult = eARPGetCacheEntry( &( ulIPAddressCopy ), &( xMACAddress ) );
xLookupResult = eARPGetCacheEntry( &( ulIPAddressCopy ), &( xMACAddress ), &( pxEndPoint ) );
if( xLookupResult == eARPCacheMiss )
{
@@ -1075,7 +1140,7 @@ BaseType_t xARPWaitResolution( uint32_t ulIPAddress,
vTaskDelay( uxSleepTime );
xLookupResult = eARPGetCacheEntry( &( ulIPAddressCopy ), &( xMACAddress ) );
xLookupResult = eARPGetCacheEntry( &( ulIPAddressCopy ), &( xMACAddress ), &( pxEndPoint ) );
if( ( xTaskCheckForTimeOut( &( xTimeOut ), &( uxTicksToWait ) ) == pdTRUE ) ||
( xLookupResult != eARPCacheMiss ) )
@@ -1183,11 +1248,28 @@ void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffe
/**
* @brief A call to this function will clear the ARP cache.
* @param[in] pxEndPoint: only clean entries with this end-point, or when NULL,
* clear the entire ARP cache.
*/
void FreeRTOS_ClearARP( void )
void FreeRTOS_ClearARP( const struct xNetworkEndPoint * pxEndPoint )
{
if( pxEndPoint != NULL )
{
BaseType_t x;
for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
{
if( xARPCache[ x ].pxEndPoint == pxEndPoint )
{
( void ) memset( &( xARPCache[ x ] ), 0, sizeof( ARPCacheRow_t ) );
}
}
}
else
{
( void ) memset( xARPCache, 0, sizeof( xARPCache ) );
}
}
/*-----------------------------------------------------------*/
#if 1
@@ -1217,7 +1299,12 @@ void FreeRTOS_ClearARP( void )
if( pxIPPacket->xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE )
{
if( memcmp( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
NetworkEndPoint_t * pxEndPoint;
pxEndPoint = FreeRTOS_FindEndPointOnMAC( &( pxIPPacket->xEthernetHeader.xDestinationAddress ), NULL );
if(( memcmp( pxIPPacket->xEthernetHeader.xDestinationAddress.ucBytes, ipLOCAL_MAC_ADDRESS, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 )
&& ( pxEndPoint != NULL ) )
{
xResult = pdTRUE;
@@ -1233,6 +1320,9 @@ void FreeRTOS_ClearARP( void )
{
IPStackEvent_t xRxEvent;
pxUseDescriptor->pxInterface = pxEndPoint->pxNetworkInterface;
pxUseDescriptor->pxEndPoint = pxEndPoint;
xRxEvent.eEventType = eNetworkRxEvent;
xRxEvent.pvData = pxUseDescriptor;

View File

@@ -108,13 +108,15 @@ BaseType_t xCheckRequiresARPResolution( const NetworkBufferDescriptor_t * pxNetw
* isn't a gateway defined) then return eCantSendPacket.
*/
eARPLookupResult_t eARPGetCacheEntry( uint32_t * pulIPAddress,
MACAddress_t * const pxMACAddress );
MACAddress_t * const pxMACAddress,
struct xNetworkEndPoint ** ppxEndPoint );
#if ( ipconfigUSE_ARP_REVERSED_LOOKUP != 0 )
/* Lookup an IP-address if only the MAC-address is known */
eARPLookupResult_t eARPGetCacheEntryByMac( const MACAddress_t * const pxMACAddress,
uint32_t * pulIPAddress );
uint32_t * pulIPAddress,
struct xNetworkInterface ** ppxInterface );
#endif
@@ -158,7 +160,7 @@ BaseType_t xCheckLoopback( NetworkBufferDescriptor_t * const pxDescriptor,
void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress );
/* Clear all entries in the ARp cache. */
/* TBD: void FreeRTOS_ClearARP( const struct xNetworkEndPoint * pxEndPoint ); */
void FreeRTOS_ClearARP( const struct xNetworkEndPoint * pxEndPoint );
/* *INDENT-OFF* */
#ifdef __cplusplus