From cc65822475b10d8eb9c01dab251ef1f647efe180 Mon Sep 17 00:00:00 2001 From: sfu5 Date: Wed, 22 Aug 2012 08:01:19 +0000 Subject: [PATCH] Add additional delay in DHCP6 InfoRequest interface to wait for link local address DAD to finish. Signed-off-by: Fu Siyuan Reviewed-by: Ye Ting Reviewed-by: qianouyang git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13664 6f19259b-4bc3-4df7-8a09-765794883524 --- NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c | 16 ++++- NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf | 4 +- NetworkPkg/Dhcp6Dxe/Dhcp6Impl.c | 101 ++++++++++++++-------------- NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 4 +- NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 102 ++++++++++++++++++++++++++++- NetworkPkg/Dhcp6Dxe/Dhcp6Io.h | 36 +++++++++- NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 39 +++++++++++ NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h | 19 +++++- 8 files changed, 262 insertions(+), 59 deletions(-) diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c index 54ef2e2783..b789f2a478 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c @@ -2,7 +2,7 @@ Driver Binding functions and Service Binding functions implementationfor for Dhcp6 Driver. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -132,6 +132,7 @@ Dhcp6CreateService ( ) { DHCP6_SERVICE *Dhcp6Srv; + EFI_STATUS Status; *Service = NULL; Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE)); @@ -165,6 +166,19 @@ Dhcp6CreateService ( sizeof (EFI_SERVICE_BINDING_PROTOCOL) ); + // + // Locate Ip6->Ip6Config and store it for get IP6 Duplicate Address Detection transmits. + // + Status = gBS->HandleProtocol ( + Controller, + &gEfiIp6ConfigProtocolGuid, + (VOID **) &Dhcp6Srv->Ip6Cfg + ); + if (EFI_ERROR (Status)) { + FreePool (Dhcp6Srv); + return Status; + } + // // Generate client Duid: If SMBIOS system UUID is located, generate DUID in DUID-UUID format. // Otherwise, in DUID-LLT format. diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf b/NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf index f10b07ac3c..7c84397431 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf @@ -1,7 +1,7 @@ ## @file # Component description file for Dhcp6 module. # -# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
# # This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License @@ -66,4 +66,4 @@ gEfiUdp6ProtocolGuid gEfiDhcp6ServiceBindingProtocolGuid gEfiDhcp6ProtocolGuid - + gEfiIp6ConfigProtocolGuid diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.c index 4bed614d2b..2c2b9f9f0e 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.c +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.c @@ -608,11 +608,12 @@ EfiDhcp6InfoRequest ( ) { EFI_STATUS Status; - EFI_TPL OldTpl; DHCP6_INSTANCE *Instance; DHCP6_SERVICE *Service; - DHCP6_INF_CB *InfCb; UINTN Index; + EFI_EVENT Timer; + EFI_STATUS TimerStatus; + UINTN GetMappingTimeOut; if (This == NULL || OptionRequest == NULL || Retransmission == NULL || ReplyCallback == NULL) { return EFI_INVALID_PARAMETER; @@ -637,57 +638,63 @@ EfiDhcp6InfoRequest ( Instance = DHCP6_INSTANCE_FROM_THIS (This); Service = Instance->Service; - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - Instance->UdpSts = EFI_ALREADY_STARTED; - - // - // Create and initialize the control block for the info-request. - // - InfCb = AllocateZeroPool (sizeof(DHCP6_INF_CB)); - - if (InfCb == NULL) { - gBS->RestoreTPL (OldTpl); - return EFI_OUT_OF_RESOURCES; - } - - InfCb->ReplyCallback = ReplyCallback; - InfCb->CallbackContext = CallbackContext; - InfCb->TimeoutEvent = TimeoutEvent; - - InsertTailList (&Instance->InfList, &InfCb->Link); - - // - // Send the info-request message to start exchange process. - // - Status = Dhcp6SendInfoRequestMsg ( + Status = Dhcp6StartInfoRequest ( Instance, - InfCb, SendClientId, OptionRequest, OptionCount, OptionList, - Retransmission + Retransmission, + TimeoutEvent, + ReplyCallback, + CallbackContext ); + if (Status == EFI_NO_MAPPING) { + // + // The link local address is not ready, wait for some time and restart + // the DHCP6 information request process. + // + Status = Dhcp6GetMappingTimeOut(Service->Ip6Cfg, &GetMappingTimeOut); + if (EFI_ERROR(Status)) { + return Status; + } - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } + Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer); + if (EFI_ERROR (Status)) { + return Status; + } - // - // Register receive callback for the stateless exchange process. - // - Status = UdpIoRecvDatagram( - Service->UdpIo, - Dhcp6ReceivePacket, - Service, - 0 - ); + // + // Start the timer, wait for link local address DAD to finish. + // + Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (Timer); + return Status; + } - if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { - goto ON_ERROR; + do { + TimerStatus = gBS->CheckEvent (Timer); + if (!EFI_ERROR (TimerStatus)) { + Status = Dhcp6StartInfoRequest ( + Instance, + SendClientId, + OptionRequest, + OptionCount, + OptionList, + Retransmission, + TimeoutEvent, + ReplyCallback, + CallbackContext + ); + } + } while (TimerStatus == EFI_NOT_READY); + + gBS->CloseEvent (Timer); + } + if (EFI_ERROR (Status)) { + return Status; } - - gBS->RestoreTPL (OldTpl); // // Poll udp out of the net tpl if synchoronus call. @@ -701,14 +708,6 @@ EfiDhcp6InfoRequest ( } return EFI_SUCCESS; - -ON_ERROR: - - RemoveEntryList (&InfCb->Link); - FreePool (InfCb); - gBS->RestoreTPL (OldTpl); - - return Status; } diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h index dda0cf37d5..0e206cd504 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h @@ -1,7 +1,7 @@ /** @file Dhcp6 internal data structure and definition declaration. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -259,6 +260,7 @@ struct _DHCP6_SERVICE { EFI_HANDLE Image; EFI_SERVICE_BINDING_PROTOCOL ServiceBinding; EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; EFI_DHCP6_DUID *ClientId; UDP_IO *UdpIo; UINT32 Xid; diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c index 7320642edd..656fd83908 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c @@ -1,7 +1,7 @@ /** @file Dhcp6 internal functions implementation. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -1626,6 +1626,106 @@ Dhcp6SendRenewRebindMsg ( return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); } +/** + Start the information request process. + + @param[in] Instance The pointer to the Dhcp6 instance. + @param[in] SendClientId If TRUE, the client identifier option will be included in + information request message. Otherwise, the client identifier + option will not be included. + @param[in] OptionRequest The pointer to the option request option. + @param[in] OptionCount The number options in the OptionList. + @param[in] OptionList The array pointers to the appended options. + @param[in] Retransmission The pointer to the retransmission control. + @param[in] TimeoutEvent The event of timeout. + @param[in] ReplyCallback The callback function when the reply was received. + @param[in] CallbackContext The pointer to the parameter passed to the callback. + + @retval EFI_SUCCESS Start the info-request process successfully. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_NO_MAPPING No source address is available for use. + @retval Others Failed to start the info-request process. + +**/ +EFI_STATUS +Dhcp6StartInfoRequest ( + IN DHCP6_INSTANCE *Instance, + IN BOOLEAN SendClientId, + IN EFI_DHCP6_PACKET_OPTION *OptionRequest, + IN UINT32 OptionCount, + IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL, + IN EFI_DHCP6_RETRANSMISSION *Retransmission, + IN EFI_EVENT TimeoutEvent OPTIONAL, + IN EFI_DHCP6_INFO_CALLBACK ReplyCallback, + IN VOID *CallbackContext OPTIONAL + ) +{ + EFI_STATUS Status; + DHCP6_INF_CB *InfCb; + DHCP6_SERVICE *Service; + EFI_TPL OldTpl; + + Service = Instance->Service; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + Instance->UdpSts = EFI_ALREADY_STARTED; + // + // Create and initialize the control block for the info-request. + // + InfCb = AllocateZeroPool (sizeof(DHCP6_INF_CB)); + + if (InfCb == NULL) { + gBS->RestoreTPL (OldTpl); + return EFI_OUT_OF_RESOURCES; + } + + InfCb->ReplyCallback = ReplyCallback; + InfCb->CallbackContext = CallbackContext; + InfCb->TimeoutEvent = TimeoutEvent; + + InsertTailList (&Instance->InfList, &InfCb->Link); + + // + // Send the info-request message to start exchange process. + // + Status = Dhcp6SendInfoRequestMsg ( + Instance, + InfCb, + SendClientId, + OptionRequest, + OptionCount, + OptionList, + Retransmission + ); + + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Register receive callback for the stateless exchange process. + // + Status = UdpIoRecvDatagram( + Service->UdpIo, + Dhcp6ReceivePacket, + Service, + 0 + ); + + if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { + goto ON_ERROR; + } + + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; + +ON_ERROR: + gBS->RestoreTPL (OldTpl); + RemoveEntryList (&InfCb->Link); + FreePool (InfCb); + + return Status; +} /** Create the information request message and send it. diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h index 31459c96d3..b0b12a79fe 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.h @@ -1,7 +1,7 @@ /** @file Dhcp6 internal functions declaration. - Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -129,6 +129,40 @@ Dhcp6SendReleaseMsg ( IN EFI_DHCP6_IA *RelIa ); +/** + Start the information request process. + + @param[in] Instance The pointer to the Dhcp6 instance. + @param[in] SendClientId If TRUE, the client identifier option will be included in + information request message. Otherwise, the client identifier + option will not be included. + @param[in] OptionRequest The pointer to the option request option. + @param[in] OptionCount The number options in the OptionList. + @param[in] OptionList The array pointers to the appended options. + @param[in] Retransmission The pointer to the retransmission control. + @param[in] TimeoutEvent The event of timeout. + @param[in] ReplyCallback The callback function when the reply was received. + @param[in] CallbackContext The pointer to the parameter passed to the callback. + + @retval EFI_SUCCESS Start the info-request process successfully. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_NO_MAPPING No source address is available for use. + @retval Others Failed to start the info-request process. + +**/ +EFI_STATUS +Dhcp6StartInfoRequest ( + IN DHCP6_INSTANCE *Instance, + IN BOOLEAN SendClientId, + IN EFI_DHCP6_PACKET_OPTION *OptionRequest, + IN UINT32 OptionCount, + IN EFI_DHCP6_PACKET_OPTION *OptionList[] OPTIONAL, + IN EFI_DHCP6_RETRANSMISSION *Retransmission, + IN EFI_EVENT TimeoutEvent OPTIONAL, + IN EFI_DHCP6_INFO_CALLBACK ReplyCallback, + IN VOID *CallbackContext OPTIONAL + ); + /** Create the information request message and send it. diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c index 6bf96a1996..4c32028680 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c @@ -1189,3 +1189,42 @@ Dhcp6AppendCacheIa ( Instance->IaCb.Ia = NewIa; } } + +/** + Calculate the Dhcp6 get mapping timeout by adding additinal delay to the IP6 DAD transmits count. + + @param[in] Ip6Cfg The pointer to Ip6 config protocol. + @param[out] TimeOut The time out value in 100ns units. + + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_SUCCESS Calculate the time out value successfully. +**/ +EFI_STATUS +Dhcp6GetMappingTimeOut ( + IN EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg, + OUT UINTN *TimeOut + ) +{ + EFI_STATUS Status; + UINTN DataSize; + EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits; + + if (Ip6Cfg == NULL || TimeOut == NULL) { + return EFI_INVALID_PARAMETER; + } + + DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS); + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeDupAddrDetectTransmits, + &DataSize, + &DadXmits + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *TimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + DHCP6_DAD_ADDITIONAL_DELAY; + + return EFI_SUCCESS; +} diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h index 61bb9f324e..2a44d0068f 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h @@ -1,7 +1,7 @@ /** @file Dhcp6 support functions declaration. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -17,7 +17,8 @@ #define __EFI_DHCP6_UTILITY_H__ -#define DHCP6_10_BIT_MASK 0x3ff +#define DHCP6_10_BIT_MASK 0x3ff +#define DHCP6_DAD_ADDITIONAL_DELAY 30000000 // 3 seconds /** Generate client Duid in the format of Duid-llt. @@ -337,4 +338,18 @@ Dhcp6AppendCacheIa ( IN DHCP6_INSTANCE *Instance ); +/** + Calculate the Dhcp6 get mapping timeout by adding additinal delay to the IP6 DAD transmits count. + + @param[in] Ip6Cfg The pointer to Ip6 config protocol. + @param[out] TimeOut The time out value in 100ns units. + + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_SUCCESS Calculate the time out value successfully. +**/ +EFI_STATUS +Dhcp6GetMappingTimeOut ( + IN EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg, + OUT UINTN *TimeOut + ); #endif -- 2.39.2