X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FIp4Dxe%2FIp4Impl.c;h=6a26143e307d3e4effe40bc1f190fb0833afd3d0;hp=cd01685a304e5a6a4dc5940db0872e4d80dae7e2;hb=a5f525fc48a71521f69e395d85a36d72917eeabd;hpb=098e9f49256e352f557fdcbcfbab37f8dd89ff63 diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c index cd01685a30..6a26143e30 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c @@ -1,6 +1,6 @@ /** @file -Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.
+Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -530,305 +530,6 @@ Ip4ServiceConfigMnp ( } -/** - The event handle for IP4 auto configuration. If IP is asked - to reconfigure the default address. The original default - interface and route table are removed as the default. If there - is active IP children using the default address, the interface - will remain valid until all the children have freed their - references. If IP is signalled when auto configuration is done, - it will configure the default interface and default route table - with the configuration information retrieved by IP4_CONFIGURE. - - @param[in] Context The IP4 service binding instance. - -**/ -VOID -EFIAPI -Ip4AutoConfigCallBackDpc ( - IN VOID *Context - ) -{ - EFI_IP4_CONFIG_PROTOCOL *Ip4Config; - EFI_IP4_IPCONFIG_DATA *Data; - EFI_IP4_ROUTE_TABLE *RouteEntry; - IP4_SERVICE *IpSb; - IP4_ROUTE_TABLE *RouteTable; - IP4_INTERFACE *IpIf; - EFI_STATUS Status; - UINTN Len; - UINT32 Index; - IP4_ADDR StationAddress; - IP4_ADDR SubnetMask; - IP4_ADDR SubnetAddress; - IP4_ADDR GatewayAddress; - IP4_PROTOCOL *Ip4Instance; - EFI_ARP_PROTOCOL *Arp; - LIST_ENTRY *Entry; - - IpSb = (IP4_SERVICE *) Context; - NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE); - - Ip4Config = IpSb->Ip4Config; - - // - // IP is asked to do the reconfiguration. If the default interface - // has been configured, release the default interface and route - // table, then create a new one. If there are some IP children - // using it, the interface won't be physically freed until all the - // children have released their reference to it. Also remember to - // restart the receive on the default address. IP4 driver only receive - // frames on the default address, and when the default interface is - // freed, Ip4AcceptFrame won't be informed. - // - if (IpSb->ActiveEvent == IpSb->ReconfigEvent) { - - if (IpSb->DefaultInterface->Configured) { - IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image); - - if (IpIf == NULL) { - return; - } - - RouteTable = Ip4CreateRouteTable (); - - if (RouteTable == NULL) { - Ip4FreeInterface (IpIf, NULL); - return; - } - - Ip4CancelReceive (IpSb->DefaultInterface); - Ip4FreeInterface (IpSb->DefaultInterface, NULL); - Ip4FreeRouteTable (IpSb->DefaultRouteTable); - - IpSb->DefaultInterface = IpIf; - InsertHeadList (&IpSb->Interfaces, &IpIf->Link); - - IpSb->DefaultRouteTable = RouteTable; - Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb); - } - - Ip4Config->Stop (Ip4Config); - Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent); - return ; - } - - // - // Get the configure data in two steps: get the length then the data. - // - Len = 0; - - if (Ip4Config->GetData (Ip4Config, &Len, NULL) != EFI_BUFFER_TOO_SMALL) { - return ; - } - - Data = AllocatePool (Len); - - if (Data == NULL) { - return ; - } - - Status = Ip4Config->GetData (Ip4Config, &Len, Data); - - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - IpIf = IpSb->DefaultInterface; - - // - // If the default address has been configured don't change it. - // This is unlikely to happen if EFI_IP4_CONFIG protocol has - // informed us to reconfigure each time it wants to change the - // configuration parameters. - // - if (IpIf->Configured) { - goto ON_EXIT; - } - - // - // Set the default interface's address, then add a directed - // route for it, that is, the route whose nexthop is zero. - // - StationAddress = EFI_NTOHL (Data->StationAddress); - SubnetMask = EFI_NTOHL (Data->SubnetMask); - Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - if (IpIf->Arp != NULL) { - // - // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address, - // but some IP children may have referenced the default interface before it is configured, - // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER. - // - Arp = NULL; - NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) { - Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE); - Status = gBS->OpenProtocol ( - IpIf->ArpHandle, - &gEfiArpProtocolGuid, - (VOID **) &Arp, - gIp4DriverBinding.DriverBindingHandle, - Ip4Instance->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - } - } - - Ip4AddRoute ( - IpSb->DefaultRouteTable, - StationAddress, - SubnetMask, - IP4_ALLZERO_ADDRESS - ); - - // - // Add routes returned by EFI_IP4_CONFIG protocol. - // - for (Index = 0; Index < Data->RouteTableSize; Index++) { - RouteEntry = &Data->RouteTable[Index]; - - SubnetAddress = EFI_NTOHL (RouteEntry->SubnetAddress); - SubnetMask = EFI_NTOHL (RouteEntry->SubnetMask); - GatewayAddress = EFI_NTOHL (RouteEntry->GatewayAddress); - Ip4AddRoute (IpSb->DefaultRouteTable, SubnetAddress, SubnetMask, GatewayAddress); - } - - IpSb->State = IP4_SERVICE_CONFIGED; - - Ip4SetVariableData (IpSb); - -ON_EXIT: - FreePool (Data); -} - -/** - Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK. - - @param Event The event that is signalled. - @param Context The IP4 service binding instance. - -**/ -VOID -EFIAPI -Ip4AutoConfigCallBack ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - IP4_SERVICE *IpSb; - - IpSb = (IP4_SERVICE *) Context; - IpSb->ActiveEvent = Event; - - // - // Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK - // - QueueDpc (TPL_CALLBACK, Ip4AutoConfigCallBackDpc, Context); -} - - -/** - Start the auto configuration for this IP service instance. - It will locates the EFI_IP4_CONFIG_PROTOCOL, then start the - auto configuration. - - @param[in] IpSb The IP4 service instance to configure - - @retval EFI_SUCCESS The auto configuration is successfull started - @retval Others Failed to start auto configuration. - -**/ -EFI_STATUS -Ip4StartAutoConfig ( - IN IP4_SERVICE *IpSb - ) -{ - EFI_IP4_CONFIG_PROTOCOL *Ip4Config; - EFI_STATUS Status; - - if (IpSb->State > IP4_SERVICE_UNSTARTED) { - return EFI_SUCCESS; - } - - // - // Create the DoneEvent and ReconfigEvent to call EFI_IP4_CONFIG - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_CALLBACK, - Ip4AutoConfigCallBack, - IpSb, - &IpSb->DoneEvent - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - Ip4AutoConfigCallBack, - IpSb, - &IpSb->ReconfigEvent - ); - - if (EFI_ERROR (Status)) { - goto CLOSE_DONE_EVENT; - } - - // - // Open the EFI_IP4_CONFIG protocol then start auto configure - // - Status = gBS->OpenProtocol ( - IpSb->Controller, - &gEfiIp4ConfigProtocolGuid, - (VOID **) &Ip4Config, - IpSb->Image, - IpSb->Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE - ); - - if (EFI_ERROR (Status)) { - Status = EFI_UNSUPPORTED; - goto CLOSE_RECONFIG_EVENT; - } - - Status = Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent); - - if (EFI_ERROR (Status)) { - gBS->CloseProtocol ( - IpSb->Controller, - &gEfiIp4ConfigProtocolGuid, - IpSb->Image, - IpSb->Controller - ); - - goto CLOSE_RECONFIG_EVENT; - } - - IpSb->Ip4Config = Ip4Config; - IpSb->State = IP4_SERVICE_STARTED; - return Status; - -CLOSE_RECONFIG_EVENT: - gBS->CloseEvent (IpSb->ReconfigEvent); - IpSb->ReconfigEvent = NULL; - -CLOSE_DONE_EVENT: - gBS->CloseEvent (IpSb->DoneEvent); - IpSb->DoneEvent = NULL; - - return Status; -} - - /** Intiialize the IP4_PROTOCOL structure to the unconfigured states. @@ -849,6 +550,7 @@ Ip4InitProtocol ( IpInstance->Signature = IP4_PROTOCOL_SIGNATURE; CopyMem (&IpInstance->Ip4Proto, &mEfiIp4ProtocolTemplete, sizeof (IpInstance->Ip4Proto)); IpInstance->State = IP4_STATE_UNCONFIGED; + IpInstance->InDestroy = FALSE; IpInstance->Service = IpSb; InitializeListHead (&IpInstance->Link); @@ -894,9 +596,13 @@ Ip4ConfigProtocol ( IP4_ADDR Ip; IP4_ADDR Netmask; EFI_ARP_PROTOCOL *Arp; + EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; + EFI_IP4_CONFIG2_POLICY Policy; IpSb = IpInstance->Service; + Ip4Config2 = NULL; + // // User is changing packet filters. It must be stopped // before the station address can be changed. @@ -972,14 +678,26 @@ Ip4ConfigProtocol ( } else { // - // Use the default address. If the default configuration hasn't - // been started, start it. + // Use the default address. Check the state. // if (IpSb->State == IP4_SERVICE_UNSTARTED) { - Status = Ip4StartAutoConfig (IpSb); - - if (EFI_ERROR (Status)) { - goto ON_ERROR; + // + // Trigger the EFI_IP4_CONFIG2_PROTOCOL to retrieve the + // default IPv4 address if it is not available yet. + // + Policy = IpSb->Ip4Config2Instance.Policy; + if (Policy != Ip4Config2PolicyDhcp) { + Ip4Config2 = &IpSb->Ip4Config2Instance.Ip4Config2; + Policy = Ip4Config2PolicyDhcp; + Status= Ip4Config2->SetData ( + Ip4Config2, + Ip4Config2DataTypePolicy, + sizeof (EFI_IP4_CONFIG2_POLICY), + &Policy + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } } } @@ -1009,6 +727,7 @@ Ip4ConfigProtocol ( EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { + Ip4FreeInterface (IpIf, IpInstance); goto ON_ERROR; } } @@ -1040,8 +759,8 @@ ON_ERROR: @param[in] IpInstance The IP4 child to clean up. - @retval EFI_SUCCESS The IP4 child is cleaned up - @retval EFI_DEVICE_ERROR Some resources failed to be released + @retval EFI_SUCCESS The IP4 child is cleaned up. + @retval EFI_DEVICE_ERROR Some resources failed to be released. **/ EFI_STATUS @@ -1109,66 +828,6 @@ Ip4CleanProtocol ( } -/** - Validate that Ip/Netmask pair is OK to be used as station - address. Only continuous netmasks are supported. and check - that StationAddress is a unicast address on the newtwork. - - @param[in] Ip The IP address to validate - @param[in] Netmask The netmaks of the IP - - @retval TRUE The Ip/Netmask pair is valid - @retval FALSE The Ip/Netmask pair is invalid - -**/ -BOOLEAN -Ip4StationAddressValid ( - IN IP4_ADDR Ip, - IN IP4_ADDR Netmask - ) -{ - IP4_ADDR NetBrdcastMask; - INTN Len; - INTN Type; - - // - // Only support the station address with 0.0.0.0/0 to enable DHCP client. - // - if (Netmask == IP4_ALLZERO_ADDRESS) { - return (BOOLEAN) (Ip == IP4_ALLZERO_ADDRESS); - } - - // - // Only support the continuous net masks - // - if ((Len = NetGetMaskLength (Netmask)) == IP4_MASK_NUM) { - return FALSE; - } - - // - // Station address can't be class D or class E address - // - if ((Type = NetGetIpClass (Ip)) > IP4_ADDR_CLASSC) { - return FALSE; - } - - // - // Station address can't be subnet broadcast/net broadcast address - // - if ((Ip == (Ip & Netmask)) || (Ip == (Ip | ~Netmask))) { - return FALSE; - } - - NetBrdcastMask = gIp4AllMasks[MIN (Len, Type << 3)]; - - if (Ip == (Ip | ~NetBrdcastMask)) { - return FALSE; - } - - return TRUE; -} - - /** Assigns an IPv4 address and subnet mask to this EFI IPv4 Protocol driver instance. @@ -1296,8 +955,7 @@ EfiIp4Configure ( Status = Ip4CleanProtocol (IpInstance); // - // Don't change the state if it is DESTROY, consider the following - // valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped, + // Consider the following valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped, // Configure (ThisIp, NULL). If the state is changed to UNCONFIGED, // the unload fails miserably. // @@ -1312,11 +970,6 @@ EfiIp4Configure ( // Ip4ServiceConfigMnp (IpInstance->Service, FALSE); - // - // Update the variable data. - // - Ip4SetVariableData (IpInstance->Service); - ON_EXIT: gBS->RestoreTPL (OldTpl); return Status; @@ -1329,12 +982,12 @@ ON_EXIT: should make sure that the parameters is valid. @param[in] IpInstance The IP4 child to change the setting. - @param[in] JoinFlag TRUE to join the group, otherwise leave it - @param[in] GroupAddress The target group address + @param[in] JoinFlag TRUE to join the group, otherwise leave it. + @param[in] GroupAddress The target group address. - @retval EFI_ALREADY_STARTED Want to join the group, but already a member of it + @retval EFI_ALREADY_STARTED Want to join the group, but already a member of it. @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources. - @retval EFI_DEVICE_ERROR Failed to set the group configuraton + @retval EFI_DEVICE_ERROR Failed to set the group configuraton. @retval EFI_SUCCESS Successfully updated the group setting. @retval EFI_NOT_FOUND Try to leave the group which it isn't a member. @@ -1395,8 +1048,8 @@ Ip4Groups ( // is decreamented each time an address is removed.. // for (Index = IpInstance->GroupCount; Index > 0 ; Index--) { + ASSERT (IpInstance->Groups != NULL); Group = IpInstance->Groups[Index - 1]; - if ((GroupAddress == NULL) || EFI_IP4_EQUAL (&Group, GroupAddress)) { if (EFI_ERROR (Ip4LeaveGroup (IpInstance, NTOHL (Group)))) { return EFI_DEVICE_ERROR; @@ -1631,10 +1284,10 @@ ON_EXIT: @param[in] Map The container of either user's transmit or receive token. - @param[in] Item Current item to check against + @param[in] Item Current item to check against. @param[in] Context The Token to check againist. - @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP + @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP. @retval EFI_SUCCESS The current item isn't the same token/event as the context. @@ -1807,7 +1460,7 @@ Ip4TxTokenValid ( are bound together. Check the comments in Ip4Output for information about IP fragmentation. - @param[in] Context The token's wrap + @param[in] Context The token's wrap. **/ VOID @@ -1855,9 +1508,9 @@ Ip4FreeTxToken ( The callback function to Ip4Output to update the transmit status. @param Ip4Instance The Ip4Instance that request the transmit. - @param Packet The user's transmit request - @param IoStatus The result of the transmission - @param Flag Not used during transmission + @param Packet The user's transmit request. + @param IoStatus The result of the transmission. + @param Flag Not used during transmission. @param Context The token's wrap. **/ @@ -1918,7 +1571,7 @@ Ip4OnPacketSent ( @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length + total data length is greater than MTU (or greater than the maximum packet size if Token.Packet.TxData.OverrideData. - DoNotFragment is TRUE.) + DoNotFragment is TRUE). **/ EFI_STATUS @@ -2269,9 +1922,9 @@ ON_EXIT: Because Ip4CancelPacket and other functions are all called in line, so, after Ip4CancelPacket returns, the Item has been freed. - @param[in] Map The IP4 child's transmit queue - @param[in] Item The current transmitted packet to test. - @param[in] Context The user's token to cancel. + @param[in] Map The IP4 child's transmit queue. + @param[in] Item The current transmitted packet to test. + @param[in] Context The user's token to cancel. @retval EFI_SUCCESS Continue to check the next Item. @retval EFI_ABORTED The user's Token (Token != NULL) is cancelled. @@ -2323,9 +1976,9 @@ Ip4CancelTxTokens ( Cancel the receive request. This is quiet simple, because it is only enqueued in our local receive map. - @param[in] Map The IP4 child's receive queue - @param[in] Item Current receive request to cancel. - @param[in] Context The user's token to cancel + @param[in] Map The IP4 child's receive queue. + @param[in] Item Current receive request to cancel. + @param[in] Context The user's token to cancel. @retval EFI_SUCCESS Continue to check the next receive request on the queue. @@ -2368,13 +2021,13 @@ Ip4CancelRxTokens ( /** Cancel the user's receive/transmit request. - @param[in] IpInstance The IP4 child + @param[in] IpInstance The IP4 child. @param[in] Token The token to cancel. If NULL, all token will be cancelled. - @retval EFI_SUCCESS The token is cancelled + @retval EFI_SUCCESS The token is cancelled. @retval EFI_NOT_FOUND The token isn't found on either the - transmit/receive queue + transmit/receive queue. @retval EFI_DEVICE_ERROR Not all token is cancelled when Token is NULL. **/ @@ -2570,10 +2223,10 @@ EfiIp4Poll ( packets. @param[in] Map The IP4 child's transmit map. - @param[in] Item Current transmitted packet + @param[in] Item Current transmitted packet. @param[in] Context Not used. - @retval EFI_SUCCESS Always returns EFI_SUCCESS + @retval EFI_SUCCESS Always returns EFI_SUCCESS. **/ EFI_STATUS @@ -2596,12 +2249,10 @@ 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. + This heart beat timer of IP4 service instance 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. @param[in] Event The IP4 service instance's heart beat timer. @param[in] Context The IP4 service instance. @@ -2618,7 +2269,64 @@ Ip4TimerTicking ( IpSb = (IP4_SERVICE *) Context; NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE); - + Ip4PacketTimerTicking (IpSb); Ip4IgmpTicking (IpSb); } + +/** + This dedicated timer is used to poll underlying network media status. In case + of cable swap or wireless network switch, 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. + +**/ +VOID +EFIAPI +Ip4TimerReconfigChecking ( + 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; + + // + // 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 && (IpSb->Ip4Config2Instance.Policy == Ip4Config2PolicyDhcp)) { + // + // 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 (); + } + } +}