From 84eda02a86d68e20c742e249af3394ebe0a38801 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Wed, 20 Dec 2023 14:30:38 -0500 Subject: [PATCH 01/18] Adds ipconfigMAC_FILTERING that when enabled, adds two MAC manipulation functions to NetworkInterface_t Adds documentation and design notes for the MAC filtering functions of the SAME70 network driver. Exposes pcLOCAL_ALL_NODES_MULTICAST_MAC[ ipMAC_ADDRESS_LENGTH_BYTES ] so that network drivers can add it to the received multicast addresses during initialization. Adds functions to the SAME70 network driver that allow modification of what MAC addresses are being received by the hardware. This implementation utilizes the 4 specific match registers and the 64bit hash match register that are present in the SAME70/V71 microcontrollers. Registes the mDNS address when the SAME70 network driver is initialized. Moves the registering of the solicited-node multicast address from the network driver to vIPNetworkUpCalls() Adds 'U' to some uint8_t[] initializers --- source/FreeRTOS_IP.c | 32 ++ source/FreeRTOS_IP_Utils.c | 32 ++ source/FreeRTOS_ND.c | 4 +- source/include/FreeRTOSIPConfigDefaults.h | 15 + source/include/FreeRTOS_ND.h | 1 + source/include/FreeRTOS_Routing.h | 24 ++ .../DriverSAM/NetworkInterface.c | 352 ++++++++++++++++-- 7 files changed, 417 insertions(+), 43 deletions(-) diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index f412e914ff..fe90f8885e 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -631,6 +631,38 @@ TaskHandle_t FreeRTOS_GetIPTaskHandle( void ) */ void vIPNetworkUpCalls( struct xNetworkEndPoint * pxEndPoint ) { + #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) + { + IPv6_Type_t xAddressType; + + if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) + { + /* Now that the network is up, pxEndPoint->ipv6_settings should hold the actual address of this + * end-point. For unicast addresses, generate the respective solicited-node multicast address. + * Note that the check below guards against the loopback address, the unspecified address, + * and against the weird scenario of someone assigning a multicast address to the end-point. */ + xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + + if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) + { + /* Tell the network driver to begin receiving this MAC address */ + if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) + { + MACAddress_t xMACAddress = { { + 0x33U, + 0x33U, + 0xFFU, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + } }; + pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); + } + } /* if( xAddressType == ... ) */ + } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ + } + #endif /* ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) */ + pxEndPoint->bits.bEndPointUp = pdTRUE_UNSIGNED; #if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 ) diff --git a/source/FreeRTOS_IP_Utils.c b/source/FreeRTOS_IP_Utils.c index 906c2b6ba6..8771e32ccf 100644 --- a/source/FreeRTOS_IP_Utils.c +++ b/source/FreeRTOS_IP_Utils.c @@ -835,6 +835,38 @@ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ) { /* The bit 'bEndPointUp' stays low until vIPNetworkUpCalls() is called. */ pxEndPoint->bits.bEndPointUp = pdFALSE_UNSIGNED; + + #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) + { + IPv6_Type_t xAddressType; + + if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) + { + xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + + /* The check below guards against the loopback address, the unspecified address, + * and against the weird scenario of someone assigning a multicast address to the end-point. */ + if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) + { + /* Every network-up event adds the MAC address corresponding to this end-point's solicited node multicast address. + * Remove it here to balance out the number of add/remove calls. */ + if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) + { + MACAddress_t xMACAddress = { { + 0x33U, + 0x33U, + 0xFFU, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + } }; + pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); + } + } /* if( xAddressType == ... ) */ + } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ + } + #endif /* ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) */ + #if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 ) { if( pxEndPoint->bits.bCallDownHook != pdFALSE_UNSIGNED ) diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index dcbf4d6ebd..9b0ccc4d6e 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -77,9 +77,9 @@ /* MISRA Ref 8.9.1 [File scoped variables] */ /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */ /* coverity[misra_c_2012_rule_8_9_violation] */ - static const uint8_t pcLOCAL_ALL_NODES_MULTICAST_IP[ ipSIZE_OF_IPv6_ADDRESS ] = { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; /* ff02:1 */ + static const uint8_t pcLOCAL_ALL_NODES_MULTICAST_IP[ ipSIZE_OF_IPv6_ADDRESS ] = { 0xffU, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U }; /* ff02::1 */ /** @brief All nodes on the local network segment: MAC address. */ - static const uint8_t pcLOCAL_ALL_NODES_MULTICAST_MAC[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 }; + const uint8_t pcLOCAL_ALL_NODES_MULTICAST_MAC[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0x33U, 0x33U, 0x00U, 0x00U, 0x00U, 0x01U }; /** @brief See if the MAC-address can be resolved because it is a multi-cast address. */ static eARPLookupResult_t prvMACResolve( const IPv6_Address_t * pxAddressToLookup, diff --git a/source/include/FreeRTOSIPConfigDefaults.h b/source/include/FreeRTOSIPConfigDefaults.h index 33db82fc40..43e3e850a1 100644 --- a/source/include/FreeRTOSIPConfigDefaults.h +++ b/source/include/FreeRTOSIPConfigDefaults.h @@ -3295,6 +3295,21 @@ /*---------------------------------------------------------------------------*/ +/* + * ipconfigMAC_FILTERING + * + * Type: BaseType_t ( ipconfigENABLE | ipconfigDISABLE ) + * + * When set to ipconfigENABLE, this macro will adds two functions + * to the network interface. Those functions allow adding/removing multicast + * MAC addresses to/from the hardware EMAC. It is up to the portable network + * code to implement these as on the specific hardware. */ +#ifndef ipconfigMAC_FILTERING + #define ipconfigMAC_FILTERING ipconfigDISABLE +#endif + +/*---------------------------------------------------------------------------*/ + /* Should only be included here, ensures trace config is set first. */ #include "IPTraceMacroDefaults.h" diff --git a/source/include/FreeRTOS_ND.h b/source/include/FreeRTOS_ND.h index bdbabdec71..60cdbd396a 100644 --- a/source/include/FreeRTOS_ND.h +++ b/source/include/FreeRTOS_ND.h @@ -204,6 +204,7 @@ void FreeRTOS_PrintNDCache( void ); #endif + extern const uint8_t pcLOCAL_ALL_NODES_MULTICAST_MAC[ ipMAC_ADDRESS_LENGTH_BYTES ]; #endif /* ipconfigUSE_IPv6 != 0 */ diff --git a/source/include/FreeRTOS_Routing.h b/source/include/FreeRTOS_Routing.h index 8b480d8f6b..13c3551bd6 100644 --- a/source/include/FreeRTOS_Routing.h +++ b/source/include/FreeRTOS_Routing.h @@ -54,6 +54,11 @@ /* Return true as long as the LinkStatus on the PHY is present. */ typedef BaseType_t ( * GetPhyLinkStatusFunction_t ) ( struct xNetworkInterface * pxDescriptor ); + #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) +/* Functions that manipulate what MAC addresses are received by this interface */ + typedef void ( * NetworkInterfaceMACFilterFunction_t ) ( const uint8_t * pucMacAddressBytes ); + #endif + /** @brief These NetworkInterface access functions are collected in a struct: */ typedef struct xNetworkInterface { @@ -62,6 +67,25 @@ NetworkInterfaceInitialiseFunction_t pfInitialise; /**< This function will be called upon initialisation and repeated until it returns pdPASS. */ NetworkInterfaceOutputFunction_t pfOutput; /**< This function is supposed to send out a packet. */ GetPhyLinkStatusFunction_t pfGetPhyLinkStatus; /**< This function will return pdTRUE as long as the PHY Link Status is high. */ + #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) + + /* The network driver is responsible for keeping track of which MAC addresses ( unicast or multicast ) + * need to be received and which are not needed anymore. The stack calls the functions + * below every time a socket subscribes to a multicast group or drops its membership. + * If multiple sockets subscribe to the same multicast IP group address + * or to multiple multicast IP group addresses corresponding to the same MAC address, + * the IP task will call the functions below multiple times for the same multicast MAC address. + * The network driver must keep track of how many times pfAddAllowedMAC() has been called + * for a certain MAC address and only stop receiving that address after pfRemoveAllowedMAC() + * has been called the same number of time for that same MAC address. + * A quick and dirty implementation option is to receive all multicast MAC addresses and + * set both pfAddAllowedMAC and pfRemoveAllowedMAC to NULL + * The optimal way to achieve this functionality depends on the specific hardware EMAC. + * For one implementation option, check out portable/NetworkInterface/DriverSAM/NetworkInterface.c + */ + NetworkInterfaceMACFilterFunction_t pfAddAllowedMAC; + NetworkInterfaceMACFilterFunction_t pfRemoveAllowedMAC; + #endif struct { uint32_t diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 81f654e033..ab0ba5c201 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -41,6 +41,7 @@ #include "FreeRTOS_DNS.h" #include "FreeRTOS_ARP.h" #include "FreeRTOS_Routing.h" +#include "FreeRTOS_ND.h" #include "NetworkBufferManagement.h" #include "NetworkInterface.h" @@ -202,7 +203,8 @@ static void hand_tx_errors( void ); /* Functions to set the hash table for multicast addresses. */ static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ); -static void prvAddMulticastMACAddress( const uint8_t * ucMacAddress ); +static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); +static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); /* Checks IP queue, buffers, and semaphore and logs diagnostic info if configured */ static void vCheckBuffersAndQueue( void ); @@ -521,6 +523,10 @@ NetworkInterface_t * pxSAM_FillInterfaceDescriptor( BaseType_t xEMACIndex, pxInterface->pfInitialise = prvSAM_NetworkInterfaceInitialise; pxInterface->pfOutput = prvSAM_NetworkInterfaceOutput; pxInterface->pfGetPhyLinkStatus = prvSAM_GetPhyLinkStatus; + #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) + pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; + pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; + #endif FreeRTOS_AddNetworkInterface( pxInterface ); @@ -700,7 +706,9 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) /* Note that 'gmac_option.uc_copy_all_frame' is false, do not copy all frames. * And 'gmac_option.uc_no_boardcast' is false, meaning that broadcast is received. * 'boardcast' is a typo. */ - memcpy( gmac_option.uc_mac_addr, pxEndPoint->xMACAddress.ucBytes, sizeof( gmac_option.uc_mac_addr ) ); + + /* Note that the gmac_option holds the MAC address that will be enabled for reception. + * Leave the MAC as zeros. It will be handled properly further down.*/ gs_gmac_dev.p_hw = GMAC; gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option ); @@ -708,45 +716,62 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY ); NVIC_EnableIRQ( GMAC_IRQn ); - /* Clear the hash table for multicast MAC addresses. - * OR set both to ~0H to receive all multicast packets. */ - GMAC->GMAC_HRB = 0U; /* Hash Register Bottom. */ - GMAC->GMAC_HRT = 0U; /* Hash Register Top. */ + /* The call to gmac_dev_init() above writes gmac_option.uc_mac_addr to the first + * MAC address register by calling gmac_set_address( GMAC, 0, p_opt->uc_mac_addr ) + * This driver however uses the prvAddAllowedMACAddress() to manipulate the specific match + * and hash match registers, so undo the setting of the first specific MAC register. */ + + /* Disable all specific MAC address match registers */ + for( int i = 0; i < GMACSA_NUMBER; i++ ) + { + /* Writing the bottom register disable this specific MAC register. */ + GMAC->GMAC_SA[ i ].GMAC_SAB = 0; + } + + /* Clear the hash table for unicast/multicast MAC addresses. */ + gmac_set_hash( GMAC, 0, 0 ); - /* gmac_enable_multicast_hash() sets the wrong bit, don't use it. */ - /* gmac_enable_multicast_hash( GMAC, pdTRUE ); */ - /* set Multicast Hash Enable. */ - GMAC->GMAC_NCFGR |= GMAC_NCFGR_MTIHEN; + /* gmac_enable_multicast_hash() sets the wrong bit, don't use it. + * There is also no equivalent for unicasts, so manipulate the bits directly. + * For now, disable both multicast and unicast hash matching. + * The appropriate bits will be set later */ + GMAC->GMAC_NCFGR &= ~( GMAC_NCFGR_MTIHEN | GMAC_NCFGR_UNIHEN ); - #if ( ipconfigUSE_LLMNR == 1 ) + /* Go through all end-points of the interface and add their MAC addresses to the GMAC. */ + for( pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + pxEndPoint != NULL; + pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { - prvAddMulticastMACAddress( xLLMNR_MacAddress.ucBytes ); + prvAddAllowedMACAddress( pxEndPoint->xMACAddress.ucBytes ); } - #endif /* ipconfigUSE_LLMNR */ - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) + #if ( ipconfigUSE_LLMNR == ipconfigENABLE ) + prvAddAllowedMACAddress( xLLMNR_MacAddress.ucBytes ); + #endif /* ipconfigUSE_LLMNR */ + + #if ( ipconfigUSE_MDNS == ipconfigENABLE ) + prvAddAllowedMACAddress( xMDNS_MacAddress.ucBytes ); + #endif /* ipconfigUSE_MDNS */ + #endif /* ipconfigIS_ENABLED( ipconfigUSE_IPv4 */ + + #if ( ipconfigUSE_IPv6 == ipconfigENABLE ) { - NetworkEndPoint_t * pxEndPoint; - #if ( ipconfigUSE_LLMNR == 1 ) + /* Register the Link-Local All-Nodes address */ + /* FF02::1 --> 33-33-00-00-00-01 */ + prvAddAllowedMACAddress( pcLOCAL_ALL_NODES_MULTICAST_MAC ); + + #if ( ipconfigUSE_LLMNR == ipconfigENABLE ) { - prvAddMulticastMACAddress( xLLMNR_MacAddressIPv6.ucBytes ); + prvAddAllowedMACAddress( xLLMNR_MacAddressIPv6.ucBytes ); } #endif /* ipconfigUSE_LLMNR */ - for( pxEndPoint = FreeRTOS_FirstEndPoint( pxMyInterface ); - pxEndPoint != NULL; - pxEndPoint = FreeRTOS_NextEndPoint( pxMyInterface, pxEndPoint ) ) + #if ( ipconfigUSE_MDNS == ipconfigENABLE ) { - if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) - { - uint8_t ucMACAddress[ 6 ] = { 0x33, 0x33, 0xff, 0, 0, 0 }; - - ucMACAddress[ 3 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ]; - ucMACAddress[ 4 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ]; - ucMACAddress[ 5 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ]; - prvAddMulticastMACAddress( ucMACAddress ); - } + prvAddAllowedMACAddress( xMDNS_MACAddressIPv6.ucBytes ); } + #endif /* ipconfigUSE_MDNS */ } #endif /* ipconfigUSE_IPv6 */ @@ -785,6 +810,19 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) } /*-----------------------------------------------------------*/ +#define GMAC_ADDRESS_HASH_BITS ( 64U ) +#define GMAC_ADDRESS_HASH_MASK ( GMAC_ADDRESS_HASH_BITS - 1 ) + +/* The ATSAM GMAC has a 64 bit register for matching multiple unicast or multicast addresses. +* This implementation keeps a counter for every one of those bits. This allows us to keep track +* of how many times each bit has been referenced by a multicast MAC the the stack wants to receive. +* In order to minimize the memory requirement, the counters are of type uint8_t which limits +* their value to 255. If a counter ever reaches that value, it is never decremented. Reaching this +* limit is extremely unlikely in any system, let alone an embedded one using an ATSAM MCU. */ +static uint8_t prvAddressHashCounters[ GMAC_ADDRESS_HASH_BITS ] = { 0U }; +static uint64_t prvAddressHashBitMask = 0U; +static uint8_t prvSpecificMatchCounters[ GMACSA_NUMBER ] = { 0U }; + static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ) { uint16_t usSum; @@ -805,29 +843,261 @@ static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ) usSum ^= ( usValues[ 4 ] >> 4 ) ^ ( usValues[ 4 ] << 2 ); usSum ^= ( usValues[ 5 ] >> 2 ) ^ ( usValues[ 5 ] << 4 ); - usSum &= 0x3FU; + usSum &= GMAC_ADDRESS_HASH_MASK; return usSum; } /*-----------------------------------------------------------*/ -static void prvAddMulticastMACAddress( const uint8_t * ucMacAddress ) +/** + * @brief Adds a multicast mac address to the GMAC's registers. Internally, this function + * keeps track of the 4 specific MAC address register as well as the hash match register. + * It keeps a counter for how many times the specific registers have been used as well as how + * many times every bit in the GMAC hash register has been hit. This way, if two multicast MAC + * addresses map to the same GMAC hash register bit, the internal counter will hold the value of 2. + * Calling prvRemoveAllowedMACAddress for one of those MACs will only decrement the counter, but + * the bit in the GMAC hash register will remain set until a call to prvRemoveAllowedMACAddress for + * the other MAC causes the counter to reach 0 and the bit to get cleared. Same logic applies to + * the specific match registers. + * + * @param[in] pucMacAddress: A pointer to the multicast MAC Address in question. + */ +static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) +{ + /* Design rationale and implementation details: + * Most network infrastructure ( both wired and wireless ) will do a pretty good job in + * limiting how much unicast MAC traffic we receive. In general, we will only be sent + * unicast frames that are destined to MAC addresses that we send from. Because of this, + * the EMAC doesn't need to do heavy filtering for unicasts. + * On the other hand, most networking hardware ( both wired and wireless ) will happily + * send us all traffic that has a multicast destination MAC. It is therefor much more + * important to filter out unnecessary multicast traffic. Ideally, we could explicitly + * allow all multicast MAC addresses that the TCP stack requests, however, this EMAC controller + * only has 4 specific MAC match registers. Beyond that, we can use the hash match register to + * match unicast and/or multicast addresses. Every bit in the hash match register corresponds + * to millions of MAC addresses, so the usage of the hash register should be kept to a minimum. + * As a side note, setting all bits in the hash register is somewhat equivalent to + * promiscuous mode and is therefor not very useful. + * Due to the filtering nature of network infrastructure, It would make sense to use the + * specific match registers for matching multicasts and use the hash match register for unicasts + * because they are already well filtered. Due to the EMAC hardware limitations, such approach + * is only feasible if very few ( no more than 4 ) multicast MAC addresses need to be received. + * + * TCP stack multicast requirements notes: + * - IPv4 only, no IGMP, no LLMNR, no mDNS - 0 multicasts required. + * - IPv4 only: IGMP 224.0.0.1, LLMNR 224.0.0.252, mDNS 224.0.0.251 - total 3 multicasts required. + * - IPv6 only, no MLD, no LLMNR, no mDNS - 1 multicast required per IPv6 endpoint for the + * solicited node multicast address + all nodes ff02::1 - total of at least 2 multicasts required. + * - IPv4+v6 with IGMP, LLMNR and mDNS = 6 + 1 for every IPv6 end-point - 7+ multicasts required. + * + * This implementation is optimized for use cases where a lot of multicasts and very few unicast + * MAC addresses need to be received. This implementation prioritizes the use of the exact match + * register and once used up, begins utilizing the hash match register. It is highly recommended + * that all the end-points of an interface use the same unicast MAC. If for some reason, the TCP + * stack adds too many unicast MAC addresses, the hash register will be used for both unicasts + * and multicasts which will result in a lot of bits being set and consequently very poor + * multicast filtering. + * One limitation of this implementation is that once it enables unicast or multicast hash + * matching, it will never disable them. This should be acceptable for a fairly static system + * and was chosen because it minimizes RAM usage by not keeping a list of all MAC addresses + * that the TCP stack has requested. One optimization that this implementation makes is as follows: + * If the MAC being added is already covered by the hash match register and that specific + * matching is already enabled, we add that new MAC to the hash register even if there is an + * empty specific match register available. The reasoning is that the hash match register is already + * allowing this new MAC address to be received and there is no reason to waste a specific + * match register. + * The implementation keep counts of how many times the individual hash bits and specific match + * registers have been used. */ + + /* Note: Only called from the IPTask, so no thread-safety is required. */ + uint8_t ucHashBit, ucIsMulticast, i, ucEmptyIndex; + + uint32_t ulSAB, ulSAT; + + configASSERT( NULL != pucMacAddress ); + + ucHashBit = prvGenerateCRC16( pucMacAddress ); + ucIsMulticast = pucMacAddress[ 0 ] & 1U; + FreeRTOS_debug_printf( "prvAddAllowedMACAddress: %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", + pucMacAddress[ 0 ], pucMacAddress[ 1 ], pucMacAddress[ 2 ], pucMacAddress[ 3 ], pucMacAddress[ 4 ], pucMacAddress[ 5 ], + ucHashBit ); + + /* Calculate what the specific match registers would look like for this MAC address so that + * we can check if this MAC address is already present in one of the specific match registers. */ + ulSAB = ( pucMacAddress[ 3 ] << 24 ) | ( pucMacAddress[ 2 ] << 16 ) | ( pucMacAddress[ 1 ] << 8 ) | ( pucMacAddress[ 0 ] ); + ulSAT = ( pucMacAddress[ 5 ] << 8 ) | ( pucMacAddress[ 4 ] ); + + /* Always try to find a match within the specific match registers first. */ + ucEmptyIndex = GMACSA_NUMBER; + + for( i = 0; i < GMACSA_NUMBER; i++ ) + { + if( prvSpecificMatchCounters[ i ] > 0U ) + { + /* This specific match register is being used. Check if the address is the same. */ + if( ( ulSAB == GMAC->GMAC_SA[ i ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ i ].GMAC_SAT ) ) + { + /* Exact match! Increment the counter and leave. */ + prvSpecificMatchCounters[ i ]++; + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", i, prvSpecificMatchCounters[ i ] ); */ + break; + } + else + { + /* No match. Do nothing. */ + } + } + else + { + /* This specific match register is empty. + * Keep track of the first empty register in case we need to use it. */ + if( ucEmptyIndex >= GMACSA_NUMBER ) + { + ucEmptyIndex = i; + } + else + { + /* We have already found an empty specific match register. Do nothing. */ + } + } + } /* for( i = 0; i < GMACSA_NUMBER; i++ ) */ + + /* do{}while(0) to allow the use of break statements. */ + do + { + if( i < GMACSA_NUMBER ) + { + /* An exact match was found in the for(;;) loop above. Do nothing. */ + break; + } + + /* No exact match found in the specific match registers, but is one of them empty? */ + if( ucEmptyIndex < GMACSA_NUMBER ) + { + /* There is an empty slot in the specific match registers. Using this empty slot should + * be a priority, except if the hash register already covers the MAC address we were given + * and the type of address we were given ( unicast/multicast ). If any of those are not + * met, simply add to the empty slot we found in the specific match registers. */ + if( ( ( ucIsMulticast != 0 ) && ( ( GMAC->GMAC_NCFGR & GMAC_NCFGR_MTIHEN ) == 0 ) ) /* multicast, but hash does not match multicasts */ || + ( ( ucIsMulticast == 0 ) && ( ( GMAC->GMAC_NCFGR & GMAC_NCFGR_UNIHEN ) == 0 ) ) /* unicast, but hash does not match unicasts */ || + ( prvAddressHashCounters[ ucHashBit ] == 0 ) /* hash matching doesn't cover this address yet. */ ) + { + /* In all cases above, simply add to the empty specific match register. */ + gmac_set_address( GMAC, ucEmptyIndex, pucMacAddress ); + prvSpecificMatchCounters[ ucEmptyIndex ] = 1U; + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: ADD at %u, new counter %u", ucEmptyIndex, prvSpecificMatchCounters[ ucEmptyIndex ] ); */ + break; + } + } + + /* If we reach here, we need to add the MAC address we were given to the hash match register. */ + /* If the bin counter corresponding to this mac address is already non-zero, */ + /* a multicast address with the same hash has already been added, so there's nothing more to do. */ + if( prvAddressHashCounters[ ucHashBit ] == 0 ) + { + /* This bin counter is zero, so this is the first time we are registering a MAC with this hash + * and we need to update the hash register. */ + prvAddressHashBitMask |= ( uint64_t ) ( ( uint64_t ) 1 << ucHashBit ); + gmac_set_hash64( GMAC, prvAddressHashBitMask ); + } + + /* Increment the counter, but make sure we don't overflow it. */ + if( prvAddressHashCounters[ ucHashBit ] < UINT8_MAX ) + { + prvAddressHashCounters[ ucHashBit ]++; + } + + /* Make sure the unicast or multicast hash enable bits are set properly. */ + if( ( ucIsMulticast == 0U ) && ( ( GMAC->GMAC_NCFGR & GMAC_NCFGR_UNIHEN ) == 0 ) ) + { + /* This is the first ever unicast address added to the hash register. Enable unicast matching. */ + GMAC->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN; + } + else if( ( ucIsMulticast != 0U ) && ( ( GMAC->GMAC_NCFGR & GMAC_NCFGR_MTIHEN ) == 0 ) ) + { + /* This is the first ever multicast address added to the hash register. Enable multicast matching. */ + GMAC->GMAC_NCFGR |= GMAC_NCFGR_MTIHEN; + } + else + { + /* The proper unicast / multicast matching is already enabled. Do nothing. */ + } + } while( pdFALSE ); +} + +/** + * @brief Removes a MAC address from the GMAC's specific match or hash match registers. + * + * @param[in] pucMacAddress: A pointer to the multicast MAC Address in question. + */ +static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) { - uint32_t ulMask; - uint16_t usIndex; + /* Note: Only called from the IPTask, so no thread-safety is required. */ + uint8_t ucHashBit, i; + uint32_t ulSAB, ulSAT; + + configASSERT( NULL != pucMacAddress ); - usIndex = prvGenerateCRC16( ucMacAddress ); + ucHashBit = prvGenerateCRC16( pucMacAddress ); + FreeRTOS_debug_printf( "prvRemoveAllowedMACAddress: %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", + pucMacAddress[ 0 ], pucMacAddress[ 1 ], pucMacAddress[ 2 ], pucMacAddress[ 3 ], pucMacAddress[ 4 ], pucMacAddress[ 5 ], + ucHashBit ); - ulMask = 1U << ( usIndex % 32 ); + /* Calculate what the specific match registers would look like for this MAC address so that + * we can check if this MAC address is already present in one of the specific match registers. */ + ulSAB = ( pucMacAddress[ 3 ] << 24 ) | ( pucMacAddress[ 2 ] << 16 ) | ( pucMacAddress[ 1 ] << 8 ) | ( pucMacAddress[ 0 ] ); + ulSAT = ( pucMacAddress[ 5 ] << 8 ) | ( pucMacAddress[ 4 ] ); - if( usIndex < 32U ) + /* Check the specific match registers first. */ + for( i = 0; i < GMACSA_NUMBER; i++ ) { - /* 0 .. 31 */ - GMAC->GMAC_HRB |= ulMask; + if( ( prvSpecificMatchCounters[ i ] > 0U ) && ( ulSAB == GMAC->GMAC_SA[ i ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ i ].GMAC_SAT ) ) + { + /* Exact match! Decrement the counter unless it's maxed out. */ + if( prvSpecificMatchCounters[ i ] < UINT8_MAX ) + { + prvSpecificMatchCounters[ i ]--; + } + + if( prvSpecificMatchCounters[ i ] == 0 ) + { + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, INDEX DISABLED", i ); */ + /* This specific match register counter is now zero. Disable it by writing it in reverse order. */ + GMAC->GMAC_SA[ i ].GMAC_SAT = 0U; /* This is not needed, just clears out the top register.*/ + GMAC->GMAC_SA[ i ].GMAC_SAB = 0U; /* Writing the bottom register disables this specific match register. */ + } + else + { + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", i, prvSpecificMatchCounters[ i ] ); */ + } + + break; + } + } + + if( i >= GMACSA_NUMBER ) + { + /* The MAC address was not found amongst the specific match registers, check the hash register. */ + if( prvAddressHashCounters[ ucHashBit ] > 0 ) + { + /* If so many multicasts with the same hash were added that the bin counter was maxed out, */ + /* we don't really know how many times we can decrement before actually unregistering this hash. */ + /* Because of this, if the bin counter ever maxes out, we can never unregister the hash. */ + if( prvAddressHashCounters[ ucHashBit ] < UINT8_MAX ) + { + prvAddressHashCounters[ ucHashBit ]--; + + if( 0 == prvAddressHashCounters[ ucHashBit ] ) + { + uint64_t hash = ( uint64_t ) ( ( uint64_t ) 1 << ucHashBit ); + prvAddressHashBitMask &= ~hash; + gmac_set_hash64( GMAC, prvAddressHashBitMask ); + } + } + } } else { - /* 32 .. 63 */ - GMAC->GMAC_HRT |= ulMask; + /* Nothing left to do. */ } } /*-----------------------------------------------------------*/ @@ -923,7 +1193,7 @@ void vGMACGenerateChecksum( uint8_t * pucBuffer, ProtocolPacket_t * xProtPacket = ( ProtocolPacket_t * ) pucBuffer; /* The SAM4E has problems offloading checksums for transmission. - * The SAME70 does not set the CRC for ICMP packets (ping). */ + * The SAME70 does not set the CRC for ICMP or IGMP packets. */ if( xProtPacket->xICMPPacket.xEthernetHeader.usFrameType == ipIPv4_FRAME_TYPE ) { From 3f3035ead3bd9d6ed3c45dbce3a46c8deea33c6f Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Wed, 3 Jan 2024 12:09:03 -0500 Subject: [PATCH 02/18] Removes ipconfigMAC_FILTERING Rewrites the comment describing the MAC filtering functions. --- source/FreeRTOS_IP.c | 50 ++++++++-------- source/FreeRTOS_IP_Utils.c | 47 +++++++-------- source/include/FreeRTOSIPConfigDefaults.h | 15 ----- source/include/FreeRTOS_Routing.h | 59 ++++++++++++------- .../DriverSAM/NetworkInterface.c | 9 +-- 5 files changed, 83 insertions(+), 97 deletions(-) diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index fe90f8885e..88bc0c75de 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -631,37 +631,33 @@ TaskHandle_t FreeRTOS_GetIPTaskHandle( void ) */ void vIPNetworkUpCalls( struct xNetworkEndPoint * pxEndPoint ) { - #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) + IPv6_Type_t xAddressType; + + if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) { - IPv6_Type_t xAddressType; + /* Now that the network is up, pxEndPoint->ipv6_settings should hold the actual address of this + * end-point. For unicast addresses, generate the respective solicited-node multicast address. + * Note that the check below guards against the loopback address, the unspecified address, + * and against the weird scenario of someone assigning a multicast address to the end-point. */ + xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) + if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) { - /* Now that the network is up, pxEndPoint->ipv6_settings should hold the actual address of this - * end-point. For unicast addresses, generate the respective solicited-node multicast address. - * Note that the check below guards against the loopback address, the unspecified address, - * and against the weird scenario of someone assigning a multicast address to the end-point. */ - xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - - if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) + /* Tell the network driver to begin receiving this MAC address */ + if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) { - /* Tell the network driver to begin receiving this MAC address */ - if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) - { - MACAddress_t xMACAddress = { { - 0x33U, - 0x33U, - 0xFFU, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - } }; - pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); - } - } /* if( xAddressType == ... ) */ - } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ - } - #endif /* ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) */ + MACAddress_t xMACAddress = { { + 0x33U, + 0x33U, + 0xFFU, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + } }; + pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); + } + } /* if( xAddressType == ... ) */ + } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ pxEndPoint->bits.bEndPointUp = pdTRUE_UNSIGNED; diff --git a/source/FreeRTOS_IP_Utils.c b/source/FreeRTOS_IP_Utils.c index 8771e32ccf..87cb4ad45c 100644 --- a/source/FreeRTOS_IP_Utils.c +++ b/source/FreeRTOS_IP_Utils.c @@ -819,6 +819,7 @@ BaseType_t xIsCallingFromIPTask( void ) void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ) { NetworkEndPoint_t * pxEndPoint; + IPv6_Type_t xAddressType; configASSERT( pxInterface != NULL ); configASSERT( pxInterface->pfInitialise != NULL ); @@ -836,36 +837,30 @@ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ) /* The bit 'bEndPointUp' stays low until vIPNetworkUpCalls() is called. */ pxEndPoint->bits.bEndPointUp = pdFALSE_UNSIGNED; - #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) + if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) { - IPv6_Type_t xAddressType; + xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) + /* The check below guards against the loopback address, the unspecified address, + * and against the weird scenario of someone assigning a multicast address to the end-point. */ + if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) { - xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - - /* The check below guards against the loopback address, the unspecified address, - * and against the weird scenario of someone assigning a multicast address to the end-point. */ - if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) + /* Every network-up event adds the MAC address corresponding to this end-point's solicited node multicast address. + * Remove it here to balance out the number of add/remove calls. */ + if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) { - /* Every network-up event adds the MAC address corresponding to this end-point's solicited node multicast address. - * Remove it here to balance out the number of add/remove calls. */ - if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) - { - MACAddress_t xMACAddress = { { - 0x33U, - 0x33U, - 0xFFU, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - } }; - pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); - } - } /* if( xAddressType == ... ) */ - } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ - } - #endif /* ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) */ + MACAddress_t xMACAddress = { { + 0x33U, + 0x33U, + 0xFFU, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + } }; + pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); + } + } /* if( xAddressType == ... ) */ + } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ #if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 ) { diff --git a/source/include/FreeRTOSIPConfigDefaults.h b/source/include/FreeRTOSIPConfigDefaults.h index 43e3e850a1..33db82fc40 100644 --- a/source/include/FreeRTOSIPConfigDefaults.h +++ b/source/include/FreeRTOSIPConfigDefaults.h @@ -3295,21 +3295,6 @@ /*---------------------------------------------------------------------------*/ -/* - * ipconfigMAC_FILTERING - * - * Type: BaseType_t ( ipconfigENABLE | ipconfigDISABLE ) - * - * When set to ipconfigENABLE, this macro will adds two functions - * to the network interface. Those functions allow adding/removing multicast - * MAC addresses to/from the hardware EMAC. It is up to the portable network - * code to implement these as on the specific hardware. */ -#ifndef ipconfigMAC_FILTERING - #define ipconfigMAC_FILTERING ipconfigDISABLE -#endif - -/*---------------------------------------------------------------------------*/ - /* Should only be included here, ensures trace config is set first. */ #include "IPTraceMacroDefaults.h" diff --git a/source/include/FreeRTOS_Routing.h b/source/include/FreeRTOS_Routing.h index 13c3551bd6..41bde5b39d 100644 --- a/source/include/FreeRTOS_Routing.h +++ b/source/include/FreeRTOS_Routing.h @@ -54,10 +54,8 @@ /* Return true as long as the LinkStatus on the PHY is present. */ typedef BaseType_t ( * GetPhyLinkStatusFunction_t ) ( struct xNetworkInterface * pxDescriptor ); - #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) /* Functions that manipulate what MAC addresses are received by this interface */ - typedef void ( * NetworkInterfaceMACFilterFunction_t ) ( const uint8_t * pucMacAddressBytes ); - #endif + typedef void ( * NetworkInterfaceMACFilterFunction_t ) ( const uint8_t * pucMacAddressBytes ); /** @brief These NetworkInterface access functions are collected in a struct: */ typedef struct xNetworkInterface @@ -67,25 +65,42 @@ NetworkInterfaceInitialiseFunction_t pfInitialise; /**< This function will be called upon initialisation and repeated until it returns pdPASS. */ NetworkInterfaceOutputFunction_t pfOutput; /**< This function is supposed to send out a packet. */ GetPhyLinkStatusFunction_t pfGetPhyLinkStatus; /**< This function will return pdTRUE as long as the PHY Link Status is high. */ - #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) - - /* The network driver is responsible for keeping track of which MAC addresses ( unicast or multicast ) - * need to be received and which are not needed anymore. The stack calls the functions - * below every time a socket subscribes to a multicast group or drops its membership. - * If multiple sockets subscribe to the same multicast IP group address - * or to multiple multicast IP group addresses corresponding to the same MAC address, - * the IP task will call the functions below multiple times for the same multicast MAC address. - * The network driver must keep track of how many times pfAddAllowedMAC() has been called - * for a certain MAC address and only stop receiving that address after pfRemoveAllowedMAC() - * has been called the same number of time for that same MAC address. - * A quick and dirty implementation option is to receive all multicast MAC addresses and - * set both pfAddAllowedMAC and pfRemoveAllowedMAC to NULL - * The optimal way to achieve this functionality depends on the specific hardware EMAC. - * For one implementation option, check out portable/NetworkInterface/DriverSAM/NetworkInterface.c - */ - NetworkInterfaceMACFilterFunction_t pfAddAllowedMAC; - NetworkInterfaceMACFilterFunction_t pfRemoveAllowedMAC; - #endif + + /* + * pfAddAllowedMAC and pfRemoveAllowedMAC form the network driver's address filtering API. + * The network stack uses these functions to alter which MAC addresses will be received. + * The MAC addresses passed to the functions can be unicast or multicast. It is important + * to note that the stack may call these functions multiple times for the the same MAC address. + * For example, if two sockets subscribe to the same multicast group, pfAddAllowedMAC() + * will be called twice with the same MAC address. The network driver is responsible for + * keeping track of these calls. The network driver should continue receiving that + * particular MAC address until pfRemoveAllowedMAC() is called the same number of times. + * + * Most EMAC hardware nowadays can filter frames based on both specific MAC address matching + * and hash matching. Specific address matching is ideal because as the name suggests, + * only frames with the exact MAC address are received. Usually however, the number of + * specific MAC addresses is limited ( to 4 in many cases ) and is sometimes not enough for + * all the MAC addresses that the network stack needs to receive. + * Hash matching is usually based around a 64-bit hash table. For every incoming frame, + * the EMAC calculates a hash value (mod 64) of the destination MAC address. + * The hash value is looked up in the 64-bit hash table and if that bit is set, the frame is + * received. If the bit is clear, the frame is dropped. With hash matching, multiple + * MAC addresses are represented by a single bit. It is the responsibility of the network + * driver to manage both the hash address matching and specific address matching capabilities + * of the EMAC hardware. + * A quick and dirty implementation option is to receive all MAC addresses and set both + * pfAddAllowedMAC and pfRemoveAllowedMAC to NULL. This results in an interface running + * in promiscuous mode and the entire burden of MAC filtering falls on the network stack. + * For a more realistic implementation, check out + * "portable/NetworkInterface/DriverSAM/NetworkInterface.c" It demonstrates the use of both + * specific and hash address matching as well as keeping count of how many time the + * individual registers/bits have been used. That implementation's init functions also + * demonstrates the use of prvAddAllowedMACAddress() function to register all end-point's + * MAC addresses whether the endpoints used the same or different MAC addresses. + */ + NetworkInterfaceMACFilterFunction_t pfAddAllowedMAC; + NetworkInterfaceMACFilterFunction_t pfRemoveAllowedMAC; + struct { uint32_t diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index ab0ba5c201..0d9c0ea54c 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -523,10 +523,8 @@ NetworkInterface_t * pxSAM_FillInterfaceDescriptor( BaseType_t xEMACIndex, pxInterface->pfInitialise = prvSAM_NetworkInterfaceInitialise; pxInterface->pfOutput = prvSAM_NetworkInterfaceOutput; pxInterface->pfGetPhyLinkStatus = prvSAM_GetPhyLinkStatus; - #if ( ipconfigIS_ENABLED( ipconfigMAC_FILTERING ) ) - pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; - pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; - #endif + pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; + pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; FreeRTOS_AddNetworkInterface( pxInterface ); @@ -694,9 +692,6 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) gmac_options_t gmac_option; - pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); - configASSERT( pxEndPoint != NULL ); - gmac_enable_management( GMAC, true ); /* Enable further GMAC maintenance. */ GMAC->GMAC_NCR |= GMAC_NCR_MPE; From aa7a128a47bb1d31ea472c880e0ae0681c22f335 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Fri, 5 Jan 2024 09:44:17 -0500 Subject: [PATCH 03/18] Adds checks for ipconfigUSE_IPv6 Fixes a copy/paste bug that was allowing pfRemoveAllowedMAC() to be called without being checked for non-NULL --- source/FreeRTOS_IP.c | 62 ++++++++++++++++++++++++-------------- source/FreeRTOS_IP_Utils.c | 58 +++++++++++++++++++++++------------ 2 files changed, 78 insertions(+), 42 deletions(-) diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index 88bc0c75de..f6dcd63c66 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -631,33 +631,51 @@ TaskHandle_t FreeRTOS_GetIPTaskHandle( void ) */ void vIPNetworkUpCalls( struct xNetworkEndPoint * pxEndPoint ) { - IPv6_Type_t xAddressType; - if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) { - /* Now that the network is up, pxEndPoint->ipv6_settings should hold the actual address of this - * end-point. For unicast addresses, generate the respective solicited-node multicast address. - * Note that the check below guards against the loopback address, the unspecified address, - * and against the weird scenario of someone assigning a multicast address to the end-point. */ - xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - - if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) { - /* Tell the network driver to begin receiving this MAC address */ - if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) + IPv6_Type_t xAddressType; + + /* Now that the network is up, pxEndPoint->ipv6_settings should hold the actual address of this + * end-point. For unicast addresses, generate the respective solicited-node multicast address. + * Note that the check below guards against the loopback address, the unspecified address, + * and against the weird scenario of someone assigning a multicast address to the end-point. */ + xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + + if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) { - MACAddress_t xMACAddress = { { - 0x33U, - 0x33U, - 0xFFU, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - } }; - pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); + /* Tell the network driver to begin receiving this MAC address */ + if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) + { + MACAddress_t xMACAddress = { { + 0x33U, + 0x33U, + 0xFFU, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + } }; + pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); + } + else + { + /* The network driver does not implement this filtering function. Nothing we can do about it. */ + } + } /* if( xAddressType == ... ) */ + else + { + /* The address of this end-point is something other than a normal unicast address... Maybe it's the + * loopback address or maybe this is an error scenario. In any case, there is no corresponding + * solicited-node multicast address that we need to manage. Do nothing.*/ } - } /* if( xAddressType == ... ) */ - } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ + } + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ + } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ + else + { + /* This is an IPv4 end-point. There are no solicited-node addresses to manage. */ + } pxEndPoint->bits.bEndPointUp = pdTRUE_UNSIGNED; diff --git a/source/FreeRTOS_IP_Utils.c b/source/FreeRTOS_IP_Utils.c index 87cb4ad45c..7f7552bd81 100644 --- a/source/FreeRTOS_IP_Utils.c +++ b/source/FreeRTOS_IP_Utils.c @@ -819,7 +819,6 @@ BaseType_t xIsCallingFromIPTask( void ) void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ) { NetworkEndPoint_t * pxEndPoint; - IPv6_Type_t xAddressType; configASSERT( pxInterface != NULL ); configASSERT( pxInterface->pfInitialise != NULL ); @@ -839,28 +838,47 @@ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ) if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) { - xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - - /* The check below guards against the loopback address, the unspecified address, - * and against the weird scenario of someone assigning a multicast address to the end-point. */ - if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) { - /* Every network-up event adds the MAC address corresponding to this end-point's solicited node multicast address. - * Remove it here to balance out the number of add/remove calls. */ - if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) + IPv6_Type_t xAddressType; + xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + + /* The check below guards against the loopback address, the unspecified address, + * and against the weird scenario of someone assigning a multicast address to the end-point. */ + if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) { - MACAddress_t xMACAddress = { { - 0x33U, - 0x33U, - 0xFFU, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - } }; - pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); + /* Every network-up event adds the MAC address corresponding to this end-point's solicited node multicast address. + * Remove it here to balance out the number of add/remove calls. */ + if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC != NULL ) ) + { + MACAddress_t xMACAddress = { { + 0x33U, + 0x33U, + 0xFFU, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + } }; + pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); + } + else + { + /* The network driver does not implement this filtering function. Nothing we can do about it. */ + } + } /* if( xAddressType == ... ) */ + else + { + /* The address of this end-point is something other than a normal unicast address... Maybe it's the + * loopback address or maybe this is an error scenario. In any case, there is no corresponding + * solicited-node multicast address that we need to manage. Do nothing.*/ } - } /* if( xAddressType == ... ) */ - } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ + } + #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ + } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ + else + { + /* This is an IPv4 end-point. There are no solicited-node addresses to manage. */ + } #if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 ) { From dfa41e02261beaae85bc5bf1c0746f4efd059d50 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Mon, 8 Jan 2024 08:21:23 -0500 Subject: [PATCH 04/18] Updates the unit tests for better coverage. Thanks @htibosch --- .../unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c | 165 +++++++++++++++ .../FreeRTOS_IP_Utils_utest.c | 193 ++++++++++++++++++ 2 files changed, 358 insertions(+) diff --git a/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c b/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c index 3b1b287154..3536725211 100644 --- a/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c +++ b/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c @@ -92,6 +92,17 @@ const IPv6_Address_t xIPAddressTen = { 0x20, 0x01, 0x12, 0x34, 0x56, 0x78, 0x00, /* MAC Address for endpoint. */ const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0xab, 0xcd, 0xef, 0x11, 0x22, 0x33 }; +/* This variable will be set when pfAddAllowedMAC() is called by vIPNetworkUpCalls(). */ +static BaseType_t xMACFunctionCalled; + +/* An implementation of pfAddAllowedMAC(). */ +static void pfAddAllowedMAC( const uint8_t * pucMacAddress ); + +/* Testing all situations for vIPNetworkUpCalls() to increase coverage. */ +#define ipHAS_METHOD 0x01U +#define ipHAS_INTERFACE 0x02U +#define ipHAS_IPV6 0x04U + /* ============================ Unity Fixtures ============================ */ /*! called before each test case */ @@ -3808,3 +3819,157 @@ void test_uxIPHeaderSizeSocket_IPv6() xReturn = uxIPHeaderSizeSocket( &xSocket ); TEST_ASSERT_EQUAL( ipSIZE_OF_IPv6_HEADER, xReturn ); } + +static void pfAddAllowedMAC( const uint8_t * pucMacAddress ) +{ + xMACFunctionCalled = pdTRUE; +} + +static BaseType_t xNetworkInterfaceInitialise_returnTrue( NetworkInterface_t * xInterface ) +{ + return pdTRUE; +} + +/** + * @brief test_prvProcessNetworkDownEvent_Fail + * To validate if prvProcessNetworkDownEvent skips hook and DHCP + * when bCallDownHook & bWantDHCP are both disabled. + */ +static void prvIPNetworkUpCalls_Generic( const uint8_t * pucAddress, + IPv6_Type_t eType, + UBaseType_t uxSetMembers ) +{ + NetworkInterface_t xInterface = { 0 }; + NetworkEndPoint_t xEndPoint = { 0 }; + BaseType_t xMACAddExpected = pdFALSE; + + xInterfaces[ 0 ].pfInitialise = &xNetworkInterfaceInitialise_returnTrue; + xInterfaces[ 0 ].pxEndPoint = &xEndPoint; + + xEndPoint.bits.bEndPointUp = pdFALSE; + xEndPoint.bits.bCallDownHook = pdFALSE_UNSIGNED; + xEndPoint.bits.bWantDHCP = pdFALSE_UNSIGNED; + memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, pucAddress, ipSIZE_OF_IPv6_ADDRESS ); + + if( ( uxSetMembers & ipHAS_METHOD ) != 0U ) + { + xInterface.pfAddAllowedMAC = pfAddAllowedMAC; + } + + if( ( uxSetMembers & ipHAS_INTERFACE ) != 0U ) + { + xEndPoint.pxNetworkInterface = &xInterface; + } + + if( ( uxSetMembers & ipHAS_IPV6 ) != 0U ) + { + xEndPoint.bits.bIPv6 = pdTRUE_UNSIGNED; + } + + xMACFunctionCalled = pdFALSE; + + if( ( ( eType == eIPv6_LinkLocal ) || ( eType == eIPv6_SiteLocal ) || ( eType == eIPv6_Global ) ) && + ( xInterface.pfAddAllowedMAC != NULL ) && + ( xEndPoint.pxNetworkInterface != NULL ) && + ( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) ) + { + xMACAddExpected = pdTRUE; + } + + if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) + { + /* The xIPv6_GetIPType() function is mocked. */ + xIPv6_GetIPType_ExpectAnyArgsAndReturn( eType ); + } + + vApplicationIPNetworkEventHook_Multi_Expect( eNetworkUp, &xEndPoint ); + vDNSInitialise_Expect(); + vARPTimerReload_Expect( pdMS_TO_TICKS( 10000 ) ); + + vIPNetworkUpCalls( &xEndPoint ); + + TEST_ASSERT_EQUAL( pdTRUE, xEndPoint.bits.bEndPointUp ); + /* See if pfAddAllowedMAC() was called when it has to. */ + TEST_ASSERT_EQUAL( xMACAddExpected, xMACFunctionCalled ); +} + +void test_prvIPNetworkUpCalls_LinkLocal() +{ + /* Use the local-link address fe80::7009 */ + static const uint8_t ucAddress[ 16 ] = + { + 0xFEU, 0x80U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x70U, 0x09U + }; + + /* Test all combinations of what might go wrong. */ + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_METHOD ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_INTERFACE ); +} + +void test_prvIPNetworkUpCalls_Global() +{ + /* Use the local-link address "2001:0470:ed44::7009" */ + static const uint8_t ucAddress[ 16 ] = + { + 0x20U, 0x01U, + 0x04U, 0x70U, + 0xEDU, 0x44U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x70U, 0x09U + }; + + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_METHOD ); +} + +void test_prvIPNetworkUpCalls_SiteLocal() +{ + /* Use the local-link address "fec0::7009" */ + static const uint8_t ucAddress[ 16 ] = + { + 0xFEU, 0xC0U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x70U, 0x09U + }; + + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_METHOD ); +} + +void test_prvIPNetworkUpCalls_Multicast() +{ + /* Use the multicast address "ff02::fb", + * just for the coverage of vIPNetworkUpCalls(). */ + static const uint8_t ucAddress[ 16 ] = + { + 0xFFU, 0x02U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0xFBU + }; + + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); +} diff --git a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c index 2de291f115..7c6296df1a 100644 --- a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c +++ b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c @@ -80,6 +80,17 @@ extern uint16_t prvGetChecksumFromPacket( const struct xPacketSummary * pxSet ); extern void prvSetChecksumInPacket( const struct xPacketSummary * pxSet, uint16_t usChecksum ); +/* This variable will be set when pfRemoveAllowedMAC() is called by prvProcessNetworkDownEvent(). */ +static BaseType_t xMACFunctionCalled; + +/* An implementation of pfRemoveAllowedMAC() */ +static void pfRemoveAllowedMAC( const uint8_t * pucMacAddress ); + +/* Testing all situations for prvProcessNetworkDownEvent() to increase coverage. */ +#define ipHAS_METHOD 0x01U +#define ipHAS_INTERFACE 0x02U +#define ipHAS_IPV6 0x04U + /* ============================== Test Cases ============================== */ /** @@ -605,6 +616,13 @@ void test_prvProcessNetworkDownEvent_PassDHCPv6( void ) vIPSetARPTimerEnableState_Expect( pdFALSE ); FreeRTOS_FirstEndPoint_IgnoreAndReturn( &xEndPoint ); + + if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) + { + /* The xIPv6_GetIPType() function is mocked. */ + xIPv6_GetIPType_ExpectAnyArgsAndReturn( eIPv6_Multicast ); + } + FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); FreeRTOS_ClearARP_ExpectAnyArgs(); @@ -635,6 +653,13 @@ void test_prvProcessNetworkDownEvent_PassRA( void ) vIPSetARPTimerEnableState_Expect( pdFALSE ); FreeRTOS_FirstEndPoint_IgnoreAndReturn( &xEndPoint ); + + if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) + { + /* The xIPv6_GetIPType() function is mocked. */ + xIPv6_GetIPType_ExpectAnyArgsAndReturn( eIPv6_Multicast ); + } + FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); FreeRTOS_ClearARP_ExpectAnyArgs(); @@ -667,6 +692,13 @@ void test_prvProcessNetworkDownEvent_PassStaticIP( void ) vIPSetARPTimerEnableState_Expect( pdFALSE ); FreeRTOS_FirstEndPoint_IgnoreAndReturn( &xEndPoint ); + + if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) + { + /* The xIPv6_GetIPType() function is mocked. */ + xIPv6_GetIPType_ExpectAnyArgsAndReturn( eIPv6_Multicast ); + } + FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); FreeRTOS_ClearARP_ExpectAnyArgs(); @@ -3038,3 +3070,164 @@ void test_prvSetChecksumInPacket_IPv6UnhandledProtocol() prvSetChecksumInPacket( &xSet, 0 ); } + +static void pfRemoveAllowedMAC( const uint8_t * pucMacAddress ) +{ + xMACFunctionCalled = pdTRUE; +} + +/** + * @brief test_prvProcessNetworkDownEvent_Fail + * To validate if prvProcessNetworkDownEvent skips hook and DHCP + * when bCallDownHook & bWantDHCP are both disabled. + */ +static void prvProcessNetworkDownEvent_Generic( const uint8_t * pucAddress, + IPv6_Type_t eType, + UBaseType_t uxSetMembers ) +{ + NetworkInterface_t xInterface = { 0 }; + NetworkEndPoint_t xEndPoint = { 0 }; + BaseType_t xMACRemoveExpected = pdFALSE; + + xCallEventHook = pdFALSE; + xInterfaces[ 0 ].pfInitialise = &xNetworkInterfaceInitialise_returnTrue; + xInterfaces[ 0 ].pxEndPoint = &xEndPoint; + + xEndPoint.bits.bEndPointUp = pdTRUE; + xEndPoint.bits.bCallDownHook = pdFALSE_UNSIGNED; + xEndPoint.bits.bWantDHCP = pdFALSE_UNSIGNED; + memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, pucAddress, ipSIZE_OF_IPv6_ADDRESS ); + + if( ( uxSetMembers & ipHAS_METHOD ) != 0U ) + { + xInterface.pfRemoveAllowedMAC = pfRemoveAllowedMAC; + } + + if( ( uxSetMembers & ipHAS_INTERFACE ) != 0U ) + { + xEndPoint.pxNetworkInterface = &xInterface; + } + + if( ( uxSetMembers & ipHAS_IPV6 ) != 0U ) + { + xEndPoint.bits.bIPv6 = pdTRUE_UNSIGNED; + } + + xMACFunctionCalled = pdFALSE; + + if( ( ( eType == eIPv6_LinkLocal ) || ( eType == eIPv6_SiteLocal ) || ( eType == eIPv6_Global ) ) && + ( xInterface.pfRemoveAllowedMAC != NULL ) && + ( xEndPoint.pxNetworkInterface != NULL ) && + ( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) ) + { + xMACRemoveExpected = pdTRUE; + } + + vIPSetARPTimerEnableState_Expect( pdFALSE ); + + FreeRTOS_FirstEndPoint_IgnoreAndReturn( &xEndPoint ); + + if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) + { + /* The xIPv6_GetIPType() function is mocked. */ + xIPv6_GetIPType_ExpectAnyArgsAndReturn( eType ); + } + + FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); + + + FreeRTOS_ClearARP_Expect( &xEndPoint ); + + vIPNetworkUpCalls_Expect( &xEndPoint ); + + prvProcessNetworkDownEvent( &xInterfaces[ 0 ] ); + + /* See if pfRemoveAllowedMAC() was called when it has to. */ + TEST_ASSERT_EQUAL( xMACRemoveExpected, xMACFunctionCalled ); +} + +void test_prvProcessNetworkDownEvent_LinkLocal() +{ + /* Use the local-link address fe80::7009 */ + static const uint8_t ucAddress[ 16 ] = + { + 0xFEU, 0x80U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x70U, 0x09U + }; + + /* Test all combinations of what might go wrong. */ + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_METHOD ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_INTERFACE ); +} + +void test_prvProcessNetworkDownEvent_Global() +{ + /* Use the local-link address "2001:0470:ed44::7009" */ + static const uint8_t ucAddress[ 16 ] = + { + 0x20U, 0x01U, + 0x04U, 0x70U, + 0xEDU, 0x44U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x70U, 0x09U + }; + + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_METHOD ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_INTERFACE ); +} + +void test_prvProcessNetworkDownEvent_SiteLocal() +{ + /* Use the local-link address "fec0::7009" */ + static const uint8_t ucAddress[ 16 ] = + { + 0xFEU, 0xC0U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x70U, 0x09U + }; + + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_METHOD ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_INTERFACE ); +} + +void test_prvProcessNetworkDownEvent_Multicast() +{ + /* Use the multicast address "ff02::fb", + * just for the coverage of prvProcessNetworkDownEvent(). */ + static const uint8_t ucAddress[ 16 ] = + { + 0xFFU, 0x02U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0xFBU + }; + + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_METHOD ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_INTERFACE ); +} From 7b743e8dd3a7cae76ad763a6173d76fa68077305 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Fri, 12 Jan 2024 13:06:55 -0500 Subject: [PATCH 05/18] Converts the indexing variables to `size_t xIndex` and avoids inline for() declarations in DriverSAM/NetworkInterface.c Consolidates the solicited-node MAC and MLD management into a single function. Calls the new solicited-node address management function on network UP/DOWN events. --- source/FreeRTOS_IP.c | 44 +---- source/FreeRTOS_IP_Utils.c | 170 ++++++++++++++---- source/include/FreeRTOS_IP_Utils.h | 10 ++ .../DriverSAM/NetworkInterface.c | 59 +++--- 4 files changed, 175 insertions(+), 108 deletions(-) diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index f6dcd63c66..8e6c00be25 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -633,48 +633,10 @@ void vIPNetworkUpCalls( struct xNetworkEndPoint * pxEndPoint ) { if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) { + /* IPv6 end-points have a solicited-node addresses that needs extra housekeeping. */ #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - { - IPv6_Type_t xAddressType; - - /* Now that the network is up, pxEndPoint->ipv6_settings should hold the actual address of this - * end-point. For unicast addresses, generate the respective solicited-node multicast address. - * Note that the check below guards against the loopback address, the unspecified address, - * and against the weird scenario of someone assigning a multicast address to the end-point. */ - xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - - if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) - { - /* Tell the network driver to begin receiving this MAC address */ - if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) ) - { - MACAddress_t xMACAddress = { { - 0x33U, - 0x33U, - 0xFFU, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - } }; - pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); - } - else - { - /* The network driver does not implement this filtering function. Nothing we can do about it. */ - } - } /* if( xAddressType == ... ) */ - else - { - /* The address of this end-point is something other than a normal unicast address... Maybe it's the - * loopback address or maybe this is an error scenario. In any case, there is no corresponding - * solicited-node multicast address that we need to manage. Do nothing.*/ - } - } - #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ - } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ - else - { - /* This is an IPv4 end-point. There are no solicited-node addresses to manage. */ + vManageSolicitedNodeAddress( pxEndPoint, pdTRUE ); + #endif } pxEndPoint->bits.bEndPointUp = pdTRUE_UNSIGNED; diff --git a/source/FreeRTOS_IP_Utils.c b/source/FreeRTOS_IP_Utils.c index 7f7552bd81..5715dcad59 100644 --- a/source/FreeRTOS_IP_Utils.c +++ b/source/FreeRTOS_IP_Utils.c @@ -838,46 +838,10 @@ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ) if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) { + /* IPv6 end-points have a solicited-node addresses that needs extra housekeeping. */ #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - { - IPv6_Type_t xAddressType; - xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - - /* The check below guards against the loopback address, the unspecified address, - * and against the weird scenario of someone assigning a multicast address to the end-point. */ - if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) ) - { - /* Every network-up event adds the MAC address corresponding to this end-point's solicited node multicast address. - * Remove it here to balance out the number of add/remove calls. */ - if( ( pxEndPoint->pxNetworkInterface != NULL ) && ( pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC != NULL ) ) - { - MACAddress_t xMACAddress = { { - 0x33U, - 0x33U, - 0xFFU, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - } }; - pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); - } - else - { - /* The network driver does not implement this filtering function. Nothing we can do about it. */ - } - } /* if( xAddressType == ... ) */ - else - { - /* The address of this end-point is something other than a normal unicast address... Maybe it's the - * loopback address or maybe this is an error scenario. In any case, there is no corresponding - * solicited-node multicast address that we need to manage. Do nothing.*/ - } - } - #endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ - } /* if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) */ - else - { - /* This is an IPv4 end-point. There are no solicited-node addresses to manage. */ + vManageSolicitedNodeAddress( pxEndPoint, pdFALSE ); + #endif } #if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 ) @@ -1809,3 +1773,131 @@ uint16_t usChar2u16( const uint8_t * pucPtr ) ( ( ( uint32_t ) pucPtr[ 1 ] ) ) ); } /*-----------------------------------------------------------*/ + +/** + * @brief Every IPv6 end-point has a solicited node multicast address and a corresponding + * multicast MAC address. The IPv6 solicited node address also has an MLD reports associated + * with it. This functions manages both the MAC address and the MLD report associated with + * the end-point's solicited node address. On network UP, this function registers the MAC address + * with the network driver's filter and creates and MLD report for the UPv6 multicast address. + * On network DOWN, the function unregisters the MAC address and removes the MLD report. + * This is a "convenience" function that keeps all these tasks under one roof for easier maintenance. + * + * @param[in] pxEndPoint The end-point for which a network up/down event is being handled. + * @param[in] xNetworkGoingUp pdTRUE when the network goes UP, pdFALSE when the network goes DOWN. + */ +#if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, + BaseType_t xNetworkGoingUp ) + { + /* _EP_: I did my best to verify that both pxEndPoint and pxEndPoint->pxNetworkInterface cannot be + * NULL but I'm leaving the checks below until I get a second opinion. */ + configASSERT( pxEndPoint != NULL ); + configASSERT( pxEndPoint->pxNetworkInterface != NULL ); + + /* do{}while(0) to allow for the use of break statements */ + do + { + IPv6_Type_t xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + MACAddress_t xMACAddress = { { + 0x33U, + 0x33U, + 0xFFU, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + } }; + + /* During the very first network DOWN event, pxEndPoint->ipv6_settings will not hold the proper address yet and + * therefor the MAC address above will be incorrect as well, however nothing bad will happen, because the address + * type check below will kick us out before the call to pfRemoveAllowedMAC() */ + + /* Solicited-node multicast addresses only apply to normal unicast non-loopback addresses. */ + if( ( xAddressType != eIPv6_LinkLocal ) && ( xAddressType != eIPv6_SiteLocal ) && ( xAddressType != eIPv6_Global ) ) + { + /* The address of this end-point is something other than a normal unicast address... Maybe it's the + * loopback address or maybe this is an error scenario. In any case, there is no corresponding + * solicited-node multicast address that we need to manage. Do nothing.*/ + break; + } + + /* Update the network driver filter */ + if( xNetworkGoingUp == pdTRUE ) + { + if( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) + { + pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); + } + } + else + { + if( pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC != NULL ) + { + pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); + } + } + + #if ( ipconfigIS_ENABLED( ipconfigSUPPORT_IP_MULTICAST ) ) + { + MCastReportData_t * pxMRD; + + /* This is sub-optimal. We only need an IP_Address_t on network DOWN, however in the + * interest of having one piece of common code, we'll have a pointer that points to either + * xIPv6Address or &pxMRD->xMCastGroupAddress.xIPAddress */ + IP_Address_t * pxIPv6Address; + IP_Address_t xIPv6Address; + + if( xNetworkGoingUp == pdTRUE ) + { + /* We will need an MLD report structure a few lines down, so allocate one. */ + if( NULL == ( pxMRD = ( MCastReportData_t * ) pvPortMalloc( sizeof( MCastReportData_t ) ) ) ) + { + break; + } + + pxIPv6Address = &( pxMRD->xMCastGroupAddress.xIPAddress ); + } + else + { + pxIPv6Address = &xIPv6Address; + } + + /* Generate the solicited-node multicast address. It has the form of + * ff02::1:ffnn:nnnn, where nn:nnnn are the last 3 bytes of the IPv6 address. */ + pxIPv6Address->xIP_IPv6.ucBytes[ 0 ] = 0xFFU; + pxIPv6Address->xIP_IPv6.ucBytes[ 1 ] = 0x02U; + ( void ) memset( &( pxIPv6Address->xIP_IPv6.ucBytes[ 2 ] ), 0x00, 9 ); + pxIPv6Address->xIP_IPv6.ucBytes[ 11 ] = 0x01U; + pxIPv6Address->xIP_IPv6.ucBytes[ 12 ] = 0xFFU; + ( void ) memcpy( &( pxIPv6Address->xIP_IPv6.ucBytes[ 13 ] ), &pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], 3 ); + + if( xNetworkGoingUp == pdTRUE ) + { + /* Network going UP. Generate and enlist an MLD report for the solicited node multicast address. */ + listSET_LIST_ITEM_OWNER( &( pxMRD->xListItem ), ( void * ) pxMRD ); + pxMRD->pxInterface = pxEndPoint->pxNetworkInterface; + pxMRD->xMCastGroupAddress.xIs_IPv6 = pdTRUE_UNSIGNED; + /* pxMRD->xMCastGroupAddress.xIPAddress was filled out through pxIPv6Address above.*/ + + if( xEnlistMulticastReport( pxMRD ) == pdFALSE ) + { + /* The report data was not consumed. This is odd since we are dealing with + * the solicited-node multicast address and there should not have been a report + * enlisted for it already. Anyway, keep things clean. */ + vPortFree( pxMRD ); + pxMRD = NULL; + } + } + else + { + /* Network going DOWN. De-list the MLD report for the solicited node multicast address. + * Todo: Check if there are other places that this same action needs to be taken. + * Places like when DHCPv6 or RA releases an address. Needs further investigation. */ + vDelistMulticastReport( pxEndPoint->pxNetworkInterface, pxIPv6Address, pdTRUE_UNSIGNED ); + } + } + #endif /* ipconfigIS_ENABLED( ipconfigSUPPORT_IP_MULTICAST ) */ + } while( pdFALSE ); + } +#endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/source/include/FreeRTOS_IP_Utils.h b/source/include/FreeRTOS_IP_Utils.h index f34255d8de..5ddfdae65f 100644 --- a/source/include/FreeRTOS_IP_Utils.h +++ b/source/include/FreeRTOS_IP_Utils.h @@ -103,6 +103,16 @@ void vPreCheckConfigs( void ); */ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ); +#if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + +/** + * @brief Called for IPv6 end-points on network up/down events. + * The function manages the MAC address and MLD report associated with the end-point's address. + */ + void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, + BaseType_t xNetworkGoingUp ); +#endif + /* *INDENT-OFF* */ #ifdef __cplusplus } /* extern "C" */ diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 0d9c0ea54c..0a302495dc 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -689,6 +689,7 @@ static BaseType_t prvSAM_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) { NetworkEndPoint_t * pxEndPoint; + size_t xIndex; gmac_options_t gmac_option; @@ -717,10 +718,10 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) * and hash match registers, so undo the setting of the first specific MAC register. */ /* Disable all specific MAC address match registers */ - for( int i = 0; i < GMACSA_NUMBER; i++ ) + for( xIndex = 0; xIndex < GMACSA_NUMBER; xIndex++ ) { /* Writing the bottom register disable this specific MAC register. */ - GMAC->GMAC_SA[ i ].GMAC_SAB = 0; + GMAC->GMAC_SA[ xIndex ].GMAC_SAB = 0; } /* Clear the hash table for unicast/multicast MAC addresses. */ @@ -904,7 +905,8 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) * registers have been used. */ /* Note: Only called from the IPTask, so no thread-safety is required. */ - uint8_t ucHashBit, ucIsMulticast, i, ucEmptyIndex; + uint8_t ucHashBit, ucIsMulticast; + size_t xIndex, xEmptyIndex; uint32_t ulSAB, ulSAT; @@ -922,18 +924,18 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) ulSAT = ( pucMacAddress[ 5 ] << 8 ) | ( pucMacAddress[ 4 ] ); /* Always try to find a match within the specific match registers first. */ - ucEmptyIndex = GMACSA_NUMBER; + xEmptyIndex = GMACSA_NUMBER; - for( i = 0; i < GMACSA_NUMBER; i++ ) + for( xIndex = 0; xIndex < GMACSA_NUMBER; xIndex++ ) { - if( prvSpecificMatchCounters[ i ] > 0U ) + if( prvSpecificMatchCounters[ xIndex ] > 0U ) { /* This specific match register is being used. Check if the address is the same. */ - if( ( ulSAB == GMAC->GMAC_SA[ i ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ i ].GMAC_SAT ) ) + if( ( ulSAB == GMAC->GMAC_SA[ xIndex ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ xIndex ].GMAC_SAT ) ) { /* Exact match! Increment the counter and leave. */ - prvSpecificMatchCounters[ i ]++; - /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", i, prvSpecificMatchCounters[ i ] ); */ + prvSpecificMatchCounters[ xIndex ]++; + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", xIndex, prvSpecificMatchCounters[ xIndex ] ); */ break; } else @@ -945,28 +947,28 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) { /* This specific match register is empty. * Keep track of the first empty register in case we need to use it. */ - if( ucEmptyIndex >= GMACSA_NUMBER ) + if( xEmptyIndex >= GMACSA_NUMBER ) { - ucEmptyIndex = i; + xEmptyIndex = xIndex; } else { /* We have already found an empty specific match register. Do nothing. */ } } - } /* for( i = 0; i < GMACSA_NUMBER; i++ ) */ + } /* for( xIndex = 0; xIndex < GMACSA_NUMBER; xIndex++ ) */ /* do{}while(0) to allow the use of break statements. */ do { - if( i < GMACSA_NUMBER ) + if( xIndex < GMACSA_NUMBER ) { /* An exact match was found in the for(;;) loop above. Do nothing. */ break; } /* No exact match found in the specific match registers, but is one of them empty? */ - if( ucEmptyIndex < GMACSA_NUMBER ) + if( xEmptyIndex < GMACSA_NUMBER ) { /* There is an empty slot in the specific match registers. Using this empty slot should * be a priority, except if the hash register already covers the MAC address we were given @@ -977,9 +979,9 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) ( prvAddressHashCounters[ ucHashBit ] == 0 ) /* hash matching doesn't cover this address yet. */ ) { /* In all cases above, simply add to the empty specific match register. */ - gmac_set_address( GMAC, ucEmptyIndex, pucMacAddress ); - prvSpecificMatchCounters[ ucEmptyIndex ] = 1U; - /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: ADD at %u, new counter %u", ucEmptyIndex, prvSpecificMatchCounters[ ucEmptyIndex ] ); */ + gmac_set_address( GMAC, xEmptyIndex, pucMacAddress ); + prvSpecificMatchCounters[ xEmptyIndex ] = 1U; + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: ADD at %u, new counter %u", xEmptyIndex, prvSpecificMatchCounters[ xEmptyIndex ] ); */ break; } } @@ -1027,8 +1029,9 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) { /* Note: Only called from the IPTask, so no thread-safety is required. */ - uint8_t ucHashBit, i; + uint8_t ucHashBit; uint32_t ulSAB, ulSAT; + size_t xIndex; configASSERT( NULL != pucMacAddress ); @@ -1043,33 +1046,33 @@ static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) ulSAT = ( pucMacAddress[ 5 ] << 8 ) | ( pucMacAddress[ 4 ] ); /* Check the specific match registers first. */ - for( i = 0; i < GMACSA_NUMBER; i++ ) + for( xIndex = 0; xIndex < GMACSA_NUMBER; xIndex++ ) { - if( ( prvSpecificMatchCounters[ i ] > 0U ) && ( ulSAB == GMAC->GMAC_SA[ i ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ i ].GMAC_SAT ) ) + if( ( prvSpecificMatchCounters[ xIndex ] > 0U ) && ( ulSAB == GMAC->GMAC_SA[ xIndex ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ xIndex ].GMAC_SAT ) ) { /* Exact match! Decrement the counter unless it's maxed out. */ - if( prvSpecificMatchCounters[ i ] < UINT8_MAX ) + if( prvSpecificMatchCounters[ xIndex ] < UINT8_MAX ) { - prvSpecificMatchCounters[ i ]--; + prvSpecificMatchCounters[ xIndex ]--; } - if( prvSpecificMatchCounters[ i ] == 0 ) + if( prvSpecificMatchCounters[ xIndex ] == 0 ) { - /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, INDEX DISABLED", i ); */ + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, INDEX DISABLED", xIndex ); */ /* This specific match register counter is now zero. Disable it by writing it in reverse order. */ - GMAC->GMAC_SA[ i ].GMAC_SAT = 0U; /* This is not needed, just clears out the top register.*/ - GMAC->GMAC_SA[ i ].GMAC_SAB = 0U; /* Writing the bottom register disables this specific match register. */ + GMAC->GMAC_SA[ xIndex ].GMAC_SAT = 0U; /* This is not needed, just clears out the top register.*/ + GMAC->GMAC_SA[ xIndex ].GMAC_SAB = 0U; /* Writing the bottom register disables this specific match register. */ } else { - /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", i, prvSpecificMatchCounters[ i ] ); */ + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", xIndex, prvSpecificMatchCounters[ xIndex ] ); */ } break; } } - if( i >= GMACSA_NUMBER ) + if( xIndex >= GMACSA_NUMBER ) { /* The MAC address was not found amongst the specific match registers, check the hash register. */ if( prvAddressHashCounters[ ucHashBit ] > 0 ) From 08649f5d37da42e30939b7b7acf8a9ebf745267f Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Sun, 14 Jan 2024 11:28:11 -0500 Subject: [PATCH 06/18] Update some comments Rewrites the generation of the solicited-node multicast IPv6 address. Thanks @htibosch Sprits the allocation and NULL check when allocating an MLD report. Thanks @AniruddhaKanhere --- source/FreeRTOS_IP.c | 2 +- source/FreeRTOS_IP_Utils.c | 39 ++++++++++++++++++------------ source/include/FreeRTOS_IP_Utils.h | 3 +++ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/source/FreeRTOS_IP.c b/source/FreeRTOS_IP.c index 8e6c00be25..e1853cb76f 100644 --- a/source/FreeRTOS_IP.c +++ b/source/FreeRTOS_IP.c @@ -633,7 +633,7 @@ void vIPNetworkUpCalls( struct xNetworkEndPoint * pxEndPoint ) { if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) { - /* IPv6 end-points have a solicited-node addresses that needs extra housekeeping. */ + /* IPv6 end-points have a solicited-node address that needs extra housekeeping. */ #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) vManageSolicitedNodeAddress( pxEndPoint, pdTRUE ); #endif diff --git a/source/FreeRTOS_IP_Utils.c b/source/FreeRTOS_IP_Utils.c index 5715dcad59..2e0c923c04 100644 --- a/source/FreeRTOS_IP_Utils.c +++ b/source/FreeRTOS_IP_Utils.c @@ -838,7 +838,7 @@ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ) if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED ) { - /* IPv6 end-points have a solicited-node addresses that needs extra housekeeping. */ + /* IPv6 end-points have a solicited-node address that needs extra housekeeping. */ #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) vManageSolicitedNodeAddress( pxEndPoint, pdFALSE ); #endif @@ -1777,8 +1777,8 @@ uint16_t usChar2u16( const uint8_t * pucPtr ) /** * @brief Every IPv6 end-point has a solicited node multicast address and a corresponding * multicast MAC address. The IPv6 solicited node address also has an MLD reports associated - * with it. This functions manages both the MAC address and the MLD report associated with - * the end-point's solicited node address. On network UP, this function registers the MAC address + * with it. This function manages both the MAC address and the MLD report associated with + * the end-point's solicited-node address. On network UP, this function registers the MAC address * with the network driver's filter and creates and MLD report for the UPv6 multicast address. * On network DOWN, the function unregisters the MAC address and removes the MLD report. * This is a "convenience" function that keeps all these tasks under one roof for easier maintenance. @@ -1790,8 +1790,6 @@ uint16_t usChar2u16( const uint8_t * pucPtr ) void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, BaseType_t xNetworkGoingUp ) { - /* _EP_: I did my best to verify that both pxEndPoint and pxEndPoint->pxNetworkInterface cannot be - * NULL but I'm leaving the checks below until I get a second opinion. */ configASSERT( pxEndPoint != NULL ); configASSERT( pxEndPoint->pxNetworkInterface != NULL ); @@ -1808,9 +1806,10 @@ uint16_t usChar2u16( const uint8_t * pucPtr ) pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] } }; - /* During the very first network DOWN event, pxEndPoint->ipv6_settings will not hold the proper address yet and - * therefor the MAC address above will be incorrect as well, however nothing bad will happen, because the address - * type check below will kick us out before the call to pfRemoveAllowedMAC() */ + /* During the very first network DOWN event, pxEndPoint->ipv6_settings does not yet hold the proper address and + * therefore the MAC address above will be incorrect as well, however nothing bad will happen, because the address + * type check below will kick us out before the call to pfRemoveAllowedMAC(). Without the check below, the network + * driver end up being called once to register 33:33:FF:00:00:00 and that MAC never gets unregistered. */ /* Solicited-node multicast addresses only apply to normal unicast non-loopback addresses. */ if( ( xAddressType != eIPv6_LinkLocal ) && ( xAddressType != eIPv6_SiteLocal ) && ( xAddressType != eIPv6_Global ) ) @@ -1850,7 +1849,9 @@ uint16_t usChar2u16( const uint8_t * pucPtr ) if( xNetworkGoingUp == pdTRUE ) { /* We will need an MLD report structure a few lines down, so allocate one. */ - if( NULL == ( pxMRD = ( MCastReportData_t * ) pvPortMalloc( sizeof( MCastReportData_t ) ) ) ) + pxMRD = ( MCastReportData_t * ) pvPortMalloc( sizeof( MCastReportData_t ) ); + + if( pxMRD == NULL ) { break; } @@ -1864,12 +1865,20 @@ uint16_t usChar2u16( const uint8_t * pucPtr ) /* Generate the solicited-node multicast address. It has the form of * ff02::1:ffnn:nnnn, where nn:nnnn are the last 3 bytes of the IPv6 address. */ - pxIPv6Address->xIP_IPv6.ucBytes[ 0 ] = 0xFFU; - pxIPv6Address->xIP_IPv6.ucBytes[ 1 ] = 0x02U; - ( void ) memset( &( pxIPv6Address->xIP_IPv6.ucBytes[ 2 ] ), 0x00, 9 ); - pxIPv6Address->xIP_IPv6.ucBytes[ 11 ] = 0x01U; - pxIPv6Address->xIP_IPv6.ucBytes[ 12 ] = 0xFFU; - ( void ) memcpy( &( pxIPv6Address->xIP_IPv6.ucBytes[ 13 ] ), &pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], 3 ); + do + { + uint8_t * pucTarget = pxIPv6Address->xIP_IPv6.ucBytes; + uint8_t * pucSource = pxEndPoint->ipv6_settings.xIPAddress.ucBytes; + + pucTarget[ 0 ] = 0xFFU; + pucTarget[ 1 ] = 0x02U; + ( void ) memset( &( pucTarget[ 2 ] ), 0x00, 9 ); + pucTarget[ 11 ] = 0x01U; + pucTarget[ 12 ] = 0xFFU; + pucTarget[ 13 ] = pucSource[ 13 ]; + pucTarget[ 14 ] = pucSource[ 14 ]; + pucTarget[ 15 ] = pucSource[ 15 ]; + } while( pdFALSE ); if( xNetworkGoingUp == pdTRUE ) { diff --git a/source/include/FreeRTOS_IP_Utils.h b/source/include/FreeRTOS_IP_Utils.h index 5ddfdae65f..325f92b48d 100644 --- a/source/include/FreeRTOS_IP_Utils.h +++ b/source/include/FreeRTOS_IP_Utils.h @@ -108,6 +108,9 @@ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ); /** * @brief Called for IPv6 end-points on network up/down events. * The function manages the MAC address and MLD report associated with the end-point's address. + * + * @param[in] pxEndPoint The end-point for which a network up/down event is being handled. + * @param[in] xNetworkGoingUp pdTRUE when the network goes UP, pdFALSE when the network goes DOWN. */ void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, BaseType_t xNetworkGoingUp ); From 9b59845ee3946d448a9e57ce9629e504978e02c4 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Tue, 16 Jan 2024 08:00:45 -0500 Subject: [PATCH 07/18] Moves vManageSolicitedNodeAddress() from FreeRTOS_IP_Utils.c to FreeRTOS_IPv6_Utils.c Changes some indexing variables prefix to "ux" --- source/FreeRTOS_IP_Utils.c | 137 ------------------ source/FreeRTOS_IPv6_Utils.c | 135 +++++++++++++++++ source/include/FreeRTOS_IP_Utils.h | 12 -- source/include/FreeRTOS_IPv6_Utils.h | 3 + .../DriverSAM/NetworkInterface.c | 58 ++++---- 5 files changed, 167 insertions(+), 178 deletions(-) diff --git a/source/FreeRTOS_IP_Utils.c b/source/FreeRTOS_IP_Utils.c index 2e0c923c04..ce21a86f9d 100644 --- a/source/FreeRTOS_IP_Utils.c +++ b/source/FreeRTOS_IP_Utils.c @@ -1773,140 +1773,3 @@ uint16_t usChar2u16( const uint8_t * pucPtr ) ( ( ( uint32_t ) pucPtr[ 1 ] ) ) ); } /*-----------------------------------------------------------*/ - -/** - * @brief Every IPv6 end-point has a solicited node multicast address and a corresponding - * multicast MAC address. The IPv6 solicited node address also has an MLD reports associated - * with it. This function manages both the MAC address and the MLD report associated with - * the end-point's solicited-node address. On network UP, this function registers the MAC address - * with the network driver's filter and creates and MLD report for the UPv6 multicast address. - * On network DOWN, the function unregisters the MAC address and removes the MLD report. - * This is a "convenience" function that keeps all these tasks under one roof for easier maintenance. - * - * @param[in] pxEndPoint The end-point for which a network up/down event is being handled. - * @param[in] xNetworkGoingUp pdTRUE when the network goes UP, pdFALSE when the network goes DOWN. - */ -#if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, - BaseType_t xNetworkGoingUp ) - { - configASSERT( pxEndPoint != NULL ); - configASSERT( pxEndPoint->pxNetworkInterface != NULL ); - - /* do{}while(0) to allow for the use of break statements */ - do - { - IPv6_Type_t xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - MACAddress_t xMACAddress = { { - 0x33U, - 0x33U, - 0xFFU, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - } }; - - /* During the very first network DOWN event, pxEndPoint->ipv6_settings does not yet hold the proper address and - * therefore the MAC address above will be incorrect as well, however nothing bad will happen, because the address - * type check below will kick us out before the call to pfRemoveAllowedMAC(). Without the check below, the network - * driver end up being called once to register 33:33:FF:00:00:00 and that MAC never gets unregistered. */ - - /* Solicited-node multicast addresses only apply to normal unicast non-loopback addresses. */ - if( ( xAddressType != eIPv6_LinkLocal ) && ( xAddressType != eIPv6_SiteLocal ) && ( xAddressType != eIPv6_Global ) ) - { - /* The address of this end-point is something other than a normal unicast address... Maybe it's the - * loopback address or maybe this is an error scenario. In any case, there is no corresponding - * solicited-node multicast address that we need to manage. Do nothing.*/ - break; - } - - /* Update the network driver filter */ - if( xNetworkGoingUp == pdTRUE ) - { - if( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) - { - pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); - } - } - else - { - if( pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC != NULL ) - { - pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); - } - } - - #if ( ipconfigIS_ENABLED( ipconfigSUPPORT_IP_MULTICAST ) ) - { - MCastReportData_t * pxMRD; - - /* This is sub-optimal. We only need an IP_Address_t on network DOWN, however in the - * interest of having one piece of common code, we'll have a pointer that points to either - * xIPv6Address or &pxMRD->xMCastGroupAddress.xIPAddress */ - IP_Address_t * pxIPv6Address; - IP_Address_t xIPv6Address; - - if( xNetworkGoingUp == pdTRUE ) - { - /* We will need an MLD report structure a few lines down, so allocate one. */ - pxMRD = ( MCastReportData_t * ) pvPortMalloc( sizeof( MCastReportData_t ) ); - - if( pxMRD == NULL ) - { - break; - } - - pxIPv6Address = &( pxMRD->xMCastGroupAddress.xIPAddress ); - } - else - { - pxIPv6Address = &xIPv6Address; - } - - /* Generate the solicited-node multicast address. It has the form of - * ff02::1:ffnn:nnnn, where nn:nnnn are the last 3 bytes of the IPv6 address. */ - do - { - uint8_t * pucTarget = pxIPv6Address->xIP_IPv6.ucBytes; - uint8_t * pucSource = pxEndPoint->ipv6_settings.xIPAddress.ucBytes; - - pucTarget[ 0 ] = 0xFFU; - pucTarget[ 1 ] = 0x02U; - ( void ) memset( &( pucTarget[ 2 ] ), 0x00, 9 ); - pucTarget[ 11 ] = 0x01U; - pucTarget[ 12 ] = 0xFFU; - pucTarget[ 13 ] = pucSource[ 13 ]; - pucTarget[ 14 ] = pucSource[ 14 ]; - pucTarget[ 15 ] = pucSource[ 15 ]; - } while( pdFALSE ); - - if( xNetworkGoingUp == pdTRUE ) - { - /* Network going UP. Generate and enlist an MLD report for the solicited node multicast address. */ - listSET_LIST_ITEM_OWNER( &( pxMRD->xListItem ), ( void * ) pxMRD ); - pxMRD->pxInterface = pxEndPoint->pxNetworkInterface; - pxMRD->xMCastGroupAddress.xIs_IPv6 = pdTRUE_UNSIGNED; - /* pxMRD->xMCastGroupAddress.xIPAddress was filled out through pxIPv6Address above.*/ - - if( xEnlistMulticastReport( pxMRD ) == pdFALSE ) - { - /* The report data was not consumed. This is odd since we are dealing with - * the solicited-node multicast address and there should not have been a report - * enlisted for it already. Anyway, keep things clean. */ - vPortFree( pxMRD ); - pxMRD = NULL; - } - } - else - { - /* Network going DOWN. De-list the MLD report for the solicited node multicast address. - * Todo: Check if there are other places that this same action needs to be taken. - * Places like when DHCPv6 or RA releases an address. Needs further investigation. */ - vDelistMulticastReport( pxEndPoint->pxNetworkInterface, pxIPv6Address, pdTRUE_UNSIGNED ); - } - } - #endif /* ipconfigIS_ENABLED( ipconfigSUPPORT_IP_MULTICAST ) */ - } while( pdFALSE ); - } -#endif /* ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ -/*-----------------------------------------------------------*/ diff --git a/source/FreeRTOS_IPv6_Utils.c b/source/FreeRTOS_IPv6_Utils.c index 848395a89f..0cedfa20c4 100644 --- a/source/FreeRTOS_IPv6_Utils.c +++ b/source/FreeRTOS_IPv6_Utils.c @@ -283,6 +283,141 @@ size_t usGetExtensionHeaderLength( const uint8_t * pucEthernetBuffer, } /*-----------------------------------------------------------*/ +/** + * @brief Every IPv6 end-point has a solicited node multicast address and a corresponding + * multicast MAC address. The IPv6 solicited node address also has an MLD reports associated + * with it. This function manages both the MAC address and the MLD report associated with + * the end-point's solicited-node address. On network UP, this function registers the MAC address + * with the network driver's filter and creates and MLD report for the UPv6 multicast address. + * On network DOWN, the function unregisters the MAC address and removes the MLD report. + * This is a "convenience" function that keeps all these tasks under one roof for easier maintenance. + * + * @param[in] pxEndPoint The end-point for which a network up/down event is being handled. + * @param[in] xNetworkGoingUp pdTRUE when the network goes UP, pdFALSE when the network goes DOWN. + */ +void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, + BaseType_t xNetworkGoingUp ) +{ + configASSERT( pxEndPoint != NULL ); + configASSERT( pxEndPoint->pxNetworkInterface != NULL ); + + /* do{}while(0) to allow for the use of break statements */ + do + { + IPv6_Type_t xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + MACAddress_t xMACAddress = { { + 0x33U, + 0x33U, + 0xFFU, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + } }; + + /* During the very first network DOWN event, pxEndPoint->ipv6_settings does not yet hold the proper address and + * therefore the MAC address above will be incorrect as well, however nothing bad will happen, because the address + * type check below will kick us out before the call to pfRemoveAllowedMAC(). Without the check below, the network + * driver end up being called once to register 33:33:FF:00:00:00 and that MAC never gets unregistered. */ + + /* Solicited-node multicast addresses only apply to normal unicast non-loopback addresses. */ + if( ( xAddressType != eIPv6_LinkLocal ) && ( xAddressType != eIPv6_SiteLocal ) && ( xAddressType != eIPv6_Global ) ) + { + /* The address of this end-point is something other than a normal unicast address... Maybe it's the + * loopback address or maybe this is an error scenario. In any case, there is no corresponding + * solicited-node multicast address that we need to manage. Do nothing.*/ + break; + } + + /* Update the network driver filter */ + if( xNetworkGoingUp == pdTRUE ) + { + if( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) + { + pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); + } + } + else + { + if( pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC != NULL ) + { + pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); + } + } + + #if ( ipconfigIS_ENABLED( ipconfigSUPPORT_IP_MULTICAST ) ) + { + MCastReportData_t * pxMRD; + + /* This is sub-optimal. We only need an IP_Address_t on network DOWN, however in the + * interest of having one piece of common code, we'll have a pointer that points to either + * xIPv6Address or &pxMRD->xMCastGroupAddress.xIPAddress */ + IP_Address_t * pxIPv6Address; + IP_Address_t xIPv6Address; + + if( xNetworkGoingUp == pdTRUE ) + { + /* We will need an MLD report structure a few lines down, so allocate one. */ + pxMRD = ( MCastReportData_t * ) pvPortMalloc( sizeof( MCastReportData_t ) ); + + if( pxMRD == NULL ) + { + break; + } + + pxIPv6Address = &( pxMRD->xMCastGroupAddress.xIPAddress ); + } + else + { + pxIPv6Address = &xIPv6Address; + } + + /* Generate the solicited-node multicast address. It has the form of + * ff02::1:ffnn:nnnn, where nn:nnnn are the last 3 bytes of the IPv6 address. */ + do + { + uint8_t * pucTarget = pxIPv6Address->xIP_IPv6.ucBytes; + uint8_t * pucSource = pxEndPoint->ipv6_settings.xIPAddress.ucBytes; + + pucTarget[ 0 ] = 0xFFU; + pucTarget[ 1 ] = 0x02U; + ( void ) memset( &( pucTarget[ 2 ] ), 0x00, 9 ); + pucTarget[ 11 ] = 0x01U; + pucTarget[ 12 ] = 0xFFU; + pucTarget[ 13 ] = pucSource[ 13 ]; + pucTarget[ 14 ] = pucSource[ 14 ]; + pucTarget[ 15 ] = pucSource[ 15 ]; + } while( pdFALSE ); + + if( xNetworkGoingUp == pdTRUE ) + { + /* Network going UP. Generate and enlist an MLD report for the solicited node multicast address. */ + listSET_LIST_ITEM_OWNER( &( pxMRD->xListItem ), ( void * ) pxMRD ); + pxMRD->pxInterface = pxEndPoint->pxNetworkInterface; + pxMRD->xMCastGroupAddress.xIs_IPv6 = pdTRUE_UNSIGNED; + /* pxMRD->xMCastGroupAddress.xIPAddress was filled out through pxIPv6Address above.*/ + + if( xEnlistMulticastReport( pxMRD ) == pdFALSE ) + { + /* The report data was not consumed. This is odd since we are dealing with + * the solicited-node multicast address and there should not have been a report + * enlisted for it already. Anyway, keep things clean. */ + vPortFree( pxMRD ); + pxMRD = NULL; + } + } + else + { + /* Network going DOWN. De-list the MLD report for the solicited node multicast address. + * Todo: Check if there are other places that this same action needs to be taken. + * Places like when DHCPv6 or RA releases an address. Needs further investigation. */ + vDelistMulticastReport( pxEndPoint->pxNetworkInterface, pxIPv6Address, pdTRUE_UNSIGNED ); + } + } + #endif /* ipconfigIS_ENABLED( ipconfigSUPPORT_IP_MULTICAST ) */ + } while( pdFALSE ); +} +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #endif /* ( ipconfigUSE_IPv6 != 0 ) */ /* *INDENT-ON* */ diff --git a/source/include/FreeRTOS_IP_Utils.h b/source/include/FreeRTOS_IP_Utils.h index 325f92b48d..09304c63db 100644 --- a/source/include/FreeRTOS_IP_Utils.h +++ b/source/include/FreeRTOS_IP_Utils.h @@ -103,18 +103,6 @@ void vPreCheckConfigs( void ); */ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface ); -#if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - -/** - * @brief Called for IPv6 end-points on network up/down events. - * The function manages the MAC address and MLD report associated with the end-point's address. - * - * @param[in] pxEndPoint The end-point for which a network up/down event is being handled. - * @param[in] xNetworkGoingUp pdTRUE when the network goes UP, pdFALSE when the network goes DOWN. - */ - void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, - BaseType_t xNetworkGoingUp ); -#endif /* *INDENT-OFF* */ #ifdef __cplusplus diff --git a/source/include/FreeRTOS_IPv6_Utils.h b/source/include/FreeRTOS_IPv6_Utils.h index 34f23e9855..2af9079ac5 100644 --- a/source/include/FreeRTOS_IPv6_Utils.h +++ b/source/include/FreeRTOS_IPv6_Utils.h @@ -66,6 +66,9 @@ size_t usGetExtensionHeaderLength( const uint8_t * pucEthernetBuffer, size_t uxBufferLength, uint8_t * pucProtocol ); +void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, + BaseType_t xNetworkGoingUp ); + /* *INDENT-OFF* */ #ifdef __cplusplus } /* extern "C" */ diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 0a302495dc..f3d9bf5268 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -689,7 +689,7 @@ static BaseType_t prvSAM_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) { NetworkEndPoint_t * pxEndPoint; - size_t xIndex; + size_t uxIndex; gmac_options_t gmac_option; @@ -718,10 +718,10 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) * and hash match registers, so undo the setting of the first specific MAC register. */ /* Disable all specific MAC address match registers */ - for( xIndex = 0; xIndex < GMACSA_NUMBER; xIndex++ ) + for( uxIndex = 0; uxIndex < GMACSA_NUMBER; uxIndex++ ) { /* Writing the bottom register disable this specific MAC register. */ - GMAC->GMAC_SA[ xIndex ].GMAC_SAB = 0; + GMAC->GMAC_SA[ uxIndex ].GMAC_SAB = 0; } /* Clear the hash table for unicast/multicast MAC addresses. */ @@ -906,7 +906,7 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) /* Note: Only called from the IPTask, so no thread-safety is required. */ uint8_t ucHashBit, ucIsMulticast; - size_t xIndex, xEmptyIndex; + size_t uxIndex, uxEmptyIndex; uint32_t ulSAB, ulSAT; @@ -924,18 +924,18 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) ulSAT = ( pucMacAddress[ 5 ] << 8 ) | ( pucMacAddress[ 4 ] ); /* Always try to find a match within the specific match registers first. */ - xEmptyIndex = GMACSA_NUMBER; + uxEmptyIndex = GMACSA_NUMBER; - for( xIndex = 0; xIndex < GMACSA_NUMBER; xIndex++ ) + for( uxIndex = 0; uxIndex < GMACSA_NUMBER; uxIndex++ ) { - if( prvSpecificMatchCounters[ xIndex ] > 0U ) + if( prvSpecificMatchCounters[ uxIndex ] > 0U ) { /* This specific match register is being used. Check if the address is the same. */ - if( ( ulSAB == GMAC->GMAC_SA[ xIndex ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ xIndex ].GMAC_SAT ) ) + if( ( ulSAB == GMAC->GMAC_SA[ uxIndex ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ uxIndex ].GMAC_SAT ) ) { /* Exact match! Increment the counter and leave. */ - prvSpecificMatchCounters[ xIndex ]++; - /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", xIndex, prvSpecificMatchCounters[ xIndex ] ); */ + prvSpecificMatchCounters[ uxIndex ]++; + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", uxIndex, prvSpecificMatchCounters[ uxIndex ] ); */ break; } else @@ -947,28 +947,28 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) { /* This specific match register is empty. * Keep track of the first empty register in case we need to use it. */ - if( xEmptyIndex >= GMACSA_NUMBER ) + if( uxEmptyIndex >= GMACSA_NUMBER ) { - xEmptyIndex = xIndex; + uxEmptyIndex = uxIndex; } else { /* We have already found an empty specific match register. Do nothing. */ } } - } /* for( xIndex = 0; xIndex < GMACSA_NUMBER; xIndex++ ) */ + } /* for( uxIndex = 0; uxIndex < GMACSA_NUMBER; uxIndex++ ) */ /* do{}while(0) to allow the use of break statements. */ do { - if( xIndex < GMACSA_NUMBER ) + if( uxIndex < GMACSA_NUMBER ) { /* An exact match was found in the for(;;) loop above. Do nothing. */ break; } /* No exact match found in the specific match registers, but is one of them empty? */ - if( xEmptyIndex < GMACSA_NUMBER ) + if( uxEmptyIndex < GMACSA_NUMBER ) { /* There is an empty slot in the specific match registers. Using this empty slot should * be a priority, except if the hash register already covers the MAC address we were given @@ -979,9 +979,9 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) ( prvAddressHashCounters[ ucHashBit ] == 0 ) /* hash matching doesn't cover this address yet. */ ) { /* In all cases above, simply add to the empty specific match register. */ - gmac_set_address( GMAC, xEmptyIndex, pucMacAddress ); - prvSpecificMatchCounters[ xEmptyIndex ] = 1U; - /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: ADD at %u, new counter %u", xEmptyIndex, prvSpecificMatchCounters[ xEmptyIndex ] ); */ + gmac_set_address( GMAC, uxEmptyIndex, pucMacAddress ); + prvSpecificMatchCounters[ uxEmptyIndex ] = 1U; + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: ADD at %u, new counter %u", uxEmptyIndex, prvSpecificMatchCounters[ uxEmptyIndex ] ); */ break; } } @@ -1031,7 +1031,7 @@ static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) /* Note: Only called from the IPTask, so no thread-safety is required. */ uint8_t ucHashBit; uint32_t ulSAB, ulSAT; - size_t xIndex; + size_t uxIndex; configASSERT( NULL != pucMacAddress ); @@ -1046,33 +1046,33 @@ static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) ulSAT = ( pucMacAddress[ 5 ] << 8 ) | ( pucMacAddress[ 4 ] ); /* Check the specific match registers first. */ - for( xIndex = 0; xIndex < GMACSA_NUMBER; xIndex++ ) + for( uxIndex = 0; uxIndex < GMACSA_NUMBER; uxIndex++ ) { - if( ( prvSpecificMatchCounters[ xIndex ] > 0U ) && ( ulSAB == GMAC->GMAC_SA[ xIndex ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ xIndex ].GMAC_SAT ) ) + if( ( prvSpecificMatchCounters[ uxIndex ] > 0U ) && ( ulSAB == GMAC->GMAC_SA[ uxIndex ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ uxIndex ].GMAC_SAT ) ) { /* Exact match! Decrement the counter unless it's maxed out. */ - if( prvSpecificMatchCounters[ xIndex ] < UINT8_MAX ) + if( prvSpecificMatchCounters[ uxIndex ] < UINT8_MAX ) { - prvSpecificMatchCounters[ xIndex ]--; + prvSpecificMatchCounters[ uxIndex ]--; } - if( prvSpecificMatchCounters[ xIndex ] == 0 ) + if( prvSpecificMatchCounters[ uxIndex ] == 0 ) { - /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, INDEX DISABLED", xIndex ); */ + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, INDEX DISABLED", uxIndex ); */ /* This specific match register counter is now zero. Disable it by writing it in reverse order. */ - GMAC->GMAC_SA[ xIndex ].GMAC_SAT = 0U; /* This is not needed, just clears out the top register.*/ - GMAC->GMAC_SA[ xIndex ].GMAC_SAB = 0U; /* Writing the bottom register disables this specific match register. */ + GMAC->GMAC_SA[ uxIndex ].GMAC_SAT = 0U; /* This is not needed, just clears out the top register.*/ + GMAC->GMAC_SA[ uxIndex ].GMAC_SAB = 0U; /* Writing the bottom register disables this specific match register. */ } else { - /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", xIndex, prvSpecificMatchCounters[ xIndex ] ); */ + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", uxIndex, prvSpecificMatchCounters[ uxIndex ] ); */ } break; } } - if( xIndex >= GMACSA_NUMBER ) + if( uxIndex >= GMACSA_NUMBER ) { /* The MAC address was not found amongst the specific match registers, check the hash register. */ if( prvAddressHashCounters[ ucHashBit ] > 0 ) From 2dd7a81e0857abedcd7bc319978692d03d4515b7 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Thu, 18 Jan 2024 09:23:06 -0500 Subject: [PATCH 08/18] Adds a macros for easy checking if a MAC address is unicast or multicast. Improves the readability of the SAME70 hash register code by adding a bunch of macros and defines Moves all hash register macros anad variables to the top of NetworkInterface.c where they belong. --- source/include/NetworkInterface.h | 3 + .../DriverSAM/NetworkInterface.c | 63 ++++++++++++------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/source/include/NetworkInterface.h b/source/include/NetworkInterface.h index a9c804cd8d..50b354ca9d 100644 --- a/source/include/NetworkInterface.h +++ b/source/include/NetworkInterface.h @@ -52,6 +52,9 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB BaseType_t xGetPhyLinkStatus( struct xNetworkInterface * pxInterface ); +#define MAC_IS_MULTICAST( pucMACAddressBytes ) ( ( pucMACAddressBytes[ 0 ] & 1U ) != 0U ) +#define MAC_IS_UNICAST( pucMACAddressBytes ) ( ( pucMACAddressBytes[ 0 ] & 1U ) == 0U ) + /* *INDENT-OFF* */ #ifdef __cplusplus } /* extern "C" */ diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index f3d9bf5268..3092847d88 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -201,6 +201,34 @@ NetworkInterface_t * pxSAM_FillInterfaceDescriptor( BaseType_t xEMACIndex, */ static void hand_tx_errors( void ); +/*-----------------------------------------------------------*/ + +/* + * GMAC hash match register definitions and macros and variables + * The ATSAM GMAC has a 64 bit register for matching multiple unicast or multicast addresses. + * This implementation keeps a counter for every one of those bits. Those counters allow us to keep track + * of how many times each bit has been referenced by a call to prvAddAllowedMACAddress(). + * In order to minimize the memory requirement, the counters are of type uint8_t which limits + * their value to 255. If a counter ever reaches that value, it is never decremented. Reaching this + * limit is extremely unlikely in any system, let alone an embedded one using an ATSAM MCU. + */ + +#define MULTICAST_HASH_IS_ENABLED( pGMAC ) ( ( pGMAC->GMAC_NCFGR & GMAC_NCFGR_MTIHEN ) != 0U ) +#define MULTICAST_HASH_IS_DISABLED( pGMAC ) ( ( pGMAC->GMAC_NCFGR & GMAC_NCFGR_MTIHEN ) == 0U ) +#define MULTICAST_HASH_ENABLE( pGMAC ) pGMAC->GMAC_NCFGR |= GMAC_NCFGR_MTIHEN +#define MULTICAST_HASH_DISABLE( pGMAC ) pGMAC->GMAC_NCFGR &= ~( GMAC_NCFGR_MTIHEN ) +#define UNICAST_HASH_IS_ENABLED( pGMAC ) ( ( pGMAC->GMAC_NCFGR & GMAC_NCFGR_UNIHEN ) != 0U ) +#define UNICAST_HASH_IS_DISABLED( pGMAC ) ( ( pGMAC->GMAC_NCFGR & GMAC_NCFGR_UNIHEN ) == 0U ) +#define UNICAST_HASH_ENABLE( pGMAC ) pGMAC->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN +#define UNICAST_HASH_DISABLE( pGMAC ) pGMAC->GMAC_NCFGR &= ~( GMAC_NCFGR_UNIHEN ) + +#define GMAC_ADDRESS_HASH_BITS ( 64U ) +#define GMAC_ADDRESS_HASH_MASK ( GMAC_ADDRESS_HASH_BITS - 1U ) + +static uint8_t prvAddressHashCounters[ GMAC_ADDRESS_HASH_BITS ] = { 0U }; +static uint64_t prvAddressHashBitMask = 0U; +static uint8_t prvSpecificMatchCounters[ GMACSA_NUMBER ] = { 0U }; + /* Functions to set the hash table for multicast addresses. */ static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ); static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); @@ -731,7 +759,8 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) * There is also no equivalent for unicasts, so manipulate the bits directly. * For now, disable both multicast and unicast hash matching. * The appropriate bits will be set later */ - GMAC->GMAC_NCFGR &= ~( GMAC_NCFGR_MTIHEN | GMAC_NCFGR_UNIHEN ); + MULTICAST_HASH_DISABLE( GMAC ); + UNICAST_HASH_DISABLE( GMAC ); /* Go through all end-points of the interface and add their MAC addresses to the GMAC. */ for( pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); @@ -806,19 +835,6 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) } /*-----------------------------------------------------------*/ -#define GMAC_ADDRESS_HASH_BITS ( 64U ) -#define GMAC_ADDRESS_HASH_MASK ( GMAC_ADDRESS_HASH_BITS - 1 ) - -/* The ATSAM GMAC has a 64 bit register for matching multiple unicast or multicast addresses. -* This implementation keeps a counter for every one of those bits. This allows us to keep track -* of how many times each bit has been referenced by a multicast MAC the the stack wants to receive. -* In order to minimize the memory requirement, the counters are of type uint8_t which limits -* their value to 255. If a counter ever reaches that value, it is never decremented. Reaching this -* limit is extremely unlikely in any system, let alone an embedded one using an ATSAM MCU. */ -static uint8_t prvAddressHashCounters[ GMAC_ADDRESS_HASH_BITS ] = { 0U }; -static uint64_t prvAddressHashBitMask = 0U; -static uint8_t prvSpecificMatchCounters[ GMACSA_NUMBER ] = { 0U }; - static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ) { uint16_t usSum; @@ -905,15 +921,14 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) * registers have been used. */ /* Note: Only called from the IPTask, so no thread-safety is required. */ - uint8_t ucHashBit, ucIsMulticast; + uint8_t ucHashBit; size_t uxIndex, uxEmptyIndex; uint32_t ulSAB, ulSAT; - configASSERT( NULL != pucMacAddress ); + configASSERT( pucMacAddress != NULL ); ucHashBit = prvGenerateCRC16( pucMacAddress ); - ucIsMulticast = pucMacAddress[ 0 ] & 1U; FreeRTOS_debug_printf( "prvAddAllowedMACAddress: %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", pucMacAddress[ 0 ], pucMacAddress[ 1 ], pucMacAddress[ 2 ], pucMacAddress[ 3 ], pucMacAddress[ 4 ], pucMacAddress[ 5 ], ucHashBit ); @@ -974,9 +989,9 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) * be a priority, except if the hash register already covers the MAC address we were given * and the type of address we were given ( unicast/multicast ). If any of those are not * met, simply add to the empty slot we found in the specific match registers. */ - if( ( ( ucIsMulticast != 0 ) && ( ( GMAC->GMAC_NCFGR & GMAC_NCFGR_MTIHEN ) == 0 ) ) /* multicast, but hash does not match multicasts */ || - ( ( ucIsMulticast == 0 ) && ( ( GMAC->GMAC_NCFGR & GMAC_NCFGR_UNIHEN ) == 0 ) ) /* unicast, but hash does not match unicasts */ || - ( prvAddressHashCounters[ ucHashBit ] == 0 ) /* hash matching doesn't cover this address yet. */ ) + if( ( ( MAC_IS_MULTICAST( pucMacAddress ) ) && ( MULTICAST_HASH_IS_DISABLED( GMAC ) ) ) || + ( ( MAC_IS_UNICAST( pucMacAddress ) ) && ( UNICAST_HASH_IS_DISABLED( GMAC ) ) ) || + ( prvAddressHashCounters[ ucHashBit ] == 0U ) /* hash matching doesn't cover this address yet. */ ) { /* In all cases above, simply add to the empty specific match register. */ gmac_set_address( GMAC, uxEmptyIndex, pucMacAddress ); @@ -1004,15 +1019,15 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) } /* Make sure the unicast or multicast hash enable bits are set properly. */ - if( ( ucIsMulticast == 0U ) && ( ( GMAC->GMAC_NCFGR & GMAC_NCFGR_UNIHEN ) == 0 ) ) + if( ( MAC_IS_UNICAST( pucMacAddress ) ) && ( UNICAST_HASH_IS_DISABLED( GMAC ) ) ) { /* This is the first ever unicast address added to the hash register. Enable unicast matching. */ - GMAC->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN; + UNICAST_HASH_ENABLE( GMAC ); } - else if( ( ucIsMulticast != 0U ) && ( ( GMAC->GMAC_NCFGR & GMAC_NCFGR_MTIHEN ) == 0 ) ) + else if( ( MAC_IS_MULTICAST( pucMacAddress ) ) && ( MULTICAST_HASH_IS_DISABLED( GMAC ) ) ) { /* This is the first ever multicast address added to the hash register. Enable multicast matching. */ - GMAC->GMAC_NCFGR |= GMAC_NCFGR_MTIHEN; + MULTICAST_HASH_ENABLE( GMAC ); } else { From 93cfc8ae3af0a9ed61d5f62e6e18b79cd9c02aa0 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Mon, 22 Jan 2024 08:18:51 -0500 Subject: [PATCH 09/18] Adds xNetworkInterface * parameters to the MAC filtering functions as requested by @HTRamsey --- source/FreeRTOS_IPv6_Utils.c | 4 ++-- source/include/FreeRTOS_Routing.h | 3 ++- test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c | 6 ++++-- test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c | 6 ++++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/source/FreeRTOS_IPv6_Utils.c b/source/FreeRTOS_IPv6_Utils.c index 0cedfa20c4..b8591526bf 100644 --- a/source/FreeRTOS_IPv6_Utils.c +++ b/source/FreeRTOS_IPv6_Utils.c @@ -333,14 +333,14 @@ void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, { if( pxEndPoint->pxNetworkInterface->pfAddAllowedMAC != NULL ) { - pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( xMACAddress.ucBytes ); + pxEndPoint->pxNetworkInterface->pfAddAllowedMAC( pxEndPoint->pxNetworkInterface, xMACAddress.ucBytes ); } } else { if( pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC != NULL ) { - pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( xMACAddress.ucBytes ); + pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( pxEndPoint->pxNetworkInterface, xMACAddress.ucBytes ); } } diff --git a/source/include/FreeRTOS_Routing.h b/source/include/FreeRTOS_Routing.h index 41bde5b39d..bce6450743 100644 --- a/source/include/FreeRTOS_Routing.h +++ b/source/include/FreeRTOS_Routing.h @@ -55,7 +55,8 @@ typedef BaseType_t ( * GetPhyLinkStatusFunction_t ) ( struct xNetworkInterface * pxDescriptor ); /* Functions that manipulate what MAC addresses are received by this interface */ - typedef void ( * NetworkInterfaceMACFilterFunction_t ) ( const uint8_t * pucMacAddressBytes ); + typedef void ( * NetworkInterfaceMACFilterFunction_t ) ( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddressBytes ); /** @brief These NetworkInterface access functions are collected in a struct: */ typedef struct xNetworkInterface diff --git a/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c b/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c index dffdf9634e..84e71346a6 100644 --- a/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c +++ b/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c @@ -97,7 +97,8 @@ const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0xab, 0xcd, 0xef, 0 static BaseType_t xMACFunctionCalled; /* An implementation of pfAddAllowedMAC(). */ -static void pfAddAllowedMAC( const uint8_t * pucMacAddress ); +static void pfAddAllowedMAC( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddress ); /* Testing all situations for vIPNetworkUpCalls() to increase coverage. */ #define ipHAS_METHOD 0x01U @@ -3821,7 +3822,8 @@ void test_uxIPHeaderSizeSocket_IPv6() TEST_ASSERT_EQUAL( ipSIZE_OF_IPv6_HEADER, xReturn ); } -static void pfAddAllowedMAC( const uint8_t * pucMacAddress ) +static void pfAddAllowedMAC( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddress ) { xMACFunctionCalled = pdTRUE; } diff --git a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c index 7c6296df1a..a2a824a1e7 100644 --- a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c +++ b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c @@ -84,7 +84,8 @@ extern void prvSetChecksumInPacket( const struct xPacketSummary * pxSet, static BaseType_t xMACFunctionCalled; /* An implementation of pfRemoveAllowedMAC() */ -static void pfRemoveAllowedMAC( const uint8_t * pucMacAddress ); +static void pfRemoveAllowedMAC( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddress ); /* Testing all situations for prvProcessNetworkDownEvent() to increase coverage. */ #define ipHAS_METHOD 0x01U @@ -3071,7 +3072,8 @@ void test_prvSetChecksumInPacket_IPv6UnhandledProtocol() prvSetChecksumInPacket( &xSet, 0 ); } -static void pfRemoveAllowedMAC( const uint8_t * pucMacAddress ) +static void pfRemoveAllowedMAC( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddress ) { xMACFunctionCalled = pdTRUE; } From ac053c415a01f9968e6624b7a1e5dbddcdddc0ed Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Mon, 22 Jan 2024 09:27:32 -0500 Subject: [PATCH 10/18] Updates the DriverSAM network inteface to include the new MAC filter function parameters. --- .../DriverSAM/NetworkInterface.c | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 3092847d88..09b9b90d2a 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -231,8 +231,10 @@ static uint8_t prvSpecificMatchCounters[ GMACSA_NUMBER ] = { 0U }; /* Functions to set the hash table for multicast addresses. */ static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ); -static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); -static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); +static void prvAddAllowedMACAddress( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddress ); +static void prvRemoveAllowedMACAddress( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddress ); /* Checks IP queue, buffers, and semaphore and logs diagnostic info if configured */ static void vCheckBuffersAndQueue( void ); @@ -767,16 +769,16 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { - prvAddAllowedMACAddress( pxEndPoint->xMACAddress.ucBytes ); + prvAddAllowedMACAddress( pxInterface, pxEndPoint->xMACAddress.ucBytes ); } #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) #if ( ipconfigUSE_LLMNR == ipconfigENABLE ) - prvAddAllowedMACAddress( xLLMNR_MacAddress.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xLLMNR_MacAddress.ucBytes ); #endif /* ipconfigUSE_LLMNR */ #if ( ipconfigUSE_MDNS == ipconfigENABLE ) - prvAddAllowedMACAddress( xMDNS_MacAddress.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xMDNS_MacAddress.ucBytes ); #endif /* ipconfigUSE_MDNS */ #endif /* ipconfigIS_ENABLED( ipconfigUSE_IPv4 */ @@ -784,17 +786,17 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface ) { /* Register the Link-Local All-Nodes address */ /* FF02::1 --> 33-33-00-00-00-01 */ - prvAddAllowedMACAddress( pcLOCAL_ALL_NODES_MULTICAST_MAC ); + prvAddAllowedMACAddress( pxInterface, pcLOCAL_ALL_NODES_MULTICAST_MAC ); #if ( ipconfigUSE_LLMNR == ipconfigENABLE ) { - prvAddAllowedMACAddress( xLLMNR_MacAddressIPv6.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xLLMNR_MacAddressIPv6.ucBytes ); } #endif /* ipconfigUSE_LLMNR */ #if ( ipconfigUSE_MDNS == ipconfigENABLE ) { - prvAddAllowedMACAddress( xMDNS_MACAddressIPv6.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xMDNS_MACAddressIPv6.ucBytes ); } #endif /* ipconfigUSE_MDNS */ } @@ -873,7 +875,8 @@ static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ) * * @param[in] pucMacAddress: A pointer to the multicast MAC Address in question. */ -static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) +static void prvAddAllowedMACAddress( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddress ) { /* Design rationale and implementation details: * Most network infrastructure ( both wired and wireless ) will do a pretty good job in @@ -927,9 +930,11 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) uint32_t ulSAB, ulSAT; configASSERT( pucMacAddress != NULL ); + configASSERT( pxDescriptor != NULL ); /* Not used, but the stack should not be sending us NULL parameters. */ ucHashBit = prvGenerateCRC16( pucMacAddress ); - FreeRTOS_debug_printf( "prvAddAllowedMACAddress: %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", + FreeRTOS_debug_printf( "prvAddAllowedMACAddress: pxIf %p, %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", + pxDescriptor, pucMacAddress[ 0 ], pucMacAddress[ 1 ], pucMacAddress[ 2 ], pucMacAddress[ 3 ], pucMacAddress[ 4 ], pucMacAddress[ 5 ], ucHashBit ); @@ -1041,7 +1046,8 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) * * @param[in] pucMacAddress: A pointer to the multicast MAC Address in question. */ -static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) +static void prvRemoveAllowedMACAddress( struct xNetworkInterface * pxDescriptor, + const uint8_t * pucMacAddress ) { /* Note: Only called from the IPTask, so no thread-safety is required. */ uint8_t ucHashBit; @@ -1049,9 +1055,11 @@ static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) size_t uxIndex; configASSERT( NULL != pucMacAddress ); + configASSERT( pxDescriptor != NULL ); /* Not used, but the stack should not be sending us NULL parameters. */ ucHashBit = prvGenerateCRC16( pucMacAddress ); - FreeRTOS_debug_printf( "prvRemoveAllowedMACAddress: %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", + FreeRTOS_debug_printf( "prvRemoveAllowedMACAddress: pxIf %p, %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", + pxDescriptor, pucMacAddress[ 0 ], pucMacAddress[ 1 ], pucMacAddress[ 2 ], pucMacAddress[ 3 ], pucMacAddress[ 4 ], pucMacAddress[ 5 ], ucHashBit ); From df6f6c8f320992708e4051610978301a87e27a3f Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Mon, 22 Jan 2024 12:38:58 -0500 Subject: [PATCH 11/18] more renaming --- source/include/FreeRTOS_Routing.h | 2 +- .../DriverSAM/NetworkInterface.c | 18 +++++++++--------- test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c | 4 ++-- .../FreeRTOS_IP_Utils_utest.c | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/source/include/FreeRTOS_Routing.h b/source/include/FreeRTOS_Routing.h index bce6450743..4a2be7f6b6 100644 --- a/source/include/FreeRTOS_Routing.h +++ b/source/include/FreeRTOS_Routing.h @@ -55,7 +55,7 @@ typedef BaseType_t ( * GetPhyLinkStatusFunction_t ) ( struct xNetworkInterface * pxDescriptor ); /* Functions that manipulate what MAC addresses are received by this interface */ - typedef void ( * NetworkInterfaceMACFilterFunction_t ) ( struct xNetworkInterface * pxDescriptor, + typedef void ( * NetworkInterfaceMACFilterFunction_t ) ( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddressBytes ); /** @brief These NetworkInterface access functions are collected in a struct: */ diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 09b9b90d2a..921b50142a 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -231,9 +231,9 @@ static uint8_t prvSpecificMatchCounters[ GMACSA_NUMBER ] = { 0U }; /* Functions to set the hash table for multicast addresses. */ static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ); -static void prvAddAllowedMACAddress( struct xNetworkInterface * pxDescriptor, +static void prvAddAllowedMACAddress( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddress ); -static void prvRemoveAllowedMACAddress( struct xNetworkInterface * pxDescriptor, +static void prvRemoveAllowedMACAddress( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddress ); /* Checks IP queue, buffers, and semaphore and logs diagnostic info if configured */ @@ -875,7 +875,7 @@ static uint16_t prvGenerateCRC16( const uint8_t * pucAddress ) * * @param[in] pucMacAddress: A pointer to the multicast MAC Address in question. */ -static void prvAddAllowedMACAddress( struct xNetworkInterface * pxDescriptor, +static void prvAddAllowedMACAddress( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddress ) { /* Design rationale and implementation details: @@ -930,11 +930,11 @@ static void prvAddAllowedMACAddress( struct xNetworkInterface * pxDescriptor, uint32_t ulSAB, ulSAT; configASSERT( pucMacAddress != NULL ); - configASSERT( pxDescriptor != NULL ); /* Not used, but the stack should not be sending us NULL parameters. */ + configASSERT( pxInterface != NULL ); /* Not used, but the stack should not be sending us NULL parameters. */ ucHashBit = prvGenerateCRC16( pucMacAddress ); FreeRTOS_debug_printf( "prvAddAllowedMACAddress: pxIf %p, %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", - pxDescriptor, + pxInterface, pucMacAddress[ 0 ], pucMacAddress[ 1 ], pucMacAddress[ 2 ], pucMacAddress[ 3 ], pucMacAddress[ 4 ], pucMacAddress[ 5 ], ucHashBit ); @@ -1046,7 +1046,7 @@ static void prvAddAllowedMACAddress( struct xNetworkInterface * pxDescriptor, * * @param[in] pucMacAddress: A pointer to the multicast MAC Address in question. */ -static void prvRemoveAllowedMACAddress( struct xNetworkInterface * pxDescriptor, +static void prvRemoveAllowedMACAddress( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddress ) { /* Note: Only called from the IPTask, so no thread-safety is required. */ @@ -1054,12 +1054,12 @@ static void prvRemoveAllowedMACAddress( struct xNetworkInterface * pxDescriptor, uint32_t ulSAB, ulSAT; size_t uxIndex; - configASSERT( NULL != pucMacAddress ); - configASSERT( pxDescriptor != NULL ); /* Not used, but the stack should not be sending us NULL parameters. */ + configASSERT( pucMacAddress != NULL ); + configASSERT( pxInterface != NULL ); /* Not used, but the stack should not be sending us NULL parameters. */ ucHashBit = prvGenerateCRC16( pucMacAddress ); FreeRTOS_debug_printf( "prvRemoveAllowedMACAddress: pxIf %p, %02X-%02X-%02X-%02X-%02X-%02X hash-bit %u", - pxDescriptor, + pxInterface, pucMacAddress[ 0 ], pucMacAddress[ 1 ], pucMacAddress[ 2 ], pucMacAddress[ 3 ], pucMacAddress[ 4 ], pucMacAddress[ 5 ], ucHashBit ); diff --git a/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c b/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c index 84e71346a6..bbecaac3e1 100644 --- a/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c +++ b/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c @@ -97,7 +97,7 @@ const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0xab, 0xcd, 0xef, 0 static BaseType_t xMACFunctionCalled; /* An implementation of pfAddAllowedMAC(). */ -static void pfAddAllowedMAC( struct xNetworkInterface * pxDescriptor, +static void pfAddAllowedMAC( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddress ); /* Testing all situations for vIPNetworkUpCalls() to increase coverage. */ @@ -3822,7 +3822,7 @@ void test_uxIPHeaderSizeSocket_IPv6() TEST_ASSERT_EQUAL( ipSIZE_OF_IPv6_HEADER, xReturn ); } -static void pfAddAllowedMAC( struct xNetworkInterface * pxDescriptor, +static void pfAddAllowedMAC( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddress ) { xMACFunctionCalled = pdTRUE; diff --git a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c index a2a824a1e7..773175f2e7 100644 --- a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c +++ b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c @@ -84,7 +84,7 @@ extern void prvSetChecksumInPacket( const struct xPacketSummary * pxSet, static BaseType_t xMACFunctionCalled; /* An implementation of pfRemoveAllowedMAC() */ -static void pfRemoveAllowedMAC( struct xNetworkInterface * pxDescriptor, +static void pfRemoveAllowedMAC( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddress ); /* Testing all situations for prvProcessNetworkDownEvent() to increase coverage. */ @@ -3072,7 +3072,7 @@ void test_prvSetChecksumInPacket_IPv6UnhandledProtocol() prvSetChecksumInPacket( &xSet, 0 ); } -static void pfRemoveAllowedMAC( struct xNetworkInterface * pxDescriptor, +static void pfRemoveAllowedMAC( struct xNetworkInterface * pxInterface, const uint8_t * pucMacAddress ) { xMACFunctionCalled = pdTRUE; From 04c34c6f39d7047b2a70b03814e530c44d9874f5 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Mon, 29 Jan 2024 07:55:40 -0500 Subject: [PATCH 12/18] Adds overflow check when incrementing the specific match register counters. Thanks @HTRamsey --- .../NetworkInterface/DriverSAM/NetworkInterface.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 921b50142a..6bd61cdc2f 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -225,8 +225,8 @@ static void hand_tx_errors( void ); #define GMAC_ADDRESS_HASH_BITS ( 64U ) #define GMAC_ADDRESS_HASH_MASK ( GMAC_ADDRESS_HASH_BITS - 1U ) -static uint8_t prvAddressHashCounters[ GMAC_ADDRESS_HASH_BITS ] = { 0U }; static uint64_t prvAddressHashBitMask = 0U; +static uint8_t prvAddressHashCounters[ GMAC_ADDRESS_HASH_BITS ] = { 0U }; static uint8_t prvSpecificMatchCounters[ GMACSA_NUMBER ] = { 0U }; /* Functions to set the hash table for multicast addresses. */ @@ -953,8 +953,12 @@ static void prvAddAllowedMACAddress( struct xNetworkInterface * pxInterface, /* This specific match register is being used. Check if the address is the same. */ if( ( ulSAB == GMAC->GMAC_SA[ uxIndex ].GMAC_SAB ) && ( ulSAT == GMAC->GMAC_SA[ uxIndex ].GMAC_SAT ) ) { - /* Exact match! Increment the counter and leave. */ - prvSpecificMatchCounters[ uxIndex ]++; + /* Exact match! Increment the counter and leave. As with the hash counters, make sure we don't overflow. */ + if( prvSpecificMatchCounters[ uxIndex ] < UINT8_MAX ) + { + prvSpecificMatchCounters[ uxIndex ]++; + } + /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: EXACT MATCH at %u, new counter %u", uxIndex, prvSpecificMatchCounters[ uxIndex ] ); */ break; } @@ -987,7 +991,8 @@ static void prvAddAllowedMACAddress( struct xNetworkInterface * pxInterface, break; } - /* No exact match found in the specific match registers, but is one of them empty? */ + /* No exact match found in the specific match registers. + * Is one of them empty so we can add the MAC there? */ if( uxEmptyIndex < GMACSA_NUMBER ) { /* There is an empty slot in the specific match registers. Using this empty slot should @@ -998,7 +1003,7 @@ static void prvAddAllowedMACAddress( struct xNetworkInterface * pxInterface, ( ( MAC_IS_UNICAST( pucMacAddress ) ) && ( UNICAST_HASH_IS_DISABLED( GMAC ) ) ) || ( prvAddressHashCounters[ ucHashBit ] == 0U ) /* hash matching doesn't cover this address yet. */ ) { - /* In all cases above, simply add to the empty specific match register. */ + /* In all cases above, simply add the MAC address to the empty specific match register. */ gmac_set_address( GMAC, uxEmptyIndex, pucMacAddress ); prvSpecificMatchCounters[ uxEmptyIndex ] = 1U; /* FreeRTOS_debug_printf("prvAddAllowedMACAddress: ADD at %u, new counter %u", uxEmptyIndex, prvSpecificMatchCounters[ uxEmptyIndex ] ); */ From d154f0e3cd9ac16ef08a54363153d70ecd46d8bb Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Fri, 16 Feb 2024 08:05:03 -0500 Subject: [PATCH 13/18] Adds proper casting when converting byte arrays to uint32_t registers. Thanks @htibosch. --- .../NetworkInterface/DriverSAM/NetworkInterface.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c index 78101f049b..6619f6afbc 100644 --- a/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c +++ b/source/portable/NetworkInterface/DriverSAM/NetworkInterface.c @@ -931,8 +931,11 @@ static void prvAddAllowedMACAddress( struct xNetworkInterface * pxInterface, /* Calculate what the specific match registers would look like for this MAC address so that * we can check if this MAC address is already present in one of the specific match registers. */ - ulSAB = ( pucMacAddress[ 3 ] << 24 ) | ( pucMacAddress[ 2 ] << 16 ) | ( pucMacAddress[ 1 ] << 8 ) | ( pucMacAddress[ 0 ] ); - ulSAT = ( pucMacAddress[ 5 ] << 8 ) | ( pucMacAddress[ 4 ] ); + ulSAB = ( ( ( uint32_t ) pucMacAddress[ 3 ] ) << 24 ) | + ( ( ( uint32_t ) pucMacAddress[ 2 ] ) << 16 ) | + ( ( ( uint32_t ) pucMacAddress[ 1 ] ) << 8 ) | + ( ( uint32_t ) pucMacAddress[ 0 ] ); + ulSAT = ( ( ( uint32_t ) pucMacAddress[ 5 ] ) << 8 ) | ( ( uint32_t ) pucMacAddress[ 4 ] ); /* Always try to find a match within the specific match registers first. */ uxEmptyIndex = GMACSA_NUMBER; @@ -1061,8 +1064,11 @@ static void prvRemoveAllowedMACAddress( struct xNetworkInterface * pxInterface, /* Calculate what the specific match registers would look like for this MAC address so that * we can check if this MAC address is already present in one of the specific match registers. */ - ulSAB = ( pucMacAddress[ 3 ] << 24 ) | ( pucMacAddress[ 2 ] << 16 ) | ( pucMacAddress[ 1 ] << 8 ) | ( pucMacAddress[ 0 ] ); - ulSAT = ( pucMacAddress[ 5 ] << 8 ) | ( pucMacAddress[ 4 ] ); + ulSAB = ( ( ( uint32_t ) pucMacAddress[ 3 ] ) << 24 ) | + ( ( ( uint32_t ) pucMacAddress[ 2 ] ) << 16 ) | + ( ( ( uint32_t ) pucMacAddress[ 1 ] ) << 8 ) | + ( ( uint32_t ) pucMacAddress[ 0 ] ); + ulSAT = ( ( ( uint32_t ) pucMacAddress[ 5 ] ) << 8 ) | ( ( uint32_t ) pucMacAddress[ 4 ] ); /* Check the specific match registers first. */ for( uxIndex = 0; uxIndex < GMACSA_NUMBER; uxIndex++ ) From 65df7afb242a81200e3fd681380c106af56959d1 Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Thu, 29 Feb 2024 09:32:41 -0500 Subject: [PATCH 14/18] Exposes pcLOCAL_ALL_NODES_MULTICAST_IP so that it can be re-used by the user --- source/FreeRTOS_ND.c | 5 +---- source/include/FreeRTOS_ND.h | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index fd440c7860..47aaf7705e 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -74,10 +74,7 @@ #define ndMAX_CACHE_AGE_BEFORE_NEW_ND_SOLICITATION ( 3U ) /** @brief All nodes on the local network segment: IP address. */ - /* MISRA Ref 8.9.1 [File scoped variables] */ - /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */ - /* coverity[misra_c_2012_rule_8_9_violation] */ - static const uint8_t pcLOCAL_ALL_NODES_MULTICAST_IP[ ipSIZE_OF_IPv6_ADDRESS ] = { 0xffU, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U }; /* ff02::1 */ + const uint8_t pcLOCAL_ALL_NODES_MULTICAST_IP[ ipSIZE_OF_IPv6_ADDRESS ] = { 0xffU, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U }; /* ff02::1 */ /** @brief All nodes on the local network segment: MAC address. */ const uint8_t pcLOCAL_ALL_NODES_MULTICAST_MAC[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0x33U, 0x33U, 0x00U, 0x00U, 0x00U, 0x01U }; diff --git a/source/include/FreeRTOS_ND.h b/source/include/FreeRTOS_ND.h index 60cdbd396a..d0f1685313 100644 --- a/source/include/FreeRTOS_ND.h +++ b/source/include/FreeRTOS_ND.h @@ -204,6 +204,7 @@ void FreeRTOS_PrintNDCache( void ); #endif + 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 ]; #endif /* ipconfigUSE_IPv6 != 0 */ From dcedcf6d21a7e6690c795f283bfdf95f24a5b49b Mon Sep 17 00:00:00 2001 From: Emil Popov Date: Wed, 27 Mar 2024 08:53:21 -0400 Subject: [PATCH 15/18] Fixes an array initializer that was not constant at compile time. Removes code that was not supposed to be in this PR --- source/FreeRTOS_IPv6_Utils.c | 100 +++++---------------------- source/include/FreeRTOS_IPv6_Utils.h | 2 +- 2 files changed, 17 insertions(+), 85 deletions(-) diff --git a/source/FreeRTOS_IPv6_Utils.c b/source/FreeRTOS_IPv6_Utils.c index c6532ebcbe..b0792f9223 100644 --- a/source/FreeRTOS_IPv6_Utils.c +++ b/source/FreeRTOS_IPv6_Utils.c @@ -297,31 +297,26 @@ size_t usGetExtensionHeaderLength( const uint8_t * pucEthernetBuffer, * @param[in] pxEndPoint The end-point for which a network up/down event is being handled. * @param[in] xNetworkGoingUp pdTRUE when the network goes UP, pdFALSE when the network goes DOWN. */ -void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, +void vManageSolicitedNodeAddress( const struct xNetworkEndPoint * pxEndPoint, BaseType_t xNetworkGoingUp ) { + IPv6_Type_t xAddressType; + MACAddress_t xMACAddress; + configASSERT( pxEndPoint != NULL ); configASSERT( pxEndPoint->pxNetworkInterface != NULL ); /* do{}while(0) to allow for the use of break statements */ do { - IPv6_Type_t xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); - MACAddress_t xMACAddress = { { - 0x33U, - 0x33U, - 0xFFU, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - } }; - /* During the very first network DOWN event, pxEndPoint->ipv6_settings does not yet hold the proper address and - * therefore the MAC address above will be incorrect as well, however nothing bad will happen, because the address + * therefore the calculated MAC address will be incorrect. Nothing bad will happen though, because the address * type check below will kick us out before the call to pfRemoveAllowedMAC(). Without the check below, the network - * driver end up being called once to register 33:33:FF:00:00:00 and that MAC never gets unregistered. */ + * driver ends up being called once to register 33:33:FF:00:00:00 and that MAC never gets unregistered. */ /* Solicited-node multicast addresses only apply to normal unicast non-loopback addresses. */ + xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) ); + if( ( xAddressType != eIPv6_LinkLocal ) && ( xAddressType != eIPv6_SiteLocal ) && ( xAddressType != eIPv6_Global ) ) { /* The address of this end-point is something other than a normal unicast address... Maybe it's the @@ -330,6 +325,14 @@ void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, break; } + /* Calculate the multicast MAC that corresponds to this endpoint's IPv6 address. */ + xMACAddress.ucBytes[ 0 ] = ipMULTICAST_MAC_ADDRESS_IPv6_0; + xMACAddress.ucBytes[ 1 ] = ipMULTICAST_MAC_ADDRESS_IPv6_0; + xMACAddress.ucBytes[ 2 ] = 0xFFU; + xMACAddress.ucBytes[ 3 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ]; + xMACAddress.ucBytes[ 4 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ]; + xMACAddress.ucBytes[ 5 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ]; + /* Update the network driver filter */ if( xNetworkGoingUp == pdTRUE ) { @@ -345,77 +348,6 @@ void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, pxEndPoint->pxNetworkInterface->pfRemoveAllowedMAC( pxEndPoint->pxNetworkInterface, xMACAddress.ucBytes ); } } - - #if ( ipconfigIS_ENABLED( ipconfigSUPPORT_IP_MULTICAST ) ) - { - MCastReportData_t * pxMRD; - - /* This is sub-optimal. We only need an IP_Address_t on network DOWN, however in the - * interest of having one piece of common code, we'll have a pointer that points to either - * xIPv6Address or &pxMRD->xMCastGroupAddress.xIPAddress */ - IP_Address_t * pxIPv6Address; - IP_Address_t xIPv6Address; - - if( xNetworkGoingUp == pdTRUE ) - { - /* We will need an MLD report structure a few lines down, so allocate one. */ - pxMRD = ( MCastReportData_t * ) pvPortMalloc( sizeof( MCastReportData_t ) ); - - if( pxMRD == NULL ) - { - break; - } - - pxIPv6Address = &( pxMRD->xMCastGroupAddress.xIPAddress ); - } - else - { - pxIPv6Address = &xIPv6Address; - } - - /* Generate the solicited-node multicast address. It has the form of - * ff02::1:ffnn:nnnn, where nn:nnnn are the last 3 bytes of the IPv6 address. */ - do - { - uint8_t * pucTarget = pxIPv6Address->xIP_IPv6.ucBytes; - uint8_t * pucSource = pxEndPoint->ipv6_settings.xIPAddress.ucBytes; - - pucTarget[ 0 ] = 0xFFU; - pucTarget[ 1 ] = 0x02U; - ( void ) memset( &( pucTarget[ 2 ] ), 0x00, 9 ); - pucTarget[ 11 ] = 0x01U; - pucTarget[ 12 ] = 0xFFU; - pucTarget[ 13 ] = pucSource[ 13 ]; - pucTarget[ 14 ] = pucSource[ 14 ]; - pucTarget[ 15 ] = pucSource[ 15 ]; - } while( pdFALSE ); - - if( xNetworkGoingUp == pdTRUE ) - { - /* Network going UP. Generate and enlist an MLD report for the solicited node multicast address. */ - listSET_LIST_ITEM_OWNER( &( pxMRD->xListItem ), ( void * ) pxMRD ); - pxMRD->pxInterface = pxEndPoint->pxNetworkInterface; - pxMRD->xMCastGroupAddress.xIs_IPv6 = pdTRUE_UNSIGNED; - /* pxMRD->xMCastGroupAddress.xIPAddress was filled out through pxIPv6Address above.*/ - - if( xEnlistMulticastReport( pxMRD ) == pdFALSE ) - { - /* The report data was not consumed. This is odd since we are dealing with - * the solicited-node multicast address and there should not have been a report - * enlisted for it already. Anyway, keep things clean. */ - vPortFree( pxMRD ); - pxMRD = NULL; - } - } - else - { - /* Network going DOWN. De-list the MLD report for the solicited node multicast address. - * Todo: Check if there are other places that this same action needs to be taken. - * Places like when DHCPv6 or RA releases an address. Needs further investigation. */ - vDelistMulticastReport( pxEndPoint->pxNetworkInterface, pxIPv6Address, pdTRUE_UNSIGNED ); - } - } - #endif /* ipconfigIS_ENABLED( ipconfigSUPPORT_IP_MULTICAST ) */ } while( pdFALSE ); } /*-----------------------------------------------------------*/ diff --git a/source/include/FreeRTOS_IPv6_Utils.h b/source/include/FreeRTOS_IPv6_Utils.h index 2af9079ac5..db80071d4b 100644 --- a/source/include/FreeRTOS_IPv6_Utils.h +++ b/source/include/FreeRTOS_IPv6_Utils.h @@ -66,7 +66,7 @@ size_t usGetExtensionHeaderLength( const uint8_t * pucEthernetBuffer, size_t uxBufferLength, uint8_t * pucProtocol ); -void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint, +void vManageSolicitedNodeAddress( const struct xNetworkEndPoint * pxEndPoint, BaseType_t xNetworkGoingUp ); /* *INDENT-OFF* */ From 7d3519a8b769d737fa2f9e0d3343d6cb5ebdfd45 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 1 Apr 2024 12:43:19 +0000 Subject: [PATCH 16/18] Uncrustify: triggered by comment. --- .../FreeRTOS_IP_Utils_utest.c | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c index ed4aa5bfda..4865a39373 100644 --- a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c +++ b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c @@ -3239,23 +3239,24 @@ void test_prvProcessNetworkDownEvent_Multicast() prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_INTERFACE ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_METHOD ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_INTERFACE ); + /** * @brief test_eGetDHCPState * To validate if eGetDHCPState returns expected * DHCP state. */ -void test_eGetDHCPState( void ) -{ - DHCPData_t xTestData; - eDHCPState_t eReturn; - int i; - struct xNetworkEndPoint xEndPoint = { 0 }, * pxEndPoint = &xEndPoint; - - for( i = 0; i < sizeof( xTestData.eDHCPState ); i++ ) + void test_eGetDHCPState( void ) { - /* Modify the global state. */ - pxEndPoint->xDHCPData.eDHCPState = i; - eReturn = eGetDHCPState( &xEndPoint ); - TEST_ASSERT_EQUAL( i, eReturn ); + DHCPData_t xTestData; + eDHCPState_t eReturn; + int i; + struct xNetworkEndPoint xEndPoint = { 0 }, * pxEndPoint = &xEndPoint; + + for( i = 0; i < sizeof( xTestData.eDHCPState ); i++ ) + { + /* Modify the global state. */ + pxEndPoint->xDHCPData.eDHCPState = i; + eReturn = eGetDHCPState( &xEndPoint ); + TEST_ASSERT_EQUAL( i, eReturn ); + } } -} From 630690dd8185c6940eba9cb50089aab1ef60c519 Mon Sep 17 00:00:00 2001 From: tony-josi-aws Date: Wed, 3 Apr 2024 16:14:05 +0530 Subject: [PATCH 17/18] Fix unit tests --- test/unit-test/CMakeLists.txt | 2 +- .../unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c | 17 +- test/unit-test/FreeRTOS_IP/ut.cmake | 1 + .../FreeRTOS_IP_DiffConfig2/ut.cmake | 1 + .../FreeRTOS_IP_Utils_utest.c | 38 ++- .../FreeRTOS_IPv6_Utils_utest.c | 228 ++++++++++++++++++ test/unit-test/FreeRTOS_IPv6_Utils/ut.cmake | 1 + 7 files changed, 255 insertions(+), 33 deletions(-) diff --git a/test/unit-test/CMakeLists.txt b/test/unit-test/CMakeLists.txt index b93680075f..253cf45b2b 100644 --- a/test/unit-test/CMakeLists.txt +++ b/test/unit-test/CMakeLists.txt @@ -311,7 +311,7 @@ include( ${UNIT_TEST_DIR}/FreeRTOS_Routing_ConfigCompatibleWithSingle/ut.cmake ) add_custom_target( coverage COMMAND ${CMAKE_COMMAND} -P ${MODULE_ROOT_DIR}/test/unit-test/cmock/coverage.cmake DEPENDS cmock unity -FreeRTOS_ARP_utest + FreeRTOS_ARP_utest FreeRTOS_ARP_DataLenLessThanMinPacket_utest FreeRTOS_BitConfig_utest FreeRTOS_DHCP_utest diff --git a/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c b/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c index 0f654899c4..d7c5af405b 100644 --- a/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c +++ b/test/unit-test/FreeRTOS_IP/FreeRTOS_IP_utest.c @@ -48,6 +48,7 @@ #include "mock_FreeRTOS_IP_Private.h" #include "mock_FreeRTOS_IPv4_Private.h" #include "mock_FreeRTOS_IP_Utils.h" +#include "mock_FreeRTOS_IPv6_Utils.h" #include "mock_FreeRTOS_IP_Timers.h" #include "mock_FreeRTOS_TCP_IP.h" #include "mock_FreeRTOS_ICMP.h" @@ -170,6 +171,7 @@ void test_vIPNetworkUpCalls( void ) NetworkEndPoint_t xEndPoint = { 0 }; xEndPoint.bits.bEndPointUp = pdFALSE; + xEndPoint.bits.bIPv6 = pdFALSE; vApplicationIPNetworkEventHook_Multi_Expect( eNetworkUp, &xEndPoint ); vDNSInitialise_Expect(); @@ -4002,11 +4004,6 @@ static void prvIPNetworkUpCalls_Generic( const uint8_t * pucAddress, xEndPoint.bits.bWantDHCP = pdFALSE_UNSIGNED; memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, pucAddress, ipSIZE_OF_IPv6_ADDRESS ); - if( ( uxSetMembers & ipHAS_METHOD ) != 0U ) - { - xInterface.pfAddAllowedMAC = pfAddAllowedMAC; - } - if( ( uxSetMembers & ipHAS_INTERFACE ) != 0U ) { xEndPoint.pxNetworkInterface = &xInterface; @@ -4029,8 +4026,8 @@ static void prvIPNetworkUpCalls_Generic( const uint8_t * pucAddress, if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) { - /* The xIPv6_GetIPType() function is mocked. */ - xIPv6_GetIPType_ExpectAnyArgsAndReturn( eType ); + /* The vManageSolicitedNodeAddress() function is mocked. */ + vManageSolicitedNodeAddress_Expect( &xEndPoint, pdTRUE ); } vApplicationIPNetworkEventHook_Multi_Expect( eNetworkUp, &xEndPoint ); @@ -4040,8 +4037,6 @@ static void prvIPNetworkUpCalls_Generic( const uint8_t * pucAddress, vIPNetworkUpCalls( &xEndPoint ); TEST_ASSERT_EQUAL( pdTRUE, xEndPoint.bits.bEndPointUp ); - /* See if pfAddAllowedMAC() was called when it has to. */ - TEST_ASSERT_EQUAL( xMACAddExpected, xMACFunctionCalled ); } void test_prvIPNetworkUpCalls_LinkLocal() @@ -4060,9 +4055,9 @@ void test_prvIPNetworkUpCalls_LinkLocal() }; /* Test all combinations of what might go wrong. */ - prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); - prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_METHOD ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 ); prvIPNetworkUpCalls_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_INTERFACE ); } diff --git a/test/unit-test/FreeRTOS_IP/ut.cmake b/test/unit-test/FreeRTOS_IP/ut.cmake index b2a33dac10..16dbceec57 100644 --- a/test/unit-test/FreeRTOS_IP/ut.cmake +++ b/test/unit-test/FreeRTOS_IP/ut.cmake @@ -23,6 +23,7 @@ list(APPEND mock_list "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IPv4_Private.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Timers.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Utils.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IPv6_Utils.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ARP.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ICMP.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_DNS.h" diff --git a/test/unit-test/FreeRTOS_IP_DiffConfig2/ut.cmake b/test/unit-test/FreeRTOS_IP_DiffConfig2/ut.cmake index 2ef4a847f8..4e31ae3ec9 100644 --- a/test/unit-test/FreeRTOS_IP_DiffConfig2/ut.cmake +++ b/test/unit-test/FreeRTOS_IP_DiffConfig2/ut.cmake @@ -20,6 +20,7 @@ list(APPEND mock_list "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IPv4_Private.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Timers.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Utils.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IPv6_Utils.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ARP.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ICMP.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_DNS.h" diff --git a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c index 4865a39373..8ac54c56c4 100644 --- a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c +++ b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c @@ -621,8 +621,8 @@ void test_prvProcessNetworkDownEvent_PassDHCPv6( void ) if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) { - /* The xIPv6_GetIPType() function is mocked. */ - xIPv6_GetIPType_ExpectAnyArgsAndReturn( eIPv6_Multicast ); + /* The vManageSolicitedNodeAddress() function is mocked. */ + vManageSolicitedNodeAddress_Expect( &xEndPoint, pdFALSE ); } FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); @@ -658,8 +658,8 @@ void test_prvProcessNetworkDownEvent_PassRA( void ) if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) { - /* The xIPv6_GetIPType() function is mocked. */ - xIPv6_GetIPType_ExpectAnyArgsAndReturn( eIPv6_Multicast ); + /* The vManageSolicitedNodeAddress() function is mocked. */ + vManageSolicitedNodeAddress_Expect( &xEndPoint, pdFALSE ); } FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); @@ -697,8 +697,8 @@ void test_prvProcessNetworkDownEvent_PassStaticIP( void ) if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) { - /* The xIPv6_GetIPType() function is mocked. */ - xIPv6_GetIPType_ExpectAnyArgsAndReturn( eIPv6_Multicast ); + /* The vManageSolicitedNodeAddress() function is mocked. */ + vManageSolicitedNodeAddress_Expect( &xEndPoint, pdFALSE ); } FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); @@ -3107,11 +3107,6 @@ static void prvProcessNetworkDownEvent_Generic( const uint8_t * pucAddress, xEndPoint.bits.bWantDHCP = pdFALSE_UNSIGNED; memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, pucAddress, ipSIZE_OF_IPv6_ADDRESS ); - if( ( uxSetMembers & ipHAS_METHOD ) != 0U ) - { - xInterface.pfRemoveAllowedMAC = pfRemoveAllowedMAC; - } - if( ( uxSetMembers & ipHAS_INTERFACE ) != 0U ) { xEndPoint.pxNetworkInterface = &xInterface; @@ -3138,8 +3133,8 @@ static void prvProcessNetworkDownEvent_Generic( const uint8_t * pucAddress, if( xEndPoint.bits.bIPv6 == pdTRUE_UNSIGNED ) { - /* The xIPv6_GetIPType() function is mocked. */ - xIPv6_GetIPType_ExpectAnyArgsAndReturn( eType ); + /* The vManageSolicitedNodeAddress() function is mocked. */ + vManageSolicitedNodeAddress_Expect( &xEndPoint, pdFALSE ); } FreeRTOS_NextEndPoint_IgnoreAndReturn( NULL ); @@ -3171,9 +3166,9 @@ void test_prvProcessNetworkDownEvent_LinkLocal() }; /* Test all combinations of what might go wrong. */ - prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); - prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_METHOD ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_IPV6 ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_LinkLocal, ipHAS_INTERFACE ); } @@ -3192,9 +3187,9 @@ void test_prvProcessNetworkDownEvent_Global() 0x70U, 0x09U }; - prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_INTERFACE ); - prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_METHOD ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_IPV6 ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Global, ipHAS_INTERFACE ); } @@ -3213,9 +3208,9 @@ void test_prvProcessNetworkDownEvent_SiteLocal() 0x70U, 0x09U }; - prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); - prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_METHOD ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_IPV6 ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_SiteLocal, ipHAS_INTERFACE ); } @@ -3235,10 +3230,11 @@ void test_prvProcessNetworkDownEvent_Multicast() 0x00U, 0xFBU }; - prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_METHOD | ipHAS_INTERFACE ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_INTERFACE ); - prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_METHOD ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 | ipHAS_INTERFACE ); + prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_IPV6 ); prvProcessNetworkDownEvent_Generic( ucAddress, eIPv6_Multicast, ipHAS_INTERFACE ); +} /** * @brief test_eGetDHCPState diff --git a/test/unit-test/FreeRTOS_IPv6_Utils/FreeRTOS_IPv6_Utils_utest.c b/test/unit-test/FreeRTOS_IPv6_Utils/FreeRTOS_IPv6_Utils_utest.c index 8eaf9f7ffa..cc3ad9e857 100644 --- a/test/unit-test/FreeRTOS_IPv6_Utils/FreeRTOS_IPv6_Utils_utest.c +++ b/test/unit-test/FreeRTOS_IPv6_Utils/FreeRTOS_IPv6_Utils_utest.c @@ -44,6 +44,7 @@ #include "mock_FreeRTOS_IP.h" #include "mock_FreeRTOS_IPv6.h" +#include "mock_FreeRTOS_Routing.h" #include "FreeRTOS_IPv6_Utils.h" @@ -642,3 +643,230 @@ void test_usGetExtensionHeaderLength_InvalidHeader( void ) TEST_ASSERT_EQUAL( pxNetworkBuffer->xDataLength, xReturn ); } + +/* This variable will be set when pfAddAllowedMAC() is called by vIPNetworkUpCalls(). */ +static BaseType_t xMACAddFunctionCalled; +static BaseType_t xMACRemoveFunctionCalled; + +static void pfAddAllowedMAC( struct xNetworkInterface * pxInterface, + const uint8_t * pucMacAddress ) +{ + xMACAddFunctionCalled = pdTRUE; +} + +static void pfRemoveAllowedMAC( struct xNetworkInterface * pxInterface, + const uint8_t * pucMacAddress ) +{ + xMACRemoveFunctionCalled = pdTRUE; +} + +/** + * @brief Check for assert if endpoint is NULL + */ +void test_vManageSolicitedNodeAddress_NoEndPoint_CatchAssert( void ) +{ + catch_assert( vManageSolicitedNodeAddress(NULL, pdTRUE) ); +} + + +/** + * @brief Check for assert if interface is NULL + */ +void test_vManageSolicitedNodeAddress_NoInterface_CatchAssert( void ) +{ + NetworkEndPoint_t xEndPoint = { 0 }; + catch_assert( vManageSolicitedNodeAddress(&xEndPoint, pdTRUE) ); +} + + +/** + * @brief Validate the case were the network is going up + */ +void test_vManageSolicitedNodeAddress_NetworkGoingUp( void ) +{ + + NetworkInterface_t xInterface = { 0 }; + NetworkEndPoint_t xEndPoint = { 0 }; + BaseType_t xMACAddExpected = pdFALSE; + /* Use the local-link address fe80::7009 */ + static const uint8_t ucAddress[ 16 ] = + { + 0xFEU, 0x80U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x70U, 0x09U + }; + + + /* Happy path eIPv6_LinkLocal */ + xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xEndPoint.bits.bEndPointUp = pdFALSE; + xEndPoint.bits.bCallDownHook = pdFALSE_UNSIGNED; + xEndPoint.bits.bWantDHCP = pdFALSE_UNSIGNED; + xEndPoint.bits.bIPv6 = pdTRUE; + xEndPoint.pxNetworkInterface = &xInterface; + memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, ucAddress, ipSIZE_OF_IPv6_ADDRESS ); + + xMACAddFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal); + + vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + + TEST_ASSERT_EQUAL(pdTRUE, xMACAddFunctionCalled); + + /* No MAC address add handler */ + xInterface.pfAddAllowedMAC = NULL; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xMACAddFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal); + + vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + + TEST_ASSERT_EQUAL(pdFALSE, xMACAddFunctionCalled); + + /* Happy path eIPv6_SiteLocal */ + xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xMACAddFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_SiteLocal); + + vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + + TEST_ASSERT_EQUAL(pdTRUE, xMACAddFunctionCalled); + + /* Happy path eIPv6_Global */ + xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xMACAddFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Global); + + vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + + TEST_ASSERT_EQUAL(pdTRUE, xMACAddFunctionCalled); + + /* Unhappy path eIPv6_Loopback */ + xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xMACAddFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Loopback); + + vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + + TEST_ASSERT_EQUAL(pdFALSE, xMACAddFunctionCalled); +} + +/** + * @brief Validate the case were the network is going down + */ +void test_vManageSolicitedNodeAddress_NetworkGoingDown( void ) +{ + + NetworkInterface_t xInterface = { 0 }; + NetworkEndPoint_t xEndPoint = { 0 }; + BaseType_t xMACAddExpected = pdFALSE; + /* Use the local-link address fe80::7009 */ + static const uint8_t ucAddress[ 16 ] = + { + 0xFEU, 0x80U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x00U, 0x00U, + 0x70U, 0x09U + }; + + + /* Happy path eIPv6_LinkLocal */ + xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xEndPoint.bits.bEndPointUp = pdFALSE; + xEndPoint.bits.bCallDownHook = pdFALSE_UNSIGNED; + xEndPoint.bits.bWantDHCP = pdFALSE_UNSIGNED; + xEndPoint.bits.bIPv6 = pdTRUE; + xEndPoint.pxNetworkInterface = &xInterface; + memcpy( xEndPoint.ipv6_settings.xIPAddress.ucBytes, ucAddress, ipSIZE_OF_IPv6_ADDRESS ); + + xMACRemoveFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal); + + vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + + TEST_ASSERT_EQUAL(pdTRUE, xMACRemoveFunctionCalled); + + /* No MAC address add handler */ + xInterface.pfAddAllowedMAC = NULL; + xInterface.pfRemoveAllowedMAC = NULL; + xInterface.pxEndPoint = &xEndPoint; + + xMACRemoveFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal); + + vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + + TEST_ASSERT_EQUAL(pdFALSE, xMACRemoveFunctionCalled); + + /* Happy path eIPv6_SiteLocal */ + xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xMACRemoveFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_SiteLocal); + + vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + + TEST_ASSERT_EQUAL(pdTRUE, xMACRemoveFunctionCalled); + + /* Happy path eIPv6_Global */ + xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xMACRemoveFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Global); + + vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + + TEST_ASSERT_EQUAL(pdTRUE, xMACRemoveFunctionCalled); + + /* Unhappy path eIPv6_Loopback */ + xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; + xInterface.pfRemoveAllowedMAC = &pfRemoveAllowedMAC; + xInterface.pxEndPoint = &xEndPoint; + + xMACRemoveFunctionCalled = pdFALSE; + + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Loopback); + + vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + + TEST_ASSERT_EQUAL(pdFALSE, xMACRemoveFunctionCalled); +} \ No newline at end of file diff --git a/test/unit-test/FreeRTOS_IPv6_Utils/ut.cmake b/test/unit-test/FreeRTOS_IPv6_Utils/ut.cmake index 6e9f105f52..16cf08c42e 100644 --- a/test/unit-test/FreeRTOS_IPv6_Utils/ut.cmake +++ b/test/unit-test/FreeRTOS_IPv6_Utils/ut.cmake @@ -18,6 +18,7 @@ list(APPEND mock_list "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IPv6.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_ICMP.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_Sockets.h" + "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_Routing.h" "${CMAKE_BINARY_DIR}/Annexed_TCP/FreeRTOS_IP_Utils.h" ) From 73b703ea11d7a858601fe7b2a5a343c4dfa27a63 Mon Sep 17 00:00:00 2001 From: tony-josi-aws Date: Wed, 3 Apr 2024 16:21:33 +0530 Subject: [PATCH 18/18] Fix formatting --- .../FreeRTOS_IP_Utils_utest.c | 26 +++---- .../FreeRTOS_IPv6_Utils_utest.c | 71 +++++++++---------- 2 files changed, 48 insertions(+), 49 deletions(-) diff --git a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c index 8ac54c56c4..aac452fcab 100644 --- a/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c +++ b/test/unit-test/FreeRTOS_IP_Utils/FreeRTOS_IP_Utils_utest.c @@ -3241,18 +3241,18 @@ void test_prvProcessNetworkDownEvent_Multicast() * To validate if eGetDHCPState returns expected * DHCP state. */ - void test_eGetDHCPState( void ) - { - DHCPData_t xTestData; - eDHCPState_t eReturn; - int i; - struct xNetworkEndPoint xEndPoint = { 0 }, * pxEndPoint = &xEndPoint; +void test_eGetDHCPState( void ) +{ + DHCPData_t xTestData; + eDHCPState_t eReturn; + int i; + struct xNetworkEndPoint xEndPoint = { 0 }, * pxEndPoint = &xEndPoint; - for( i = 0; i < sizeof( xTestData.eDHCPState ); i++ ) - { - /* Modify the global state. */ - pxEndPoint->xDHCPData.eDHCPState = i; - eReturn = eGetDHCPState( &xEndPoint ); - TEST_ASSERT_EQUAL( i, eReturn ); - } + for( i = 0; i < sizeof( xTestData.eDHCPState ); i++ ) + { + /* Modify the global state. */ + pxEndPoint->xDHCPData.eDHCPState = i; + eReturn = eGetDHCPState( &xEndPoint ); + TEST_ASSERT_EQUAL( i, eReturn ); } +} diff --git a/test/unit-test/FreeRTOS_IPv6_Utils/FreeRTOS_IPv6_Utils_utest.c b/test/unit-test/FreeRTOS_IPv6_Utils/FreeRTOS_IPv6_Utils_utest.c index cc3ad9e857..12b731ab07 100644 --- a/test/unit-test/FreeRTOS_IPv6_Utils/FreeRTOS_IPv6_Utils_utest.c +++ b/test/unit-test/FreeRTOS_IPv6_Utils/FreeRTOS_IPv6_Utils_utest.c @@ -655,7 +655,7 @@ static void pfAddAllowedMAC( struct xNetworkInterface * pxInterface, } static void pfRemoveAllowedMAC( struct xNetworkInterface * pxInterface, - const uint8_t * pucMacAddress ) + const uint8_t * pucMacAddress ) { xMACRemoveFunctionCalled = pdTRUE; } @@ -665,7 +665,7 @@ static void pfRemoveAllowedMAC( struct xNetworkInterface * pxInterface, */ void test_vManageSolicitedNodeAddress_NoEndPoint_CatchAssert( void ) { - catch_assert( vManageSolicitedNodeAddress(NULL, pdTRUE) ); + catch_assert( vManageSolicitedNodeAddress( NULL, pdTRUE ) ); } @@ -675,7 +675,8 @@ void test_vManageSolicitedNodeAddress_NoEndPoint_CatchAssert( void ) void test_vManageSolicitedNodeAddress_NoInterface_CatchAssert( void ) { NetworkEndPoint_t xEndPoint = { 0 }; - catch_assert( vManageSolicitedNodeAddress(&xEndPoint, pdTRUE) ); + + catch_assert( vManageSolicitedNodeAddress( &xEndPoint, pdTRUE ) ); } @@ -684,7 +685,6 @@ void test_vManageSolicitedNodeAddress_NoInterface_CatchAssert( void ) */ void test_vManageSolicitedNodeAddress_NetworkGoingUp( void ) { - NetworkInterface_t xInterface = { 0 }; NetworkEndPoint_t xEndPoint = { 0 }; BaseType_t xMACAddExpected = pdFALSE; @@ -716,11 +716,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingUp( void ) xMACAddFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal ); - vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + vManageSolicitedNodeAddress( &xEndPoint, pdTRUE ); - TEST_ASSERT_EQUAL(pdTRUE, xMACAddFunctionCalled); + TEST_ASSERT_EQUAL( pdTRUE, xMACAddFunctionCalled ); /* No MAC address add handler */ xInterface.pfAddAllowedMAC = NULL; @@ -729,11 +729,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingUp( void ) xMACAddFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal ); - vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + vManageSolicitedNodeAddress( &xEndPoint, pdTRUE ); - TEST_ASSERT_EQUAL(pdFALSE, xMACAddFunctionCalled); + TEST_ASSERT_EQUAL( pdFALSE, xMACAddFunctionCalled ); /* Happy path eIPv6_SiteLocal */ xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; @@ -742,11 +742,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingUp( void ) xMACAddFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_SiteLocal); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_SiteLocal ); - vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + vManageSolicitedNodeAddress( &xEndPoint, pdTRUE ); - TEST_ASSERT_EQUAL(pdTRUE, xMACAddFunctionCalled); + TEST_ASSERT_EQUAL( pdTRUE, xMACAddFunctionCalled ); /* Happy path eIPv6_Global */ xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; @@ -755,11 +755,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingUp( void ) xMACAddFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Global); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Global ); - vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + vManageSolicitedNodeAddress( &xEndPoint, pdTRUE ); - TEST_ASSERT_EQUAL(pdTRUE, xMACAddFunctionCalled); + TEST_ASSERT_EQUAL( pdTRUE, xMACAddFunctionCalled ); /* Unhappy path eIPv6_Loopback */ xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; @@ -768,11 +768,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingUp( void ) xMACAddFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Loopback); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Loopback ); - vManageSolicitedNodeAddress(&xEndPoint, pdTRUE); + vManageSolicitedNodeAddress( &xEndPoint, pdTRUE ); - TEST_ASSERT_EQUAL(pdFALSE, xMACAddFunctionCalled); + TEST_ASSERT_EQUAL( pdFALSE, xMACAddFunctionCalled ); } /** @@ -780,7 +780,6 @@ void test_vManageSolicitedNodeAddress_NetworkGoingUp( void ) */ void test_vManageSolicitedNodeAddress_NetworkGoingDown( void ) { - NetworkInterface_t xInterface = { 0 }; NetworkEndPoint_t xEndPoint = { 0 }; BaseType_t xMACAddExpected = pdFALSE; @@ -812,11 +811,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingDown( void ) xMACRemoveFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal ); - vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + vManageSolicitedNodeAddress( &xEndPoint, pdFALSE ); - TEST_ASSERT_EQUAL(pdTRUE, xMACRemoveFunctionCalled); + TEST_ASSERT_EQUAL( pdTRUE, xMACRemoveFunctionCalled ); /* No MAC address add handler */ xInterface.pfAddAllowedMAC = NULL; @@ -825,11 +824,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingDown( void ) xMACRemoveFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_LinkLocal ); - vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + vManageSolicitedNodeAddress( &xEndPoint, pdFALSE ); - TEST_ASSERT_EQUAL(pdFALSE, xMACRemoveFunctionCalled); + TEST_ASSERT_EQUAL( pdFALSE, xMACRemoveFunctionCalled ); /* Happy path eIPv6_SiteLocal */ xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; @@ -838,11 +837,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingDown( void ) xMACRemoveFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_SiteLocal); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_SiteLocal ); - vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + vManageSolicitedNodeAddress( &xEndPoint, pdFALSE ); - TEST_ASSERT_EQUAL(pdTRUE, xMACRemoveFunctionCalled); + TEST_ASSERT_EQUAL( pdTRUE, xMACRemoveFunctionCalled ); /* Happy path eIPv6_Global */ xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; @@ -851,11 +850,11 @@ void test_vManageSolicitedNodeAddress_NetworkGoingDown( void ) xMACRemoveFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Global); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Global ); - vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + vManageSolicitedNodeAddress( &xEndPoint, pdFALSE ); - TEST_ASSERT_EQUAL(pdTRUE, xMACRemoveFunctionCalled); + TEST_ASSERT_EQUAL( pdTRUE, xMACRemoveFunctionCalled ); /* Unhappy path eIPv6_Loopback */ xInterface.pfAddAllowedMAC = &pfAddAllowedMAC; @@ -864,9 +863,9 @@ void test_vManageSolicitedNodeAddress_NetworkGoingDown( void ) xMACRemoveFunctionCalled = pdFALSE; - xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Loopback); + xIPv6_GetIPType_ExpectAndReturn( &xEndPoint.ipv6_settings.xIPAddress, eIPv6_Loopback ); - vManageSolicitedNodeAddress(&xEndPoint, pdFALSE); + vManageSolicitedNodeAddress( &xEndPoint, pdFALSE ); - TEST_ASSERT_EQUAL(pdFALSE, xMACRemoveFunctionCalled); -} \ No newline at end of file + TEST_ASSERT_EQUAL( pdFALSE, xMACRemoveFunctionCalled ); +}