Add additional delay in DHCP6 InfoRequest interface to wait for link local address DAD to finish.

Signed-off-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: qianouyang <qian.ouyang@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13664 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
sfu5 2012-08-22 08:01:19 +00:00
parent 7fb60a98ca
commit cc65822475
8 changed files with 263 additions and 60 deletions

View File

@ -2,7 +2,7 @@
Driver Binding functions and Service Binding functions
implementationfor for Dhcp6 Driver.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
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.

View File

@ -1,7 +1,7 @@
## @file
# Component description file for Dhcp6 module.
#
# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
#
# 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

View File

@ -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,58 +638,64 @@ 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;
}
Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
if (EFI_ERROR (Status)) {
return Status;
}
//
// 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;
}
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)) {
goto ON_ERROR;
return Status;
}
//
// 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);
//
// 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;
}

View File

@ -1,7 +1,7 @@
/** @file
Dhcp6 internal data structure and definition declaration.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
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 <Protocol/Dhcp6.h>
#include <Protocol/Udp6.h>
#include <Protocol/Ip6Config.h>
#include <Protocol/ServiceBinding.h>
#include <Protocol/DriverBinding.h>
@ -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;

View File

@ -1,7 +1,7 @@
/** @file
Dhcp6 internal functions implementation.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
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.

View File

@ -1,7 +1,7 @@
/** @file
Dhcp6 internal functions declaration.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
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.

View File

@ -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;
}

View File

@ -1,7 +1,7 @@
/** @file
Dhcp6 support functions declaration.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
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