diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index 8ed81640dc..c7ebe1866c 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -1260,7 +1260,8 @@ * @param[out] pxIPAddress The location where the new IPv6 address will be stored. * @param[in] pxPrefix The prefix to be used. * @param[in] uxPrefixLength The length of the prefix. - * @param[in] xDoRandom A non-zero value if the bits after the prefix should have a random value. + * @param[in] pxHost: Host part of the address. It will be filled with + * a random value if NULL. * * @return pdPASS if the operation was successful. Or pdFAIL in case xApplicationGetRandomNumber() * returned an error. @@ -1268,13 +1269,13 @@ BaseType_t FreeRTOS_CreateIPv6Address( IPv6_Address_t * pxIPAddress, const IPv6_Address_t * pxPrefix, size_t uxPrefixLength, - BaseType_t xDoRandom ) + const IPv6_Address_t * pxHost ) { - uint32_t pulRandom[ 4 ]; + uint32_t pulRandom[ ipSIZE_OF_IPv6_ADDRESS / sizeof( uint32_t ) ]; uint8_t * pucSource; BaseType_t xIndex, xResult = pdPASS; - if( xDoRandom != pdFALSE ) + if( pxHost == NULL ) { /* Create an IP-address, based on a net prefix and a * random host address. @@ -1292,7 +1293,7 @@ } else { - ( void ) memset( pulRandom, 0, sizeof( pulRandom ) ); + ( void ) memcpy( pulRandom, pxHost->ucBytes, ipSIZE_OF_IPv6_ADDRESS ); } if( xResult == pdPASS ) @@ -1317,14 +1318,13 @@ uint8_t ucNetMask = ( uint8_t ) ~( uxHostMask ); pxIPAddress->ucBytes[ uxIndex ] &= ucNetMask; - pxIPAddress->ucBytes[ uxIndex ] |= ( pucSource[ 0 ] & ( ( uint8_t ) uxHostMask ) ); - pucSource = &( pucSource[ 1 ] ); + pxIPAddress->ucBytes[ uxIndex ] |= ( pucSource[ uxIndex ] & ( ( uint8_t ) uxHostMask ) ); uxIndex++; } if( uxIndex < ipSIZE_OF_IPv6_ADDRESS ) { - ( void ) memcpy( &( pxIPAddress->ucBytes[ uxIndex ] ), pucSource, ipSIZE_OF_IPv6_ADDRESS - uxIndex ); + ( void ) memcpy( &( pxIPAddress->ucBytes[ uxIndex ] ), &pucSource[ uxIndex ], ipSIZE_OF_IPv6_ADDRESS - uxIndex ); } } diff --git a/source/FreeRTOS_RA.c b/source/FreeRTOS_RA.c index 9b0afc73fd..fce9a2ae86 100644 --- a/source/FreeRTOS_RA.c +++ b/source/FreeRTOS_RA.c @@ -412,7 +412,7 @@ pxEndPoint->xRAData.bits.bRouterReplied = pdTRUE_UNSIGNED; pxEndPoint->xRAData.uxRetryCount = 0U; pxEndPoint->xRAData.ulPreferredLifeTime = FreeRTOS_ntohl( pxPrefixOption->ulPreferredLifeTime ); - /* Force taking a new random IP-address. */ + /* Force taking a new IP-address. */ pxEndPoint->xRAData.bits.bIPAddressInUse = pdTRUE_UNSIGNED; pxEndPoint->xRAData.eRAState = eRAStateIPTest; vRAProcess( pdFALSE, pxEndPoint ); @@ -521,6 +521,29 @@ return uxNewReloadTime; } + +/*-----------------------------------------------------------*/ + +/** + * @brief Assign an EUI64 address based on MAC address + * + * @param[out] pxIPAddress The assigned IPv6 address. + * @param[in] pxMACAddress The MAC address of the interface. + */ + static void vRAProcessAssignEUI64( IPv6_Address_t * pxIPAddress, + const MACAddress_t * pxMACAddress ) + { + memset( pxIPAddress, 0, sizeof( IPv6_Address_t ) ); + pxIPAddress->ucBytes[ 8 ] = pxMACAddress->ucBytes[ 0 ] ^ 0x2; + pxIPAddress->ucBytes[ 9 ] = pxMACAddress->ucBytes[ 1 ]; + pxIPAddress->ucBytes[ 10 ] = pxMACAddress->ucBytes[ 2 ]; + pxIPAddress->ucBytes[ 11 ] = 0xff; + pxIPAddress->ucBytes[ 12 ] = 0xfe; + pxIPAddress->ucBytes[ 13 ] = pxMACAddress->ucBytes[ 3 ]; + pxIPAddress->ucBytes[ 14 ] = pxMACAddress->ucBytes[ 4 ]; + pxIPAddress->ucBytes[ 15 ] = pxMACAddress->ucBytes[ 5 ]; + } + /*-----------------------------------------------------------*/ /** @@ -571,15 +594,25 @@ { size_t uxNeededSize; NetworkBufferDescriptor_t * pxNetworkBuffer; + IPv6_Address_t xIPAddress; + IPv6_Address_t * pxIPAddress; + + pxIPAddress = NULL; /* Get an IP-address, using the network prefix and a random host address. */ if( pxEndPoint->xRAData.bits.bIPAddressInUse != 0U ) { pxEndPoint->xRAData.bits.bIPAddressInUse = pdFALSE_UNSIGNED; - ( void ) FreeRTOS_CreateIPv6Address( &pxEndPoint->ipv6_settings.xIPAddress, &pxEndPoint->ipv6_settings.xPrefix, pxEndPoint->ipv6_settings.uxPrefixLength, pdTRUE ); + if( pxEndPoint->bits.bWantEUI64 != pdFALSE_UNSIGNED ) + { + pxIPAddress = &xIPAddress; + vRAProcessAssignEUI64( pxIPAddress, &pxEndPoint->xMACAddress ); + } + + ( void ) FreeRTOS_CreateIPv6Address( &pxEndPoint->ipv6_settings.xIPAddress, &pxEndPoint->ipv6_settings.xPrefix, pxEndPoint->ipv6_settings.uxPrefixLength, pxIPAddress ); - FreeRTOS_printf( ( "RA: Creating a random IP-address\n" ) ); + FreeRTOS_printf( ( "RA: Creating an IP-address\n" ) ); } FreeRTOS_printf( ( "RA: Neighbour solicitation for %pip\n", ( void * ) pxEndPoint->ipv6_settings.xIPAddress.ucBytes ) ); diff --git a/source/include/FreeRTOS_ND.h b/source/include/FreeRTOS_ND.h index 3b78461e91..ee66869b2a 100644 --- a/source/include/FreeRTOS_ND.h +++ b/source/include/FreeRTOS_ND.h @@ -160,14 +160,14 @@ #endif /** - * @brief Create an IPv16 address, based on a prefix. + * @brief Create an IPv6 address, based on a prefix. * * @param[out] pxIPAddress: The location where the new IPv6 address * will be stored. * @param[in] pxPrefix: The prefix to be used. * @param[in] uxPrefixLength: The length of the prefix. - * @param[in] xDoRandom: A non-zero value if the bits after the - * prefix should have a random value. + * @param[in] pxHost: Host part of the address. It will be filled with + * a random value if NULL. * * @return pdPASS if the operation was successful. Or pdFAIL in * case xApplicationGetRandomNumber() @@ -176,7 +176,7 @@ BaseType_t FreeRTOS_CreateIPv6Address( IPv6_Address_t * pxIPAddress, const IPv6_Address_t * pxPrefix, size_t uxPrefixLength, - BaseType_t xDoRandom ); + const IPv6_Address_t * pxHost ); /* Receive a Neighbour Advertisement. */ diff --git a/source/include/FreeRTOS_Routing.h b/source/include/FreeRTOS_Routing.h index 0fa9fab88e..783b4e3926 100644 --- a/source/include/FreeRTOS_Routing.h +++ b/source/include/FreeRTOS_Routing.h @@ -200,6 +200,7 @@ #endif /* ipconfigUSE_DHCP */ #if ( ipconfigUSE_RA != 0 ) bWantRA : 1, /**< This end-point wants to use RA/SLAAC to obtain an IP-address. */ + bWantEUI64 : 1, /**< This end-point wants to use EUI64 for IP-address generation. */ #endif /* ipconfigUSE_RA */ bIPv6 : 1, /**< This end-point has an IP-address of type IPv6. */ #if ( ipconfigUSE_NETWORK_EVENT_HOOK != 0 ) diff --git a/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c b/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c index 4c3fda8ff8..3e6bf51032 100644 --- a/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c +++ b/test/unit-test/FreeRTOS_ND/FreeRTOS_ND_utest.c @@ -1834,12 +1834,12 @@ void test_FreeRTOS_OutputAdvertiseIPv6_HappyPath( void ) */ void test_FreeRTOS_CreateIPv6Address_RandomFail( void ) { - IPv6_Address_t xIPAddress, xPrefix = { 0 }; - BaseType_t xDoRandom = pdTRUE, xReturn; + IPv6_Address_t xIPAddress, xPrefix = { 0 }, * pxHost = NULL; + BaseType_t xReturn; xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdFALSE ); - xReturn = FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, sizeof( xPrefix ), xDoRandom ); + xReturn = FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, sizeof( xPrefix ), pxHost ); TEST_ASSERT_EQUAL( xReturn, pdFAIL ); } @@ -1851,30 +1851,30 @@ void test_FreeRTOS_CreateIPv6Address_RandomFail( void ) */ void test_FreeRTOS_CreateIPv6Address_Assert1( void ) { - IPv6_Address_t xIPAddress, xPrefix = { 0 }; - BaseType_t xDoRandom = pdTRUE, xReturn, xIndex; + IPv6_Address_t xIPAddress, xPrefix = { 0 }, * pxHost = NULL; + BaseType_t xReturn, xIndex; for( xIndex = 0; xIndex < 4; xIndex++ ) { xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); } - catch_assert( FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, 0, xDoRandom ) ); + catch_assert( FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, 0, pxHost ) ); } /** * @brief Create an IPv6 address, based on a prefix. - * with the bits after the prefix having random value - * but incorrect prefix length and xDoRandom is 0. + * with the bits after the prefix having a specified value + * but incorrect prefix length. */ void test_FreeRTOS_CreateIPv6Address_Assert2( void ) { - IPv6_Address_t xIPAddress, xPrefix; + IPv6_Address_t xIPAddress, xPrefix, xHost = { 0 }; /* The maximum allowed prefix length was increased to 128 because of the loopback address. */ size_t uxPrefixLength = 8U * ipSIZE_OF_IPv6_ADDRESS + 1; - BaseType_t xDoRandom = pdFALSE, xReturn, xIndex; + BaseType_t xReturn, xIndex; - catch_assert( FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, uxPrefixLength, xDoRandom ) ); + catch_assert( FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, uxPrefixLength, &xHost ) ); } /** @@ -1883,16 +1883,16 @@ void test_FreeRTOS_CreateIPv6Address_Assert2( void ) */ void test_FreeRTOS_CreateIPv6Address_Pass1( void ) { - IPv6_Address_t xIPAddress, xPrefix; + IPv6_Address_t xIPAddress, xPrefix, * pxHost = NULL; size_t uxPrefixLength = 8U; - BaseType_t xDoRandom = pdTRUE, xReturn, xIndex; + BaseType_t xReturn, xIndex; for( xIndex = 0; xIndex < 4; xIndex++ ) { xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); } - xReturn = FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, uxPrefixLength, xDoRandom ); + xReturn = FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, uxPrefixLength, pxHost ); TEST_ASSERT_EQUAL( xReturn, pdPASS ); } @@ -1904,7 +1904,7 @@ void test_FreeRTOS_CreateIPv6Address_Pass1( void ) */ void test_FreeRTOS_CreateIPv6Address_Pass2( void ) { - IPv6_Address_t xIPAddress, xPrefix; + IPv6_Address_t xIPAddress, xPrefix, * pxHost = NULL; size_t uxPrefixLength = 7; BaseType_t xDoRandom = pdTRUE, xReturn, xIndex; @@ -1913,7 +1913,7 @@ void test_FreeRTOS_CreateIPv6Address_Pass2( void ) xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); } - xReturn = FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, uxPrefixLength, xDoRandom ); + xReturn = FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, uxPrefixLength, pxHost ); TEST_ASSERT_EQUAL( xReturn, pdPASS ); } @@ -1925,7 +1925,7 @@ void test_FreeRTOS_CreateIPv6Address_Pass2( void ) */ void test_FreeRTOS_CreateIPv6Address_Pass3( void ) { - IPv6_Address_t xIPAddress, xPrefix; + IPv6_Address_t xIPAddress, xPrefix, * pxHost = NULL; size_t uxPrefixLength = 128; BaseType_t xDoRandom = pdTRUE, xReturn, xIndex; @@ -1934,7 +1934,7 @@ void test_FreeRTOS_CreateIPv6Address_Pass3( void ) xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); } - xReturn = FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, uxPrefixLength, xDoRandom ); + xReturn = FreeRTOS_CreateIPv6Address( &xIPAddress, &xPrefix, uxPrefixLength, pxHost ); TEST_ASSERT_EQUAL( xReturn, pdPASS ); } diff --git a/test/unit-test/FreeRTOS_RA/FreeRTOS_RA_stubs.c b/test/unit-test/FreeRTOS_RA/FreeRTOS_RA_stubs.c index e88ec77474..a35b6e3b04 100644 --- a/test/unit-test/FreeRTOS_RA/FreeRTOS_RA_stubs.c +++ b/test/unit-test/FreeRTOS_RA/FreeRTOS_RA_stubs.c @@ -45,8 +45,8 @@ eResolutionLookupResult_t eNDGetCacheEntry( IPv6_Address_t * pxIPAddress, * will be stored. * @param[in] pxPrefix: The prefix to be used. * @param[in] uxPrefixLength: The length of the prefix. - * @param[in] xDoRandom: A non-zero value if the bits after the - * prefix should have a random value. + * @param[in] pxHost: Host part of the address. It will be filled with + * a random value if NULL. * * @return pdPASS if the operation was successful. Or pdFAIL in * case xApplicationGetRandomNumber() @@ -55,7 +55,7 @@ eResolutionLookupResult_t eNDGetCacheEntry( IPv6_Address_t * pxIPAddress, BaseType_t FreeRTOS_CreateIPv6Address( IPv6_Address_t * pxIPAddress, const IPv6_Address_t * pxPrefix, size_t uxPrefixLength, - BaseType_t xDoRandom ) + const IPv6_Address_t * pxHost ) { } diff --git a/test/unit-test/FreeRTOS_RA/FreeRTOS_RA_utest.c b/test/unit-test/FreeRTOS_RA/FreeRTOS_RA_utest.c index e39fb67eae..12e2e8e181 100644 --- a/test/unit-test/FreeRTOS_RA/FreeRTOS_RA_utest.c +++ b/test/unit-test/FreeRTOS_RA/FreeRTOS_RA_utest.c @@ -959,6 +959,56 @@ void test_vReceiveRA_vRAProcess( void ) TEST_ASSERT_EQUAL( eRAStateIPWait, pxEndPoint->xRAData.eRAState ); } +/** + * @brief This function verify vReceiveRA success case for an EUI64 address. + */ +void test_vReceiveRA_vRAProcess_EUI64( void ) +{ + NetworkBufferDescriptor_t * pxNetworkBuffer, xNetworkBuffer; + EthernetPacketICMPv6RouterAdvertisementPrefixOption_t xICMPPacket; + NetworkInterface_t xInterface; + NetworkEndPoint_t xEndPoint, * pxEndPoint = &xEndPoint; + ICMPPrefixOption_IPv6_t * pxPrefixOption; + ICMPRouterAdvertisement_IPv6_t * pxAdvertisement; + + memset( &xNetworkBuffer, 0, sizeof( NetworkBufferDescriptor_t ) ); + memset( &xICMPPacket, 0, sizeof( xICMPPacket ) ); + memset( &xInterface, 0, sizeof( NetworkInterface_t ) ); + memset( &xEndPoint, 0, sizeof( NetworkEndPoint_t ) ); + + pxNetworkBuffer = &xNetworkBuffer; + pxNetworkBuffer->pucEthernetBuffer = ( uint8_t * ) &xICMPPacket; + pxNetworkBuffer->pxInterface = &xInterface; + pxNetworkBuffer->xDataLength = raHeaderBytesRA + raPrefixOptionlen; + pxAdvertisement = &xICMPPacket.xAdvertisement; + pxAdvertisement->usLifetime = pdTRUE_UNSIGNED; + + pxPrefixOption = &xICMPPacket.xPrefixOption; + pxPrefixOption->ucType = ndICMP_PREFIX_INFORMATION; + /* Only 1 option */ + pxPrefixOption->ucLength = 1; + + pxEndPoint->bits.bWantRA = pdTRUE_UNSIGNED; + pxEndPoint->bits.bWantEUI64 = pdTRUE_UNSIGNED; + pxEndPoint->xRAData.eRAState = eRAStateWait; + + FreeRTOS_FirstEndPoint_ExpectAnyArgsAndReturn( pxEndPoint ); + FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); + + pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); + vDHCP_RATimerReload_ExpectAnyArgs(); + + vReceiveRA( pxNetworkBuffer ); + + + TEST_ASSERT_EQUAL( pxEndPoint->ipv6_settings.uxPrefixLength, pxPrefixOption->ucPrefixLength ); + TEST_ASSERT_EQUAL( pdTRUE_UNSIGNED, pxEndPoint->xRAData.bits.bRouterReplied ); + TEST_ASSERT_EQUAL( 0, pxEndPoint->xRAData.uxRetryCount ); + TEST_ASSERT_EQUAL( FreeRTOS_ntohl( pxPrefixOption->ulPreferredLifeTime ), pxEndPoint->xRAData.ulPreferredLifeTime ); + TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, pxEndPoint->xRAData.bits.bIPAddressInUse ); + TEST_ASSERT_EQUAL( eRAStateIPWait, pxEndPoint->xRAData.eRAState ); +} + /** * @brief This function verify RA state machine * with RA NULL endpoint.