X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ShellPkg%2FLibrary%2FUefiShellNetwork2CommandsLib%2FPing6.c;h=2cdf484c06151635ca9733a0025e82443d38e823;hp=af7d08f3ec516bfd3932d0715fcaafe86850fee0;hb=2d70c90d2e8bf4405c5c16c0c7ea5b2446d1517a;hpb=43ca17532bd7292eee5ad979e26b19ddd0d3e55a
diff --git a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
index af7d08f3ec..2cdf484c06 100644
--- a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
+++ b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
@@ -1,7 +1,7 @@
/** @file
The implementation for Ping6 application.
- Copyright (c) 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2016 - 2017, 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
@@ -19,12 +19,7 @@
#define PING6_MAX_SEND_NUMBER 10000
#define PING6_MAX_BUFFER_SIZE 32768
#define PING6_ONE_SECOND 10000000
-
-//
-// A similar amount of time that passes in femtoseconds
-// for each increment of TimerValue. It is for NT32 only.
-//
-#define NTTIMERPERIOD 358049
+#define STALL_1_MILLI_SECOND 1000
#pragma pack(1)
@@ -34,7 +29,7 @@ typedef struct _ICMP6_ECHO_REQUEST_REPLY {
UINT16 Checksum;
UINT16 Identifier;
UINT16 SequenceNum;
- UINT64 TimeStamp;
+ UINT32 TimeStamp;
UINT8 Data[1];
} ICMP6_ECHO_REQUEST_REPLY;
@@ -43,7 +38,7 @@ typedef struct _ICMP6_ECHO_REQUEST_REPLY {
typedef struct _PING6_ICMP6_TX_INFO {
LIST_ENTRY Link;
UINT16 SequenceNum;
- UINT64 TimeStamp;
+ UINT32 TimeStamp;
EFI_IP6_COMPLETION_TOKEN *Token;
} PING6_ICMP6_TX_INFO;
@@ -54,6 +49,10 @@ typedef struct _PING6_PRIVATE_DATA {
EFI_IP6_PROTOCOL *Ip6;
EFI_EVENT Timer;
+ UINT32 TimerPeriod;
+ UINT32 RttTimerTick;
+ EFI_EVENT RttTimer;
+
EFI_STATUS Status;
LIST_ENTRY TxList;
EFI_IP6_COMPLETION_TOKEN RxToken;
@@ -99,96 +98,189 @@ SHELL_PARAM_ITEM Ping6ParamList[] = {
//
CONST CHAR16 *mIp6DstString;
CONST CHAR16 *mIp6SrcString;
-UINT64 mFrequency = 0;
-UINT64 mIp6CurrentTick = 0;
EFI_CPU_ARCH_PROTOCOL *Cpu = NULL;
+/**
+ RTT timer tick routine.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
+
+**/
+VOID
+EFIAPI
+Ping6RttTimerTickRoutine (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINT32 *RttTimerTick;
+ RttTimerTick = (UINT32*) Context;
+ (*RttTimerTick)++;
+}
/**
- Reads and returns the current value of the Time.
+ Get the timer period of the system.
+
+ This function tries to get the system timer period by creating
+ an 1ms period timer.
- @return The current tick value.
+ @return System timer period in MS, or 0 if operation failed.
**/
-UINT64
-Ping6ReadTime ()
+UINT32
+Ping6GetTimerPeriod(
+ VOID
+ )
{
- UINT64 TimerPeriod;
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ UINT32 RttTimerTick;
+ EFI_EVENT TimerEvent;
+ UINT32 StallCounter;
+ EFI_TPL OldTpl;
- ASSERT (Cpu != NULL);
+ RttTimerTick = 0;
+ StallCounter = 0;
- Status = Cpu->GetTimerValue (Cpu, 0, &mIp6CurrentTick, &TimerPeriod);
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ Ping6RttTimerTickRoutine,
+ &RttTimerTick,
+ &TimerEvent
+ );
if (EFI_ERROR (Status)) {
- //
- // The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the
- // TimerPeriod by ourselves.
- //
- mIp6CurrentTick += 1000000;
+ return 0;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+ Status = gBS->SetTimer (
+ TimerEvent,
+ TimerPeriodic,
+ TICKS_PER_MS
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (TimerEvent);
+ return 0;
}
- return mIp6CurrentTick;
+ while (RttTimerTick < 10) {
+ gBS->Stall (STALL_1_MILLI_SECOND);
+ ++StallCounter;
+ }
+
+ gBS->RestoreTPL (OldTpl);
+
+ gBS->SetTimer (TimerEvent, TimerCancel, 0);
+ gBS->CloseEvent (TimerEvent);
+
+ return StallCounter / RttTimerTick;
}
+
/**
- Get and calculate the frequency in tick/ms.
- The result is saved in the globle variable mFrequency
+ Initialize the timer event for RTT (round trip time).
- @retval EFI_SUCCESS Calculated the frequency successfully.
- @retval Others Failed to calculate the frequency.
+ @param[in] Private The pointer to PING6_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS RTT timer is started.
+ @retval Others Failed to start the RTT timer.
**/
EFI_STATUS
-Ping6GetFrequency (
- VOID
+Ping6InitRttTimer (
+ IN PING6_PRIVATE_DATA *Private
)
{
- EFI_STATUS Status;
- UINT64 CurrentTick;
- UINT64 TimerPeriod;
-
- Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Cpu);
+ EFI_STATUS Status;
+ Private->TimerPeriod = Ping6GetTimerPeriod ();
+ if (Private->TimerPeriod == 0) {
+ return EFI_ABORTED;
+ }
+
+ Private->RttTimerTick = 0;
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ Ping6RttTimerTickRoutine,
+ &Private->RttTimerTick,
+ &Private->RttTimer
+ );
if (EFI_ERROR (Status)) {
return Status;
}
- Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, &TimerPeriod);
-
+ Status = gBS->SetTimer (
+ Private->RttTimer,
+ TimerPeriodic,
+ TICKS_PER_MS
+ );
if (EFI_ERROR (Status)) {
- //
- // For NT32 Simulator only. 358049 is a similar value to keep timer granularity.
- // Set the timer period by ourselves.
- //
- TimerPeriod = (UINT64) NTTIMERPERIOD;
+ gBS->CloseEvent (Private->RttTimer);
+ 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);
return EFI_SUCCESS;
+
+}
+
+/**
+ Free RTT timer event resource.
+
+ @param[in] Private The pointer to PING6_PRIVATE_DATA.
+
+**/
+VOID
+Ping6FreeRttTimer (
+ IN PING6_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 PING6_PRIVATE_DATA.
+
+ @retval the current tick value.
+**/
+UINT32
+Ping6ReadTime (
+ IN PING6_PRIVATE_DATA *Private
+ )
+{
+ return Private->RttTimerTick;
}
/**
Get and calculate the duration in ms.
+ @param[in] Private The pointer to PING6_PRIVATE_DATA.
@param[in] Begin The start point of time.
@param[in] End The end point of time.
@return The duration in ms.
**/
-UINT64
+UINT32
Ping6CalculateTick (
- IN UINT64 Begin,
- IN UINT64 End
+ IN PING6_PRIVATE_DATA *Private,
+ IN UINT32 Begin,
+ IN UINT32 End
)
{
- ASSERT (End > Begin);
- return DivU64x64Remainder (End - Begin, mFrequency, NULL);
+ if (End < Begin) {
+ return (0);
+ }
+
+ return (End - Begin) * Private->TimerPeriod;
+
}
/**
@@ -312,8 +404,7 @@ Ping6OnEchoReplyReceived6 (
EFI_IP6_RECEIVE_DATA *RxData;
ICMP6_ECHO_REQUEST_REPLY *Reply;
UINT32 PayLoad;
- UINT64 Rtt;
- CHAR8 Near;
+ UINT32 Rtt;
Private = (PING6_PRIVATE_DATA *) Context;
@@ -352,12 +443,7 @@ Ping6OnEchoReplyReceived6 (
//
// Display statistics on this icmp6 echo reply packet.
//
- Rtt = Ping6CalculateTick (Reply->TimeStamp, Ping6ReadTime ());
- if (Rtt != 0) {
- Near = (CHAR8) '=';
- } else {
- Near = (CHAR8) '<';
- }
+ Rtt = Ping6CalculateTick (Private, Reply->TimeStamp, Ping6ReadTime (Private));
Private->RttSum += Rtt;
Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin;
@@ -373,8 +459,8 @@ Ping6OnEchoReplyReceived6 (
mIp6DstString,
Reply->SequenceNum,
RxData->Header->HopLimit,
- Near,
- Rtt
+ Rtt,
+ Rtt + Private->TimerPeriod
);
ON_EXIT:
@@ -388,6 +474,7 @@ ON_EXIT:
Status = Private->Ip6->Receive (Private->Ip6, RxToken);
if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_RECEIVE), gShellNetwork2HiiHandle, Status);
Private->Status = EFI_ABORTED;
}
} else {
@@ -415,7 +502,7 @@ ON_EXIT:
EFI_IP6_COMPLETION_TOKEN *
Ping6GenerateToken (
IN PING6_PRIVATE_DATA *Private,
- IN UINT64 TimeStamp,
+ IN UINT32 TimeStamp,
IN UINT16 SequenceNum
)
{
@@ -513,7 +600,7 @@ Ping6SendEchoRequest (
return EFI_OUT_OF_RESOURCES;
}
- TxInfo->TimeStamp = Ping6ReadTime ();
+ TxInfo->TimeStamp = Ping6ReadTime (Private);
TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);
TxInfo->Token = Ping6GenerateToken (
@@ -572,7 +659,11 @@ Ping6OnReceiveEchoReply (
Private->RxToken.Status = EFI_NOT_READY;
- return Private->Ip6->Receive (Private->Ip6, &Private->RxToken);
+ Status = Private->Ip6->Receive (Private->Ip6, &Private->RxToken);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_RECEIVE), gShellNetwork2HiiHandle, Status);
+ }
+ return Status;
}
/**
@@ -615,7 +706,7 @@ Ping6OnTimerRoutine6 (
//
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);
- Time = Ping6CalculateTick (TxInfo->TimeStamp, Ping6ReadTime ());
+ Time = Ping6CalculateTick (Private, TxInfo->TimeStamp, Ping6ReadTime (Private));
//
// Remove the timeout echo request from txlist.
@@ -663,6 +754,8 @@ Ping6CreateIpInstance (
UINTN HandleIndex;
UINTN HandleNum;
EFI_HANDLE *HandleBuffer;
+ BOOLEAN UnspecifiedSrc;
+ EFI_STATUS MediaStatus;
EFI_SERVICE_BINDING_PROTOCOL *Ip6Sb;
EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
EFI_IP6_CONFIG_DATA Ip6Config;
@@ -671,10 +764,12 @@ Ping6CreateIpInstance (
EFI_IPv6_ADDRESS *Addr;
UINTN AddrIndex;
- HandleBuffer = NULL;
- Ip6Sb = NULL;
- IfInfo = NULL;
- IfInfoSize = 0;
+ HandleBuffer = NULL;
+ UnspecifiedSrc = FALSE;
+ MediaStatus = EFI_SUCCESS;
+ Ip6Sb = NULL;
+ IfInfo = NULL;
+ IfInfoSize = 0;
//
// Locate all the handles with ip6 service binding protocol.
@@ -689,17 +784,23 @@ Ping6CreateIpInstance (
if (EFI_ERROR (Status) || (HandleNum == 0)) {
return EFI_ABORTED;
}
+
+ if (NetIp6IsUnspecifiedAddr (&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 (NetIp6IsLinkLocalAddr (&Private->DstAddress) &&
- NetIp6IsUnspecifiedAddr (&Private->SrcAddress) &&
- (HandleNum > 1)) {
+ if (NetIp6IsLinkLocalAddr (&Private->DstAddress) && UnspecifiedSrc) {
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SOURCE), gShellNetwork2HiiHandle);
Status = EFI_INVALID_PARAMETER;
goto ON_ERROR;
}
+
//
// For each ip6 protocol, check interface addresses list.
//
@@ -709,6 +810,19 @@ Ping6CreateIpInstance (
IfInfo = 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],
&gEfiIp6ServiceBindingProtocolGuid,
@@ -718,80 +832,81 @@ Ping6CreateIpInstance (
goto ON_ERROR;
}
- if (NetIp6IsUnspecifiedAddr (&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],
- &gEfiIp6ConfigProtocolGuid,
- (VOID **) &Ip6Cfg
- );
+ //
+ // Ip6config protocol and ip6 service binding protocol are installed
+ // on the same handle.
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ &gEfiIp6ConfigProtocolGuid,
+ (VOID **) &Ip6Cfg
+ );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Get the interface information size.
- //
- Status = Ip6Cfg->GetData (
- Ip6Cfg,
- Ip6ConfigDataTypeInterfaceInfo,
- &IfInfoSize,
- NULL
- );
-
- if (Status != EFI_BUFFER_TOO_SMALL) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
- goto ON_ERROR;
- }
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface information size.
+ //
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
- IfInfo = AllocateZeroPool (IfInfoSize);
+ IfInfo = AllocateZeroPool (IfInfoSize);
- if (IfInfo == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_ERROR;
- }
- //
- // Get the interface info.
- //
- Status = Ip6Cfg->GetData (
- Ip6Cfg,
- Ip6ConfigDataTypeInterfaceInfo,
- &IfInfoSize,
- IfInfo
- );
+ if (IfInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface info.
+ //
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ IfInfo
+ );
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
- goto ON_ERROR;
- }
- //
- // Check whether the source address is one of the interface addresses.
- //
- for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ //
+ // Check whether the source address is one of the interface addresses.
+ //
+ for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {
+ Addr = &(IfInfo->AddressInfo[AddrIndex].Address);
- Addr = &(IfInfo->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 < IfInfo->AddressInfoCount) {
+ } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
//
- // Found a nic handle with right interface address.
+ // Match a certain interface address.
//
break;
- }
+ }
+ }
+
+ if (AddrIndex < IfInfo->AddressInfoCount) {
+ //
+ // Found a nic handle with right interface address.
+ //
+ break;
}
FreePool (IfInfo);
@@ -802,7 +917,7 @@ Ping6CreateIpInstance (
//
if (HandleIndex == HandleNum) {
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SOURCE_NOT_FOUND), gShellNetwork2HiiHandle, mIp6SrcString);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_CONFIGD_NIC_NF), gShellNetwork2HiiHandle);
Status = EFI_NOT_FOUND;
goto ON_ERROR;
}
@@ -937,7 +1052,11 @@ ShellPing6 (
ShellStatus = SHELL_SUCCESS;
Private = AllocateZeroPool (sizeof (PING6_PRIVATE_DATA));
- ASSERT (Private != NULL);
+ if (Private == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"Ping6");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
Private->ImageHandle = ImageHandle;
Private->SendNum = SendNumber;
@@ -987,6 +1106,16 @@ ShellPing6 (
ShellStatus = SHELL_ACCESS_DENIED;
goto ON_EXIT;
}
+
+ //
+ // Start a timer to calculate the RTT.
+ //
+ Status = Ping6InitRttTimer (Private);
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
//
// Create a ipv6 token to send the first icmp6 echo request packet.
//
@@ -1065,8 +1194,11 @@ ON_STAT:
STRING_TOKEN (STR_PING6_RTT),
gShellNetwork2HiiHandle,
Private->RttMin,
+ Private->RttMin + Private->TimerPeriod,
Private->RttMax,
- DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)
+ Private->RttMax + Private->TimerPeriod,
+ DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL),
+ DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL) + Private->TimerPeriod
);
}
@@ -1084,6 +1216,8 @@ ON_EXIT:
Ping6DestroyTxInfo (TxInfo);
}
+ Ping6FreeRttTimer (Private);
+
if (Private->Timer != NULL) {
gBS->CloseEvent (Private->Timer);
}
@@ -1149,7 +1283,7 @@ ShellCommandRunPing6 (
BufferSize = 16;
//
- // Parse the paramter of count number.
+ // Parse the parameter of count number.
//
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");
ValueStrPtr = ValueStr;
@@ -1166,7 +1300,7 @@ ShellCommandRunPing6 (
}
}
//
- // Parse the paramter of buffer size.
+ // Parse the parameter of buffer size.
//
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
ValueStrPtr = ValueStr;
@@ -1187,7 +1321,7 @@ ShellCommandRunPing6 (
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");
ValueStrPtr = ValueStr;
@@ -1201,7 +1335,7 @@ ShellCommandRunPing6 (
}
}
//
- // Parse the paramter of destination ip address.
+ // Parse the parameter of destination ip address.
//
NonOptionCount = ShellCommandLineGetCount(ParamPackage);
ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32)(NonOptionCount-1));
@@ -1220,15 +1354,7 @@ ShellCommandRunPing6 (
goto ON_EXIT;
}
}
- //
- // Get frequency to calculate the time from ticks.
- //
- Status = Ping6GetFrequency ();
- if (EFI_ERROR(Status)) {
- ShellStatus = SHELL_ACCESS_DENIED;
- goto ON_EXIT;
- }
//
// Enter into ping6 process.
//