4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Implement IP6 pesudo interface.
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 Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Event The transmit token's event.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The Context which is pointed to the token.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6OnFrameSent (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_EVENT Event,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fileter function to cancel all the frame related to an IP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Frame The transmit request to test whether to cancel.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The context which is the Ip instance that issued
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the transmit.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval TRUE The frame belongs to this instance and is to be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval FALSE The frame doesn't belong to this instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CancelInstanceFrame (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_LINK_TX_TOKEN *Frame,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Frame->IpInstance == (IP6_PROTOCOL *) Context) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Set the interface's address. This will trigger the DAD process for the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync address to set. To set an already set address, the lifetimes wil be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync updated to the new value passed in.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Interface The interface to set the address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Ip6Addr The interface's to be assigned IPv6 address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IsAnycast If TRUE, the unicast IPv6 address is anycast.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, it is not anycast.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PrefixLength The prefix length of the Ip6Addr.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] ValidLifetime The valid lifetime for this address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PreferredLifetime The preferred lifetime for this address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DadCallback The caller's callback to trigger when DAD finishes.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This is an optional parameter that may be NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The context that will be passed to DadCallback.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This is an optional parameter that may be NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The interface is scheduled to be configured with
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the specified address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to set the interface's address due to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync lack of resources.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6SetAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *Interface,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Ip6Addr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN IsAnycast,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ValidLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 PreferredLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_DAD_CALLBACK DadCallback OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ADDRESS_INFO *AddressInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_LIST_ENTRY *PrefixEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 Delay;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DELAY_JOIN_LIST *DelayNode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = Interface->Service;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Ip6IsOneOfSetAddress (IpSb, Ip6Addr, NULL, &AddressInfo)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (AddressInfo != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the lifetime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->ValidLifetime = ValidLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->PreferredLifetime = PreferredLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DadCallback != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DadCallback (TRUE, Ip6Addr, Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo = (IP6_ADDRESS_INFO *) AllocatePool (sizeof (IP6_ADDRESS_INFO));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AddressInfo == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->Signature = IP6_ADDR_INFO_SIGNATURE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&AddressInfo->Address, Ip6Addr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->IsAnycast = IsAnycast;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->PrefixLength = PrefixLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->ValidLifetime = ValidLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->PreferredLifetime = PreferredLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AddressInfo->PrefixLength == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find an appropriate prefix from on-link prefixes and update the prefixlength.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Longest prefix match is used here.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NetIp6IsNetEqual (&PrefixEntry->Prefix, &AddressInfo->Address, PrefixEntry->PrefixLength)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->PrefixLength = PrefixEntry->PrefixLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AddressInfo->PrefixLength == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the prefix length is still zero, try the autonomous prefixes.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Longest prefix match is used here.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->AutonomousPrefix) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NetIp6IsNetEqual (&PrefixEntry->Prefix, &AddressInfo->Address, PrefixEntry->PrefixLength)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->PrefixLength = PrefixEntry->PrefixLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AddressInfo->PrefixLength == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // BUGBUG: Stil fail, use 64 as the default prefix length.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddressInfo->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Node should delay joining the solicited-node mulitcast address by a random delay
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // between 0 and MAX_RTR_SOLICITATION_DELAY (1 second).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Thus queue the address to be processed in Duplicate Address Detection module
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // after the delay time (in milliseconds).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Delay = (UINT64) NET_RANDOM (NetRandomInitSeed ());
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Delay = MultU64x32 (Delay, IP6_ONE_SECOND_IN_MS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Delay = RShiftU64 (Delay, 32);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode = (IP6_DELAY_JOIN_LIST *) AllocatePool (sizeof (IP6_DELAY_JOIN_LIST));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DelayNode == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (AddressInfo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->DelayTime = (UINT32) (DivU64x32 (Delay, IP6_TIMER_INTERVAL_IN_MS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->Interface = Interface;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->AddressInfo = AddressInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->DadCallback = DadCallback;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->Context = Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&Interface->DelayJoinList, &DelayNode->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create an IP6_INTERFACE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] LinkLocal If TRUE, the instance is created for link-local address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, it is not for a link-local address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Point to the created IP6_INTERFACE, otherwise NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_INTERFACE *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CreateInterface (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN LinkLocal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_INTERFACE *Interface;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS *Ip6Addr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface = AllocatePool (sizeof (IP6_INTERFACE));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Interface == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->Signature = IP6_INTERFACE_SIGNATURE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->RefCnt = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Interface->AddressList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->AddressCount = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->Configured = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->Service = IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->Controller = IpSb->Controller;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->Image = IpSb->Image;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Interface->ArpQues);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Interface->SentFrames);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->DupAddrDetect = IpSb->Ip6ConfigInstance.DadXmits.DupAddrDetectTransmits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Interface->DupAddrDetectList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Interface->DelayJoinList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Interface->IpInstances);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface->PromiscRecv = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!LinkLocal) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Interface;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the link local addr
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6Addr = Ip6CreateLinkLocalAddr (IpSb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Ip6Addr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Perform DAD - Duplicate Address Detection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SetAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Interface,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6Addr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_LOCAL_PREFIX_LENGTH,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT32) IP6_INFINIT_LIFETIME,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT32) IP6_INFINIT_LIFETIME,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Ip6Addr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Interface;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncON_ERROR:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Interface);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Free the interface used by IpInstance. All the IP instance with
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the same Ip/prefix pair share the same interface. It is reference
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync counted. All the frames that haven't been sent will be cancelled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Because the IpInstance is optional, the caller must remove
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpInstance from the interface's instance list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Interface The interface used by the IpInstance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpInstance The IP instance that free the interface. NULL if
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the IP driver is releasing the default interface.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CleanInterface (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *Interface,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_PROTOCOL *IpInstance OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DAD_ENTRY *Duplicate;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DELAY_JOIN_LIST *Delay;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Interface->RefCnt > 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove all the pending transmit token related to this IP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6CancelFrames (Interface, EFI_ABORTED, Ip6CancelInstanceFrame, IpInstance);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (--Interface->RefCnt > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Destory the interface if this is the last IP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove all the system transmitted packets
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // from this interface, cancel the receive request if exists.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6CancelFrames (Interface, EFI_ABORTED, Ip6CancelInstanceFrame, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IsListEmpty (&Interface->IpInstances));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IsListEmpty (&Interface->ArpQues));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IsListEmpty (&Interface->SentFrames));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (!IsListEmpty (&Interface->DupAddrDetectList)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Duplicate = NET_LIST_HEAD (&Interface->DupAddrDetectList, IP6_DAD_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetListRemoveHead (&Interface->DupAddrDetectList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Duplicate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (!IsListEmpty (&Interface->DelayJoinList)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Delay = NET_LIST_HEAD (&Interface->DelayJoinList, IP6_DELAY_JOIN_LIST, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetListRemoveHead (&Interface->DelayJoinList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Delay);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6RemoveAddr (Interface->Service, &Interface->AddressList, &Interface->AddressCount, NULL, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Interface->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Interface);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create and wrap a transmit request into a newly allocated IP6_LINK_TX_TOKEN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Interface The interface to send out from.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpInstance The IpInstance that transmit the packet. NULL if
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the packet is sent by the IP6 driver itself.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The packet to transmit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] CallBack Call back function to execute if transmission
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync finished.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context Opaque parameter to the callback.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The wrapped token if succeed or NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_LINK_TX_TOKEN *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CreateLinkTxToken (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *Interface,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_PROTOCOL *IpInstance OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_FRAME_CALLBACK CallBack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MANAGED_NETWORK_TRANSMIT_DATA *MnpTxData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_TX_TOKEN *Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token = AllocatePool (sizeof (IP6_LINK_TX_TOKEN) + (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Token == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->Signature = IP6_LINK_TX_SIGNATURE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Token->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->IpInstance = IpInstance;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->CallBack = CallBack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->Packet = Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->Context = Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&Token->DstMac, sizeof (EFI_MAC_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_LINK_ADDRESS (&Token->SrcMac, &Interface->Service->SnpMode.CurrentAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpToken = &(Token->MnpToken);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpToken->Status = EFI_NOT_READY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->CreateEvent (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EVT_NOTIFY_SIGNAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TPL_NOTIFY,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6OnFrameSent,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &MnpToken->Event
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Token);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpTxData = &Token->MnpTxData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpToken->Packet.TxData = MnpTxData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpTxData->DestinationAddress = &Token->DstMac;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpTxData->SourceAddress = &Token->SrcMac;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpTxData->ProtocolType = IP6_ETHER_PROTO;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpTxData->DataLength = Packet->TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpTxData->HeaderLength = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count = Packet->BlockOpNum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufBuildExt (Packet, (NET_FRAGMENT *) MnpTxData->FragmentTable, &Count);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpTxData->FragmentCount = (UINT16)Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Free the link layer transmit token. It will close the event,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync then free the memory used.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Token Token to free.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6FreeLinkTxToken (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_LINK_TX_TOKEN *Token
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Token, IP6_LINK_TX_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseEvent (Token->MnpToken.Event);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Token);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Callback function when the received packet is freed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check Ip6OnFrameReceived for information.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context Points to EFI_MANAGED_NETWORK_RECEIVE_DATA.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6RecycleFrame (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RxData = (EFI_MANAGED_NETWORK_RECEIVE_DATA *) Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->SignalEvent (RxData->RecycleEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Received a frame from MNP. Wrap it in net buffer then deliver
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync it to IP's input function. The ownship of the packet also
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync is transferred to IP. When Ip is finished with this packet, it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync will call NetbufFree to release the packet, NetbufFree will
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync again call the Ip6RecycleFrame to signal MNP's event and free
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the token used.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context Context for the callback.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6OnFrameReceivedDpc (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MANAGED_NETWORK_RECEIVE_DATA *MnpRxData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_RX_TOKEN *Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_FRAGMENT Netfrag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token = (IP6_LINK_RX_TOKEN *) Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Token, IP6_LINK_RX_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First clear the interface's receive request in case the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // caller wants to call Ip6ReceiveFrame in the callback.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = (IP6_SERVICE *) Token->Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpToken = &Token->MnpToken;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MnpRxData = MnpToken->Packet.RxData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (MnpToken->Status) || (MnpRxData == NULL)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->CallBack (NULL, MnpToken->Status, 0, Token->Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Wrap the frame in a net buffer then deliever it to IP input.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // IP will reassemble the packet, and deliver it to upper layer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Netfrag.Len = MnpRxData->DataLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Netfrag.Bulk = MnpRxData->PacketData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NetbufFromExt (&Netfrag, 1, IP6_MAX_HEADLEN, 0, Ip6RecycleFrame, Token->MnpToken.Packet.RxData);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->SignalEvent (MnpRxData->RecycleEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->CallBack (NULL, EFI_OUT_OF_RESOURCES, 0, Token->Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Flag = (MnpRxData->BroadcastFlag ? IP6_LINK_BROADCAST : 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Flag |= (MnpRxData->MulticastFlag ? IP6_LINK_MULTICAST : 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Flag |= (MnpRxData->PromiscuousFlag ? IP6_LINK_PROMISC : 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->CallBack (Packet, EFI_SUCCESS, Flag, Token->Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Request Ip6OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Event The receive event delivered to MNP for receive.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Context Context for the callback.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6OnFrameReceived (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_EVENT Event,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Request Ip6OnFrameReceivedDpc as a DPC at TPL_CALLBACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync QueueDpc (TPL_CALLBACK, Ip6OnFrameReceivedDpc, Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Request to receive the packet from the interface.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] CallBack Function to call when receive finished.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb Points to IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_ALREADY_STARTED There is already a pending receive request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The recieve request has been started.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6ReceiveFrame (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_FRAME_CALLBACK CallBack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_RX_TOKEN *Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpSb->InDestroy) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token = &IpSb->RecvRequest;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->CallBack = CallBack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->Context = (VOID *) IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IpSb->Mnp->Receive (IpSb->Mnp, &Token->MnpToken);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Callback funtion when frame transmission is finished. It will
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync call the frame owner's callback function to tell it the result.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context Context which points to the token.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6OnFrameSentDpc (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_TX_TOKEN *Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token = (IP6_LINK_TX_TOKEN *) Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Token, IP6_LINK_TX_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Token->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->CallBack (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->MnpToken.Status,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6FreeLinkTxToken (Token);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Event The transmit token's event.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context Context which points to the token.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6OnFrameSent (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_EVENT Event,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Request Ip6OnFrameSentDpc as a DPC at TPL_CALLBACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync QueueDpc (TPL_CALLBACK, Ip6OnFrameSentDpc, Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send a frame from the interface. If the next hop is a multicast address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync it is transmitted immediately. If the next hop is a unicast,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync and the NextHop's MAC is not known, it will perform address resolution.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If an error occurred, the CallBack won't be called. So, the caller
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync must test the return value, and take action when there is an error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Interface The interface to send the frame from
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpInstance The IP child that request the transmission.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL if it is the IP6 driver itself.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The packet to transmit.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] NextHop The immediate destination to transmit the packet to.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] CallBack Function to call back when transmit finished.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context Opaque parameter to the callback.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The packet successfully transmitted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6SendFrame (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *Interface,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_PROTOCOL *IpInstance OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *NextHop,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_FRAME_CALLBACK CallBack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_TX_TOKEN *Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *NeighborCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *ArpQue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = Interface->Service;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only when link local address is performing DAD, the interface could be used in unconfigured.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpSb->LinkLocalOk) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Interface->Configured);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token = Ip6CreateLinkTxToken (Interface, IpInstance, Packet, CallBack, Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Token == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IP6_IS_MULTICAST (NextHop)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6GetMulticastMac (IpSb->Mnp, NextHop, &Token->DstMac);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SendNow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If send to itself, directly send out
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_IP6_EQUAL (&Packet->Ip.Ip6->DestinationAddress, &Packet->Ip.Ip6->SourceAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_LINK_ADDRESS (&Token->DstMac, &IpSb->SnpMode.CurrentAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SendNow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If unicast, check the neighbor state.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache = Ip6FindNeighborEntry (IpSb, NextHop);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (NeighborCache != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Interface == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Interface = Interface;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (NeighborCache->State) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EfiNeighborStale:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborDelay;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = (UINT32) IP6_GET_TICKS (IP6_DELAY_FIRST_PROBE_TIME);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fall through
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EfiNeighborReachable:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EfiNeighborDelay:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EfiNeighborProbe:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_LINK_ADDRESS (&Token->DstMac, &NeighborCache->LinkAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SendNow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Have to do asynchronous ARP resolution. First check whether there is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // already a pending request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &Interface->ArpQues) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ArpQue = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, ArpList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ArpQue == NeighborCache) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NeighborCache->Frames, &Token->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->ArpFree = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First frame requires ARP.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&NeighborCache->Frames, &Token->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&Interface->ArpQues, &NeighborCache->ArpList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->ArpFree = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSendNow:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove it if the returned status is not EFI_SUCCESS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&Interface->SentFrames, &Token->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IpSb->Mnp->Transmit (IpSb->Mnp, &Token->MnpToken);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Token->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Error;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncError:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6FreeLinkTxToken (Token);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The heartbeat timer of IP6 service instance. It times out
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync all of its IP6 children's received-but-not-delivered and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync transmitted-but-not-recycle packets.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Event The IP6 service instance's heartbeat timer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The IP6 service instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6TimerTicking (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_EVENT Event,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = (IP6_SERVICE *) Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6PacketTimerTicking (IpSb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6NdTimerTicking (IpSb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6MldTimerTicking (IpSb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}