Skip to content

Commit 9ea0f53

Browse files
author
Emil Popov
committed
Adds defines for MLD packets like the Multicast Listener Report.
Adds a function to generate and send MLD v1 Report packets. Begins sending unsolicited MLD Reports on a hard-coded 15s interval. Generates an MLD report for the solicited-node multicast addresses corresponding to all unicast IPv6 addresses Uncrustify + lots of refactoring
1 parent 64a4dab commit 9ea0f53

File tree

8 files changed

+769
-432
lines changed

8 files changed

+769
-432
lines changed

source/FreeRTOS_IGMP.c

Lines changed: 642 additions & 411 deletions
Large diffs are not rendered by default.

source/FreeRTOS_IP.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,8 +659,66 @@ TaskHandle_t FreeRTOS_GetIPTaskHandle( void )
659659
*/
660660
void vIPNetworkUpCalls( struct xNetworkEndPoint * pxEndPoint )
661661
{
662+
#if ( ipconfigSUPPORT_IP_MULTICAST != 0 )
663+
MCastReportData_t * pxMRD;
664+
IPv6_Type_t xAddressType;
665+
MACAddress_t xMACAddress;
666+
#endif /* ( ipconfigSUPPORT_IP_MULTICAST != 0 ) */
667+
662668
pxEndPoint->bits.bEndPointUp = pdTRUE_UNSIGNED;
663669

670+
#if ( ipconfigSUPPORT_IP_MULTICAST != 0 )
671+
if( pxEndPoint->bits.bIPv6 == pdTRUE_UNSIGNED )
672+
{
673+
/* Now that the network is up, pxEndPoint->ipv6_settings should hold the actual address of this
674+
* end-point. For unicast addresses, generate the solicited-node multicast address that corresponds
675+
* to the address and generate an MLD report for it.
676+
* ToDo: Figure out what the proper place is to remove multicast addresses that are no longer valid. For
677+
* example when a DHCPv6 lease expires. */
678+
xAddressType = xIPv6_GetIPType( &( pxEndPoint->ipv6_settings.xIPAddress ) );
679+
680+
if( ( xAddressType == eIPv6_LinkLocal ) || ( xAddressType == eIPv6_SiteLocal ) || ( xAddressType == eIPv6_Global ) )
681+
{
682+
if( NULL != ( pxMRD = ( MCastReportData_t * ) pvPortMalloc( sizeof( MCastReportData_t ) ) ) )
683+
{
684+
listSET_LIST_ITEM_OWNER( &( pxMRD->xListItem ), ( void * ) pxMRD );
685+
pxMRD->pxEndPoint = pxEndPoint;
686+
pxMRD->xMCastGroupAddress.xIs_IPv6 = pdTRUE_UNSIGNED;
687+
688+
/* Generate the solicited-node multicast address in the form of
689+
* ff02::1:ffnn:nnnn, where nn:nnnn are the last 3 bytes of the IPv6 address. */
690+
pxMRD->xMCastGroupAddress.xIPAddress.xIP_IPv6.ucBytes[ 0 ] = 0xFFU;
691+
pxMRD->xMCastGroupAddress.xIPAddress.xIP_IPv6.ucBytes[ 1 ] = 0x02U;
692+
( void ) memset( &pxMRD->xMCastGroupAddress.xIPAddress.xIP_IPv6.ucBytes[ 2 ], 0x00, 9 );
693+
pxMRD->xMCastGroupAddress.xIPAddress.xIP_IPv6.ucBytes[ 11 ] = 0x01U;
694+
pxMRD->xMCastGroupAddress.xIPAddress.xIP_IPv6.ucBytes[ 12 ] = 0xFFU;
695+
( void ) memcpy( &pxMRD->xMCastGroupAddress.xIPAddress.xIP_IPv6.ucBytes[ 13 ], &pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], 3 );
696+
697+
if( pdTRUE != xAddIGMPReportToList( pxMRD ) )
698+
{
699+
vPortFree( pxMRD );
700+
pxMRD = NULL;
701+
}
702+
else
703+
{
704+
/* The report was consumed, therfore it was added to the list. Tell the network
705+
* driver to begin receiving the associated MAC address */
706+
if( pxEndPoint->pxNetworkInterface && ( pxEndPoint->pxNetworkInterface->pfAddMulticastMAC != NULL ) )
707+
{
708+
xMACAddress.ucBytes[ 0 ] = 0x33;
709+
xMACAddress.ucBytes[ 1 ] = 0x33;
710+
xMACAddress.ucBytes[ 2 ] = 0xFF;
711+
xMACAddress.ucBytes[ 3 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ];
712+
xMACAddress.ucBytes[ 4 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ];
713+
xMACAddress.ucBytes[ 5 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ];
714+
pxEndPoint->pxNetworkInterface->pfAddMulticastMAC( xMACAddress.ucBytes );
715+
}
716+
}
717+
}
718+
}
719+
}
720+
#endif /* ( ipconfigSUPPORT_IP_MULTICAST != 0 ) */
721+
664722
#if ( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )
665723
#if ( ipconfigIPv4_BACKWARD_COMPATIBLE == 1 )
666724
{

source/FreeRTOS_IPv6.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ BaseType_t xIsIPv6AllowedMulticast( const IPv6_Address_t * pxIPAddress )
386386
/**
387387
* @brief Compares 2 IPv6 addresses and checks if the one
388388
* on the left can handle the one on right. Note that 'xCompareIPv6_Address' will also check if 'pxRight' is
389-
* the special unicast address: ff02::1:ffnn:nnnn, where nn:nnnn are
389+
* the special multicast address: ff02::1:ffnn:nnnn, where nn:nnnn are
390390
* the last 3 bytes of the IPv6 address.
391391
*
392392
* @param[in] pxLeft First IP address.
@@ -410,6 +410,7 @@ BaseType_t xCompareIPv6_Address( const IPv6_Address_t * pxLeft,
410410
( pxRight->ucBytes[ 12 ] == 0xffU ) )
411411
{
412412
/* This is an LLMNR address. */
413+
/* _EP_: I don't think this is LLMNR. Did someone mean to say "the solicited-node multicast address" ? */
413414
xResult = memcmp( &( pxLeft->ucBytes[ 13 ] ), &( pxRight->ucBytes[ 13 ] ), 3 );
414415
}
415416
else

