4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Multicast Listener Discovery support routines.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "Ip6Impl.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create a IP6_MLD_GROUP list entry node and record to IP6 service binding data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] IpSb Points to IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MulticastAddr The IPv6 multicast address to be recorded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DelayTimer The maximum allowed delay before sending a responding
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync report, in units of milliseconds.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The created IP6_ML_GROUP list entry or NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_MLD_GROUP *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CreateMldEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *MulticastAddr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 DelayTimer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = AllocatePool (sizeof (IP6_MLD_GROUP));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Entry != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->RefCnt = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->DelayTimer = DelayTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->SendByUs = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Entry->Address, MulticastAddr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&IpSb->MldCtrl.Groups, &Entry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Search a IP6_MLD_GROUP list entry node from a list array.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb Points to IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MulticastAddr The IPv6 multicast address to be searched.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The found IP6_ML_GROUP list entry or NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_MLD_GROUP *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6FindMldEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *MulticastAddr
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_IP6_EQUAL (MulticastAddr, &Group->Address)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count the number of IP6 multicast groups that are mapped to the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync same MAC address. Several IP6 multicast address may be mapped to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the same MAC address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MldCtrl The MLD control block to search in.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Mac The MAC address to search.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The number of the IP6 multicast group that mapped to the same
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync multicast group Mac.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6FindMac (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_MLD_SERVICE_DATA *MldCtrl,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MAC_ADDRESS *Mac
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &MldCtrl->Groups) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NET_MAC_EQUAL (&Group->Mac, Mac, sizeof (EFI_MAC_ADDRESS))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Generate MLD report message and send it out to MulticastAddr.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service to send the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Interface The IP interface to send the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If NULL, a system interface will be selected.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MulticastAddr The specific IPv6 multicast address to which
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the message sender is listening.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The MLD report message was successfully sent out.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6SendMldReport (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *Interface OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *MulticastAddr
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_HEAD *MldHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_HEADER Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 PayloadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN OptionLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Options;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 HeadChecksum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 PseudoChecksum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate the packet to be sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // IPv6 basic header + Hop by Hop option + MLD message
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptionLen = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6FillHopByHop (NULL, &OptionLen, IP6_ICMP);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Status == EFI_BUFFER_TOO_SMALL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PayloadLen = (UINT16) (OptionLen + sizeof (IP6_MLD_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create the basic IPv6 header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RFC3590: Use link-local address as source address if it is available,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // otherwise use the unspecified address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelL = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelH = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.PayloadLength = HTONS (PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.NextHeader = IP6_HOP_BY_HOP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.HopLimit = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.DestinationAddress, MulticastAddr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If Link-Local address is not ready, we use unspecified address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.SourceAddress, &IpSb->LinkLocalAddr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Options = NetbufAllocSpace (Packet, (UINT32) OptionLen, FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Options != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6FillHopByHop (Options, &OptionLen, IP6_ICMP);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill in MLD message - Report
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldHead = (IP6_MLD_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_MLD_HEAD), FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MldHead != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (MldHead, sizeof (IP6_MLD_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldHead->Head.Type = ICMP_V6_LISTENER_REPORT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldHead->Head.Code = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&MldHead->Group, MulticastAddr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HeadChecksum = NetblockChecksum ((UINT8 *) MldHead, sizeof (IP6_MLD_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PseudoChecksum = NetIp6PseudoHeadChecksum (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Head.SourceAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Head.DestinationAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (IP6_MLD_HEAD)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldHead->Head.Checksum = (UINT16) ~NetAddChecksum (HeadChecksum, PseudoChecksum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transmit the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Ip6Output (IpSb, Interface, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Generate MLD Done message and send it out to MulticastAddr.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service to send the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MulticastAddr The specific IPv6 multicast address to which
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the message sender is ceasing to listen.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The MLD report message was successfully sent out.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6SendMldDone (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *MulticastAddr
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_HEAD *MldHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_HEADER Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 PayloadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN OptionLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Options;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS Destination;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 HeadChecksum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 PseudoChecksum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MulticastAddr != NULL && IP6_IS_MULTICAST (MulticastAddr));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate the packet to be sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // IPv6 basic header + Hop by Hop option + MLD message
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptionLen = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6FillHopByHop (NULL, &OptionLen, IP6_ICMP);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Status == EFI_BUFFER_TOO_SMALL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PayloadLen = (UINT16) (OptionLen + sizeof (IP6_MLD_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create the basic IPv6 header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelL = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelH = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.PayloadLength = HTONS (PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.NextHeader = IP6_HOP_BY_HOP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.HopLimit = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If Link-Local address is not ready, we use unspecified address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.SourceAddress, &IpSb->LinkLocalAddr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6SetToAllNodeMulticast (TRUE, IP6_LINK_LOCAL_SCOPE, &Destination);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.DestinationAddress, &Destination);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill a IPv6 Router Alert option in a Hop-by-Hop Options Header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Options = NetbufAllocSpace (Packet, (UINT32) OptionLen, FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Options != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6FillHopByHop (Options, &OptionLen, IP6_ICMP);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill in MLD message - Done
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldHead = (IP6_MLD_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_MLD_HEAD), FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (MldHead != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (MldHead, sizeof (IP6_MLD_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldHead->Head.Type = ICMP_V6_LISTENER_DONE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldHead->Head.Code = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&MldHead->Group, MulticastAddr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HeadChecksum = NetblockChecksum ((UINT8 *) MldHead, sizeof (IP6_MLD_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PseudoChecksum = NetIp6PseudoHeadChecksum (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Head.SourceAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Head.DestinationAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (IP6_MLD_HEAD)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldHead->Head.Checksum = (UINT16) ~NetAddChecksum (HeadChecksum, PseudoChecksum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transmit the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Ip6Output (IpSb, NULL, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Init the MLD data of the IP6 service instance. Configure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MNP to receive ALL SYSTEM multicast.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service whose MLD is to be initialized.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES There are not sufficient resourcet to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The MLD module successfully initialized.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6InitMld (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS AllNodes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Join the link-scope all-nodes multicast address (FF02::1).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // This address is started in Idle Listener state and never transitions to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // another state, and never sends a Report or Done for that address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = Ip6CreateMldEntry (IpSb, &AllNodes, (UINT32) IP6_INFINIT_LIFETIME);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Group == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6GetMulticastMac (IpSb->Mnp, &AllNodes, &Group->Mac);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Configure MNP to receive all-nodes multicast
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IpSb->Mnp->Groups (IpSb->Mnp, TRUE, &Group->Mac);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncERROR:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Group->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Add a group address to the array of group addresses.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The caller should make sure that no duplicated address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync existed in the array.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] IpInstance Points to an IP6_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Group The IP6 multicast address to add.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES There are not sufficient resources to complete
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCESS The address is added to the group address array.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CombineGroups (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT IP6_PROTOCOL *IpInstance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Group
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS *GroupList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Group != NULL && IP6_IS_MULTICAST (Group));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpInstance->GroupCount++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GroupList = AllocatePool (IpInstance->GroupCount * sizeof (EFI_IPv6_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (GroupList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpInstance->GroupCount > 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IpInstance->GroupList != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GroupList,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpInstance->GroupList,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (IpInstance->GroupCount - 1) * sizeof (EFI_IPv6_ADDRESS)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (IpInstance->GroupList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (GroupList + (IpInstance->GroupCount - 1), Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpInstance->GroupList = GroupList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Remove a group address from the array of group addresses.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Although the function doesn't assume the byte order of Group,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the network byte order is used by the caller.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] IpInstance Points to an IP6_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Group The IP6 multicast address to remove.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_FOUND Cannot find the to be removed group address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The group address was successfully removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6RemoveGroup (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT IP6_PROTOCOL *IpInstance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Group
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count = IpInstance->GroupCount;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < Count; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, Group)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Index == Count) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Index < Count - 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (IpInstance->GroupList + Index, IpInstance->GroupList + Index + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Index++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IpInstance->GroupCount > 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpInstance->GroupCount--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Join the multicast group on behalf of this IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Interface Points to an IP6_INTERFACE structure.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Address The group address to join.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Successfully join the multicast group.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to join the multicast group.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6JoinGroup (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *Interface,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = Ip6FindMldEntry (IpSb, Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Group != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group->RefCnt++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Repeat the report once or twcie after short delays [Unsolicited Report Interval] (default:10s)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Simulate this operation as a Multicast-Address-Specific Query was received for that addresss.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = Ip6CreateMldEntry (IpSb, Address, IP6_UNSOLICITED_REPORT_INTERVAL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Group == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group->SendByUs = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6GetMulticastMac (IpSb->Mnp, Address, &Group->Mac);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IpSb->Mnp->Groups (IpSb->Mnp, TRUE, &Group->Mac);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send unsolicited report when a node starts listening to a multicast address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SendMldReport (IpSb, Interface, Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncERROR:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Group->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Leave the IP6 multicast group.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Address The group address to leave.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_FOUND The IP6 service instance isn't in the group.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Successfully leave the multicast group..
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to leave the multicast group.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6LeaveGroup (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = Ip6FindMldEntry (IpSb, Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Group == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If more than one instance is in the group, decrease
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the RefCnt then return.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Group->RefCnt > 0) && (--Group->RefCnt > 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If multiple IP6 group addresses are mapped to the same
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // multicast MAC address, don't configure the MNP to leave
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the MAC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Ip6FindMac (&IpSb->MldCtrl, &Group->Mac) == 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IpSb->Mnp->Groups (IpSb->Mnp, FALSE, &Group->Mac);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send a leave report if we are the last node to report
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Group->SendByUs) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SendMldDone (IpSb, Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Group->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Worker function for EfiIp6Groups(). The caller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync should make sure that the parameters are valid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpInstance The IP6 child to change the setting.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] JoinFlag TRUE to join the group, otherwise leave it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] GroupAddress The target group address. If NULL, leave all
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the group addresses.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_ALREADY_STARTED Wants to join the group, but is already a member of it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate sufficient resources.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR Failed to set the group configuraton.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Successfully updated the group setting.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_FOUND Try to leave the group which it isn't a member.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6Groups (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_PROTOCOL *IpInstance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN JoinFlag,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = IpInstance->Service;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (JoinFlag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (GroupAddress != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < IpInstance->GroupCount; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_IP6_EQUAL (IpInstance->GroupList + Index, GroupAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_ALREADY_STARTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6JoinGroup (IpSb, IpInstance->Interface, GroupAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Ip6CombineGroups (IpInstance, GroupAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Leave the group. Leave all the groups if GroupAddress is NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = IpInstance->GroupCount; Index > 0; Index--) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = IpInstance->GroupList + (Index - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((GroupAddress == NULL) || EFI_IP6_EQUAL (Group, GroupAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6LeaveGroup (IpInstance->Service, Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6RemoveGroup (IpInstance, Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpInstance->GroupCount == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Index == 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (IpInstance->GroupList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpInstance->GroupList = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (GroupAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ((GroupAddress != NULL) ? EFI_NOT_FOUND : EFI_SUCCESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Set a random value of the delay timer for the multicast address from the range
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync [0, Maximum Response Delay]. If a timer for any address is already
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync running, it is reset to the new random value only if the requested
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Maximum Response Delay is less than the remaining value of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync running timer. If the Query packet specifies a Maximum Response
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Delay of zero, each timer is effectively set to zero, and the action
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync specified below for timer expiration is performed immediately.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MaxRespDelay The Maximum Response Delay, in milliseconds.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MulticastAddr The multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Group Points to a IP6_MLD_GROUP list entry node.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The delay timer is successfully updated or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync timer expiration is performed immediately.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to send out MLD report message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6UpdateDelayTimer (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT16 MaxRespDelay,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *MulticastAddr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT IP6_MLD_GROUP *Group
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Delay;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the Query packet specifies a Maximum Response Delay of zero, perform timer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // expiration immediately.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (MaxRespDelay == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group->DelayTimer = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Ip6SendMldReport (IpSb, NULL, MulticastAddr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Delay = (UINT32) (MaxRespDelay / 1000);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Sets a delay timer to a random value selected from the range [0, Maximum Response Delay]
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If a timer is already running, resets it if the request Maximum Response Delay
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is less than the remaining value of the running timer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Group->DelayTimer == 0 || Delay < Group->DelayTimer) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group->DelayTimer = Delay / 4294967295UL * NET_RANDOM (NetRandomInitSeed ());
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the Multicast Listener Query message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service that received the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Head The IP head of the MLD query packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The content of the MLD query packet with IP head
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The MLD query packet processed successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER The packet is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to process the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6ProcessMldQuery (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP6_HEADER *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS AllNodes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_HEAD MldPacket;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the validity of the packet, generic query or specific query
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!NetIp6IsUnspecifiedAddr (&Head->SourceAddress) && !NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->HopLimit != 1 || !IP6_IS_MULTICAST (&Head->DestinationAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The Packet points to MLD report raw data without Hop-By-Hop option.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, 0, sizeof (IP6_MLD_HEAD), (UINT8 *) &MldPacket);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldPacket.MaxRespDelay = NTOHS (MldPacket.MaxRespDelay);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &AllNodes)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Receives a Multicast-Address-Specific Query, check it firstly
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &MldPacket.Group)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The node is not listening but it receives the specific query. Just return.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = Ip6FindMldEntry (IpSb, &MldPacket.Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Group == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6UpdateDelayTimer (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MldPacket.MaxRespDelay,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &MldPacket.Group,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Receives a General Query, sets a delay timer for each multicast address it is listening
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6UpdateDelayTimer (IpSb, MldPacket.MaxRespDelay, &Group->Address, Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncExit:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the Multicast Listener Report message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service that received the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Head The IP head of the MLD report packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The content of the MLD report packet with IP head
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The MLD report packet processed successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER The packet is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6ProcessMldReport (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP6_HEADER *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_HEAD MldPacket;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Validate the incoming message, if invalid, drop it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!NetIp6IsUnspecifiedAddr (&Head->SourceAddress) && !NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->HopLimit != 1 || !IP6_IS_MULTICAST (&Head->DestinationAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The Packet points to MLD report raw data without Hop-By-Hop option.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, 0, sizeof (IP6_MLD_HEAD), (UINT8 *) &MldPacket);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_IP6_EQUAL (&Head->DestinationAddress, &MldPacket.Group)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = Ip6FindMldEntry (IpSb, &MldPacket.Group);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Group == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The report is sent by another node, stop its own timer relates to the multicast address and clear
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Group->SendByUs) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group->DelayTimer = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncExit:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The heartbeat timer of MLD module. It sends out a solicited MLD report when
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayTimer expires.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6MldTimerTicking (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MLD_GROUP *Group;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send solicited report when timer expires
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->MldCtrl.Groups) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Group = NET_LIST_USER_STRUCT (Entry, IP6_MLD_GROUP, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Group->DelayTimer > 0) && (--Group->DelayTimer == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6SendMldReport (IpSb, NULL, &Group->Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync