From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 3B45081D8B for ; Tue, 8 Nov 2016 03:08:29 -0800 (PST) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP; 08 Nov 2016 03:08:31 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,609,1473145200"; d="scan'208";a="28910637" Received: from shwdeopenpsi116.ccr.corp.intel.com ([10.239.9.20]) by orsmga004.jf.intel.com with ESMTP; 08 Nov 2016 03:08:29 -0800 From: Zhang Lubo To: edk2-devel@lists.01.org Cc: Ni Ruiyu , Ye Ting , Fu Siyuan Date: Tue, 8 Nov 2016 19:08:04 +0800 Message-Id: <1478603284-27560-1-git-send-email-lubo.zhang@intel.com> X-Mailer: git-send-email 1.9.5.msysgit.1 Subject: [patch] ShellPkg: update ping6 to use timer service instead of timer arch protocol . X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Nov 2016 11:08:29 -0000 This patch update the shell ping command to use timer service to calculate the RTT time, instead of using the timer arch protocol. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Zhang Lubo Cc: Ni Ruiyu Cc: Ye Ting Cc: Fu Siyuan --- .../Library/UefiShellNetwork2CommandsLib/Ping6.c | 241 ++++++++++++++------- .../UefiShellNetwork2CommandsLib.inf | 1 + .../UefiShellNetwork2CommandsLib.uni | 4 +- 3 files changed, 170 insertions(+), 76 deletions(-) diff --git a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c index 90a2604..a30c064 100644 --- a/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c +++ b/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c @@ -17,45 +17,44 @@ #define PING6_DEFAULT_TIMEOUT 5000 #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) typedef struct _ICMP6_ECHO_REQUEST_REPLY { UINT8 Type; UINT8 Code; UINT16 Checksum; UINT16 Identifier; UINT16 SequenceNum; - UINT64 TimeStamp; + UINT32 TimeStamp; UINT8 Data[1]; } ICMP6_ECHO_REQUEST_REPLY; #pragma pack() typedef struct _PING6_ICMP6_TX_INFO { LIST_ENTRY Link; UINT16 SequenceNum; - UINT64 TimeStamp; + UINT32 TimeStamp; EFI_IP6_COMPLETION_TOKEN *Token; } PING6_ICMP6_TX_INFO; typedef struct _PING6_PRIVATE_DATA { EFI_HANDLE ImageHandle; EFI_HANDLE NicHandle; EFI_HANDLE Ip6ChildHandle; 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; UINT16 RxCount; UINT16 TxCount; @@ -97,100 +96,193 @@ SHELL_PARAM_ITEM Ping6ParamList[] = { // // Global Variables in Ping6 application. // 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; + } + + while (RttTimerTick < 10) { + gBS->Stall (STALL_1_MILLI_SECOND); + ++StallCounter; } - return mIp6CurrentTick; + 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; + } /** Destroy IPING6_ICMP6_TX_INFO, and recollect the memory. @@ -310,12 +402,11 @@ Ping6OnEchoReplyReceived6 ( PING6_PRIVATE_DATA *Private; EFI_IP6_COMPLETION_TOKEN *RxToken; EFI_IP6_RECEIVE_DATA *RxData; ICMP6_ECHO_REQUEST_REPLY *Reply; UINT32 PayLoad; - UINT64 Rtt; - CHAR8 Near; + UINT32 Rtt; Private = (PING6_PRIVATE_DATA *) Context; if (Private->Status == EFI_ABORTED) { return; @@ -350,16 +441,11 @@ Ping6OnEchoReplyReceived6 ( goto ON_EXIT; } // // 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; Private->RttMax = Private->RttMax < Rtt ? Rtt : Private->RttMax; @@ -371,12 +457,12 @@ Ping6OnEchoReplyReceived6 ( gShellNetwork2HiiHandle, PayLoad, mIp6DstString, Reply->SequenceNum, RxData->Header->HopLimit, - Near, - Rtt + Rtt, + Rtt + Private->TimerPeriod ); ON_EXIT: if (Private->RxCount < Private->SendNum) { @@ -413,11 +499,11 @@ ON_EXIT: **/ EFI_IP6_COMPLETION_TOKEN * Ping6GenerateToken ( IN PING6_PRIVATE_DATA *Private, - IN UINT64 TimeStamp, + IN UINT32 TimeStamp, IN UINT16 SequenceNum ) { EFI_STATUS Status; EFI_IP6_COMPLETION_TOKEN *Token; @@ -511,11 +597,11 @@ Ping6SendEchoRequest ( if (TxInfo == NULL) { return EFI_OUT_OF_RESOURCES; } - TxInfo->TimeStamp = Ping6ReadTime (); + TxInfo->TimeStamp = Ping6ReadTime (Private); TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1); TxInfo->Token = Ping6GenerateToken ( Private, TxInfo->TimeStamp, @@ -613,11 +699,11 @@ Ping6OnTimerRoutine6 ( // // Check whether any icmp6 echo request in the list timeout. // 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. // if (Time > PING6_DEFAULT_TIMEOUT) { @@ -1013,10 +1099,20 @@ ShellPing6 ( if (EFI_ERROR (Status)) { 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. // Status = Ping6SendEchoRequest (Private); // @@ -1091,12 +1187,15 @@ ON_STAT: -1, NULL, 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 ); } ON_EXIT: @@ -1110,10 +1209,12 @@ ON_EXIT: RemoveEntryList (&TxInfo->Link); Ping6DestroyTxInfo (TxInfo); } + Ping6FreeRttTimer (Private); + if (Private->Timer != NULL) { gBS->CloseEvent (Private->Timer); } if (Private->Ip6 != NULL) { @@ -1246,19 +1347,11 @@ ShellCommandRunPing6 ( ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), gShellNetwork2HiiHandle, ValueStr); ShellStatus = SHELL_INVALID_PARAMETER; 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. // ShellStatus = ShellPing6 ( ImageHandle, diff --git a/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf b/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf index 426efcc..8f253d2 100644 --- a/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf +++ b/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf @@ -53,10 +53,11 @@ [Pcd] gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES [Protocols] gEfiCpuArchProtocolGuid ## CONSUMES + gEfiTimerArchProtocolGuid gEfiIp6ProtocolGuid ## SOMETIMES_CONSUMES gEfiIp6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES [Guids] diff --git a/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni b/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni index 89e8e37..c3445bb 100644 --- a/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni +++ b/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni @@ -36,13 +36,13 @@ #string STR_PING6_SEND_REQUEST #language en-US "Echo request sequence %d fails.\r\n" #string STR_PING6_CONFIGD_NIC_NF #language en-US "%Ping6: No configured interfaces were found.\r\n" #string STR_PING6_NOSOURCE_INDOMAIN #language en-US "No sources in %s's multicast domain.\r\n" #string STR_PING6_START #language en-US "Ping %s %d data bytes\r\n" #string STR_PING6_TIMEOUT #language en-US "Echo request sequence %d timeout.\r\n" -#string STR_PING6_REPLY_INFO #language en-US "%d bytes from %s : icmp_seq=%d ttl=%d time%c%dms\r\n" +#string STR_PING6_REPLY_INFO #language en-US "%d bytes from %s : icmp_seq=%d ttl=%d time%d~%dms\r\n" #string STR_PING6_STAT #language en-US "\n%d packets transmitted, %d received, %d%% packet loss, time %dms\r\n" -#string STR_PING6_RTT #language en-US "\nRtt(round trip time) min=%dms max=%dms avg=%dms\r\n" +#string STR_PING6_RTT #language en-US "\nRtt(round trip time) min=%d~%dms max=%d~%dms avg=%d~%dms\r\n" #string STR_IFCONFIG6_ERR_IP6CFG_GETDATA #language en-US "Get data of the interface information %hr\r\n" #string STR_IFCONFIG6_INFO_BREAK #language en-US "-----------------------------------------------------------------" #string STR_IFCONFIG6_INFO_COLON #language en-US ":" #string STR_IFCONFIG6_INFO_JOINT #language en-US " >> " -- 1.9.5.msysgit.1