source/FreeRTOS_Sockets.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6442,12 +6442,12 @@ void * pvSocketGetSocketID( const ConstSocket_t xSocket )
64426442

64436443
if( ( pxSocket->bits.bIsIPv6 == pdFALSE_UNSIGNED ) || ( pxSocket->ucProtocol != ( uint8_t ) FREERTOS_IPPROTO_UDP ) || ( uxOptionLength != sizeof( BaseType_t ) ) )
64446444
{
6445-
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
6445+
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
64466446
}
64476447

64486448
if( ( xValue < -1 ) || ( xValue > 255 ) )
64496449
{
6450-
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
6450+
break; /* will return -pdFREERTOS_ERRNO_EINVAL */
64516451
}
64526452
else if( xValue == -1 )
64536453
{

source/include/FreeRTOS_IGMP.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@
9292
void vRemoveIGMPReportFromList( struct freertos_ip_mreq * pMCastGroup );
9393
BaseType_t xAddIGMPReportToList( MCastReportData_t * pNewEntry );
9494
eFrameProcessingResult_t eProcessIGMPPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );
95+
BaseType_t xSendMulticastListenerReport_v1( const IPv6_Address_t * pxGroupAddress,
96+
NetworkEndPoint_t * pxEndPoint,
97+
TickType_t uxBlockTimeTicks );
9598

9699

97100
#ifdef __cplusplus

