]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
ShellPkg:Ping: Ping command hangs with intermittent packet losses
[mirror_edk2.git] / ShellPkg / Library / UefiShellNetwork1CommandsLib / Ping.c
index fd4aa8d81e7c0ff9609e65280098f1edf772b554..e2dc76570ac9dff957e887e036cb9d5a3f5b80b8 100644 (file)
@@ -1,7 +1,9 @@
 /** @file\r
   The implementation for Ping shell command.\r
 \r
 /** @file\r
   The implementation for Ping shell command.\r
 \r
-  Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -17,7 +19,7 @@
 \r
 #define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))\r
 \r
 \r
 #define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))\r
 \r
-UINT64          CurrentTick = 0;\r
+UINT64          mCurrentTick = 0;\r
 \r
 //\r
 // Function templates to match the IPv4 and IPv6 commands that we use.\r
 \r
 //\r
 // Function templates to match the IPv4 and IPv6 commands that we use.\r
@@ -133,6 +135,7 @@ typedef struct _PING_PRIVATE_DATA {
   UINT8                       SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
   UINT8                       DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
   PING_IPX_COMPLETION_TOKEN   RxToken;\r
   UINT8                       SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
   UINT8                       DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
   PING_IPX_COMPLETION_TOKEN   RxToken;\r
+  UINT16                      FailedCount;\r
 } PING_PRIVATE_DATA;\r
 \r
 /**\r
 } PING_PRIVATE_DATA;\r
 \r
 /**\r
@@ -196,6 +199,10 @@ STATIC CONST SHELL_PARAM_ITEM    PingParamList[] = {
     L"-n",\r
     TypeValue\r
   },\r
     L"-n",\r
     TypeValue\r
   },\r
+  {\r
+    L"-s",\r
+    TypeValue\r
+  },\r
   {\r
     L"-_s",\r
     TypeValue\r
   {\r
     L"-_s",\r
     TypeValue\r
@@ -234,25 +241,25 @@ ReadTime (
 \r
   ASSERT (gCpu != NULL);\r
 \r
 \r
   ASSERT (gCpu != NULL);\r
 \r
-  Status = gCpu->GetTimerValue (gCpu, 0, &CurrentTick, &TimerPeriod);\r
+  Status = gCpu->GetTimerValue (gCpu, 0, &mCurrentTick, &TimerPeriod);\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the\r
     // TimerPeriod by ourselves.\r
     //\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the\r
     // TimerPeriod by ourselves.\r
     //\r
-    CurrentTick += 1000000;\r
+    mCurrentTick += 1000000;\r
   }\r
   \r
   }\r
   \r
-  return CurrentTick;\r
+  return mCurrentTick;\r
 }\r
 \r
 \r
 /**\r
 }\r
 \r
 \r
 /**\r
-  Get and caculate the frequency in tick/ms.\r
-  The result is saved in the globle variable mFrequency\r
+  Get and calculate the frequency in ticks/ms.\r
+  The result is saved in the global variable mFrequency\r
 \r
 \r
-  @retval EFI_SUCCESS    Caculated the frequency successfully.\r
-  @retval Others         Failed to caculate the frequency.\r
+  @retval EFI_SUCCESS    Calculated the frequency successfully.\r
+  @retval Others         Failed to calculate the frequency.\r
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
@@ -278,7 +285,7 @@ GetFrequency (
 \r
   //\r
   // The timer period is in femtosecond (1 femtosecond is 1e-15 second).\r
 \r
   //\r
   // The timer period is in femtosecond (1 femtosecond is 1e-15 second).\r
-  // So 1e+12 is divided by timer period to produce the freq in tick/ms.\r
+  // So 1e+12 is divided by timer period to produce the freq in ticks/ms.\r
   //\r
   mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);\r
 \r
   //\r
   mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);\r
 \r
@@ -286,7 +293,7 @@ GetFrequency (
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Caculate a duration in ms.\r
+  Calculate a duration in ms.\r
 \r
   @param[in]  Begin     The start point of time.\r
   @param[in]  End       The end point of time.\r
 \r
   @param[in]  Begin     The start point of time.\r
   @param[in]  End       The end point of time.\r
@@ -597,7 +604,7 @@ PingGenerateToken (
   //\r
   Request->Type        = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST);\r
   Request->Code        = 0;\r
   //\r
   Request->Type        = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST);\r
   Request->Code        = 0;\r
-  Request->SequenceNum = SequenceNum;\r
+  Request->SequenceNum = SequenceNum; \r
   Request->Identifier  = 0;\r
   Request->Checksum    = 0;\r
 \r
   Request->Identifier  = 0;\r
   Request->Checksum    = 0;\r
 \r
@@ -605,6 +612,7 @@ PingGenerateToken (
   // Assembly token for transmit.\r
   //\r
   if (Private->IpChoice==PING_IP_CHOICE_IP6) {\r
   // Assembly token for transmit.\r
   //\r
   if (Private->IpChoice==PING_IP_CHOICE_IP6) {\r
+    Request->TimeStamp   = TimeStamp;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength                   = 0;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs                         = NULL;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData                    = 0;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength                   = 0;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs                         = NULL;\r
     ((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData                    = 0;\r
@@ -803,10 +811,8 @@ Ping6OnTimerRoutine (
       RemoveEntryList (&TxInfo->Link);\r
       PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
 \r
       RemoveEntryList (&TxInfo->Link);\r
       PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
 \r
-      //\r
-      // We dont need to wait for this some other time...\r
-      //\r
       Private->RxCount++;\r
       Private->RxCount++;\r
+      Private->FailedCount++;\r
 \r
       if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {\r
         //\r
 \r
       if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {\r
         //\r
@@ -875,6 +881,8 @@ PingCreateIpInstance (
   UINTN                            HandleIndex;\r
   UINTN                            HandleNum;\r
   EFI_HANDLE                       *HandleBuffer;\r
   UINTN                            HandleIndex;\r
   UINTN                            HandleNum;\r
   EFI_HANDLE                       *HandleBuffer;\r
+  BOOLEAN                          UnspecifiedSrc;\r
+  BOOLEAN                          MediaPresent;\r
   EFI_SERVICE_BINDING_PROTOCOL     *EfiSb;\r
   VOID                             *IpXCfg;\r
   EFI_IP6_CONFIG_DATA              Ip6Config;\r
   EFI_SERVICE_BINDING_PROTOCOL     *EfiSb;\r
   VOID                             *IpXCfg;\r
   EFI_IP6_CONFIG_DATA              Ip6Config;\r
@@ -885,6 +893,8 @@ PingCreateIpInstance (
   UINTN                            AddrIndex;\r
 \r
   HandleBuffer      = NULL;\r
   UINTN                            AddrIndex;\r
 \r
   HandleBuffer      = NULL;\r
+  UnspecifiedSrc    = FALSE;\r
+  MediaPresent      = TRUE;\r
   EfiSb             = NULL;\r
   IpXInterfaceInfo  = NULL;\r
   IfInfoSize        = 0;\r
   EfiSb             = NULL;\r
   IpXInterfaceInfo  = NULL;\r
   IfInfoSize        = 0;\r
@@ -902,37 +912,54 @@ PingCreateIpInstance (
   if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) {\r
     return EFI_ABORTED;\r
   }\r
   if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) {\r
     return EFI_ABORTED;\r
   }\r
+\r
+  if (Private->IpChoice == PING_IP_CHOICE_IP6 ? NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) : \\r
+      PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {\r
+    //\r
+    // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected. \r
+    //\r
+    UnspecifiedSrc = TRUE;\r
+  }\r
+  \r
   //\r
   //\r
-  // Source address is required when pinging a link-local address on multi-\r
-  // interfaces host.\r
+  // Source address is required when pinging a link-local address.\r
   //\r
   if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
   //\r
   if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
-    if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) &&\r
-        NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) &&\r
-        (HandleNum > 1)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+    if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);\r
       Status = EFI_INVALID_PARAMETER;\r
       goto ON_ERROR;\r
     }\r
   } else {\r
     ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);\r
       Status = EFI_INVALID_PARAMETER;\r
       goto ON_ERROR;\r
     }\r
   } else {\r
     ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);\r
-    if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) &&\r
-        PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress) &&\r
-        (HandleNum > 1)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+    if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle); \r
       Status = EFI_INVALID_PARAMETER;\r
       goto ON_ERROR;\r
     }\r
   }\r
       Status = EFI_INVALID_PARAMETER;\r
       goto ON_ERROR;\r
     }\r
   }\r
+  \r
   //\r
   // For each ip6 protocol, check interface addresses list.\r
   //\r
   for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {\r
   //\r
   // For each ip6 protocol, check interface addresses list.\r
   //\r
   for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {\r
-\r
     EfiSb             = NULL;\r
     IpXInterfaceInfo  = NULL;\r
     IfInfoSize        = 0;\r
 \r
     EfiSb             = NULL;\r
     IpXInterfaceInfo  = NULL;\r
     IfInfoSize        = 0;\r
 \r
+    if (UnspecifiedSrc) {\r
+      //\r
+      // Check media.\r
+      //\r
+      NetLibDetectMedia (HandleBuffer[HandleIndex], &MediaPresent);\r
+      if (!MediaPresent) {\r
+        //\r
+        // Skip this one.\r
+        //\r
+        continue;\r
+      }\r
+    }\r
+\r
     Status = gBS->HandleProtocol (\r
                     HandleBuffer[HandleIndex],\r
                     Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,\r
     Status = gBS->HandleProtocol (\r
                     HandleBuffer[HandleIndex],\r
                     Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,\r
@@ -942,114 +969,122 @@ PingCreateIpInstance (
       goto ON_ERROR;\r
     }\r
 \r
       goto ON_ERROR;\r
     }\r
 \r
-    if (Private->IpChoice == PING_IP_CHOICE_IP6?NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress):PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {\r
-      //\r
-      // No need to match interface address.\r
-      //\r
-      break;\r
-    } else {\r
-      //\r
-      // Ip6config protocol and ip6 service binding protocol are installed\r
-      // on the same handle.\r
-      //\r
-      Status = gBS->HandleProtocol (\r
-                      HandleBuffer[HandleIndex],\r
-                      Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4ConfigProtocolGuid,\r
-                      (VOID **) &IpXCfg\r
-                      );\r
+    //\r
+    // Ip6config protocol and ip6 service binding protocol are installed\r
+    // on the same handle.\r
+    //\r
+    Status = gBS->HandleProtocol (\r
+                    HandleBuffer[HandleIndex],\r
+                    Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4Config2ProtocolGuid,\r
+                    (VOID **) &IpXCfg\r
+                    );\r
 \r
 \r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Get the interface information size.\r
-      //\r
-      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
-        Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
-                           IpXCfg,\r
-                           Ip6ConfigDataTypeInterfaceInfo,\r
-                           &IfInfoSize,\r
-                           NULL\r
-                           );\r
-      } else {\r
-        Status = ((EFI_IP4_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
-                           IpXCfg,\r
-                           &IfInfoSize,\r
-                           NULL\r
-                           );\r
-      }\r
-      \r
-      //\r
-      // Skip the ones not in current use.\r
-      //\r
-      if (Status == EFI_NOT_STARTED) {\r
-        continue;\r
-      }\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the interface information size.\r
+    //\r
+    if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+      Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
+                         IpXCfg,\r
+                         Ip6ConfigDataTypeInterfaceInfo,\r
+                         &IfInfoSize,\r
+                         NULL\r
+                         );\r
+    } else {\r
+      Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (\r
+                         IpXCfg,\r
+                         Ip4Config2DataTypeInterfaceInfo,\r
+                         &IfInfoSize,\r
+                         NULL\r
+                         );\r
+    }\r
+    \r
+    //\r
+    // Skip the ones not in current use.\r
+    //\r
+    if (Status == EFI_NOT_STARTED) {\r
+      continue;\r
+    }\r
 \r
 \r
-      if (Status != EFI_BUFFER_TOO_SMALL) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
-        goto ON_ERROR;\r
-      }\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
 \r
 \r
-      IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);\r
+    IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);\r
 \r
 \r
-      if (IpXInterfaceInfo == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Get the interface info.\r
-      //\r
-      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
-        Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
-                           IpXCfg,\r
-                           Ip6ConfigDataTypeInterfaceInfo,\r
-                           &IfInfoSize,\r
-                           IpXInterfaceInfo\r
-                           );\r
-      } else {\r
-        Status = ((EFI_IP4_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
-                           IpXCfg,\r
-                           &IfInfoSize,\r
-                           IpXInterfaceInfo\r
-                           );\r
-      }\r
+    if (IpXInterfaceInfo == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Get the interface info.\r
+    //\r
+    if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+      Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
+                         IpXCfg,\r
+                         Ip6ConfigDataTypeInterfaceInfo,\r
+                         &IfInfoSize,\r
+                         IpXInterfaceInfo\r
+                         );\r
+    } else {\r
+      Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (\r
+                         IpXCfg,\r
+                         Ip4Config2DataTypeInterfaceInfo,\r
+                         &IfInfoSize,\r
+                         IpXInterfaceInfo\r
+                         );\r
+    }\r
 \r
 \r
-      if (EFI_ERROR (Status)) {\r
-        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
-        goto ON_ERROR;\r
-      }\r
-      //\r
-      // Check whether the source address is one of the interface addresses.\r
-      //\r
-      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
-        for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Check whether the source address is one of the interface addresses.\r
+    //\r
+    if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+      for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {\r
+        Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);\r
 \r
 \r
-          Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);\r
-          if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
+        if (UnspecifiedSrc) {\r
+          if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {\r
             //\r
             //\r
-            // Match a certain interface address.\r
+            // Select the interface automatically.\r
             //\r
             //\r
+            CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));\r
             break;\r
           }\r
             break;\r
           }\r
-        }\r
-\r
-        if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {\r
+        } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
           //\r
           //\r
-          // Found a nic handle with right interface address.\r
+          // Match a certain interface address.\r
           //\r
           break;\r
         }\r
           //\r
           break;\r
         }\r
-      } else {\r
+      }\r
+\r
+      if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {\r
         //\r
         //\r
-        // IP4 address check\r
+        // Found a nic handle with right interface address.\r
         //\r
         //\r
-        if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_IPCONFIG_DATA*)IpXInterfaceInfo)->StationAddress)) {\r
+        break;\r
+      }\r
+    } else {\r
+      if (UnspecifiedSrc) {\r
+        if (!PingNetIp4IsUnspecifiedAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress) && \r
+            !PingNetIp4IsLinkLocalAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {\r
           //\r
           //\r
-          // Match a certain interface address.\r
+          // Select the interface automatically.\r
           //\r
           break;\r
         }\r
           //\r
           break;\r
         }\r
+      } else if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {\r
+        //\r
+        // Match a certain interface address.\r
+        //\r
+        break;\r
       }\r
     }\r
 \r
       }\r
     }\r
 \r
@@ -1061,7 +1096,7 @@ PingCreateIpInstance (
   //\r
 \r
   if (HandleIndex == HandleNum) {\r
   //\r
 \r
   if (HandleIndex == HandleNum) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIGD_NIC_NF), gShellNetwork1HiiHandle, L"ping");  \r
     Status = EFI_NOT_FOUND;\r
     goto ON_ERROR;\r
   }\r
     Status = EFI_NOT_FOUND;\r
     goto ON_ERROR;\r
   }\r
@@ -1136,11 +1171,6 @@ PingCreateIpInstance (
     //\r
     // Configure the ip4 instance for icmp4 packet exchange.\r
     //\r
     //\r
     // Configure the ip4 instance for icmp4 packet exchange.\r
     //\r
-//    PING_IP4_COPY_ADDRESS (&Ip4Config.StationAddress,     &Private->SrcAddress);\r
-//    Ip4Config.SubnetMask.Addr[0] = 0xFF;\r
-//    Ip4Config.SubnetMask.Addr[1] = 0xFF;\r
-//    Ip4Config.SubnetMask.Addr[2] = 0xFF;\r
-//    Ip4Config.SubnetMask.Addr[3] = 0x00;\r
     Ip4Config.DefaultProtocol   = 1;\r
     Ip4Config.AcceptAnyProtocol = FALSE;\r
     Ip4Config.AcceptBroadcast   = FALSE;\r
     Ip4Config.DefaultProtocol   = 1;\r
     Ip4Config.AcceptAnyProtocol = FALSE;\r
     Ip4Config.AcceptBroadcast   = FALSE;\r
@@ -1321,7 +1351,7 @@ ShellPing (
     } else if (Status == RETURN_NO_MAPPING) {\r
       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString);\r
     } else {\r
     } else if (Status == RETURN_NO_MAPPING) {\r
       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString);\r
     } else {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, Status);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, L"ping", Status);  \r
     }\r
 \r
     goto ON_EXIT;\r
     }\r
 \r
     goto ON_EXIT;\r
@@ -1367,13 +1397,13 @@ ON_STAT:
       STRING_TOKEN (STR_PING_STAT),\r
       gShellNetwork1HiiHandle,\r
       Private->TxCount,\r
       STRING_TOKEN (STR_PING_STAT),\r
       gShellNetwork1HiiHandle,\r
       Private->TxCount,\r
-      Private->RxCount,\r
-      (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount,\r
+      (Private->RxCount - Private->FailedCount),\r
+      (100 - ((100 * (Private->RxCount - Private->FailedCount)) / Private->TxCount)),\r
       Private->RttSum\r
       );\r
   }\r
 \r
       Private->RttSum\r
       );\r
   }\r
 \r
-  if (Private->RxCount != 0) {\r
+  if (Private->RxCount > Private->FailedCount) {\r
     ShellPrintHiiEx (\r
       -1,\r
       -1,\r
     ShellPrintHiiEx (\r
       -1,\r
       -1,\r
@@ -1382,7 +1412,7 @@ ON_STAT:
       gShellNetwork1HiiHandle,\r
       Private->RttMin,\r
       Private->RttMax,\r
       gShellNetwork1HiiHandle,\r
       Private->RttMin,\r
       Private->RttMax,\r
-      DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)\r
+      DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL)\r
       );\r
   }\r
 \r
       );\r
   }\r
 \r
@@ -1428,6 +1458,10 @@ ON_EXIT:
 \r
   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
 \r
   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
+\r
+  @retval SHELL_SUCCESS  The ping processed successfullly.\r
+  @retval others         The ping processed unsuccessfully.\r
+  \r
 **/\r
 SHELL_STATUS\r
 EFIAPI\r
 **/\r
 SHELL_STATUS\r
 EFIAPI\r
