From: Jiaxin Wu Date: Fri, 14 Sep 2018 07:47:52 +0000 (+0800) Subject: NetworkPkg/Mtftp6Dxe: Support windowsize in read request operation. X-Git-Tag: edk2-stable201903~956 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=f3427f12a4a53b8cc32a6816934dbcf59072c1db;p=mirror_edk2.git NetworkPkg/Mtftp6Dxe: Support windowsize in read request operation. 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 Tested-by: Laszlo Ersek Reviewed-by: Fu Siyuan Reviewed-by: Ye Ting --- 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,7 +1,7 @@ /** @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 @@ -46,6 +46,7 @@ typedef struct _MTFTP6_INSTANCE MTFTP6_INSTANCE; #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) @@ -77,6 +78,16 @@ struct _MTFTP6_INSTANCE { 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; 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,7 +1,7 @@ /** @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 @@ -17,6 +17,7 @@ CHAR8 *mMtftp6SupportedOptions[MTFTP6_SUPPORTED_OPTIONS_NUM] = { "blksize", + "windowsize", "timeout", "tsize", "multicast" @@ -146,6 +147,7 @@ Mtftp6ParseMcastOption ( @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. @@ -158,6 +160,7 @@ Mtftp6ParseExtensionOption ( IN EFI_MTFTP6_OPTION *Options, IN UINT32 Count, IN BOOLEAN IsRequest, + IN UINT16 Operation, IN MTFTP6_EXT_OPTION_INFO *ExtInfo ) { @@ -228,6 +231,23 @@ Mtftp6ParseExtensionOption ( 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. 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,7 +1,7 @@ /** @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 @@ -26,7 +26,7 @@ #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 @@ -39,11 +39,13 @@ #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; @@ -76,11 +78,12 @@ Mtftp6ParseMcastOption ( @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 @@ -88,6 +91,7 @@ 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,7 +1,7 @@ /** @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 @@ -35,6 +35,9 @@ Mtftp6RrqSendAck ( { EFI_MTFTP6_PACKET *Ack; NET_BUF *Packet; + EFI_STATUS Status; + + Status = EFI_SUCCESS; // // Allocate net buffer to create ack packet. @@ -61,7 +64,12 @@ Mtftp6RrqSendAck ( Instance->CurRetry = 0; Instance->LastPacket = Packet; - return Mtftp6TransmitPacket (Instance, Packet); + Status = Mtftp6TransmitPacket (Instance, Packet); + if (!EFI_ERROR (Status)) { + Instance->AckedBlock = Instance->TotalBlock; + } + + return Status; } @@ -94,7 +102,6 @@ Mtftp6RrqSaveBlock ( UINT16 Block; UINT64 Start; UINT32 DataLen; - UINT64 TotalBlock; BOOLEAN Completed; Completed = FALSE; @@ -118,7 +125,7 @@ Mtftp6RrqSaveBlock ( // 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; @@ -154,7 +161,7 @@ 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); // @@ -224,15 +231,16 @@ Mtftp6RrqHandleData ( 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)) { // @@ -242,8 +250,10 @@ Mtftp6RrqHandleData ( 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); @@ -288,10 +298,12 @@ Mtftp6RrqHandleData ( 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; } @@ -326,12 +338,13 @@ Mtftp6RrqOackValid ( } // - // 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; } @@ -485,7 +498,7 @@ Mtftp6RrqHandleOack ( // // 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)) { // @@ -515,7 +528,7 @@ Mtftp6RrqHandleOack ( // // 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; @@ -612,6 +625,10 @@ Mtftp6RrqHandleOack ( Instance->BlkSize = ExtInfo.BlkSize; } + if (ExtInfo.WindowSize != 0) { + Instance->WindowSize = ExtInfo.WindowSize; + } + if (ExtInfo.Timeout != 0) { Instance->Timeout = ExtInfo.Timeout; } @@ -625,6 +642,10 @@ Mtftp6RrqHandleOack ( 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 @@ -979,6 +979,10 @@ Mtftp6OperationClean ( 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; @@ -1051,6 +1055,8 @@ Mtftp6OperationStart ( Status = EFI_SUCCESS; Instance->OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + Instance->Operation = OpCode; + // // Parse the extension options in the request packet. // @@ -1060,6 +1066,7 @@ Mtftp6OperationStart ( Token->OptionList, Token->OptionCount, TRUE, + Instance->Operation, &Instance->ExtInfo ); @@ -1105,6 +1112,9 @@ Mtftp6OperationStart ( 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; } 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 @@ -318,7 +318,7 @@ Mtftp6WrqHandleOack ( } 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)) { //