Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds NetIf functions for filtering MAC addresses #1065

Merged
merged 44 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
84eda02
Adds ipconfigMAC_FILTERING that when enabled, adds two MAC manipulati…
Dec 20, 2023
3f3035e
Removes ipconfigMAC_FILTERING
Jan 3, 2024
aa7a128
Adds checks for ipconfigUSE_IPv6
Jan 5, 2024
5a559a9
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Jan 6, 2024
dfa41e0
Updates the unit tests for better coverage. Thanks @htibosch
Jan 8, 2024
1b8c5df
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Jan 8, 2024
5bd7944
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Jan 9, 2024
95c6abe
Merge branch 'main' into MAC_Filtering_PR
AniruddhaKanhere Jan 10, 2024
5f263fd
Merge branch 'main' into MAC_Filtering_PR
AniruddhaKanhere Jan 12, 2024
7b743e8
Converts the indexing variables to `size_t xIndex` and avoids inline …
Jan 12, 2024
08649f5
Update some comments
evpopov Jan 14, 2024
9b59845
Moves vManageSolicitedNodeAddress() from FreeRTOS_IP_Utils.c to FreeR…
Jan 16, 2024
1006221
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Jan 17, 2024
2dd7a81
Adds a macros for easy checking if a MAC address is unicast or multic…
Jan 18, 2024
93cfc8a
Adds xNetworkInterface * parameters to the MAC filtering functions as…
Jan 22, 2024
26987e6
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Jan 22, 2024
ac053c4
Updates the DriverSAM network inteface to include the new MAC filter …
Jan 22, 2024
df6f6c8
more renaming
Jan 22, 2024
0767f40
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Jan 26, 2024
04c34c6
Adds overflow check when incrementing the specific match register cou…
Jan 29, 2024
d4227fc
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Jan 30, 2024
c594186
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Feb 5, 2024
e57a629
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Feb 7, 2024
a52e1b0
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Feb 13, 2024
d154f0e
Adds proper casting when converting byte arrays to uint32_t registers…
Feb 16, 2024
363b85b
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Feb 21, 2024
e710ebe
Merge branch 'main' into MAC_Filtering_PR
Feb 29, 2024
65df7af
Exposes pcLOCAL_ALL_NODES_MULTICAST_IP so that it can be re-used by t…
Feb 29, 2024
9125393
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Mar 13, 2024
b6917c5
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Mar 14, 2024
cff5c9c
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Mar 15, 2024
0047028
Merge branch 'main' into MAC_Filtering_PR
Mar 18, 2024
c0d7c4e
Merge branch 'main' into MAC_Filtering_PR
Mar 22, 2024
c256186
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Mar 25, 2024
dcedcf6
Fixes an array initializer that was not constant at compile time.
Mar 27, 2024
13fe7a1
Merge branch 'main' into MAC_Filtering_PR
Mar 27, 2024
999ce51
Merge branch 'main' into MAC_Filtering_PR
Mar 29, 2024
7d3519a
Uncrustify: triggered by comment.
actions-user Apr 1, 2024
4d9b2df
Merge remote-tracking branch 'upstream/main' into MAC_Filtering_PR
Apr 1, 2024
630690d
Fix unit tests
tony-josi-aws Apr 3, 2024
73b703e
Fix formatting
tony-josi-aws Apr 3, 2024
7a4957d
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Apr 3, 2024
1c54ccc
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Apr 5, 2024
5ad3ac8
Merge branch 'main' into MAC_Filtering_PR
tony-josi-aws Apr 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions source/FreeRTOS_IP.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,14 @@ TaskHandle_t FreeRTOS_GetIPTaskHandle( void )
*/
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 ) )
vManageSolicitedNodeAddress( pxEndPoint, pdTRUE );
#endif
}

pxEndPoint->bits.bEndPointUp = pdTRUE_UNSIGNED;

#if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )
Expand Down
137 changes: 137 additions & 0 deletions source/FreeRTOS_IP_Utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,15 @@ void prvProcessNetworkDownEvent( struct xNetworkInterface * pxInterface )
{
/* The bit 'bEndPointUp' stays low until vIPNetworkUpCalls() is called. */
pxEndPoint->bits.bEndPointUp = pdFALSE_UNSIGNED;

AniruddhaKanhere marked this conversation as resolved.
Show resolved Hide resolved
if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED )
{
/* IPv6 end-points have a solicited-node addresses that needs extra housekeeping. */
#if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) )
vManageSolicitedNodeAddress( pxEndPoint, pdFALSE );
#endif
}

#if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )
{
if( pxEndPoint->bits.bCallDownHook != pdFALSE_UNSIGNED )
Expand Down Expand Up @@ -1764,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 );
evpopov marked this conversation as resolved.
Show resolved Hide resolved

/* 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 ) ) ) )
evpopov marked this conversation as resolved.
Show resolved Hide resolved
{
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 ) ) */
/*-----------------------------------------------------------*/
4 changes: 2 additions & 2 deletions source/FreeRTOS_ND.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 10 additions & 0 deletions source/include/FreeRTOS_IP_Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
evpopov marked this conversation as resolved.
Show resolved Hide resolved
void vManageSolicitedNodeAddress( struct xNetworkEndPoint * pxEndPoint,
BaseType_t xNetworkGoingUp );
#endif

/* *INDENT-OFF* */
#ifdef __cplusplus
} /* extern "C" */
Expand Down
1 change: 1 addition & 0 deletions source/include/FreeRTOS_ND.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */


Expand Down
39 changes: 39 additions & 0 deletions source/include/FreeRTOS_Routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
/* Return true as long as the LinkStatus on the PHY is present. */
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 );

/** @brief These NetworkInterface access functions are collected in a struct: */
typedef struct xNetworkInterface
{
Expand All @@ -62,6 +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. */

/*
* 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
Expand Down
Loading
Loading