Update PXE driver to wait for IPv6 duplicate address detection 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@13485 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
sfu5 2012-07-04 04:34:10 +00:00
parent 9d8fa791f5
commit ed2bfecbcd
4 changed files with 85 additions and 10 deletions

View File

@ -1,7 +1,7 @@
/** @file /** @file
This EFI_DHCP6_PROTOCOL interface implementation. This EFI_DHCP6_PROTOCOL interface implementation.
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
@ -200,13 +200,13 @@ EfiDhcp6Stop (
ASSERT (Instance->IaCb.Ia != NULL); ASSERT (Instance->IaCb.Ia != NULL);
// //
// The instance has already been stopped. // No valid REPLY message received yet, cleanup this instance directly.
// //
if (Instance->IaCb.Ia->State == Dhcp6Init || if (Instance->IaCb.Ia->State == Dhcp6Init ||
Instance->IaCb.Ia->State == Dhcp6Selecting || Instance->IaCb.Ia->State == Dhcp6Selecting ||
Instance->IaCb.Ia->State == Dhcp6Requesting Instance->IaCb.Ia->State == Dhcp6Requesting
) { ) {
return Status; goto ON_EXIT;
} }
// //
@ -215,7 +215,10 @@ EfiDhcp6Stop (
OldTpl = gBS->RaiseTPL (TPL_CALLBACK); OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
Instance->UdpSts = EFI_ALREADY_STARTED; Instance->UdpSts = EFI_ALREADY_STARTED;
Dhcp6SendReleaseMsg (Instance, Instance->IaCb.Ia); Status = Dhcp6SendReleaseMsg (Instance, Instance->IaCb.Ia);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
gBS->RestoreTPL (OldTpl); gBS->RestoreTPL (OldTpl);
@ -229,7 +232,8 @@ EfiDhcp6Stop (
} }
Status = Instance->UdpSts; Status = Instance->UdpSts;
} }
ON_EXIT:
// //
// Clean up the session data for the released Ia. // Clean up the session data for the released Ia.
// //

View File

@ -1260,6 +1260,8 @@ PxeBcRegisterIp6Address (
EFI_EVENT TimeOutEvt; EFI_EVENT TimeOutEvt;
EFI_EVENT MappedEvt; EFI_EVENT MappedEvt;
EFI_STATUS Status; EFI_STATUS Status;
UINT64 DadTriggerTime;
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
TimeOutEvt = NULL; TimeOutEvt = NULL;
@ -1303,6 +1305,20 @@ PxeBcRegisterIp6Address (
goto ON_EXIT; goto ON_EXIT;
} }
//
// Get Duplicate Address Detection Transmits count.
//
DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
Status = Ip6Cfg->GetData (
Ip6Cfg,
Ip6ConfigDataTypeDupAddrDetectTransmits,
&DataSize,
&DadXmits
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
// //
// Create a timer as setting address timeout event since DAD in IP6 driver. // Create a timer as setting address timeout event since DAD in IP6 driver.
// //
@ -1354,7 +1370,8 @@ PxeBcRegisterIp6Address (
// Start the 5 secondes timer to wait for setting address. // Start the 5 secondes timer to wait for setting address.
// //
Status = EFI_NO_MAPPING; Status = EFI_NO_MAPPING;
gBS->SetTimer (TimeOutEvt, TimerRelative, PXEBC_DHCP6_MAPPING_TIMEOUT); DadTriggerTime = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY;
gBS->SetTimer (TimeOutEvt, TimerRelative, DadTriggerTime);
while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) { while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
Ip6->Poll (Ip6); Ip6->Poll (Ip6);
@ -1698,9 +1715,17 @@ PxeBcDhcp6Sarr (
UINT8 Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE]; UINT8 Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE];
UINT32 OptCount; UINT32 OptCount;
EFI_STATUS Status; EFI_STATUS Status;
EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
EFI_STATUS TimerStatus;
EFI_EVENT Timer;
UINT64 GetMappingTimeOut;
UINTN DataSize;
EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
PxeMode = Private->PxeBc.Mode; PxeMode = Private->PxeBc.Mode;
Ip6Cfg = Private->Ip6Cfg;
Timer = NULL;
// //
// Build option list for the request packet. // Build option list for the request packet.
@ -1735,8 +1760,8 @@ PxeBcDhcp6Sarr (
// Configure the DHCPv6 instance for PXE boot. // Configure the DHCPv6 instance for PXE boot.
// //
Status = Dhcp6->Configure (Dhcp6, &Config); Status = Dhcp6->Configure (Dhcp6, &Config);
FreePool (Retransmit);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Retransmit);
return Status; return Status;
} }
@ -1754,6 +1779,52 @@ PxeBcDhcp6Sarr (
// Start DHCPv6 S.A.R.R. process to acquire IPv6 address. // Start DHCPv6 S.A.R.R. process to acquire IPv6 address.
// //
Status = Dhcp6->Start (Dhcp6); Status = Dhcp6->Start (Dhcp6);
if (Status == EFI_NO_MAPPING) {
//
// IP6 Linklocal address is not available for use, so stop current Dhcp process
// and wait for duplicate address detection to finish.
//
Dhcp6->Stop (Dhcp6);
//
// Get Duplicate Address Detection Transmits count.
//
DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
Status = Ip6Cfg->GetData (
Ip6Cfg,
Ip6ConfigDataTypeDupAddrDetectTransmits,
&DataSize,
&DadXmits
);
if (EFI_ERROR (Status)) {
Dhcp6->Configure (Dhcp6, NULL);
return Status;
}
Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
if (EFI_ERROR (Status)) {
Dhcp6->Configure (Dhcp6, NULL);
return Status;
}
GetMappingTimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY;
Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut);
if (EFI_ERROR (Status)) {
gBS->CloseEvent (Timer);
Dhcp6->Configure (Dhcp6, NULL);
return Status;
}
do {
TimerStatus = gBS->CheckEvent (Timer);
if (!EFI_ERROR (TimerStatus)) {
Status = Dhcp6->Start (Dhcp6);
}
} while (TimerStatus == EFI_NOT_READY);
gBS->CloseEvent (Timer);
}
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
if (Status == EFI_ICMP_ERROR) { if (Status == EFI_ICMP_ERROR) {
PxeMode->IcmpErrorReceived = TRUE; PxeMode->IcmpErrorReceived = TRUE;

View File

@ -1,7 +1,7 @@
/** @file /** @file
Functions declaration related with DHCPv6 for UefiPxeBc Driver. Functions declaration related with DHCPv6 for UefiPxeBc Driver.
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
@ -19,7 +19,6 @@
#define PXEBC_DHCP6_OPTION_MAX_NUM 16 #define PXEBC_DHCP6_OPTION_MAX_NUM 16
#define PXEBC_DHCP6_OPTION_MAX_SIZE 312 #define PXEBC_DHCP6_OPTION_MAX_SIZE 312
#define PXEBC_DHCP6_PACKET_MAX_SIZE 1472 #define PXEBC_DHCP6_PACKET_MAX_SIZE 1472
#define PXEBC_DHCP6_MAPPING_TIMEOUT 50000000 // 5 seconds, unit is 10nanosecond.
#define PXEBC_IP6_POLICY_MAX 0xff #define PXEBC_IP6_POLICY_MAX 0xff
#define PXEBC_DHCP6_S_PORT 547 #define PXEBC_DHCP6_S_PORT 547

View File

@ -2,7 +2,7 @@
This EFI_PXE_BASE_CODE_PROTOCOL and EFI_LOAD_FILE_PROTOCOL. This EFI_PXE_BASE_CODE_PROTOCOL and EFI_LOAD_FILE_PROTOCOL.
interfaces declaration. interfaces declaration.
Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR> Copyright (c) 2007 - 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
@ -65,6 +65,7 @@ typedef struct _PXEBC_VIRTUAL_NIC PXEBC_VIRTUAL_NIC;
#define PXEBC_DEFAULT_HOPLIMIT 64 #define PXEBC_DEFAULT_HOPLIMIT 64
#define PXEBC_DEFAULT_LIFETIME 50000 // 50 ms, unit is microsecond #define PXEBC_DEFAULT_LIFETIME 50000 // 50 ms, unit is microsecond
#define PXEBC_UDP_TIMEOUT 30000000 // 3 seconds, unit is 100nanosecond #define PXEBC_UDP_TIMEOUT 30000000 // 3 seconds, unit is 100nanosecond
#define PXEBC_DAD_ADDITIONAL_DELAY 30000000 // 3 seconds
#define PXEBC_MTFTP_TIMEOUT 4 #define PXEBC_MTFTP_TIMEOUT 4
#define PXEBC_MTFTP_RETRIES 6 #define PXEBC_MTFTP_RETRIES 6
#define PXEBC_DHCP_RETRIES 4 // refers to mPxeDhcpTimeout, also by PXE2.1 spec. #define PXEBC_DHCP_RETRIES 4 // refers to mPxeDhcpTimeout, also by PXE2.1 spec.