source/include/FreeRTOS_IPv6.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,13 @@
5454
#define ipICMP_PARAMETER_PROBLEM_IPv6 ( ( uint8_t ) 4U )
5555
#define ipICMP_PING_REQUEST_IPv6 ( ( uint8_t ) 128U )
5656
#define ipICMP_PING_REPLY_IPv6 ( ( uint8_t ) 129U )
57+
#define ipICMP_MULTICAST_LISTENER_QUERY ( ( uint8_t ) 130U )
58+
#define ipICMP_MULTICAST_LISTENER_REPORT_V1 ( ( uint8_t ) 131U )
5759
#define ipICMP_ROUTER_SOLICITATION_IPv6 ( ( uint8_t ) 133U )
5860
#define ipICMP_ROUTER_ADVERTISEMENT_IPv6 ( ( uint8_t ) 134U )
5961
#define ipICMP_NEIGHBOR_SOLICITATION_IPv6 ( ( uint8_t ) 135U )
6062
#define ipICMP_NEIGHBOR_ADVERTISEMENT_IPv6 ( ( uint8_t ) 136U )
63+
#define ipICMP_MULTICAST_LISTENER_REPORT_V2 ( ( uint8_t ) 143U )
6164

6265

6366
#define ipIPv6_EXT_HEADER_HOP_BY_HOP 0U
@@ -113,7 +116,7 @@ extern void FreeRTOS_ClearND( void );
113116
BaseType_t xIsIPv6AllowedMulticast( const IPv6_Address_t * pxIPAddress );
114117

