MdeModulePkg: IP4 should re-initiate a DHCP if it detects network reconnection

v2:
* Update the MediaPresent detect declaring.

IP4 driver should re-initiate a DHCP if it detects that there is a network.
To fix this issue, we can implement the DHCP re-initiate policy while the media
change detected. The Ip4 driver should set a timer to signal the Ip4 to run the
DHCP configuration again(D.O.R.A). IP4 driver should free old IP address related
resource, then initiate a DHCP process to acquire new IP.

Cc: Ye Ting <ting.ye@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: Lubo Zhang <lubo.zhang@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18232 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Jiaxin Wu 2015-08-18 03:12:16 +00:00 committed by jiaxinwu
parent 3667305420
commit 2c3200072f
4 changed files with 133 additions and 6 deletions

View File

@ -492,6 +492,7 @@ Ip4Config2SetDefaultAddr (
ASSERT (IpIf != NULL);
if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) {
IpSb->State = IP4_SERVICE_CONFIGED;
return EFI_SUCCESS;
}

View File

@ -210,6 +210,10 @@ Ip4CreateService (
IpSb->Timer = NULL;
IpSb->ReconfigEvent = NULL;
IpSb->MediaPresent = TRUE;
//
// Create various resources. First create the route table, timer
// event and MNP child. IGMP, interface's initialization depend
@ -386,6 +390,12 @@ Ip4CleanService (
IpSb->Timer = NULL;
}
if (IpSb->ReconfigEvent != NULL) {
gBS->CloseEvent (IpSb->ReconfigEvent);
IpSb->ReconfigEvent = NULL;
}
if (IpSb->MacString != NULL) {
FreePool (IpSb->MacString);
}

View File

@ -563,6 +563,54 @@ Ip4InitProtocol (
}
/**
The event handle for IP4 auto reconfiguration. The original default
interface and route table will be removed as the default.
@param[in] Context The IP4 service binding instance.
**/
VOID
EFIAPI
Ip4AutoReconfigCallBackDpc (
IN VOID *Context
)
{
IP4_SERVICE *IpSb;
IpSb = (IP4_SERVICE *) Context;
NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
if (IpSb->State > IP4_SERVICE_UNSTARTED) {
IpSb->State = IP4_SERVICE_UNSTARTED;
}
Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);
return ;
}
/**
Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.
@param Event The event that is signalled.
@param Context The IP4 service binding instance.
**/
VOID
EFIAPI
Ip4AutoReconfigCallBack (
IN EFI_EVENT Event,
IN VOID *Context
)
{
//
// Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK
//
QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context);
}
/**
Configure the IP4 child. If the child is already configured,
@ -678,10 +726,27 @@ Ip4ConfigProtocol (
// been started, start it.
//
if (IpSb->State == IP4_SERVICE_UNSTARTED) {
//
// Create the ReconfigEvent to start the new configuration.
//
if (IpSb->ReconfigEvent == NULL) {
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
Ip4AutoReconfigCallBack,
IpSb,
&IpSb->ReconfigEvent
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
}
Status = Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
goto CLOSE_RECONFIG_EVENT;
}
}
@ -711,7 +776,7 @@ Ip4ConfigProtocol (
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
goto CLOSE_RECONFIG_EVENT;
}
}
InsertTailList (&IpIf->IpInstances, &IpInstance->AddrLink);
@ -730,6 +795,12 @@ Ip4ConfigProtocol (
return EFI_SUCCESS;
CLOSE_RECONFIG_EVENT:
if (IpSb->ReconfigEvent != NULL) {
gBS->CloseEvent (IpSb->ReconfigEvent);
IpSb->ReconfigEvent = NULL;
}
ON_ERROR:
Ip4FreeRouteTable (IpInstance->RouteTable);
IpInstance->RouteTable = NULL;
@ -2295,10 +2366,16 @@ Ip4SentPacketTicking (
/**
The heart beat timer of IP4 service instance. It times out
all of its IP4 children's received-but-not-delivered and
transmitted-but-not-recycle packets, and provides time input
for its IGMP protocol.
There are two steps for this the heart beat timer of IP4 service instance.
First, it times out all of its IP4 children's received-but-not-delivered
and transmitted-but-not-recycle packets, and provides time input for its
IGMP protocol.
Second, a dedicated timer is used to poll underlying media status. In case
of cable swap, a new round auto configuration will be initiated. The timer
will signal the IP4 to run DHCP configuration again. IP4 driver will free
old IP address related resource, such as route table and Interface, then
initiate a DHCP process to acquire new IP, eventually create route table
for new IP address.
@param[in] Event The IP4 service instance's heart beat timer.
@param[in] Context The IP4 service instance.
@ -2312,10 +2389,42 @@ Ip4TimerTicking (
)
{
IP4_SERVICE *IpSb;
BOOLEAN OldMediaPresent;
EFI_STATUS Status;
EFI_SIMPLE_NETWORK_MODE SnpModeData;
IpSb = (IP4_SERVICE *) Context;
NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
OldMediaPresent = IpSb->MediaPresent;
Ip4PacketTimerTicking (IpSb);
Ip4IgmpTicking (IpSb);
//
// Get fresh mode data from MNP, since underlying media status may change.
// Here, it needs to mention that the MediaPresent can also be checked even if
// EFI_NOT_STARTED returned while this MNP child driver instance isn't configured.
//
Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &SnpModeData);
if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
return;
}
IpSb->MediaPresent = SnpModeData.MediaPresent;
//
// Media transimit Unpresent to Present means new link movement is detected.
//
if (!OldMediaPresent && IpSb->MediaPresent) {
//
// Signal the IP4 to run the dhcp configuration again. IP4 driver will free
// old IP address related resource, such as route table and Interface, then
// initiate a DHCP round to acquire new IP, eventually
// create route table for new IP address.
//
if (IpSb->ReconfigEvent != NULL) {
Status = gBS->SignalEvent (IpSb->ReconfigEvent);
DispatchDpc ();
}
}
}

View File

@ -203,6 +203,13 @@ struct _IP4_SERVICE {
EFI_EVENT Timer;
EFI_EVENT ReconfigEvent;
//
// Underlying media present status.
//
BOOLEAN MediaPresent;
//
// IPv4 Configuration II Protocol instance
//