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

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