X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ShellPkg%2FLibrary%2FUefiShellNetwork1CommandsLib%2FPing.c;h=bec9535a8b436338c91e94290fde58a900e43804;hp=493de26f8a95992543350c391ac475fb3eb06798;hb=2d70c90d2e8bf4405c5c16c0c7ea5b2446d1517a;hpb=68fb05272b45b473fe030ac11dcb79d3f3c0aecd
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
index 493de26f8a..bec9535a8b 100644
--- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
+++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
@@ -1,7 +1,9 @@
/** @file
The implementation for Ping shell command.
- Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -17,6 +19,7 @@
#define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))
+UINT64 mCurrentTick = 0;
//
// Function templates to match the IPv4 and IPv6 commands that we use.
@@ -83,7 +86,7 @@ typedef struct _ICMPX_ECHO_REQUEST_REPLY {
UINT16 Checksum;
UINT16 Identifier;
UINT16 SequenceNum;
- UINT64 TimeStamp;
+ UINT32 TimeStamp;
UINT8 Data[1];
} ICMPX_ECHO_REQUEST_REPLY;
#pragma pack()
@@ -91,7 +94,7 @@ typedef struct _ICMPX_ECHO_REQUEST_REPLY {
typedef struct _PING_ICMP_TX_INFO {
LIST_ENTRY Link;
UINT16 SequenceNum;
- UINT64 TimeStamp;
+ UINT32 TimeStamp;
PING_IPX_COMPLETION_TOKEN *Token;
} PING_ICMPX_TX_INFO;
@@ -106,6 +109,7 @@ typedef struct _PING_ICMP_TX_INFO {
#define DEFAULT_BUFFER_SIZE 16
#define ICMP_V4_ECHO_REQUEST 0x8
#define ICMP_V4_ECHO_REPLY 0x0
+#define STALL_1_MILLI_SECOND 1000
#define PING_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'i', 'n', 'g')
typedef struct _PING_PRIVATE_DATA {
@@ -114,6 +118,10 @@ typedef struct _PING_PRIVATE_DATA {
EFI_HANDLE IpChildHandle;
EFI_EVENT Timer;
+ UINT32 TimerPeriod;
+ UINT32 RttTimerTick;
+ EFI_EVENT RttTimer;
+
EFI_STATUS Status;
LIST_ENTRY TxList;
UINT16 RxCount;
@@ -132,31 +140,23 @@ typedef struct _PING_PRIVATE_DATA {
UINT8 SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS) , sizeof(EFI_IPv4_ADDRESS) )];
UINT8 DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS) , sizeof(EFI_IPv4_ADDRESS) )];
PING_IPX_COMPLETION_TOKEN RxToken;
+ UINT16 FailedCount;
} PING_PRIVATE_DATA;
+/**
+ Calculate the internet checksum (see RFC 1071).
+
+ @param[in] Packet Buffer which contains the data to be checksummed.
+ @param[in] Length Length to be checksummed.
+
+ @retval Checksum Returns the 16 bit ones complement of
+ ones complement sum of 16 bit words
+**/
UINT16
-EFIAPI
NetChecksum (
IN UINT8 *Buffer,
IN UINT32 Length
)
-/*++
-
-Routine Description:
-
- Calculate the internet checksum (see RFC 1071)
-
-Arguments:
-
- Packet - Buffer which contains the data to be checksummed
- Length - Length to be checksummed
-
-Returns:
-
- Checksum - Returns the 16 bit ones complement of
- ones complement sum of 16 bit words
-
---*/
{
UINT32 Sum;
UINT8 Odd;
@@ -167,11 +167,11 @@ Returns:
Sum = 0;
Odd = (UINT8) (Length & 1);
Length >>= 1;
- while (Length--) {
+ while ((Length--) != 0) {
Sum += *Packet++;
}
- if (Odd) {
+ if (Odd != 0) {
Sum += *(UINT8 *) Packet;
}
@@ -193,11 +193,6 @@ Returns:
@return The current value of the register.
**/
-UINT64
-EFIAPI
-ReadTime (
- VOID
- );
STATIC CONST SHELL_PARAM_ITEM PingParamList[] = {
{
@@ -208,6 +203,10 @@ STATIC CONST SHELL_PARAM_ITEM PingParamList[] = {
L"-n",
TypeValue
},
+ {
+ L"-s",
+ TypeValue
+ },
{
L"-_s",
TypeValue
@@ -227,68 +226,185 @@ STATIC CONST SHELL_PARAM_ITEM PingParamList[] = {
//
STATIC CONST CHAR16 *mDstString;
STATIC CONST CHAR16 *mSrcString;
-STATIC UINT64 mFrequency = 0;
/**
- Get and caculate the frequency in tick/ms.
- The result is saved in the globle variable mFrequency
+ RTT timer tick routine.
- @retval EFI_SUCCESS Caculated the frequency successfully.
- @retval Others Failed to caculate the frequency.
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
**/
-EFI_STATUS
+VOID
EFIAPI
-GetFrequency (
+RttTimerTickRoutine (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINT32 *RttTimerTick;
+
+ RttTimerTick = (UINT32*) Context;
+ (*RttTimerTick)++;
+}
+
+/**
+ Get the timer period of the system.
+
+ This function tries to get the system timer period by creating
+ an 1ms period timer.
+
+ @return System timer period in MS, or 0 if operation failed.
+
+**/
+UINT32
+GetTimerPeriod(
VOID
)
{
- EFI_STATUS Status;
- EFI_CPU_ARCH_PROTOCOL *Cpu;
- UINT64 CurrentTick;
- UINT64 TimerPeriod;
+ EFI_STATUS Status;
+ UINT32 RttTimerTick;
+ EFI_EVENT TimerEvent;
+ UINT32 StallCounter;
+ EFI_TPL OldTpl;
- Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Cpu);
+ RttTimerTick = 0;
+ StallCounter = 0;
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ RttTimerTickRoutine,
+ &RttTimerTick,
+ &TimerEvent
+ );
if (EFI_ERROR (Status)) {
- return Status;
+ return 0;
}
- Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, &TimerPeriod);
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+ Status = gBS->SetTimer (
+ TimerEvent,
+ TimerPeriodic,
+ TICKS_PER_MS
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (TimerEvent);
+ return 0;
+ }
+
+ while (RttTimerTick < 10) {
+ gBS->Stall (STALL_1_MILLI_SECOND);
+ ++StallCounter;
+ }
+
+ gBS->RestoreTPL (OldTpl);
+
+ gBS->SetTimer (TimerEvent, TimerCancel, 0);
+ gBS->CloseEvent (TimerEvent);
+
+ return StallCounter / RttTimerTick;
+}
+
+/**
+ Initialize the timer event for RTT (round trip time).
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS RTT timer is started.
+ @retval Others Failed to start the RTT timer.
+
+**/
+EFI_STATUS
+PingInitRttTimer (
+ PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ Private->TimerPeriod = GetTimerPeriod ();
+ if (Private->TimerPeriod == 0) {
+ return EFI_ABORTED;
+ }
+
+ Private->RttTimerTick = 0;
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ RttTimerTickRoutine,
+ &Private->RttTimerTick,
+ &Private->RttTimer
+ );
if (EFI_ERROR (Status)) {
- TimerPeriod = DEFAULT_TIMER_PERIOD;
+ return Status;
}
- //
- // The timer period is in femtosecond (1 femtosecond is 1e-15 second).
- // So 1e+12 is divided by timer period to produce the freq in tick/ms.
- //
- mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);
+ Status = gBS->SetTimer (
+ Private->RttTimer,
+ TimerPeriodic,
+ TICKS_PER_MS
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (Private->RttTimer);
+ return Status;
+ }
return EFI_SUCCESS;
}
/**
- Caculate a duration in ms.
+ Free RTT timer event resource.
- @param[in] Begin The start point of time.
- @param[in] End The end point of time.
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+
+**/
+VOID
+PingFreeRttTimer (
+ PING_PRIVATE_DATA *Private
+ )
+{
+ if (Private->RttTimer != NULL) {
+ gBS->SetTimer (Private->RttTimer, TimerCancel, 0);
+ gBS->CloseEvent (Private->RttTimer);
+ }
+}
+
+/**
+ Read the current time.
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+
+ @retval the current tick value.
+**/
+UINT32
+ReadTime (
+ PING_PRIVATE_DATA *Private
+ )
+{
+ return Private->RttTimerTick;
+}
+
+/**
+ Calculate a duration in ms.
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+ @param[in] Begin The start point of time.
+ @param[in] End The end point of time.
@return The duration in ms.
@retval 0 The parameters were not valid.
**/
-UINT64
-EFIAPI
+UINT32
CalculateTick (
- IN UINT64 Begin,
- IN UINT64 End
+ PING_PRIVATE_DATA *Private,
+ IN UINT32 Begin,
+ IN UINT32 End
)
{
- if (End <= Begin) {
+ if (End < Begin) {
return (0);
}
- return DivU64x64Remainder (End - Begin, mFrequency, NULL);
+
+ return (End - Begin) * Private->TimerPeriod;
}
/**
@@ -298,7 +414,6 @@ CalculateTick (
@param[in] IpChoice Whether the token is IPv4 or IPv6
**/
VOID
-EFIAPI
PingDestroyTxInfo (
IN PING_ICMPX_TX_INFO *TxInfo,
IN UINT32 IpChoice
@@ -370,7 +485,6 @@ PingDestroyTxInfo (
**/
EFI_STATUS
-EFIAPI
Ping6MatchEchoReply (
IN PING_PRIVATE_DATA *Private,
IN ICMPX_ECHO_REQUEST_REPLY *Packet
@@ -431,8 +545,7 @@ Ping6OnEchoReplyReceived (
PING_PRIVATE_DATA *Private;
ICMPX_ECHO_REQUEST_REPLY *Reply;
UINT32 PayLoad;
- UINT64 Rtt;
- CHAR8 Near;
+ UINT32 Rtt;
Private = (PING_PRIVATE_DATA *) Context;
@@ -485,12 +598,7 @@ Ping6OnEchoReplyReceived (
//
// Display statistics on this icmp6 echo reply packet.
//
- Rtt = CalculateTick (Reply->TimeStamp, ReadTime ());
- if (Rtt != 0) {
- Near = (CHAR8) '=';
- } else {
- Near = (CHAR8) '<';
- }
+ Rtt = CalculateTick (Private, Reply->TimeStamp, ReadTime (Private));
Private->RttSum += Rtt;
Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin;
@@ -506,8 +614,8 @@ Ping6OnEchoReplyReceived (
mDstString,
Reply->SequenceNum,
Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->HopLimit:0,
- Near,
- Rtt
+ Rtt,
+ Rtt + Private->TimerPeriod
);
ON_EXIT:
@@ -521,6 +629,7 @@ ON_EXIT:
Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);
if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_RECEIVE), gShellNetwork1HiiHandle, Status);
Private->Status = EFI_ABORTED;
}
} else {
@@ -546,10 +655,9 @@ ON_EXIT:
**/
PING_IPX_COMPLETION_TOKEN *
-EFIAPI
PingGenerateToken (
IN PING_PRIVATE_DATA *Private,
- IN UINT64 TimeStamp,
+ IN UINT32 TimeStamp,
IN UINT16 SequenceNum
)
{
@@ -581,7 +689,7 @@ PingGenerateToken (
//
Request->Type = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST);
Request->Code = 0;
- Request->SequenceNum = SequenceNum;
+ Request->SequenceNum = SequenceNum;
Request->Identifier = 0;
Request->Checksum = 0;
@@ -589,6 +697,7 @@ PingGenerateToken (
// Assembly token for transmit.
//
if (Private->IpChoice==PING_IP_CHOICE_IP6) {
+ Request->TimeStamp = TimeStamp;
((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength = 0;
((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs = NULL;
((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData = 0;
@@ -648,7 +757,6 @@ PingGenerateToken (
**/
EFI_STATUS
-EFIAPI
PingSendEchoRequest (
IN PING_PRIVATE_DATA *Private
)
@@ -662,7 +770,7 @@ PingSendEchoRequest (
return EFI_OUT_OF_RESOURCES;
}
- TxInfo->TimeStamp = ReadTime ();
+ TxInfo->TimeStamp = ReadTime (Private);
TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);
TxInfo->Token = PingGenerateToken (
Private,
@@ -699,7 +807,6 @@ PingSendEchoRequest (
**/
EFI_STATUS
-EFIAPI
Ping6ReceiveEchoReply (
IN PING_PRIVATE_DATA *Private
)
@@ -722,7 +829,11 @@ Ping6ReceiveEchoReply (
Private->RxToken.Status = EFI_NOT_READY;
- return (Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken));
+ Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_RECEIVE), gShellNetwork1HiiHandle, Status);
+ }
+ return Status;
}
/**
@@ -769,7 +880,7 @@ Ping6OnTimerRoutine (
//
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);
- Time = CalculateTick (TxInfo->TimeStamp, ReadTime ());
+ Time = CalculateTick (Private, TxInfo->TimeStamp, ReadTime (Private));
//
// Remove the timeout echo request from txlist.
@@ -787,10 +898,8 @@ Ping6OnTimerRoutine (
RemoveEntryList (&TxInfo->Link);
PingDestroyTxInfo (TxInfo, Private->IpChoice);
- //
- // We dont need to wait for this some other time...
- //
Private->RxCount++;
+ Private->FailedCount++;
if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {
//
@@ -813,7 +922,6 @@ Ping6OnTimerRoutine (
@retval FALSE It is not.
**/
BOOLEAN
-EFIAPI
PingNetIp4IsLinkLocalAddr (
IN CONST EFI_IPv4_ADDRESS *Address
)
@@ -830,7 +938,6 @@ PingNetIp4IsLinkLocalAddr (
@retval FALSE It is not.
**/
BOOLEAN
-EFIAPI
PingNetIp4IsUnspecifiedAddr (
IN CONST EFI_IPv4_ADDRESS *Address
)
@@ -850,7 +957,6 @@ PingNetIp4IsUnspecifiedAddr (
@retval EFI_NOT_FOUND The source address is not found.
**/
EFI_STATUS
-EFIAPI
PingCreateIpInstance (
IN PING_PRIVATE_DATA *Private
)
@@ -859,6 +965,8 @@ PingCreateIpInstance (
UINTN HandleIndex;
UINTN HandleNum;
EFI_HANDLE *HandleBuffer;
+ BOOLEAN UnspecifiedSrc;
+ EFI_STATUS MediaStatus;
EFI_SERVICE_BINDING_PROTOCOL *EfiSb;
VOID *IpXCfg;
EFI_IP6_CONFIG_DATA Ip6Config;
@@ -869,6 +977,8 @@ PingCreateIpInstance (
UINTN AddrIndex;
HandleBuffer = NULL;
+ UnspecifiedSrc = FALSE;
+ MediaStatus = EFI_SUCCESS;
EfiSb = NULL;
IpXInterfaceInfo = NULL;
IfInfoSize = 0;
@@ -883,40 +993,57 @@ PingCreateIpInstance (
&HandleNum,
&HandleBuffer
);
- if (EFI_ERROR (Status) || (HandleNum == 0)) {
+ if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) {
return EFI_ABORTED;
}
+
+ if (Private->IpChoice == PING_IP_CHOICE_IP6 ? NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) : \
+ PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {
+ //
+ // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected.
+ //
+ UnspecifiedSrc = TRUE;
+ }
+
//
- // Source address is required when pinging a link-local address on multi-
- // interfaces host.
+ // Source address is required when pinging a link-local address.
//
if (Private->IpChoice == PING_IP_CHOICE_IP6) {
- if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) &&
- NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) &&
- (HandleNum > 1)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);
+ if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);
Status = EFI_INVALID_PARAMETER;
goto ON_ERROR;
}
} else {
ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);
- if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) &&
- PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress) &&
- (HandleNum > 1)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);
+ if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);
Status = EFI_INVALID_PARAMETER;
goto ON_ERROR;
}
}
+
//
// For each ip6 protocol, check interface addresses list.
//
for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
-
EfiSb = NULL;
IpXInterfaceInfo = NULL;
IfInfoSize = 0;
+ if (UnspecifiedSrc) {
+ //
+ // Check media.
+ //
+ NetLibDetectMediaWaitTimeout (HandleBuffer[HandleIndex], 0, &MediaStatus);
+ if (MediaStatus != EFI_SUCCESS) {
+ //
+ // Skip this one.
+ //
+ continue;
+ }
+ }
+
Status = gBS->HandleProtocol (
HandleBuffer[HandleIndex],
Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,
@@ -926,114 +1053,122 @@ PingCreateIpInstance (
goto ON_ERROR;
}
- if (Private->IpChoice == PING_IP_CHOICE_IP6?NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress):PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {
- //
- // No need to match interface address.
- //
- break;
- } else {
- //
- // Ip6config protocol and ip6 service binding protocol are installed
- // on the same handle.
- //
- Status = gBS->HandleProtocol (
- HandleBuffer[HandleIndex],
- Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4ConfigProtocolGuid,
- (VOID **) &IpXCfg
- );
+ //
+ // Ip6config protocol and ip6 service binding protocol are installed
+ // on the same handle.
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4Config2ProtocolGuid,
+ (VOID **) &IpXCfg
+ );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Get the interface information size.
- //
- if (Private->IpChoice == PING_IP_CHOICE_IP6) {
- Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
- IpXCfg,
- Ip6ConfigDataTypeInterfaceInfo,
- &IfInfoSize,
- NULL
- );
- } else {
- Status = ((EFI_IP4_CONFIG_PROTOCOL*)IpXCfg)->GetData (
- IpXCfg,
- &IfInfoSize,
- NULL
- );
- }
-
- //
- // Skip the ones not in current use.
- //
- if (Status == EFI_NOT_STARTED) {
- continue;
- }
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface information size.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+ } else {
+ Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip4Config2DataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+ }
+
+ //
+ // Skip the ones not in current use.
+ //
+ if (Status == EFI_NOT_STARTED) {
+ continue;
+ }
- if (Status != EFI_BUFFER_TOO_SMALL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
- goto ON_ERROR;
- }
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
- IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);
+ IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);
- if (IpXInterfaceInfo == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_ERROR;
- }
- //
- // Get the interface info.
- //
- if (Private->IpChoice == PING_IP_CHOICE_IP6) {
- Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
- IpXCfg,
- Ip6ConfigDataTypeInterfaceInfo,
- &IfInfoSize,
- IpXInterfaceInfo
- );
- } else {
- Status = ((EFI_IP4_CONFIG_PROTOCOL*)IpXCfg)->GetData (
- IpXCfg,
- &IfInfoSize,
- IpXInterfaceInfo
- );
- }
+ if (IpXInterfaceInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface info.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ IpXInterfaceInfo
+ );
+ } else {
+ Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip4Config2DataTypeInterfaceInfo,
+ &IfInfoSize,
+ IpXInterfaceInfo
+ );
+ }
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
- goto ON_ERROR;
- }
- //
- // Check whether the source address is one of the interface addresses.
- //
- if (Private->IpChoice == PING_IP_CHOICE_IP6) {
- for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ //
+ // Check whether the source address is one of the interface addresses.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {
+ Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);
- Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);
- if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
+ if (UnspecifiedSrc) {
+ if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {
//
- // Match a certain interface address.
+ // Select the interface automatically.
//
+ CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));
break;
}
- }
-
- if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {
+ } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
//
- // Found a nic handle with right interface address.
+ // Match a certain interface address.
//
break;
}
- } else {
+ }
+
+ if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {
//
- // IP4 address check
+ // Found a nic handle with right interface address.
//
- if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_IPCONFIG_DATA*)IpXInterfaceInfo)->StationAddress)) {
+ break;
+ }
+ } else {
+ if (UnspecifiedSrc) {
+ if (!PingNetIp4IsUnspecifiedAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress) &&
+ !PingNetIp4IsLinkLocalAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
//
- // Match a certain interface address.
+ // Select the interface automatically.
//
break;
}
+ } else if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
+ //
+ // Match a certain interface address.
+ //
+ break;
}
}
@@ -1045,7 +1180,7 @@ PingCreateIpInstance (
//
if (HandleIndex == HandleNum) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIGD_NIC_NF), gShellNetwork1HiiHandle, L"ping");
Status = EFI_NOT_FOUND;
goto ON_ERROR;
}
@@ -1120,11 +1255,6 @@ PingCreateIpInstance (
//
// Configure the ip4 instance for icmp4 packet exchange.
//
-// PING_IP4_COPY_ADDRESS (&Ip4Config.StationAddress, &Private->SrcAddress);
-// Ip4Config.SubnetMask.Addr[0] = 0xFF;
-// Ip4Config.SubnetMask.Addr[1] = 0xFF;
-// Ip4Config.SubnetMask.Addr[2] = 0xFF;
-// Ip4Config.SubnetMask.Addr[3] = 0x00;
Ip4Config.DefaultProtocol = 1;
Ip4Config.AcceptAnyProtocol = FALSE;
Ip4Config.AcceptBroadcast = FALSE;
@@ -1174,14 +1304,13 @@ ON_ERROR:
}
/**
- Destory the IP instance.
+ Destroy the IP instance.
@param[in] Private The pointer of PING_PRIVATE_DATA.
**/
VOID
-EFIAPI
-Ping6DestoryIp6Instance (
+Ping6DestroyIp6Instance (
IN PING_PRIVATE_DATA *Private
)
{
@@ -1206,6 +1335,7 @@ Ping6DestoryIp6Instance (
}
}
+
/**
The Ping Process.
@@ -1219,7 +1349,6 @@ Ping6DestoryIp6Instance (
@retval others The ping processed unsuccessfully.
**/
SHELL_STATUS
-EFIAPI
ShellPing (
IN UINT32 SendNumber,
IN UINT32 BufferSize,
@@ -1291,6 +1420,16 @@ ShellPing (
ShellStatus = SHELL_ACCESS_DENIED;
goto ON_EXIT;
}
+
+ //
+ // Start a timer to calculate the RTT.
+ //
+ Status = PingInitRttTimer (Private);
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
//
// Create a ipv6 token to send the first icmp6 echo request packet.
//
@@ -1305,7 +1444,7 @@ ShellPing (
} else if (Status == RETURN_NO_MAPPING) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString);
} else {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, Status);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, L"ping", Status);
}
goto ON_EXIT;
@@ -1351,13 +1490,13 @@ ON_STAT:
STRING_TOKEN (STR_PING_STAT),
gShellNetwork1HiiHandle,
Private->TxCount,
- Private->RxCount,
- (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount,
+ (Private->RxCount - Private->FailedCount),
+ (100 - ((100 * (Private->RxCount - Private->FailedCount)) / Private->TxCount)),
Private->RttSum
);
}
- if (Private->RxCount != 0) {
+ if (Private->RxCount > Private->FailedCount) {
ShellPrintHiiEx (
-1,
-1,
@@ -1365,8 +1504,11 @@ ON_STAT:
STRING_TOKEN (STR_PING_RTT),
gShellNetwork1HiiHandle,
Private->RttMin,
+ Private->RttMin + Private->TimerPeriod,
Private->RttMax,
- DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)
+ Private->RttMax + Private->TimerPeriod,
+ DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL),
+ DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL) + Private->TimerPeriod
);
}
@@ -1385,6 +1527,8 @@ ON_EXIT:
PingDestroyTxInfo (TxInfo, Private->IpChoice);
}
+ PingFreeRttTimer (Private);
+
if (Private->Timer != NULL) {
gBS->CloseEvent (Private->Timer);
}
@@ -1398,7 +1542,7 @@ ON_EXIT:
}
if (Private->IpChildHandle != NULL) {
- Ping6DestoryIp6Instance (Private);
+ Ping6DestroyIp6Instance (Private);
}
FreePool (Private);
@@ -1412,6 +1556,10 @@ ON_EXIT:
@param[in] ImageHandle Handle to the Image (NULL if Internal).
@param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS The ping processed successfullly.
+ @retval others The ping processed unsuccessfully.
+
**/
SHELL_STATUS
EFIAPI
@@ -1430,6 +1578,7 @@ ShellCommandRunPing (
CONST CHAR16 *ValueStr;
UINTN NonOptionCount;
UINT32 IpChoice;
+ CHAR16 *ProblemParam;
//
// we use IPv6 buffers to hold items...
@@ -1441,10 +1590,11 @@ ShellCommandRunPing (
IpChoice = PING_IP_CHOICE_IP4;
ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
- Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, NULL, TRUE, FALSE);
+ Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, &ProblemParam, TRUE, FALSE);
if (EFI_ERROR(Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ProblemParam);
ShellStatus = SHELL_INVALID_PARAMETER;
goto ON_EXIT;
}
@@ -1454,7 +1604,7 @@ ShellCommandRunPing (
}
//
- // Parse the paramter of count number.
+ // Parse the parameter of count number.
//
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");
if (ValueStr != NULL) {
@@ -1464,7 +1614,7 @@ ShellCommandRunPing (
// ShellStrToUintn will return 0 when input is 0 or an invalid input string.
//
if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
ShellStatus = SHELL_INVALID_PARAMETER;
goto ON_EXIT;
}
@@ -1472,7 +1622,7 @@ ShellCommandRunPing (
SendNumber = DEFAULT_SEND_COUNT;
}
//
- // Parse the paramter of buffer size.
+ // Parse the parameter of buffer size.
//
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
if (ValueStr != NULL) {
@@ -1482,7 +1632,7 @@ ShellCommandRunPing (
// ShellStrToUintn will return 0 when input is 0 or an invalid input string.
//
if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
ShellStatus = SHELL_INVALID_PARAMETER;
goto ON_EXIT;
}
@@ -1494,9 +1644,13 @@ ShellCommandRunPing (
ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));
//
- // Parse the paramter of source ip address.
+ // Parse the parameter of source ip address.
//
- ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
+ if (ValueStr == NULL) {
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");
+ }
+
if (ValueStr != NULL) {
mSrcString = ValueStr;
if (IpChoice == PING_IP_CHOICE_IP6) {
@@ -1505,22 +1659,22 @@ ShellCommandRunPing (
Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress);
}
if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
ShellStatus = SHELL_INVALID_PARAMETER;
goto ON_EXIT;
}
}
//
- // Parse the paramter of destination ip address.
+ // Parse the parameter of destination ip address.
//
NonOptionCount = ShellCommandLineGetCount(ParamPackage);
if (NonOptionCount < 2) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ping");
ShellStatus = SHELL_INVALID_PARAMETER;
goto ON_EXIT;
}
if (NonOptionCount > 2) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle, L"ping");
ShellStatus = SHELL_INVALID_PARAMETER;
goto ON_EXIT;
}
@@ -1533,19 +1687,12 @@ ShellCommandRunPing (
Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress);
}
if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
ShellStatus = SHELL_INVALID_PARAMETER;
goto ON_EXIT;
}
}
- //
- // Get frequency to calculate the time from ticks.
- //
- Status = GetFrequency ();
- if (EFI_ERROR(Status)) {
- goto ON_EXIT;
- }
//
// Enter into ping process.
//