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:
@@ -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;
|
||||
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user