The implementation for Ping shell command.\r
\r
(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
- Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<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
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
L"-n",\r
TypeValue\r
},\r
+ {\r
+ L"-s",\r
+ TypeValue\r
+ },\r
{\r
L"-_s",\r
TypeValue\r
RemoveEntryList (&TxInfo->Link);\r
PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
\r
+ Private->RxCount++;\r
+ Private->FailedCount++;\r
+\r
if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {\r
//\r
// All the left icmp6 echo request in the list timeout.\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
UINTN AddrIndex;\r
\r
HandleBuffer = NULL;\r
+ UnspecifiedSrc = FALSE;\r
+ MediaPresent = TRUE;\r
EfiSb = NULL;\r
IpXInterfaceInfo = NULL;\r
IfInfoSize = 0;\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
- // 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
- 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_PARAM_INV), gShellNetwork1HiiHandle, L"ping", 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
- 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_PARAM_INV), gShellNetwork1HiiHandle, L"ping", 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
+ \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
+ 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
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:&gEfiIp4Config2ProtocolGuid,\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
- 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
+ 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
- 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
- IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);\r
+ IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);\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
+ 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
- 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
- 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
- // Match a certain interface address.\r
+ // Select the interface automatically.\r
//\r
+ CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));\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
- // Found a nic handle with right interface address.\r
+ // Match a certain interface address.\r
//\r
break;\r
}\r
- } else {\r
+ }\r
+\r
+ if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {\r
//\r
- // IP4 address check\r
+ // Found a nic handle with right interface address.\r
//\r
- if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)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
- // Match a certain interface address.\r
+ // Select the interface automatically.\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
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
- if (Private->RxCount != 0) {\r
+ if (Private->RxCount > Private->FailedCount) {\r
ShellPrintHiiEx (\r
-1,\r
-1,\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
// 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