From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=134.134.136.126; helo=mga18.intel.com; envelope-from=jiaxin.wu@intel.com; receiver=edk2-devel@lists.01.org Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) (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 09B4521138AA2 for ; Sun, 16 Sep 2018 22:43:55 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Sep 2018 22:43:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,384,1531810800"; d="scan'208";a="263181518" Received: from jiaxinwu-mobl.ccr.corp.intel.com ([10.239.192.143]) by fmsmga005.fm.intel.com with ESMTP; 16 Sep 2018 22:43:53 -0700 From: Jiaxin Wu To: edk2-devel@lists.01.org Cc: Ye Ting , Fu Siyuan , Shao Ming , Wu Jiaxin Date: Mon, 17 Sep 2018 13:43:45 +0800 Message-Id: <20180917054348.19228-3-Jiaxin.wu@intel.com> X-Mailer: git-send-email 2.17.1.windows.2 In-Reply-To: <20180917054348.19228-1-Jiaxin.wu@intel.com> References: <20180917054348.19228-1-Jiaxin.wu@intel.com> Subject: [Patch 2/5] NetworkPkg/Mtftp6Dxe: Support windowsize in read request operation. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 17 Sep 2018 05:43:55 -0000 Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=886 This patch is to support the TFTP windowsize option described in RFC 7440. The feature allows the client and server to negotiate a window size of consecutive blocks to send as an alternative for replacing the single-block lockstep schema. Currently, the windowsize for write request operation is not supported since there is no real use cases. Cc: Ye Ting Cc: Fu Siyuan Cc: Shao Ming Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Wu Jiaxin --- NetworkPkg/Mtftp6Dxe/Mtftp6Impl.h | 13 ++++++- NetworkPkg/Mtftp6Dxe/Mtftp6Option.c | 22 +++++++++++- NetworkPkg/Mtftp6Dxe/Mtftp6Option.h | 14 +++++--- NetworkPkg/Mtftp6Dxe/Mtftp6Rrq.c | 53 +++++++++++++++++++--------- NetworkPkg/Mtftp6Dxe/Mtftp6Support.c | 10 ++++++ NetworkPkg/Mtftp6Dxe/Mtftp6Wrq.c | 2 +- 6 files changed, 90 insertions(+), 24 deletions(-) diff --git a/NetworkPkg/Mtftp6Dxe/Mtftp6Impl.h b/NetworkPkg/Mtftp6Dxe/Mtftp6Impl.h index 6b1ce7f853..cf1b6abacc 100644 --- a/NetworkPkg/Mtftp6Dxe/Mtftp6Impl.h +++ b/NetworkPkg/Mtftp6Dxe/Mtftp6Impl.h @@ -1,9 +1,9 @@ /** @file Mtftp6 internal data structure and definition declaration. - Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2018, 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 which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php. @@ -44,10 +44,11 @@ typedef struct _MTFTP6_INSTANCE MTFTP6_INSTANCE; #define MTFTP6_DEFAULT_SERVER_CMD_PORT 69 #define MTFTP6_DEFAULT_TIMEOUT 3 #define MTFTP6_GET_MAPPING_TIMEOUT 3 #define MTFTP6_DEFAULT_MAX_RETRY 5 #define MTFTP6_DEFAULT_BLK_SIZE 512 +#define MTFTP6_DEFAULT_WINDOWSIZE 1 #define MTFTP6_TICK_PER_SECOND 10000000U #define MTFTP6_SERVICE_FROM_THIS(a) CR (a, MTFTP6_SERVICE, ServiceBinding, MTFTP6_SERVICE_SIGNATURE) #define MTFTP6_INSTANCE_FROM_THIS(a) CR (a, MTFTP6_INSTANCE, Mtftp6, MTFTP6_INSTANCE_SIGNATURE) @@ -75,10 +76,20 @@ struct _MTFTP6_INSTANCE { UINT16 BlkSize; UINT16 LastBlk; LIST_ENTRY BlkList; + UINT16 Operation; + + UINT16 WindowSize; + + // + // Record the total received block number and the already acked block number. + // + UINT64 TotalBlock; + UINT64 AckedBlock; + EFI_IPv6_ADDRESS ServerIp; UINT16 ServerCmdPort; UINT16 ServerDataPort; UDP_IO *UdpIo; diff --git a/NetworkPkg/Mtftp6Dxe/Mtftp6Option.c b/NetworkPkg/Mtftp6Dxe/Mtftp6Option.c index 0dcf546fa8..94790e3ad6 100644 --- a/NetworkPkg/Mtftp6Dxe/Mtftp6Option.c +++ b/NetworkPkg/Mtftp6Dxe/Mtftp6Option.c @@ -1,9 +1,9 @@ /** @file Mtftp6 option parse functions implementation. - Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2018, 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 which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php. @@ -15,10 +15,11 @@ #include "Mtftp6Impl.h" CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = { "blksize", + "windowsize", "timeout", "tsize", "multicast" }; @@ -144,10 +145,11 @@ Mtftp6ParseMcastOption ( @param[in] Options The pointer to the extension options list. @param[in] Count The num of the extension options. @param[in] IsRequest If FALSE, the extension options is included by a request packet. + @param[in] Operation The current performed operation. @param[in] ExtInfo The pointer to the option information to be filled. @retval EFI_SUCCESS Parse the multicast option successfully. @retval EFI_INVALID_PARAMETER There is one option is malformatted at least. @retval EFI_UNSUPPORTED There is one option is not supported at least. @@ -156,10 +158,11 @@ Mtftp6ParseMcastOption ( EFI_STATUS Mtftp6ParseExtensionOption ( IN EFI_MTFTP6_OPTION *Options, IN UINT32 Count, IN BOOLEAN IsRequest, + IN UINT16 Operation, IN MTFTP6_EXT_OPTION_INFO *ExtInfo ) { EFI_STATUS Status; EFI_MTFTP6_OPTION *Opt; @@ -226,10 +229,27 @@ Mtftp6ParseExtensionOption ( return EFI_INVALID_PARAMETER; } ExtInfo->BitMap |= MTFTP6_OPT_MCAST_BIT; + } else if (AsciiStriCmp ((CHAR8 *) Opt->OptionStr, "windowsize") == 0) { + if (Operation == EFI_MTFTP6_OPCODE_WRQ) { + // + // Currently, windowsize is not supported in the write operation. + // + return EFI_UNSUPPORTED; + } + + Value = (UINT32) AsciiStrDecimalToUintn ((CHAR8 *) Opt->ValueStr); + + if ((Value < 1)) { + return EFI_INVALID_PARAMETER; + } + + ExtInfo->WindowSize = (UINT16) Value; + ExtInfo->BitMap |= MTFTP6_OPT_WINDOWSIZE_BIT; + } else if (IsRequest) { // // If it's a request, unsupported; else if it's a reply, ignore. // return EFI_UNSUPPORTED; diff --git a/NetworkPkg/Mtftp6Dxe/Mtftp6Option.h b/NetworkPkg/Mtftp6Dxe/Mtftp6Option.h index 8e2671fa21..08aa45ff63 100644 --- a/NetworkPkg/Mtftp6Dxe/Mtftp6Option.h +++ b/NetworkPkg/Mtftp6Dxe/Mtftp6Option.h @@ -1,9 +1,9 @@ /** @file Mtftp6 option parse functions declaration. - Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2018, 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 which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php. @@ -24,11 +24,11 @@ #include #include #include #include -#define MTFTP6_SUPPORTED_OPTIONS_NUM 4 +#define MTFTP6_SUPPORTED_OPTIONS_NUM 5 #define MTFTP6_OPCODE_LEN 2 #define MTFTP6_ERRCODE_LEN 2 #define MTFTP6_BLKNO_LEN 2 #define MTFTP6_DATA_HEAD_LEN 4 @@ -37,15 +37,17 @@ // #define MTFTP6_OPT_BLKSIZE_BIT 0x01 #define MTFTP6_OPT_TIMEOUT_BIT 0x02 #define MTFTP6_OPT_TSIZE_BIT 0x04 #define MTFTP6_OPT_MCAST_BIT 0x08 +#define MTFTP6_OPT_WINDOWSIZE_BIT 0X10 extern CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM]; typedef struct { UINT16 BlkSize; + UINT16 WindowSize; UINT8 Timeout; UINT32 Tsize; EFI_IPv6_ADDRESS McastIp; UINT16 McastPort; BOOLEAN IsMaster; @@ -74,22 +76,24 @@ Mtftp6ParseMcastOption ( @param[in] Options The pointer to the extension options list. @param[in] Count The num of the extension options. @param[in] IsRequest If FALSE, the extension options is included by a request packet. + @param[in] Operation The current performed operation. @param[in] ExtInfo The pointer to the option information to be filled. - @retval EFI_SUCCESS Parse the multi-cast option successfully. - @retval EFI_INVALID_PARAMETER An option is malformatted. - @retval EFI_UNSUPPORTED An option is not supported. + @retval EFI_SUCCESS Parse the multicast option successfully. + @retval EFI_INVALID_PARAMETER There is one option is malformatted at least. + @retval EFI_UNSUPPORTED There is one option is not supported at least. **/ EFI_STATUS Mtftp6ParseExtensionOption ( IN EFI_MTFTP6_OPTION *Options, IN UINT32 Count, IN BOOLEAN IsRequest, + IN UINT16 Operation, IN MTFTP6_EXT_OPTION_INFO *ExtInfo ); /** diff --git a/NetworkPkg/Mtftp6Dxe/Mtftp6Rrq.c b/NetworkPkg/Mtftp6Dxe/Mtftp6Rrq.c index 2aadef076c..1f685b2bfe 100644 --- a/NetworkPkg/Mtftp6Dxe/Mtftp6Rrq.c +++ b/NetworkPkg/Mtftp6Dxe/Mtftp6Rrq.c @@ -1,9 +1,9 @@ /** @file Mtftp6 Rrq process functions implementation. - Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2018, 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 which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php. @@ -33,10 +33,13 @@ Mtftp6RrqSendAck ( IN UINT16 BlockNum ) { EFI_MTFTP6_PACKET *Ack; NET_BUF *Packet; + EFI_STATUS Status; + + Status = EFI_SUCCESS; // // Allocate net buffer to create ack packet. // Packet = NetbufAlloc (sizeof (EFI_MTFTP6_ACK_HEADER)); @@ -59,11 +62,16 @@ Mtftp6RrqSendAck ( // Reset current retry count of the instance. // Instance->CurRetry = 0; Instance->LastPacket = Packet; - return Mtftp6TransmitPacket (Instance, Packet); + Status = Mtftp6TransmitPacket (Instance, Packet); + if (!EFI_ERROR (Status)) { + Instance->AckedBlock = Instance->TotalBlock; + } + + return Status; } /** Deliver the received data block to the user, which can be saved @@ -92,11 +100,10 @@ Mtftp6RrqSaveBlock ( EFI_MTFTP6_TOKEN *Token; EFI_STATUS Status; UINT16 Block; UINT64 Start; UINT32 DataLen; - UINT64 TotalBlock; BOOLEAN Completed; Completed = FALSE; Token = Instance->Token; Block = NTOHS (Packet->Data.Block); @@ -116,11 +123,11 @@ Mtftp6RrqSaveBlock ( // returns EFI_NOT_FOUND, the block has been saved, don't save it again. // Note that : For bigger files, allowing the block counter to roll over // to accept transfers of unlimited size. So TotalBlock is memorised as // continuous block counter. // - Status = Mtftp6RemoveBlockNum (&Instance->BlkList, Block, Completed, &TotalBlock); + Status = Mtftp6RemoveBlockNum (&Instance->BlkList, Block, Completed, &Instance->TotalBlock); if (Status == EFI_NOT_FOUND) { return EFI_SUCCESS; } else if (EFI_ERROR (Status)) { return Status; @@ -152,11 +159,11 @@ Mtftp6RrqSaveBlock ( } } if (Token->Buffer != NULL) { - Start = MultU64x32 (TotalBlock - 1, Instance->BlkSize); + Start = MultU64x32 (Instance->TotalBlock - 1, Instance->BlkSize); if (Start + DataLen <= Token->BufferSize) { CopyMem ((UINT8 *) Token->Buffer + Start, Packet->Data.Data, DataLen); // // Update the file size when received the last block // @@ -222,30 +229,33 @@ Mtftp6RrqHandleData ( EFI_STATUS Status; UINT16 BlockNum; INTN Expected; *IsCompleted = FALSE; + Status = EFI_SUCCESS; BlockNum = NTOHS (Packet->Data.Block); Expected = Mtftp6GetNextBlockNum (&Instance->BlkList); ASSERT (Expected >= 0); // - // If we are active and received an unexpected packet, retransmit - // the last ACK then restart receiving. If we are passive, save - // the block. + // If we are active and received an unexpected packet, transmit + // the ACK for the block we received, then restart receiving the + // expected one. If we are passive, save the block. // if (Instance->IsMaster && (Expected != BlockNum)) { // // Free the received packet before send new packet in ReceiveNotify, // since the udpio might need to be reconfigured. // NetbufFree (*UdpPacket); *UdpPacket = NULL; - Mtftp6TransmitPacket (Instance, Instance->LastPacket); - return EFI_SUCCESS; + // + // If Expected is 0, (UINT16) (Expected - 1) is also the expected Ack number (65535). + // + return Mtftp6RrqSendAck (Instance, (UINT16) (Expected - 1)); } Status = Mtftp6RrqSaveBlock (Instance, Packet, Len, UdpPacket); if (EFI_ERROR (Status)) { @@ -286,14 +296,16 @@ Mtftp6RrqHandleData ( // since the udpio might need to be reconfigured. // NetbufFree (*UdpPacket); *UdpPacket = NULL; - Mtftp6RrqSendAck (Instance, BlockNum); + if (Instance->WindowSize == (Instance->TotalBlock - Instance->AckedBlock) || Expected < 0) { + Status = Mtftp6RrqSendAck (Instance, BlockNum); + } } - return EFI_SUCCESS; + return Status; } /** Validate whether the options received in the server's OACK packet is valid. @@ -324,16 +336,17 @@ Mtftp6RrqOackValid ( if ((ReplyInfo->BitMap & ~RequestInfo->BitMap) != 0) { return FALSE; } // - // Server can only specify a smaller block size to be used and + // Server can only specify a smaller block size and windowsize to be used and // return the timeout matches that requested. // if ((((ReplyInfo->BitMap & MTFTP6_OPT_BLKSIZE_BIT) != 0) && (ReplyInfo->BlkSize > RequestInfo->BlkSize)) || + (((ReplyInfo->BitMap & MTFTP6_OPT_WINDOWSIZE_BIT) != 0) && (ReplyInfo->BlkSize > RequestInfo->BlkSize)) || (((ReplyInfo->BitMap & MTFTP6_OPT_TIMEOUT_BIT) != 0) && (ReplyInfo->Timeout != RequestInfo->Timeout)) - ) { + ) { return FALSE; } // // The server can send ",,master" to client to change its master @@ -483,11 +496,11 @@ Mtftp6RrqHandleOack ( ASSERT (Options != NULL); // // Parse the extensive options in the packet. // - Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, &ExtInfo); + Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, Instance->Operation, &ExtInfo); if (EFI_ERROR (Status) || !Mtftp6RrqOackValid (Instance, &ExtInfo, &Instance->ExtInfo)) { // // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES. // @@ -513,11 +526,11 @@ Mtftp6RrqHandleOack ( if ((ExtInfo.BitMap & MTFTP6_OPT_MCAST_BIT) != 0) { // // Save the multicast info. Always update the Master, only update the - // multicast IP address, block size, timeoute at the first time. If IP + // multicast IP address, block size, window size, timeoute at the first time. If IP // address is updated, create a UDP child to receive the multicast. // Instance->IsMaster = ExtInfo.IsMaster; if (NetIp6IsUnspecifiedAddr (&Instance->McastIp)) { @@ -610,10 +623,14 @@ Mtftp6RrqHandleOack ( // if (ExtInfo.BlkSize != 0) { Instance->BlkSize = ExtInfo.BlkSize; } + if (ExtInfo.WindowSize != 0) { + Instance->WindowSize = ExtInfo.WindowSize; + } + if (ExtInfo.Timeout != 0) { Instance->Timeout = ExtInfo.Timeout; } } @@ -623,10 +640,14 @@ Mtftp6RrqHandleOack ( if (ExtInfo.BlkSize != 0) { Instance->BlkSize = ExtInfo.BlkSize; } + if (ExtInfo.WindowSize != 0) { + Instance->WindowSize = ExtInfo.WindowSize; + } + if (ExtInfo.Timeout != 0) { Instance->Timeout = ExtInfo.Timeout; } } diff --git a/NetworkPkg/Mtftp6Dxe/Mtftp6Support.c b/NetworkPkg/Mtftp6Dxe/Mtftp6Support.c index 282a9c8e49..275272b89e 100644 --- a/NetworkPkg/Mtftp6Dxe/Mtftp6Support.c +++ b/NetworkPkg/Mtftp6Dxe/Mtftp6Support.c @@ -977,10 +977,14 @@ Mtftp6OperationClean ( Instance->ServerCmdPort = 0; Instance->ServerDataPort = 0; Instance->McastPort = 0; Instance->BlkSize = 0; + Instance->Operation = 0; + Instance->WindowSize = 1; + Instance->TotalBlock = 0; + Instance->AckedBlock = 0; Instance->LastBlk = 0; Instance->PacketToLive = 0; Instance->MaxRetry = 0; Instance->CurRetry = 0; Instance->Timeout = 0; @@ -1049,19 +1053,22 @@ Mtftp6OperationStart ( } Status = EFI_SUCCESS; Instance->OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + Instance->Operation = OpCode; + // // Parse the extension options in the request packet. // if (Token->OptionCount != 0) { Status = Mtftp6ParseExtensionOption ( Token->OptionList, Token->OptionCount, TRUE, + Instance->Operation, &Instance->ExtInfo ); if (EFI_ERROR (Status)) { goto ON_ERROR; @@ -1103,10 +1110,13 @@ Mtftp6OperationStart ( Instance->ServerCmdPort = MTFTP6_DEFAULT_SERVER_CMD_PORT; } if (Instance->BlkSize == 0) { Instance->BlkSize = MTFTP6_DEFAULT_BLK_SIZE; } + if (Instance->WindowSize == 0) { + Instance->WindowSize = MTFTP6_DEFAULT_WINDOWSIZE; + } if (Instance->MaxRetry == 0) { Instance->MaxRetry = MTFTP6_DEFAULT_MAX_RETRY; } if (Instance->Timeout == 0) { Instance->Timeout = MTFTP6_DEFAULT_TIMEOUT; diff --git a/NetworkPkg/Mtftp6Dxe/Mtftp6Wrq.c b/NetworkPkg/Mtftp6Dxe/Mtftp6Wrq.c index 254b757f7e..055fbe6d1b 100644 --- a/NetworkPkg/Mtftp6Dxe/Mtftp6Wrq.c +++ b/NetworkPkg/Mtftp6Dxe/Mtftp6Wrq.c @@ -316,11 +316,11 @@ Mtftp6WrqHandleOack ( if (EFI_ERROR (Status)) { return Status; } ASSERT (Options != NULL); - Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, &ExtInfo); + Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, Instance->Operation, &ExtInfo); if (EFI_ERROR(Status) || !Mtftp6WrqOackValid (&ExtInfo, &Instance->ExtInfo)) { // // Don't send a MTFTP error packet when out of resource, it can // only make it worse. -- 2.17.1.windows.2