115118
/* Note that 'xCompareIPv6_Address' will also check if 'pxRight' is
116-
* the special unicast address: ff02::1:ffnn:nnnn, where nn:nnnn are
119+
* the special multicast address: ff02::1:ffnn:nnnn, where nn:nnnn are
117120
* the last 3 bytes of the IPv6 address. */
118121
BaseType_t xCompareIPv6_Address( const IPv6_Address_t * pxLeft,
119122
const IPv6_Address_t * pxRight,

source/include/FreeRTOS_IPv6_Private.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,62 @@ typedef struct xICMPRouterSolicitation_IPv6 ICMPRouterSolicitation_IPv6_t;
212212
typedef struct xICMPPrefixOption_IPv6 ICMPPrefixOption_IPv6_t;
213213
#endif /* ipconfigUSE_RA != 0 */
214214

215+
#if ( ipconfigSUPPORT_IP_MULTICAST != 0 )
216+
#include "pack_struct_start.h"
217+
struct xIP_HOP_BY_HOP_EXT_ROUTER_ALERT_IPv6
218+
{
219+
uint8_t ucNextHeader; /**< Next header: TCP, UDP, or ICMP. 0 + 1 = 1 */
220+
uint8_t ucHeaderExtLength; /**< Length of this header in 8-octet units, not including the first 8 octets. 1 + 1 = 2 */
221+
struct
222+
{
223+
uint8_t ucType;
224+
uint8_t ucLength;
225+
uint16_t usValue;
226+
}
227+
xRouterAlert;
228+
struct
229+
{
230+
uint8_t ucType;
231+
uint8_t ucLength;
232+
}
233+
xPadding;
234+
}
235+
#include "pack_struct_end.h"
236+
typedef struct xIP_HOP_BY_HOP_EXT_ROUTER_ALERT_IPv6 IPHopByHopExtRouterAlert_IPv6_t;
237+
238+
#include "pack_struct_start.h"
239+
struct xICMPv6_MLD_REPORTv1
240+
{
241+
uint8_t ucTypeOfMessage; /**< The message type. 0 + 1 = 1 */
242+
uint8_t ucTypeOfService; /**< Type of service. 1 + 1 = 2 */
243+
uint16_t usChecksum; /**< Checksum. 2 + 2 = 4 */
244+
uint16_t usMaxResponseDelay; /**< Max Response Delay. 4 + 2 = 6 */
245+
uint16_t usReserved; /**< Reserved. 6 + 2 = 8 */
246+
IPv6_Address_t xGroupAddress; /**< The IPv6 address. 8 + 16 = 24 */
247+
}
248+
#include "pack_struct_end.h"
249+
typedef struct xICMPv6_MLD_REPORTv1 ICMPv6_MLDReportv1_t;
250+
251+
struct xICMPv6_MLD_REPORTv1_PACKET
252+
{
253+
EthernetHeader_t xEthernetHeader; /* 0 + 14 = 14 */
254+
IPHeader_IPv6_t xIPHeader; /* 14 + 40 = 54 */
255+
IPHopByHopExtRouterAlert_IPv6_t xRAOption; /* 54 + 8 = 62 */
256+
ICMPv6_MLDReportv1_t xICMPv6_MLDReport; /* 62 + 24 = 86 */
257+
}
258+
#include "pack_struct_end.h"
259+
typedef struct xICMPv6_MLD_REPORTv1_PACKET MLDReportPacket_v1_t;
260+
261+
/** @brief Options that can be sent in a Multicast Listener Report packet.
262+
* more info at https://www.rfc-editor.org/rfc/rfc2711#section-2.0 */
263+
#define ipROUTER_ALERT_VALUE_MLD 0
264+
265+
/** from https://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml#ipv6-parameters-2 */
266+
#define ipHOP_BY_HOP_ROUTER_ALERT 5
267+
#define ipHOP_BY_HOP_PadN 1
268+
269+
#endif /* ( ipconfigSUPPORT_IP_MULTICAST != 0 ) */
270+
215271
/*-----------------------------------------------------------*/
216272
/* Nested protocol packets. */
217273
/*-----------------------------------------------------------*/

source/portable/NetworkInterface/DriverSAM/NetworkInterface.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ static uint32_t prvEMACRxPoll( void );
188188

189189
static BaseType_t prvSAM_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface );
190190
static BaseType_t prvSAM_NetworkInterfaceOutput( NetworkInterface_t * pxInterface,
191-
NetworkBufferDescriptor_t * const pxBuffer,
191+
NetworkBufferDescriptor_t * const pxDescriptor,
192192
BaseType_t bReleaseAfterSend );
193193
static BaseType_t prvSAM_GetPhyLinkStatus( NetworkInterface_t * pxInterface );
194194

@@ -741,21 +741,6 @@ static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface )
741741
}
742742
#endif /* ipconfigUSE_MDNS */
743743

744-
for( pxEndPoint = FreeRTOS_FirstEndPoint( pxMyInterface );
745-
pxEndPoint != NULL;
746-
pxEndPoint = FreeRTOS_NextEndPoint( pxMyInterface, pxEndPoint ) )
747-
{
748-
if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED )
749-
{
750-
/* Since this is an IPv6 end point, add the solicited-node MAC address. */
751-
uint8_t ucMACAddress[ 6 ] = { 0x33, 0x33, 0xff, 0, 0, 0 };
752-
753-
ucMACAddress[ 3 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ];
754-
ucMACAddress[ 4 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ];
755-
ucMACAddress[ 5 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ];
756-
prvAddMulticastMACAddress( ucMACAddress );
757-
}
758-
}
759744
}
760745
#endif /* ipconfigUSE_IPv6 */
761746

@@ -848,7 +833,7 @@ static void prvAddMulticastMACAddress( const uint8_t * ucMacAddress )
848833

849834
vTaskSuspendAll();
850835

851-
/* If the bin counter corresponding to this mac address has is already non-zero, */
836+
/* If the bin counter corresponding to this mac address is already non-zero, */
852837
/* a multicast address with the same hash has already been added, so there's nothing more to do. */
853838
if( 0 == prvAddressHashCounters[ ucBinNumber ] )
854839
{

0 commit comments

Comments
 (0)