2 Multicast Listener Discovery support routines.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Create a IP6_MLD_GROUP list entry node and record to IP6 service binding data.
21 @param[in, out] IpSb Points to IP6 service binding instance.
22 @param[in] MulticastAddr The IPv6 multicast address to be recorded.
23 @param[in] DelayTimer The maximum allowed delay before sending a responding
24 report, in units of milliseconds.
25 @return The created IP6_ML_GROUP list entry or NULL.
30 IN OUT IP6_SERVICE
*IpSb
,
31 IN EFI_IPv6_ADDRESS
*MulticastAddr
,
37 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
38 ASSERT (MulticastAddr
!= NULL
&& IP6_IS_MULTICAST (MulticastAddr
));
40 Entry
= AllocatePool (sizeof (IP6_MLD_GROUP
));
43 Entry
->DelayTimer
= DelayTimer
;
44 Entry
->SendByUs
= FALSE
;
45 IP6_COPY_ADDRESS (&Entry
->Address
, MulticastAddr
);
46 InsertTailList (&IpSb
->MldCtrl
.Groups
, &Entry
->Link
);
53 Search a IP6_MLD_GROUP list entry node from a list array.
55 @param[in] IpSb Points to IP6 service binding instance.
56 @param[in] MulticastAddr The IPv6 multicast address to be searched.
58 @return The found IP6_ML_GROUP list entry or NULL.
64 IN EFI_IPv6_ADDRESS
*MulticastAddr
70 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
71 ASSERT (MulticastAddr
!= NULL
&& IP6_IS_MULTICAST (MulticastAddr
));
73 NET_LIST_FOR_EACH (Entry
, &IpSb
->MldCtrl
.Groups
) {
74 Group
= NET_LIST_USER_STRUCT (Entry
, IP6_MLD_GROUP
, Link
);
75 if (EFI_IP6_EQUAL (MulticastAddr
, &Group
->Address
)) {
84 Count the number of IP6 multicast groups that are mapped to the
85 same MAC address. Several IP6 multicast address may be mapped to
88 @param[in] MldCtrl The MLD control block to search in.
89 @param[in] Mac The MAC address to search.
91 @return The number of the IP6 multicast group that mapped to the same
97 IN IP6_MLD_SERVICE_DATA
*MldCtrl
,
98 IN EFI_MAC_ADDRESS
*Mac
102 IP6_MLD_GROUP
*Group
;
107 NET_LIST_FOR_EACH (Entry
, &MldCtrl
->Groups
) {
108 Group
= NET_LIST_USER_STRUCT (Entry
, IP6_MLD_GROUP
, Link
);
110 if (NET_MAC_EQUAL (&Group
->Mac
, Mac
, sizeof (EFI_MAC_ADDRESS
))) {
119 Generate MLD report message and send it out to MulticastAddr.
121 @param[in] IpSb The IP service to send the packet.
122 @param[in] Interface The IP interface to send the packet.
123 If NULL, a system interface will be selected.
124 @param[in] MulticastAddr The specific IPv6 multicast address to which
125 the message sender is listening.
127 @retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
129 @retval EFI_SUCCESS The MLD report message was successfully sent out.
134 IN IP6_SERVICE
*IpSb
,
135 IN IP6_INTERFACE
*Interface OPTIONAL
,
136 IN EFI_IPv6_ADDRESS
*MulticastAddr
139 IP6_MLD_HEAD
*MldHead
;
147 UINT16 PseudoChecksum
;
149 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
150 ASSERT (MulticastAddr
!= NULL
&& IP6_IS_MULTICAST (MulticastAddr
));
153 // Generate the packet to be sent
154 // IPv6 basic header + Hop by Hop option + MLD message
158 Status
= Ip6FillHopByHop (NULL
, &OptionLen
, IP6_ICMP
);
159 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
161 PayloadLen
= (UINT16
) (OptionLen
+ sizeof (IP6_MLD_HEAD
));
162 Packet
= NetbufAlloc (sizeof (EFI_IP6_HEADER
) + (UINT32
) PayloadLen
);
163 if (Packet
== NULL
) {
164 return EFI_OUT_OF_RESOURCES
;
168 // Create the basic IPv6 header.
169 // RFC3590: Use link-local address as source address if it is available,
170 // otherwise use the unspecified address.
174 Head
.PayloadLength
= HTONS (PayloadLen
);
175 Head
.NextHeader
= IP6_HOP_BY_HOP
;
177 IP6_COPY_ADDRESS (&Head
.DestinationAddress
, MulticastAddr
);
180 // If Link-Local address is not ready, we use unspecified address.
182 IP6_COPY_ADDRESS (&Head
.SourceAddress
, &IpSb
->LinkLocalAddr
);
184 NetbufReserve (Packet
, sizeof (EFI_IP6_HEADER
));
187 // Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
189 Options
= NetbufAllocSpace (Packet
, (UINT32
) OptionLen
, FALSE
);
190 ASSERT (Options
!= NULL
);
191 Status
= Ip6FillHopByHop (Options
, &OptionLen
, IP6_ICMP
);
192 if (EFI_ERROR (Status
)) {
199 // Fill in MLD message - Report
201 MldHead
= (IP6_MLD_HEAD
*) NetbufAllocSpace (Packet
, sizeof (IP6_MLD_HEAD
), FALSE
);
202 ASSERT (MldHead
!= NULL
);
203 ZeroMem (MldHead
, sizeof (IP6_MLD_HEAD
));
204 MldHead
->Head
.Type
= ICMP_V6_LISTENER_REPORT
;
205 MldHead
->Head
.Code
= 0;
206 IP6_COPY_ADDRESS (&MldHead
->Group
, MulticastAddr
);
208 HeadChecksum
= NetblockChecksum ((UINT8
*) MldHead
, sizeof (IP6_MLD_HEAD
));
209 PseudoChecksum
= NetIp6PseudoHeadChecksum (
211 &Head
.DestinationAddress
,
213 sizeof (IP6_MLD_HEAD
)
216 MldHead
->Head
.Checksum
= (UINT16
) ~NetAddChecksum (HeadChecksum
, PseudoChecksum
);
219 // Transmit the packet
221 return Ip6Output (IpSb
, Interface
, NULL
, Packet
, &Head
, NULL
, 0, Ip6SysPacketSent
, NULL
);
225 Generate MLD Done message and send it out to MulticastAddr.
227 @param[in] IpSb The IP service to send the packet.
228 @param[in] MulticastAddr The specific IPv6 multicast address to which
229 the message sender is ceasing to listen.
231 @retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
233 @retval EFI_SUCCESS The MLD report message was successfully sent out.
238 IN IP6_SERVICE
*IpSb
,
239 IN EFI_IPv6_ADDRESS
*MulticastAddr
242 IP6_MLD_HEAD
*MldHead
;
249 EFI_IPv6_ADDRESS Destination
;
251 UINT16 PseudoChecksum
;
253 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
254 ASSERT (MulticastAddr
!= NULL
&& IP6_IS_MULTICAST (MulticastAddr
));
257 // Generate the packet to be sent
258 // IPv6 basic header + Hop by Hop option + MLD message
262 Status
= Ip6FillHopByHop (NULL
, &OptionLen
, IP6_ICMP
);
263 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
265 PayloadLen
= (UINT16
) (OptionLen
+ sizeof (IP6_MLD_HEAD
));
266 Packet
= NetbufAlloc (sizeof (EFI_IP6_HEADER
) + (UINT32
) PayloadLen
);
267 if (Packet
== NULL
) {
268 return EFI_OUT_OF_RESOURCES
;
272 // Create the basic IPv6 header.
276 Head
.PayloadLength
= HTONS (PayloadLen
);
277 Head
.NextHeader
= IP6_HOP_BY_HOP
;
281 // If Link-Local address is not ready, we use unspecified address.
283 IP6_COPY_ADDRESS (&Head
.SourceAddress
, &IpSb
->LinkLocalAddr
);
285 Ip6SetToAllNodeMulticast (TRUE
, IP6_LINK_LOCAL_SCOPE
, &Destination
);
286 IP6_COPY_ADDRESS (&Head
.DestinationAddress
, &Destination
);
288 NetbufReserve (Packet
, sizeof (EFI_IP6_HEADER
));
291 // Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
293 Options
= NetbufAllocSpace (Packet
, (UINT32
) OptionLen
, FALSE
);
294 ASSERT (Options
!= NULL
);
295 Status
= Ip6FillHopByHop (Options
, &OptionLen
, IP6_ICMP
);
296 if (EFI_ERROR (Status
)) {
303 // Fill in MLD message - Done
305 MldHead
= (IP6_MLD_HEAD
*) NetbufAllocSpace (Packet
, sizeof (IP6_MLD_HEAD
), FALSE
);
306 ASSERT (MldHead
!= NULL
);
307 ZeroMem (MldHead
, sizeof (IP6_MLD_HEAD
));
308 MldHead
->Head
.Type
= ICMP_V6_LISTENER_DONE
;
309 MldHead
->Head
.Code
= 0;
310 IP6_COPY_ADDRESS (&MldHead
->Group
, MulticastAddr
);
312 HeadChecksum
= NetblockChecksum ((UINT8
*) MldHead
, sizeof (IP6_MLD_HEAD
));
313 PseudoChecksum
= NetIp6PseudoHeadChecksum (
315 &Head
.DestinationAddress
,
317 sizeof (IP6_MLD_HEAD
)
320 MldHead
->Head
.Checksum
= (UINT16
) ~NetAddChecksum (HeadChecksum
, PseudoChecksum
);
323 // Transmit the packet
325 return Ip6Output (IpSb
, NULL
, NULL
, Packet
, &Head
, NULL
, 0, Ip6SysPacketSent
, NULL
);
329 Init the MLD data of the IP6 service instance. Configure
330 MNP to receive ALL SYSTEM multicast.
332 @param[in] IpSb The IP6 service whose MLD is to be initialized.
334 @retval EFI_OUT_OF_RESOURCES There are not sufficient resourcet to complete the
336 @retval EFI_SUCCESS The MLD module successfully initialized.
344 EFI_IPv6_ADDRESS AllNodes
;
345 IP6_MLD_GROUP
*Group
;
349 // Join the link-scope all-nodes multicast address (FF02::1).
350 // This address is started in Idle Listener state and never transitions to
351 // another state, and never sends a Report or Done for that address.
354 Ip6SetToAllNodeMulticast (FALSE
, IP6_LINK_LOCAL_SCOPE
, &AllNodes
);
356 Group
= Ip6CreateMldEntry (IpSb
, &AllNodes
, (UINT32
) IP6_INFINIT_LIFETIME
);
358 return EFI_OUT_OF_RESOURCES
;
361 Status
= Ip6GetMulticastMac (IpSb
->Mnp
, &AllNodes
, &Group
->Mac
);
362 if (EFI_ERROR (Status
)) {
367 // Configure MNP to receive all-nodes multicast
369 Status
= IpSb
->Mnp
->Groups (IpSb
->Mnp
, TRUE
, &Group
->Mac
);
370 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
377 RemoveEntryList (&Group
->Link
);
383 Add a group address to the array of group addresses.
384 The caller should make sure that no duplicated address
385 existed in the array.
387 @param[in, out] IpInstance Points to an IP6_PROTOCOL instance.
388 @param[in] Group The IP6 multicast address to add.
390 @retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete
392 @retval EFI_SUCESS The address is added to the group address array.
397 IN OUT IP6_PROTOCOL
*IpInstance
,
398 IN EFI_IPv6_ADDRESS
*Group
401 EFI_IPv6_ADDRESS
*GroupList
;
403 NET_CHECK_SIGNATURE (IpInstance
, IP6_PROTOCOL_SIGNATURE
);
404 ASSERT (Group
!= NULL
&& IP6_IS_MULTICAST (Group
));
406 IpInstance
->GroupCount
++;
408 GroupList
= AllocatePool (IpInstance
->GroupCount
* sizeof (EFI_IPv6_ADDRESS
));
409 if (GroupList
== NULL
) {
410 return EFI_OUT_OF_RESOURCES
;
413 if (IpInstance
->GroupCount
> 1) {
414 ASSERT (IpInstance
->GroupList
!= NULL
);
418 IpInstance
->GroupList
,
419 (IpInstance
->GroupCount
- 1) * sizeof (EFI_IPv6_ADDRESS
)
422 FreePool (IpInstance
->GroupList
);
425 IP6_COPY_ADDRESS (GroupList
+ (IpInstance
->GroupCount
- 1), Group
);
427 IpInstance
->GroupList
= GroupList
;
433 Remove a group address from the array of group addresses.
434 Although the function doesn't assume the byte order of Group,
435 the network byte order is used by the caller.
437 @param[in, out] IpInstance Points to an IP6_PROTOCOL instance.
438 @param[in] Group The IP6 multicast address to remove.
440 @retval EFI_NOT_FOUND Cannot find the to be removed group address.
441 @retval EFI_SUCCESS The group address was successfully removed.
446 IN OUT IP6_PROTOCOL
*IpInstance
,
447 IN EFI_IPv6_ADDRESS
*Group
453 Count
= IpInstance
->GroupCount
;
455 for (Index
= 0; Index
< Count
; Index
++) {
456 if (EFI_IP6_EQUAL (IpInstance
->GroupList
+ Index
, Group
)) {
461 if (Index
== Count
) {
462 return EFI_NOT_FOUND
;
465 while (Index
< Count
- 1) {
466 IP6_COPY_ADDRESS (IpInstance
->GroupList
+ Index
, IpInstance
->GroupList
+ Index
+ 1);
470 ASSERT (IpInstance
->GroupCount
> 0);
471 IpInstance
->GroupCount
--;
477 Join the multicast group on behalf of this IP6 service binding instance.
479 @param[in] IpSb The IP6 service binding instance.
480 @param[in] Interface Points to an IP6_INTERFACE structure.
481 @param[in] Address The group address to join.
483 @retval EFI_SUCCESS Successfully join the multicast group.
484 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
485 @retval Others Failed to join the multicast group.
490 IN IP6_SERVICE
*IpSb
,
491 IN IP6_INTERFACE
*Interface
,
492 IN EFI_IPv6_ADDRESS
*Address
495 IP6_MLD_GROUP
*Group
;
498 Group
= Ip6FindMldEntry (IpSb
, Address
);
505 // Repeat the report once or twcie after short delays [Unsolicited Report Interval] (default:10s)
506 // Simulate this operation as a Multicast-Address-Specific Query was received for that addresss.
508 Group
= Ip6CreateMldEntry (IpSb
, Address
, IP6_UNSOLICITED_REPORT_INTERVAL
);
510 return EFI_OUT_OF_RESOURCES
;
513 Group
->SendByUs
= TRUE
;
515 Status
= Ip6GetMulticastMac (IpSb
->Mnp
, Address
, &Group
->Mac
);
516 if (EFI_ERROR (Status
)) {
520 Status
= IpSb
->Mnp
->Groups (IpSb
->Mnp
, TRUE
, &Group
->Mac
);
521 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
526 // Send unsolicited report when a node starts listening to a multicast address
528 Status
= Ip6SendMldReport (IpSb
, Interface
, Address
);
529 if (EFI_ERROR (Status
)) {
536 RemoveEntryList (&Group
->Link
);
542 Leave the IP6 multicast group.
544 @param[in] IpSb The IP6 service binding instance.
545 @param[in] Address The group address to leave.
547 @retval EFI_NOT_FOUND The IP6 service instance isn't in the group.
548 @retval EFI_SUCCESS Successfully leave the multicast group..
549 @retval Others Failed to leave the multicast group.
554 IN IP6_SERVICE
*IpSb
,
555 IN EFI_IPv6_ADDRESS
*Address
558 IP6_MLD_GROUP
*Group
;
561 Group
= Ip6FindMldEntry (IpSb
, Address
);
563 return EFI_NOT_FOUND
;
567 // If more than one instance is in the group, decrease
568 // the RefCnt then return.
570 if ((Group
->RefCnt
> 0) && (--Group
->RefCnt
> 0)) {
575 // If multiple IP6 group addresses are mapped to the same
576 // multicast MAC address, don't configure the MNP to leave
579 if (Ip6FindMac (&IpSb
->MldCtrl
, &Group
->Mac
) == 1) {
580 Status
= IpSb
->Mnp
->Groups (IpSb
->Mnp
, FALSE
, &Group
->Mac
);
581 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_FOUND
)) {
587 // Send a leave report if we are the last node to report
589 if (Group
->SendByUs
) {
590 Status
= Ip6SendMldDone (IpSb
, Address
);
591 if (EFI_ERROR (Status
)) {
596 RemoveEntryList (&Group
->Link
);
603 Worker function for EfiIp6Groups(). The caller
604 should make sure that the parameters are valid.
606 @param[in] IpInstance The IP6 child to change the setting.
607 @param[in] JoinFlag TRUE to join the group, otherwise leave it.
608 @param[in] GroupAddress The target group address. If NULL, leave all
611 @retval EFI_ALREADY_STARTED Wants to join the group, but is already a member of it
612 @retval EFI_OUT_OF_RESOURCES Failed to allocate sufficient resources.
613 @retval EFI_DEVICE_ERROR Failed to set the group configuraton.
614 @retval EFI_SUCCESS Successfully updated the group setting.
615 @retval EFI_NOT_FOUND Try to leave the group which it isn't a member.
620 IN IP6_PROTOCOL
*IpInstance
,
622 IN EFI_IPv6_ADDRESS
*GroupAddress OPTIONAL
628 EFI_IPv6_ADDRESS
*Group
;
630 IpSb
= IpInstance
->Service
;
633 ASSERT (GroupAddress
!= NULL
);
635 for (Index
= 0; Index
< IpInstance
->GroupCount
; Index
++) {
636 if (EFI_IP6_EQUAL (IpInstance
->GroupList
+ Index
, GroupAddress
)) {
637 return EFI_ALREADY_STARTED
;
641 Status
= Ip6JoinGroup (IpSb
, IpInstance
->Interface
, GroupAddress
);
642 if (!EFI_ERROR (Status
)) {
643 return Ip6CombineGroups (IpInstance
, GroupAddress
);
650 // Leave the group. Leave all the groups if GroupAddress is NULL.
652 for (Index
= IpInstance
->GroupCount
; Index
> 0; Index
--) {
653 Group
= IpInstance
->GroupList
+ (Index
- 1);
655 if ((GroupAddress
== NULL
) || EFI_IP6_EQUAL (Group
, GroupAddress
)) {
656 Status
= Ip6LeaveGroup (IpInstance
->Service
, Group
);
657 if (EFI_ERROR (Status
)) {
661 Ip6RemoveGroup (IpInstance
, Group
);
663 if (IpInstance
->GroupCount
== 0) {
665 FreePool (IpInstance
->GroupList
);
666 IpInstance
->GroupList
= NULL
;
669 if (GroupAddress
!= NULL
) {
675 return ((GroupAddress
!= NULL
) ? EFI_NOT_FOUND
: EFI_SUCCESS
);
679 Set a random value of the delay timer for the multicast address from the range
680 [0, Maximum Response Delay]. If a timer for any address is already
681 running, it is reset to the new random value only if the requested
682 Maximum Response Delay is less than the remaining value of the
683 running timer. If the Query packet specifies a Maximum Response
684 Delay of zero, each timer is effectively set to zero, and the action
685 specified below for timer expiration is performed immediately.
687 @param[in] IpSb The IP6 service binding instance.
688 @param[in] MaxRespDelay The Maximum Response Delay, in milliseconds.
689 @param[in] MulticastAddr The multicast address.
690 @param[in, out] Group Points to a IP6_MLD_GROUP list entry node.
692 @retval EFI_SUCCESS The delay timer is successfully updated or
693 timer expiration is performed immediately.
694 @retval Others Failed to send out MLD report message.
698 Ip6UpdateDelayTimer (
699 IN IP6_SERVICE
*IpSb
,
700 IN UINT16 MaxRespDelay
,
701 IN EFI_IPv6_ADDRESS
*MulticastAddr
,
702 IN OUT IP6_MLD_GROUP
*Group
708 // If the Query packet specifies a Maximum Response Delay of zero, perform timer
709 // expiration immediately.
711 if (MaxRespDelay
== 0) {
712 Group
->DelayTimer
= 0;
713 return Ip6SendMldReport (IpSb
, NULL
, MulticastAddr
);
716 Delay
= (UINT32
) (MaxRespDelay
/ 1000);
719 // Sets a delay timer to a random value selected from the range [0, Maximum Response Delay]
720 // If a timer is already running, resets it if the request Maximum Response Delay
721 // is less than the remaining value of the running timer.
723 if (Group
->DelayTimer
== 0 || Delay
< Group
->DelayTimer
) {
724 Group
->DelayTimer
= Delay
/ 4294967295UL * NET_RANDOM (NetRandomInitSeed ());
731 Process the Multicast Listener Query message.
733 @param[in] IpSb The IP service that received the packet.
734 @param[in] Head The IP head of the MLD query packet.
735 @param[in] Packet The content of the MLD query packet with IP head
738 @retval EFI_SUCCESS The MLD query packet processed successfully.
739 @retval EFI_INVALID_PARAMETER The packet is invalid.
740 @retval Others Failed to process the packet.
745 IN IP6_SERVICE
*IpSb
,
746 IN EFI_IP6_HEADER
*Head
,
750 EFI_IPv6_ADDRESS AllNodes
;
751 IP6_MLD_GROUP
*Group
;
752 IP6_MLD_HEAD MldPacket
;
756 Status
= EFI_INVALID_PARAMETER
;
759 // Check the validity of the packet, generic query or specific query
761 if (!NetIp6IsUnspecifiedAddr (&Head
->SourceAddress
) && !NetIp6IsLinkLocalAddr (&Head
->SourceAddress
)) {
765 if (Head
->HopLimit
!= 1 || !IP6_IS_MULTICAST (&Head
->DestinationAddress
)) {
770 // The Packet points to MLD report raw data without Hop-By-Hop option.
772 NetbufCopy (Packet
, 0, sizeof (IP6_MLD_HEAD
), (UINT8
*) &MldPacket
);
773 MldPacket
.MaxRespDelay
= NTOHS (MldPacket
.MaxRespDelay
);
775 Ip6SetToAllNodeMulticast (FALSE
, IP6_LINK_LOCAL_SCOPE
, &AllNodes
);
776 if (!EFI_IP6_EQUAL (&Head
->DestinationAddress
, &AllNodes
)) {
778 // Receives a Multicast-Address-Specific Query, check it firstly
780 if (!EFI_IP6_EQUAL (&Head
->DestinationAddress
, &MldPacket
.Group
)) {
784 // The node is not listening but it receives the specific query. Just return.
786 Group
= Ip6FindMldEntry (IpSb
, &MldPacket
.Group
);
788 Status
= EFI_SUCCESS
;
792 Status
= Ip6UpdateDelayTimer (
794 MldPacket
.MaxRespDelay
,
802 // Receives a General Query, sets a delay timer for each multicast address it is listening
804 NET_LIST_FOR_EACH (Entry
, &IpSb
->MldCtrl
.Groups
) {
805 Group
= NET_LIST_USER_STRUCT (Entry
, IP6_MLD_GROUP
, Link
);
806 Status
= Ip6UpdateDelayTimer (IpSb
, MldPacket
.MaxRespDelay
, &Group
->Address
, Group
);
807 if (EFI_ERROR (Status
)) {
812 Status
= EFI_SUCCESS
;
820 Process the Multicast Listener Report message.
822 @param[in] IpSb The IP service that received the packet.
823 @param[in] Head The IP head of the MLD report packet.
824 @param[in] Packet The content of the MLD report packet with IP head
827 @retval EFI_SUCCESS The MLD report packet processed successfully.
828 @retval EFI_INVALID_PARAMETER The packet is invalid.
832 Ip6ProcessMldReport (
833 IN IP6_SERVICE
*IpSb
,
834 IN EFI_IP6_HEADER
*Head
,
838 IP6_MLD_HEAD MldPacket
;
839 IP6_MLD_GROUP
*Group
;
842 Status
= EFI_INVALID_PARAMETER
;
845 // Validate the incoming message, if invalid, drop it.
847 if (!NetIp6IsUnspecifiedAddr (&Head
->SourceAddress
) && !NetIp6IsLinkLocalAddr (&Head
->SourceAddress
)) {
851 if (Head
->HopLimit
!= 1 || !IP6_IS_MULTICAST (&Head
->DestinationAddress
)) {
856 // The Packet points to MLD report raw data without Hop-By-Hop option.
858 NetbufCopy (Packet
, 0, sizeof (IP6_MLD_HEAD
), (UINT8
*) &MldPacket
);
859 if (!EFI_IP6_EQUAL (&Head
->DestinationAddress
, &MldPacket
.Group
)) {
863 Group
= Ip6FindMldEntry (IpSb
, &MldPacket
.Group
);
869 // The report is sent by another node, stop its own timer relates to the multicast address and clear
872 if (!Group
->SendByUs
) {
873 Group
->DelayTimer
= 0;
876 Status
= EFI_SUCCESS
;
884 The heartbeat timer of MLD module. It sends out a solicited MLD report when
887 @param[in] IpSb The IP6 service binding instance.
895 IP6_MLD_GROUP
*Group
;
899 // Send solicited report when timer expires
901 NET_LIST_FOR_EACH (Entry
, &IpSb
->MldCtrl
.Groups
) {
902 Group
= NET_LIST_USER_STRUCT (Entry
, IP6_MLD_GROUP
, Link
);
903 if ((Group
->DelayTimer
> 0) && (--Group
->DelayTimer
== 0)) {
904 Ip6SendMldReport (IpSb
, NULL
, &Group
->Address
);