From 4772f1c4e85c28a1a71dbb397e6ac3a8268effaf Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 1 Aug 2024 15:31:10 -0400 Subject: [PATCH] Add ND Timer event implementation --- source/FreeRTOS_IP.c | 133 ++++++++--- source/FreeRTOS_IP_Timers.c | 220 ++++++++++++++---- source/FreeRTOS_IP_Utils.c | 7 +- source/FreeRTOS_ND.c | 20 ++ source/include/FreeRTOSIPConfigDefaults.h | 31 +++ source/include/FreeRTOS_IP.h | 9 +- source/include/FreeRTOS_IP_Private.h | 25 +- source/include/FreeRTOS_IP_Timers.h | 50 ++-- source/include/FreeRTOS_ND.h | 2 + source/include/IPTraceMacroDefaults.h | 38 ++- .../unit-test/FreeRTOS_ND/FreeRTOS_ND_stubs.c | 4 +- .../unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c | 45 ++-- test/unit-test/FreeRTOS_ND/ut.cmake | 3 +- 13 files changed, 435 insertions(+), 152 deletions(-) diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index e9b5ef029..4113931e3 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -64,34 +64,50 @@ #ifndef ipINITIALISATION_RETRY_DELAY #define ipINITIALISATION_RETRY_DELAY ( pdMS_TO_TICKS( 3000U ) ) #endif + #if ( ipconfigUSE_TCP_MEM_STATS != 0 ) #include "tcp_mem_stats.h" #endif -/** @brief Maximum time to wait for a resolution while holding a packet. */ -#ifndef ipADDR_RES_MAX_DELAY - #define ipADDR_RES_MAX_DELAY ( pdMS_TO_TICKS( 2000U ) ) +/** @brief Maximum time to wait for an ARP resolution while holding a packet. */ +#ifndef ipARP_RESOLUTION_MAX_DELAY + #define ipARP_RESOLUTION_MAX_DELAY ( pdMS_TO_TICKS( 2000U ) ) #endif -#ifndef iptraceIP_TASK_STARTING - #define iptraceIP_TASK_STARTING() do {} while( ipFALSE_BOOL ) /**< Empty definition in case iptraceIP_TASK_STARTING is not defined. */ +/** @brief Maximum time to wait for a ND resolution while holding a packet. */ +#ifndef ipND_RESOLUTION_MAX_DELAY + #define ipND_RESOLUTION_MAX_DELAY ( pdMS_TO_TICKS( 2000U ) ) #endif -#if ( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) ) - /** @brief When initialising the TCP timer, give it an initial time-out of 1 second. */ - #define ipTCP_TIMER_PERIOD_MS ( 1000U ) +/** @brief Defines how often the ARP resolution timer callback function is executed. The time is + * shorter in the Windows simulator as simulated time is not real time. */ +#ifndef ipARP_TIMER_PERIOD_MS + #ifdef _WINDOWS_ + #define ipARP_TIMER_PERIOD_MS ( 500U ) /* For windows simulator builds. */ + #else + #define ipARP_TIMER_PERIOD_MS ( 10000U ) + #endif #endif -/** @brief Defines how often the resolution timer callback function is executed. The time is +/** @brief Defines how often the ND resolution timer callback function is executed. The time is * shorter in the Windows simulator as simulated time is not real time. */ -#ifndef ipADDR_RES_TIMER_PERIOD_MS +#ifndef ipND_TIMER_PERIOD_MS #ifdef _WINDOWS_ - #define ipADDR_RES_TIMER_PERIOD_MS ( 500U ) /* For windows simulator builds. */ + #define ipND_TIMER_PERIOD_MS ( 500U ) /* For windows simulator builds. */ #else - #define ipADDR_RES_TIMER_PERIOD_MS ( 10000U ) + #define ipND_TIMER_PERIOD_MS ( 10000U ) #endif #endif +#if ( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) ) + /** @brief When initialising the TCP timer, give it an initial time-out of 1 second. */ + #define ipTCP_TIMER_PERIOD_MS ( 1000U ) +#endif + +#ifndef iptraceIP_TASK_STARTING + #define iptraceIP_TASK_STARTING() do {} while( ipFALSE_BOOL ) /**< Empty definition in case iptraceIP_TASK_STARTING is not defined. */ +#endif + /** @brief The frame type field in the Ethernet header must have a value greater than 0x0600. * If the configuration option ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES is enabled, the stack * will discard packets with a frame type value less than or equal to 0x0600. @@ -106,8 +122,15 @@ static void prvIPTask_CheckPendingEvents( void ); /*-----------------------------------------------------------*/ -/** @brief The pointer to buffer with packet waiting for resolution. */ -NetworkBufferDescriptor_t * pxResolutionWaitingNetworkBuffer = NULL; +/** @brief The pointer to buffer with packet waiting for ARP resolution. */ +#if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + NetworkBufferDescriptor_t * pxARPWaitingNetworkBuffer = NULL; +#endif + +/** @brief The pointer to buffer with packet waiting for ND resolution. */ +#if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + NetworkBufferDescriptor_t * pxNDWaitingNetworkBuffer = NULL; +#endif /*-----------------------------------------------------------*/ @@ -293,16 +316,18 @@ static void prvProcessIPEventsAndTimers( void ) prvForwardTxPacket( ( ( NetworkBufferDescriptor_t * ) xReceivedEvent.pvData ), pdTRUE ); break; - case eResolutionTimerEvent: - /* The Resolution timer has expired, process the cache. */ - #if ( ipconfigUSE_IPv4 != 0 ) + case eARPTimerEvent: + /* The ARP Resolution timer has expired, process the cache. */ + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) vARPAgeCache(); #endif /* ( ipconfigUSE_IPv4 != 0 ) */ + break; - #if ( ipconfigUSE_IPv6 != 0 ) + case eNDTimerEvent: + /* The ND Resolution timer has expired, process the cache. */ + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) vNDAgeCache(); #endif /* ( ipconfigUSE_IPv6 != 0 ) */ - break; case eSocketBindEvent: @@ -493,8 +518,15 @@ static void prvIPTask_Initialise( void ) } #endif - /* Mark the timer as inactive since we are not waiting on any resolution as of now. */ - vIPSetResolutionTimerEnableState( pdFALSE ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + /* Mark the ARP timer as inactive since we are not waiting on any resolution as of now. */ + vIPSetARPResolutionTimerEnableState( pdFALSE ); + #endif + + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + /* Mark the ND timer as inactive since we are not waiting on any resolution as of now. */ + vIPSetNDResolutionTimerEnableState( pdFALSE ); + #endif #if ( ( ipconfigDNS_USE_CALLBACKS != 0 ) && ( ipconfigUSE_DNS != 0 ) ) { @@ -648,7 +680,13 @@ void vIPNetworkUpCalls( struct xNetworkEndPoint * pxEndPoint ) #endif /* ipconfigDNS_USE_CALLBACKS != 0 */ /* Set remaining time to 0 so it will become active immediately. */ - vResolutionTimerReload( pdMS_TO_TICKS( ipADDR_RES_TIMER_PERIOD_MS ) ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + vARPTimerReload( pdMS_TO_TICKS( ipARP_TIMER_PERIOD_MS ) ); + #endif + + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + vNDTimerReload( pdMS_TO_TICKS( ipND_TIMER_PERIOD_MS ) ); + #endif } /*-----------------------------------------------------------*/ @@ -1733,20 +1771,47 @@ static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetwor case eWaitingResolution: - if( pxResolutionWaitingNetworkBuffer == NULL ) - { - pxResolutionWaitingNetworkBuffer = pxNetworkBuffer; - vIPTimerStartResolution( ipADDR_RES_MAX_DELAY ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + if( pxEthernetHeader->usFrameType == ipIPv4_FRAME_TYPE ) + { + if( pxARPWaitingNetworkBuffer == NULL ) + { + pxARPWaitingNetworkBuffer = pxNetworkBuffer; + vIPTimerStartARPResolution( ipARP_RESOLUTION_MAX_DELAY ); - iptraceDELAYED_RESOLUTION_REQUEST_STARTED(); - } - else - { - /* We are already waiting on one resolution. This frame will be dropped. */ - vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + iptraceDELAYED_ARP_REQUEST_STARTED(); + } + else + { + /* We are already waiting on one resolution. This frame will be dropped. */ + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); - iptraceDELAYED_RESOLUTION_BUFFER_FULL(); - } + iptraceDELAYED_ARP_BUFFER_FULL(); + } + break; + } + #endif + + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + if( pxEthernetHeader->usFrameType == ipIPv6_FRAME_TYPE ) + { + if( pxNDWaitingNetworkBuffer == NULL ) + { + pxNDWaitingNetworkBuffer = pxNetworkBuffer; + vIPTimerStartNDResolution( ipND_RESOLUTION_MAX_DELAY ); + + iptraceDELAYED_ND_REQUEST_STARTED(); + } + else + { + /* We are already waiting on one resolution. This frame will be dropped. */ + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + + iptraceDELAYED_ND_BUFFER_FULL(); + } + break; + } + #endif break; diff --git a/source/FreeRTOS_IP_Timers.c b/source/FreeRTOS_IP_Timers.c index 87ffe4e14..e5ce73fbd 100644 --- a/source/FreeRTOS_IP_Timers.c +++ b/source/FreeRTOS_IP_Timers.c @@ -49,6 +49,8 @@ #include "FreeRTOS_IP_Private.h" #include "FreeRTOS_UDP_IP.h" #include "FreeRTOS_DHCP.h" +#include "FreeRTOS_ARP.h" +#include "FreeRTOS_ND.h" #include "NetworkInterface.h" #include "NetworkBufferManagement.h" #include "FreeRTOS_Routing.h" @@ -92,20 +94,22 @@ static void prvIPTimerReload( IPTimer_t * pxTimer, * regular basis */ +#if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) /** @brief Timer to limit the maximum time a packet should be stored while * awaiting an ARP resolution. */ -static IPTimer_t xARPResolutionTimer; + static IPTimer_t xARPResolutionTimer; /** @brief ARP timer, to check its table entries. */ -static IPTimer_t xARPTimer; - + static IPTimer_t xARPTimer; +#endif +#if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) /** @brief Timer to limit the maximum time a packet should be stored while * awaiting an ND resolution. */ -static IPTimer_t xNDResolutionTimer; + static IPTimer_t xNDResolutionTimer; /** @brief ND timer, to check its table entries. */ -static IPTimer_t xNDTimer; - + static IPTimer_t xNDTimer; +#endif #if ( ipconfigUSE_TCP != 0 ) /** @brief TCP timer, to check for timeouts, resends. */ static IPTimer_t xTCPTimer; @@ -142,13 +146,25 @@ TickType_t xCalculateSleepTime( void ) * time in any other timers that are active. */ uxMaximumSleepTime = ipconfigMAX_IP_TASK_SLEEP_TIME; - if( xARPTimer.bActive != pdFALSE_UNSIGNED ) - { - if( xARPTimer.ulRemainingTime < uxMaximumSleepTime ) + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + if( xARPTimer.bActive != pdFALSE_UNSIGNED ) { - uxMaximumSleepTime = xARPTimer.ulRemainingTime; + if( xARPTimer.ulRemainingTime < uxMaximumSleepTime ) + { + uxMaximumSleepTime = xARPTimer.ulRemainingTime; + } } - } + #endif + + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + if( xNDTimer.bActive != pdFALSE_UNSIGNED ) + { + if( xNDTimer.ulRemainingTime < uxMaximumSleepTime ) + { + uxMaximumSleepTime = xNDTimer.ulRemainingTime; + } + } + #endif #if ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 ) { @@ -198,7 +214,7 @@ TickType_t xCalculateSleepTime( void ) /*-----------------------------------------------------------*/ /** - * @brief Check the network timers (ARP/DHCP/DNS/TCP) and if they are + * @brief Check the network timers (ARP/ND/DHCP/DNS/TCP) and if they are * expired, send an event to the IP-Task. */ /* MISRA Ref 8.9.1 [File scoped variables] */ @@ -209,30 +225,59 @@ void vCheckNetworkTimers( void ) { NetworkInterface_t * pxInterface; - /* Is it time for ARP processing? */ - if( prvIPTimerCheck( &xARPTimer ) != pdFALSE ) - { - ( void ) xSendEventToIPTask( eARPTimerEvent ); - } + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + /* Is it time for ARP processing? */ + if( prvIPTimerCheck( &xARPTimer ) != pdFALSE ) + { + ( void ) xSendEventToIPTask( eARPTimerEvent ); + } - /* Is the ARP resolution timer expired? */ - if( prvIPTimerCheck( &xARPResolutionTimer ) != pdFALSE ) - { - if( pxARPWaitingNetworkBuffer != NULL ) + /* Is the ARP resolution timer expired? */ + if( prvIPTimerCheck( &xARPResolutionTimer ) != pdFALSE ) { - /* Disable the ARP resolution timer. */ - vIPSetARPResolutionTimerEnableState( pdFALSE ); + if( pxARPWaitingNetworkBuffer != NULL ) + { + /* Disable the ARP resolution timer. */ + vIPSetARPResolutionTimerEnableState( pdFALSE ); - /* We have waited long enough for the ARP response. Now, free the network - * buffer. */ - vReleaseNetworkBufferAndDescriptor( pxARPWaitingNetworkBuffer ); + /* We have waited long enough for the ARP response. Now, free the network + * buffer. */ + vReleaseNetworkBufferAndDescriptor( pxARPWaitingNetworkBuffer ); - /* Clear the pointer. */ - pxARPWaitingNetworkBuffer = NULL; + /* Clear the pointer. */ + pxARPWaitingNetworkBuffer = NULL; - iptraceDELAYED_ARP_TIMER_EXPIRED(); + iptraceDELAYED_ARP_TIMER_EXPIRED(); + } + } + #endif + + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + /* Is it time for ND processing? */ + if( prvIPTimerCheck( &xNDTimer ) != pdFALSE ) + { + ( void ) xSendEventToIPTask( eNDTimerEvent ); } - } + + /* Is the ND resolution timer expired? */ + if( prvIPTimerCheck( &xNDResolutionTimer ) != pdFALSE ) + { + if( pxNDWaitingNetworkBuffer != NULL ) + { + /* Disable the ND resolution timer. */ + vIPSetNDResolutionTimerEnableState( pdFALSE ); + + /* We have waited long enough for the ND response. Now, free the network + * buffer. */ + vReleaseNetworkBufferAndDescriptor( pxNDWaitingNetworkBuffer ); + + /* Clear the pointer. */ + pxNDWaitingNetworkBuffer = NULL; + + iptraceDELAYED_ND_TIMER_EXPIRED(); + } + } + #endif #if ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 ) { @@ -365,15 +410,32 @@ static void prvIPTimerStart( IPTimer_t * pxTimer, } /*-----------------------------------------------------------*/ +#if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + /** * @brief Start an ARP Resolution timer. * * @param[in] xTime Time to be loaded into the ARP Resolution timer. */ -void vIPTimerStartARPResolution( TickType_t xTime ) -{ - prvIPTimerStart( &( xARPResolutionTimer ), xTime ); -} + void vIPTimerStartARPResolution( TickType_t xTime ) + { + prvIPTimerStart( &( xARPResolutionTimer ), xTime ); + } +#endif +/*-----------------------------------------------------------*/ + +#if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + +/** + * @brief Start an ND Resolution timer. + * + * @param[in] xTime Time to be loaded into the ND Resolution timer. + */ + void vIPTimerStartNDResolution( TickType_t xTime ) + { + prvIPTimerStart( &( xNDResolutionTimer ), xTime ); + } +#endif /*-----------------------------------------------------------*/ /** @@ -404,6 +466,8 @@ static void prvIPTimerReload( IPTimer_t * pxTimer, #endif /*-----------------------------------------------------------*/ +#if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + /** * @brief Sets the reload time of the ARP timer and restarts it. * @@ -413,7 +477,21 @@ void vARPTimerReload( TickType_t xTime ) { prvIPTimerReload( &xARPTimer, xTime ); } +#endif +/*-----------------------------------------------------------*/ + +#if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) +/** + * @brief Sets the reload time of the ND timer and restarts it. + * + * @param[in] xTime Time to be reloaded into the ND timer. + */ +void vNDTimerReload( TickType_t xTime ) +{ + prvIPTimerReload( &xNDTimer, xTime ); +} +#endif /*-----------------------------------------------------------*/ #if ( ipconfigDNS_USE_CALLBACKS != 0 ) @@ -525,40 +603,82 @@ static BaseType_t prvIPTimerCheck( IPTimer_t * pxTimer ) #endif /* if ( ipconfigUSE_TCP == 1 ) */ /*-----------------------------------------------------------*/ +#if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + /** * @brief Enable/disable the ARP timer. * * @param[in] xEnableState pdTRUE - enable timer; pdFALSE - disable timer. */ -void vIPSetARPTimerEnableState( BaseType_t xEnableState ) -{ - if( xEnableState != pdFALSE ) + void vIPSetARPTimerEnableState( BaseType_t xEnableState ) { - xARPTimer.bActive = pdTRUE_UNSIGNED; + if( xEnableState != pdFALSE ) + { + xARPTimer.bActive = pdTRUE_UNSIGNED; + } + else + { + xARPTimer.bActive = pdFALSE_UNSIGNED; + } } - else + /*-----------------------------------------------------------*/ + +/** + * @brief Enable or disable the ARP resolution timer. + * + * @param[in] xEnableState pdTRUE if the timer must be enabled, pdFALSE otherwise. + */ + void vIPSetARPResolutionTimerEnableState( BaseType_t xEnableState ) { - xARPTimer.bActive = pdFALSE_UNSIGNED; + if( xEnableState != pdFALSE ) + { + xARPResolutionTimer.bActive = pdTRUE_UNSIGNED; + } + else + { + xARPResolutionTimer.bActive = pdFALSE_UNSIGNED; + } } -} +#endif /*-----------------------------------------------------------*/ +#if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + /** - * @brief Enable or disable the ARP resolution timer. + * @brief Enable/disable the ND timer. * - * @param[in] xEnableState pdTRUE if the timer must be enabled, pdFALSE otherwise. + * @param[in] xEnableState pdTRUE - enable timer; pdFALSE - disable timer. */ -void vIPSetARPResolutionTimerEnableState( BaseType_t xEnableState ) -{ - if( xEnableState != pdFALSE ) + void vIPSetNDTimerEnableState( BaseType_t xEnableState ) { - xARPResolutionTimer.bActive = pdTRUE_UNSIGNED; + if( xEnableState != pdFALSE ) + { + xNDTimer.bActive = pdTRUE_UNSIGNED; + } + else + { + xNDTimer.bActive = pdFALSE_UNSIGNED; + } } - else + /*-----------------------------------------------------------*/ + +/** + * @brief Enable or disable the ND resolution timer. + * + * @param[in] xEnableState pdTRUE if the timer must be enabled, pdFALSE otherwise. + */ + void vIPSetNDResolutionTimerEnableState( BaseType_t xEnableState ) { - xARPResolutionTimer.bActive = pdFALSE_UNSIGNED; + if( xEnableState != pdFALSE ) + { + xNDResolutionTimer.bActive = pdTRUE_UNSIGNED; + } + else + { + xNDResolutionTimer.bActive = pdFALSE_UNSIGNED; + } } -} +#endif /*-----------------------------------------------------------*/ #if ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 ) || ( ipconfigUSE_DHCPv6 == 1 ) diff --git a/source/FreeRTOS_IP_Utils.c b/source/FreeRTOS_IP_Utils.c index 95880c851..f1bae8a0a 100644 --- a/source/FreeRTOS_IP_Utils.c +++ b/source/FreeRTOS_IP_Utils.c @@ -823,7 +823,12 @@ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ) configASSERT( pxInterface != NULL ); configASSERT( pxInterface->pfInitialise != NULL ); /* Stop the Address Resolution timer while there is no network. */ - vIPSetAddrResTimerEnableState( pdFALSE ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + vIPSetARPTimerEnableState( pdFALSE ); + #endif + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + vIPSetNDTimerEnableState( pdFALSE ); + #endif /* The first network down event is generated by the IP stack itself to * initialise the network hardware, so do not call the network down event diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index d187681b9..4350ad39d 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -97,6 +97,10 @@ /** @brief The ND cache. */ static NDCacheRow_t xNDCache[ ipconfigND_CACHE_ENTRIES ]; +/** @brief The time at which the last unsolicited ND was sent. Unsolicited NDs are used + * to ensure ND tables are up to date and to detect IP address conflicts. */ + static TickType_t xLastUnsolicitedNDTime = 0U; + /*-----------------------------------------------------------*/ /* @@ -1395,5 +1399,21 @@ return xNeedsNDResolution; } + +/*-----------------------------------------------------------*/ + +/** + * @brief Send an unsolicited ND packet to allow this node to announce the IP-MAC + * mapping to the entire network. + */ + void vNDSendUnsolicited( void ) + { + /* Setting xLastUnsolicitedNDTime to 0 will force an unsolicited ND the next + * time vNDAgeCache() is called. */ + xLastUnsolicitedNDTime = ( TickType_t ) 0; + + /* Let the IP-task call vARPAgeCache(). */ + ( void ) xSendEventToIPTask( eNDTimerEvent ); + } /*-----------------------------------------------------------*/ #endif /* ipconfigUSE_IPv6 */ diff --git a/source/include/FreeRTOSIPConfigDefaults.h b/source/include/FreeRTOSIPConfigDefaults.h index a31d962ea..245a56840 100644 --- a/source/include/FreeRTOSIPConfigDefaults.h +++ b/source/include/FreeRTOSIPConfigDefaults.h @@ -2951,6 +2951,37 @@ STATIC_ASSERT( ipconfigDNS_SEND_BLOCK_TIME_TICKS <= portMAX_DELAY ); /*---------------------------------------------------------------------------*/ +/* + * ipconfigMAX_ND_AGE + * + * Type: uint8_t + * Unit: decaseconds + * Minimum: 0 + * + * Defines the maximum time between an entry in the ND table being created or + * refreshed and the entry being removed because it is stale. New ND requests + * are sent for ND cache entries that are nearing their maximum age. + * The maximum age of an entry in the ND cache table can be + * calculated as 'ipND_TIMER_PERIOD_MS' x 'ipconfigMAX_ND_AGE'. + * + * Units are derived from ipND_TIMER_PERIOD_MS, which is 10000 ms or 10 sec. + * So, a value of 150 is equal to 1500 seconds. + */ + +#ifndef ipconfigMAX_ND_AGE + #define ipconfigMAX_ND_AGE ( 150 ) +#endif + +#if ( ipconfigMAX_ND_AGE < 0 ) + #error ipconfigMAX_ND_AGE must be at least 0 +#endif + +#if ( ipconfigMAX_ND_AGE > UINT8_MAX ) + #error ipconfigMAX_ND_AGE overflows a uint8_t +#endif + +/*---------------------------------------------------------------------------*/ + /*===========================================================================*/ /* ND CONFIG */ /*===========================================================================*/ diff --git a/source/include/FreeRTOS_IP.h b/source/include/FreeRTOS_IP.h index 2423990ed..72516894c 100644 --- a/source/include/FreeRTOS_IP.h +++ b/source/include/FreeRTOS_IP.h @@ -439,10 +439,11 @@ BaseType_t xIsNetworkDownEventPending( void ); * be defined in a user module. */ BaseType_t xApplicationGetRandomNumber( uint32_t * pulNumber ); -/** @brief The pointer to buffer with packet waiting for resolution. This variable - * is defined in FreeRTOS_IP.c. - * This pointer is for internal use only. */ -extern NetworkBufferDescriptor_t * pxResolutionWaitingNetworkBuffer; +/** @brief The pointers to buffers with packet waiting for resolution. These variables + * are defined in FreeRTOS_IP.c. + * These pointers are for internal use only. */ +extern NetworkBufferDescriptor_t * pxARPWaitingNetworkBuffer; +extern NetworkBufferDescriptor_t * pxNDWaitingNetworkBuffer; #if ( ipconfigENABLE_BACKWARD_COMPATIBILITY == 1 ) #define xIPStackEvent_t IPStackEvent_t diff --git a/source/include/FreeRTOS_IP_Private.h b/source/include/FreeRTOS_IP_Private.h index 16fe1967d..c667f4d35 100644 --- a/source/include/FreeRTOS_IP_Private.h +++ b/source/include/FreeRTOS_IP_Private.h @@ -66,7 +66,7 @@ typedef enum eFrameProcessingResult eProcessBuffer, /* An Ethernet frame has a valid address - continue process its contents. */ eReturnEthernetFrame, /* The Ethernet frame contains an ARP or ICMP packet that can be returned to its source. */ eFrameConsumed, /* Processing the Ethernet packet contents resulted in the payload being sent to the stack. */ - eWaitingAddrRes /* Frame is awaiting resolution. */ + eWaitingResolution /* Frame is awaiting resolution. */ } eFrameProcessingResult_t; typedef enum @@ -75,17 +75,18 @@ typedef enum eNetworkDownEvent, /* 0: The network interface has been lost and/or needs [re]connecting. */ eNetworkRxEvent, /* 1: The network interface has queued a received Ethernet frame. */ eNetworkTxEvent, /* 2: Let the IP-task send a network packet. */ - eAddrResTimerEvent, /* 3: The resolution timer expired. */ - eStackTxEvent, /* 4: The software stack has queued a packet to transmit. */ - eDHCPEvent, /* 5: Process the DHCP state machine. */ - eTCPTimerEvent, /* 6: See if any TCP socket needs attention. */ - eTCPAcceptEvent, /* 7: Client API FreeRTOS_accept() waiting for client connections. */ - eTCPNetStat, /* 8: IP-task is asked to produce a netstat listing. */ - eSocketBindEvent, /* 9: Send a message to the IP-task to bind a socket to a port. */ - eSocketCloseEvent, /*10: Send a message to the IP-task to close a socket. */ - eSocketSelectEvent, /*11: Send a message to the IP-task for select(). */ - eSocketSignalEvent, /*12: A socket must be signalled. */ - eSocketSetDeleteEvent /*13: A socket set must be deleted. */ + eARPTimerEvent, /* 3: The ARP timer expired. */ + eNDTimerEvent, /* 4: The ND timer expired. */ + eStackTxEvent, /* 5: The software stack has queued a packet to transmit. */ + eDHCPEvent, /* 6: Process the DHCP state machine. */ + eTCPTimerEvent, /* 7: See if any TCP socket needs attention. */ + eTCPAcceptEvent, /* 8: Client API FreeRTOS_accept() waiting for client connections. */ + eTCPNetStat, /* 9: IP-task is asked to produce a netstat listing. */ + eSocketBindEvent, /*10: Send a message to the IP-task to bind a socket to a port. */ + eSocketCloseEvent, /*11: Send a message to the IP-task to close a socket. */ + eSocketSelectEvent, /*12: Send a message to the IP-task for select(). */ + eSocketSignalEvent, /*13: A socket must be signalled. */ + eSocketSetDeleteEvent /*14: A socket set must be deleted. */ } eIPEvent_t; /** diff --git a/source/include/FreeRTOS_IP_Timers.h b/source/include/FreeRTOS_IP_Timers.h index f73e9c7e0..0c7328911 100644 --- a/source/include/FreeRTOS_IP_Timers.h +++ b/source/include/FreeRTOS_IP_Timers.h @@ -77,45 +77,49 @@ TickType_t xCalculateSleepTime( void ); */ void vIPSetTCPTimerExpiredState( BaseType_t xExpiredState ); +#if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) /** * Sets the reload time of an ARP timer and restarts it. */ -void vARPTimerReload( TickType_t xTime ); + void vARPTimerReload( TickType_t xTime ); /* * Start an ARP Resolution timer. */ -void vIPTimerStartARPResolution( TickType_t xTime ); + void vIPTimerStartARPResolution( TickType_t xTime ); /* * Enable/disable the ARP timer. */ -void vIPSetARPTimerEnableState( BaseType_t xEnableState ); + void vIPSetARPTimerEnableState( BaseType_t xEnableState ); /* * Enable or disable the ARP resolution timer. */ -void vIPSetARPResolutionTimerEnableState( BaseType_t xEnableState ); - -/** - * Sets the reload time of an ND timer and restarts it. - */ -void vNDTimerReload( TickType_t xTime ); - -/* - * Start an ND Resolution timer. - */ -void vIPTimerStartNDResolution( TickType_t xTime ); - -/* - * Enable/disable the ND timer. - */ -void vIPSetNDTimerEnableState( BaseType_t xEnableState ); + void vIPSetARPResolutionTimerEnableState( BaseType_t xEnableState ); +#endif -/* - * Enable or disable the ARP resolution timer. - */ -void vIPSetNDResolutionTimerEnableState( BaseType_t xEnableState ); +#if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + /** + * Sets the reload time of an ND timer and restarts it. + */ + void vNDTimerReload( TickType_t xTime ); + + /* + * Start an ND Resolution timer. + */ + void vIPTimerStartNDResolution( TickType_t xTime ); + + /* + * Enable/disable the ND timer. + */ + void vIPSetNDTimerEnableState( BaseType_t xEnableState ); + + /* + * Enable or disable the ARP resolution timer. + */ + void vIPSetNDResolutionTimerEnableState( BaseType_t xEnableState ); +#endif #if ( ipconfigUSE_DHCP == 1 ) || ( ipconfigUSE_RA == 1 ) diff --git a/source/include/FreeRTOS_ND.h b/source/include/FreeRTOS_ND.h index 5f1771eee..9ca2d32af 100644 --- a/source/include/FreeRTOS_ND.h +++ b/source/include/FreeRTOS_ND.h @@ -209,6 +209,8 @@ /* Clear all entries in the ND cache. */ void FreeRTOS_ClearND( const struct xNetworkEndPoint * pxEndPoint ); + void vNDSendUnsolicited( void ); + extern const uint8_t pcLOCAL_ALL_NODES_MULTICAST_IP[ ipSIZE_OF_IPv6_ADDRESS ]; extern const uint8_t pcLOCAL_ALL_NODES_MULTICAST_MAC[ ipMAC_ADDRESS_LENGTH_BYTES ]; diff --git a/source/include/IPTraceMacroDefaults.h b/source/include/IPTraceMacroDefaults.h index c9fd6eac6..fa2b17fd0 100644 --- a/source/include/IPTraceMacroDefaults.h +++ b/source/include/IPTraceMacroDefaults.h @@ -129,7 +129,7 @@ * [re]connecting. * eNetworkRxEvent - The network interface has queued a received Ethernet * frame. - * eResolutionTimerEvent - The Resolution timer expired. + * eARPTimerEvent - The Resolution timer expired. * eStackTxEvent - The software stack has queued a packet to transmit. * eDHCPEvent - Process the DHCP state machine. * @@ -610,6 +610,18 @@ /*---------------------------------------------------------------------------*/ +/* + * iptraceDELAYED_ND_BUFFER_FULL + * + * A packet has come in from an unknown IPv6 address. An ND request has been + * sent, but the queue is still filled with a different packet. + */ +#ifndef iptraceDELAYED_ND_BUFFER_FULL + #define iptraceDELAYED_ND_BUFFER_FULL() +#endif + +/*---------------------------------------------------------------------------*/ + /* * iptrace_DELAYED_ND_REQUEST_REPLIED */ @@ -619,6 +631,30 @@ /*---------------------------------------------------------------------------*/ +/* + * iptraceDELAYED_ND_REQUEST_STARTED + * + * A packet came in from an unknown IPv6 address. An ND request has been sent + * and the network buffer is stored for processing later. + */ +#ifndef iptraceDELAYED_ND_REQUEST_STARTED + #define iptraceDELAYED_ND_REQUEST_STARTED() +#endif + +/*---------------------------------------------------------------------------*/ + +/* + * iptraceDELAYED_ND_TIMER_EXPIRED + * + * A packet was stored for delayed processing, but there is no ND reply. The + * network buffer will be released without being processed. + */ +#ifndef iptraceDELAYED_ND_TIMER_EXPIRED + #define iptraceDELAYED_ND_TIMER_EXPIRED() +#endif + +/*---------------------------------------------------------------------------*/ + /*===========================================================================*/ /* ND TRACE MACROS */ /*===========================================================================*/ diff --git a/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_stubs.c b/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_stubs.c index 52e1a290a..ac2dae11f 100644 --- a/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_stubs.c +++ b/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_stubs.c @@ -14,10 +14,10 @@ /* =========================== EXTERN VARIABLES =========================== */ -/** @brief The pointer to buffer with packet waiting for ARP resolution. This variable +/** @brief The pointer to buffer with packet waiting for ND resolution. This variable * is defined in FreeRTOS_IP.c. * This pointer is for internal use only. */ -NetworkBufferDescriptor_t * pxARPWaitingNetworkBuffer; +NetworkBufferDescriptor_t * pxNDWaitingNetworkBuffer; BaseType_t NetworkInterfaceOutputFunction_Stub_Called = 0; diff --git a/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c b/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c index 084866a1c..672bfac25 100644 --- a/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c +++ b/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c @@ -43,7 +43,6 @@ #include "mock_queue.h" #include "mock_event_groups.h" -#include "mock_FreeRTOS_ARP.h" #include "mock_FreeRTOS_IP.h" #include "mock_FreeRTOS_IPv6.h" #include "mock_FreeRTOS_IP_Private.h" @@ -523,7 +522,7 @@ void test_vNDRefreshCacheEntry_NoMatchingEntryAdd( void ) /* Since no matching entry will be found, 0th entry will be updated to have the below details. */ vNDRefreshCacheEntry( &xMACAddress, &xIPAddress, &xEndPoint ); - TEST_ASSERT_EQUAL( xNDCache[ xUseEntry ].ucAge, ( uint8_t ) ipconfigMAX_ARP_AGE ); + TEST_ASSERT_EQUAL( xNDCache[ xUseEntry ].ucAge, ( uint8_t ) ipconfigMAX_ND_AGE ); TEST_ASSERT_EQUAL( xNDCache[ xUseEntry ].ucValid, pdTRUE ); TEST_ASSERT_EQUAL_MEMORY( xNDCache[ xUseEntry ].xIPAddress.ucBytes, xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); TEST_ASSERT_EQUAL_MEMORY( xNDCache[ xUseEntry ].xMACAddress.ucBytes, xMACAddress.ucBytes, sizeof( MACAddress_t ) ); @@ -550,7 +549,7 @@ void test_vNDRefreshCacheEntry_MatchingEntryRefresh( void ) /* Since a matching entry is found at xUseEntry = 1st location, the entry will be refreshed.*/ vNDRefreshCacheEntry( &xMACAddress, &xIPAddress, &xEndPoint ); - TEST_ASSERT_EQUAL( xNDCache[ xUseEntry ].ucAge, ( uint8_t ) ipconfigMAX_ARP_AGE ); + TEST_ASSERT_EQUAL( xNDCache[ xUseEntry ].ucAge, ( uint8_t ) ipconfigMAX_ND_AGE ); TEST_ASSERT_EQUAL_MEMORY( xNDCache[ xUseEntry ].xMACAddress.ucBytes, xMACAddress.ucBytes, sizeof( MACAddress_t ) ); TEST_ASSERT_EQUAL_MEMORY( xNDCache[ xUseEntry ].pxEndPoint, &xEndPoint, sizeof( NetworkEndPoint_t ) ); } @@ -1546,7 +1545,7 @@ void test_prvProcessICMPMessage_IPv6_NeighborSolicitation( void ) /** * @brief This function process ICMP message when message type is * ipICMP_NEIGHBOR_ADVERTISEMENT_IPv6. - * It handles case when pxARPWaitingNetworkBuffer is NULL. + * It handles case when pxNDWaitingNetworkBuffer is NULL. */ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement1( void ) { @@ -1560,7 +1559,7 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement1( void ) pxNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xICMPPacket; pxNetworkBuffer->pxEndPoint = &xEndPoint; xICMPPacket.xICMPHeaderIPv6.ucTypeOfMessage = ipICMP_NEIGHBOR_ADVERTISEMENT_IPv6; - pxARPWaitingNetworkBuffer = NULL; + pxNDWaitingNetworkBuffer = NULL; eReturn = prvProcessICMPMessage_IPv6( pxNetworkBuffer ); @@ -1580,14 +1579,14 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement2( void ) ICMPHeader_IPv6_t * pxICMPHeader_IPv6 = ( ( ICMPHeader_IPv6_t * ) &( xICMPPacket.xICMPHeaderIPv6 ) ); NetworkEndPoint_t xEndPoint; eFrameProcessingResult_t eReturn; - NetworkBufferDescriptor_t xARPWaitingNetworkBuffer; + NetworkBufferDescriptor_t xNDWaitingNetworkBuffer; xEndPoint.bits.bIPv6 = pdTRUE_UNSIGNED; pxNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xICMPPacket; pxNetworkBuffer->pxEndPoint = &xEndPoint; xICMPPacket.xICMPHeaderIPv6.ucTypeOfMessage = ipICMP_NEIGHBOR_ADVERTISEMENT_IPv6; - pxARPWaitingNetworkBuffer = &xARPWaitingNetworkBuffer; + pxNDWaitingNetworkBuffer = &xNDWaitingNetworkBuffer; uxIPHeaderSizePacket_IgnoreAndReturn( ipSIZE_OF_IPv4_HEADER ); eReturn = prvProcessICMPMessage_IPv6( pxNetworkBuffer ); @@ -1598,7 +1597,7 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement2( void ) /** * @brief This function process ICMP message when message type is * ipICMP_NEIGHBOR_ADVERTISEMENT_IPv6. - * This verifies a case 'pxARPWaitingNetworkBuffer' was + * This verifies a case 'pxNDWaitingNetworkBuffer' was * not waiting for this new address look-up. */ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement3( void ) @@ -1608,12 +1607,12 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement3( void ) ICMPHeader_IPv6_t * pxICMPHeader_IPv6 = ( ( ICMPHeader_IPv6_t * ) &( xICMPPacket.xICMPHeaderIPv6 ) ); NetworkEndPoint_t xEndPoint; eFrameProcessingResult_t eReturn; - NetworkBufferDescriptor_t xARPWaitingNetworkBuffer; + NetworkBufferDescriptor_t xNDWaitingNetworkBuffer; IPPacket_IPv6_t xIPPacket; IPHeader_IPv6_t * pxIPHeader = &( xIPPacket.xIPHeader ); - pxARPWaitingNetworkBuffer = &xARPWaitingNetworkBuffer; - pxARPWaitingNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xIPPacket; + pxNDWaitingNetworkBuffer = &xNDWaitingNetworkBuffer; + pxNDWaitingNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xIPPacket; xEndPoint.bits.bIPv6 = pdTRUE_UNSIGNED; pxNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xICMPPacket; pxNetworkBuffer->pxEndPoint = &xEndPoint; @@ -1632,7 +1631,7 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement3( void ) * ipICMP_NEIGHBOR_ADVERTISEMENT_IPv6. * This verifies a case where a packet is handled as a new * incoming IP packet when a neighbour advertisement has been received, - * and 'pxARPWaitingNetworkBuffer' was waiting for this new address look-up. + * and 'pxNDWaitingNetworkBuffer' was waiting for this new address look-up. */ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement4( void ) { @@ -1641,12 +1640,12 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement4( void ) ICMPHeader_IPv6_t * pxICMPHeader_IPv6 = ( ( ICMPHeader_IPv6_t * ) &( xICMPPacket.xICMPHeaderIPv6 ) ); NetworkEndPoint_t xEndPoint; eFrameProcessingResult_t eReturn; - NetworkBufferDescriptor_t xARPWaitingNetworkBuffer; + NetworkBufferDescriptor_t xNDWaitingNetworkBuffer; IPPacket_IPv6_t xIPPacket; IPHeader_IPv6_t * pxIPHeader = &( xIPPacket.xIPHeader ); - pxARPWaitingNetworkBuffer = &xARPWaitingNetworkBuffer; - pxARPWaitingNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xIPPacket; + pxNDWaitingNetworkBuffer = &xNDWaitingNetworkBuffer; + pxNDWaitingNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xIPPacket; xEndPoint.bits.bIPv6 = pdTRUE_UNSIGNED; pxNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xICMPPacket; @@ -1659,12 +1658,12 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement4( void ) uxIPHeaderSizePacket_IgnoreAndReturn( ipSIZE_OF_IPv6_HEADER ); xSendEventStructToIPTask_IgnoreAndReturn( pdFAIL ); vReleaseNetworkBufferAndDescriptor_Ignore(); - vIPSetARPResolutionTimerEnableState_ExpectAnyArgs(); + vIPSetNDResolutionTimerEnableState_ExpectAnyArgs(); eReturn = prvProcessICMPMessage_IPv6( pxNetworkBuffer ); TEST_ASSERT_EQUAL( eReturn, eReleaseBuffer ); - TEST_ASSERT_EQUAL( pxARPWaitingNetworkBuffer, NULL ); + TEST_ASSERT_EQUAL( pxNDWaitingNetworkBuffer, NULL ); } /** @@ -1672,7 +1671,7 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement4( void ) * ipICMP_NEIGHBOR_ADVERTISEMENT_IPv6. * This verifies a case where a packet is handled as a new * incoming IP packet when a neighbour advertisement has been received, - * and 'pxARPWaitingNetworkBuffer' was waiting for this new address look-up. + * and 'pxNDWaitingNetworkBuffer' was waiting for this new address look-up. */ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement5( void ) { @@ -1681,12 +1680,12 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement5( void ) ICMPHeader_IPv6_t * pxICMPHeader_IPv6 = ( ( ICMPHeader_IPv6_t * ) &( xICMPPacket.xICMPHeaderIPv6 ) ); NetworkEndPoint_t xEndPoint; eFrameProcessingResult_t eReturn; - NetworkBufferDescriptor_t xARPWaitingNetworkBuffer; + NetworkBufferDescriptor_t xNDWaitingNetworkBuffer; IPPacket_IPv6_t xIPPacket; IPHeader_IPv6_t * pxIPHeader = &( xIPPacket.xIPHeader ); - pxARPWaitingNetworkBuffer = &xARPWaitingNetworkBuffer; - pxARPWaitingNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xIPPacket; + pxNDWaitingNetworkBuffer = &xNDWaitingNetworkBuffer; + pxNDWaitingNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xIPPacket; xEndPoint.bits.bIPv6 = pdTRUE_UNSIGNED; pxNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xICMPPacket; @@ -1698,12 +1697,12 @@ void test_prvProcessICMPMessage_IPv6_NeighborAdvertisement5( void ) uxIPHeaderSizePacket_IgnoreAndReturn( ipSIZE_OF_IPv6_HEADER ); xSendEventStructToIPTask_IgnoreAndReturn( pdPASS ); - vIPSetARPResolutionTimerEnableState_ExpectAnyArgs(); + vIPSetNDResolutionTimerEnableState_ExpectAnyArgs(); eReturn = prvProcessICMPMessage_IPv6( pxNetworkBuffer ); TEST_ASSERT_EQUAL( eReturn, eReleaseBuffer ); - TEST_ASSERT_EQUAL( pxARPWaitingNetworkBuffer, NULL ); + TEST_ASSERT_EQUAL( pxNDWaitingNetworkBuffer, NULL ); } /** diff --git a/test/unit-test/FreeRTOS_ND/ut.cmake b/test/unit-test/FreeRTOS_ND/ut.cmake index 9e113d158..09fbf7bc2 100644 --- a/test/unit-test/FreeRTOS_ND/ut.cmake +++ b/test/unit-test/FreeRTOS_ND/ut.cmake @@ -14,7 +14,6 @@ list(APPEND mock_list "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/list.h" "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/queue.h" "${MODULE_ROOT_DIR}/test/FreeRTOS-Kernel/include/event_groups.h" - "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ARP.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Private.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IPv6.h" @@ -113,4 +112,4 @@ create_test(${utest_name} "${utest_link_list}" "${utest_dep_list}" "${test_include_directories}" - ) \ No newline at end of file + )