@@ -1446,6 +1480,7 @@ ShellCommandRunPing (
   CONST CHAR16        *ValueStr;\r
   UINTN               NonOptionCount;\r
   UINT32              IpChoice;\r
   CONST CHAR16        *ValueStr;\r
   UINTN               NonOptionCount;\r
   UINT32              IpChoice;\r
+  CHAR16              *ProblemParam;\r
 \r
   //\r
   // we use IPv6 buffers to hold items... \r
 \r
   //\r
   // we use IPv6 buffers to hold items... \r
@@ -1457,10 +1492,11 @@ ShellCommandRunPing (
   IpChoice = PING_IP_CHOICE_IP4;\r
 \r
   ShellStatus = SHELL_SUCCESS;\r
   IpChoice = PING_IP_CHOICE_IP4;\r
 \r
   ShellStatus = SHELL_SUCCESS;\r
+  ProblemParam = NULL;\r
 \r
 \r
-  Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, NULL, TRUE, FALSE);\r
+  Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, &ProblemParam, TRUE, FALSE);\r
   if (EFI_ERROR(Status)) {\r
   if (EFI_ERROR(Status)) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle);\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ProblemParam);\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
@@ -1480,7 +1516,7 @@ ShellCommandRunPing (
     // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
     //\r
     if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) {\r
     // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
     //\r
     if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
@@ -1498,7 +1534,7 @@ ShellCommandRunPing (
     // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
     //\r
     if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) {\r
     // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
     //\r
     if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
@@ -1512,7 +1548,11 @@ ShellCommandRunPing (
   //\r
   // Parse the paramter of source ip address.\r
   //\r
   //\r
   // Parse the paramter of source ip address.\r
   //\r
-  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");\r
+  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");\r
+  if (ValueStr == NULL) {\r
+    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");\r
+  }\r
+  \r
   if (ValueStr != NULL) {\r
     mSrcString = ValueStr;\r
     if (IpChoice == PING_IP_CHOICE_IP6) {\r
   if (ValueStr != NULL) {\r
     mSrcString = ValueStr;\r
     if (IpChoice == PING_IP_CHOICE_IP6) {\r
@@ -1521,7 +1561,7 @@ ShellCommandRunPing (
       Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress);\r
     }\r
     if (EFI_ERROR (Status)) {\r
       Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress);\r
     }\r
     if (EFI_ERROR (Status)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
@@ -1531,12 +1571,12 @@ ShellCommandRunPing (
   //\r
   NonOptionCount = ShellCommandLineGetCount(ParamPackage);\r
   if (NonOptionCount < 2) {\r
   //\r
   NonOptionCount = ShellCommandLineGetCount(ParamPackage);\r
   if (NonOptionCount < 2) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ping");  \r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
   if (NonOptionCount > 2) {\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
   if (NonOptionCount > 2) {\r
-    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle);\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle, L"ping");  \r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
     ShellStatus = SHELL_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
@@ -1549,7 +1589,7 @@ ShellCommandRunPing (
       Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress);\r
     }\r
     if (EFI_ERROR (Status)) {\r
       Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress);\r
     }\r
     if (EFI_ERROR (Status)) {\r
-      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);  \r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r
       ShellStatus = SHELL_INVALID_PARAMETER;\r
       goto ON_EXIT;\r
     }\r