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 Driver Binding functions and Service Binding functions
implementationfor for Dhcp6 Driver. 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 This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -132,6 +132,7 @@ Dhcp6CreateService (
) )
{ {
DHCP6_SERVICE *Dhcp6Srv; DHCP6_SERVICE *Dhcp6Srv;
EFI_STATUS Status;
*Service = NULL; *Service = NULL;
Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE)); Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));
@ -165,6 +166,19 @@ Dhcp6CreateService (
sizeof (EFI_SERVICE_BINDING_PROTOCOL) 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. // Generate client Duid: If SMBIOS system UUID is located, generate DUID in DUID-UUID format.
// Otherwise, in DUID-LLT format. // Otherwise, in DUID-LLT format.

View File

@ -1,7 +1,7 @@
## @file ## @file
# Component description file for Dhcp6 module. # 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 # This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License # are licensed and made available under the terms and conditions of the BSD License
@ -66,4 +66,4 @@
gEfiUdp6ProtocolGuid gEfiUdp6ProtocolGuid
gEfiDhcp6ServiceBindingProtocolGuid gEfiDhcp6ServiceBindingProtocolGuid
gEfiDhcp6ProtocolGuid gEfiDhcp6ProtocolGuid
gEfiIp6ConfigProtocolGuid

View File

@ -608,11 +608,12 @@ EfiDhcp6InfoRequest (
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
EFI_TPL OldTpl;
DHCP6_INSTANCE *Instance; DHCP6_INSTANCE *Instance;
DHCP6_SERVICE *Service; DHCP6_SERVICE *Service;
DHCP6_INF_CB *InfCb;
UINTN Index; UINTN Index;
EFI_EVENT Timer;
EFI_STATUS TimerStatus;
UINTN GetMappingTimeOut;
if (This == NULL || OptionRequest == NULL || Retransmission == NULL || ReplyCallback == NULL) { if (This == NULL || OptionRequest == NULL || Retransmission == NULL || ReplyCallback == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -637,58 +638,64 @@ EfiDhcp6InfoRequest (
Instance = DHCP6_INSTANCE_FROM_THIS (This); Instance = DHCP6_INSTANCE_FROM_THIS (This);
Service = Instance->Service; Service = Instance->Service;
OldTpl = gBS->RaiseTPL (TPL_CALLBACK); Status = Dhcp6StartInfoRequest (
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, Instance,
InfCb,
SendClientId, SendClientId,
OptionRequest, OptionRequest,
OptionCount, OptionCount,
OptionList, 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)) { 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. // Poll udp out of the net tpl if synchoronus call.
// //
@ -701,14 +708,6 @@ EfiDhcp6InfoRequest (
} }
return EFI_SUCCESS; return EFI_SUCCESS;
ON_ERROR:
RemoveEntryList (&InfCb->Link);
FreePool (InfCb);
gBS->RestoreTPL (OldTpl);
return Status;
} }

View File

@ -1,7 +1,7 @@
/** @file /** @file
Dhcp6 internal data structure and definition declaration. 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 This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -21,6 +21,7 @@
#include <Protocol/Dhcp6.h> #include <Protocol/Dhcp6.h>
#include <Protocol/Udp6.h> #include <Protocol/Udp6.h>
#include <Protocol/Ip6Config.h>
#include <Protocol/ServiceBinding.h> #include <Protocol/ServiceBinding.h>
#include <Protocol/DriverBinding.h> #include <Protocol/DriverBinding.h>
@ -259,6 +260,7 @@ struct _DHCP6_SERVICE {
EFI_HANDLE Image; EFI_HANDLE Image;
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding; EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp; EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
EFI_DHCP6_DUID *ClientId; EFI_DHCP6_DUID *ClientId;
UDP_IO *UdpIo; UDP_IO *UdpIo;
UINT32 Xid; UINT32 Xid;

View File

@ -1,7 +1,7 @@
/** @file /** @file
Dhcp6 internal functions implementation. 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 This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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); 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. Create the information request message and send it.

View File

@ -1,7 +1,7 @@
/** @file /** @file
Dhcp6 internal functions declaration. 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 This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -129,6 +129,40 @@ Dhcp6SendReleaseMsg (
IN EFI_DHCP6_IA *RelIa 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. Create the information request message and send it.

View File

@ -1189,3 +1189,42 @@ Dhcp6AppendCacheIa (
Instance->IaCb.Ia = NewIa; 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 /** @file
Dhcp6 support functions declaration. 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 This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -17,7 +17,8 @@
#define __EFI_DHCP6_UTILITY_H__ #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. Generate client Duid in the format of Duid-llt.
@ -337,4 +338,18 @@ Dhcp6AppendCacheIa (
IN DHCP6_INSTANCE *Instance 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 #endif