v2: * Update the MediaPresent detect declaring. IP4 driver should re-initiate a DHCP if it detects that there is a network reconnection. 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...@intel.com> Cc: Zhang Lubo <lubo.zh...@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiaxin Wu <jiaxin...@intel.com> --- .../Universal/Network/Ip4Dxe/Ip4Config2Impl.c | 1 + MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c | 10 ++ MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c | 121 ++++++++++++++++++++- MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h | 7 ++ 4 files changed, 133 insertions(+), 6 deletions(-) diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c index fcb2bdd..caf84fb 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c @@ -490,10 +490,11 @@ Ip4Config2SetDefaultAddr ( IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); IpIf = IpSb->DefaultInterface; ASSERT (IpIf != NULL); if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) { + IpSb->State = IP4_SERVICE_CONFIGED; return EFI_SUCCESS; } // // The default address is changed, free the previous interface first. diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c index 101390c..4d3ccec 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c @@ -208,10 +208,14 @@ Ip4CreateService ( ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE)); 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 // on the MNP child. // @@ -384,10 +388,16 @@ Ip4CleanService ( gBS->CloseEvent (IpSb->Timer); IpSb->Timer = NULL; } + if (IpSb->ReconfigEvent != NULL) { + gBS->CloseEvent (IpSb->ReconfigEvent); + + IpSb->ReconfigEvent = NULL; + } + if (IpSb->MacString != NULL) { FreePool (IpSb->MacString); } Ip4Config2CleanInstance (&IpSb->Ip4Config2Instance); diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c index 2fb4f4c..ac8fb1a 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c @@ -561,10 +561,58 @@ Ip4InitProtocol ( EfiInitializeLock (&IpInstance->RecycleLock, TPL_NOTIFY); } +/** + 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, change the configuration parameter. Otherwise configure it for the first time. The caller should validate the configuration @@ -676,14 +724,31 @@ Ip4ConfigProtocol ( // // Use the default address. If the default configuration hasn't // 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; } } IpIf = IpSb->DefaultInterface; NET_GET_REF (IpSb->DefaultInterface); @@ -709,11 +774,11 @@ Ip4ConfigProtocol ( gIp4DriverBinding.DriverBindingHandle, IpInstance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { - goto ON_ERROR; + goto CLOSE_RECONFIG_EVENT; } } InsertTailList (&IpIf->IpInstances, &IpInstance->AddrLink); CopyMem (&IpInstance->ConfigData, Config, sizeof (IpInstance->ConfigData)); @@ -728,10 +793,16 @@ Ip4ConfigProtocol ( return EFI_NO_MAPPING; } 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; return Status; } @@ -2293,14 +2364,20 @@ Ip4SentPacketTicking ( return EFI_SUCCESS; } /** - 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. **/ @@ -2310,12 +2387,44 @@ Ip4TimerTicking ( IN EFI_EVENT Event, IN VOID *Context ) { 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 (); + } + } } diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h index 84dfa80..4bb0089 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h @@ -201,10 +201,17 @@ struct _IP4_SERVICE { EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData; EFI_SIMPLE_NETWORK_MODE SnpMode; EFI_EVENT Timer; + EFI_EVENT ReconfigEvent; + + // + // Underlying media present status. + // + BOOLEAN MediaPresent; + // // IPv4 Configuration II Protocol instance // IP4_CONFIG2_INSTANCE Ip4Config2Instance; -- 1.9.5.msysgit.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel