This patch is to support the tftp windowsize option that 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.
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
---
.../Universal/Network/Mtftp4Dxe/Mtftp4Impl.c | 5 ++-
.../Universal/Network/Mtftp4Dxe/Mtftp4Impl.h | 11 +++++-
.../Universal/Network/Mtftp4Dxe/Mtftp4Option.c | 12 +++++-
.../Universal/Network/Mtftp4Dxe/Mtftp4Option.h | 6 ++-
.../Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c | 44 ++++++++++++++++------
.../Universal/Network/Mtftp4Dxe/Mtftp4Support.c | 14 +++----
.../Universal/Network/Mtftp4Dxe/Mtftp4Support.h | 16 +-------
.../Universal/Network/Mtftp4Dxe/Mtftp4Wrq.c | 41 +++++++++++++++++---
8 files changed, 104 insertions(+), 45 deletions(-)
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
index a2583a4..9d4de42 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
@@ -1,10 +1,10 @@
/** @file
Interface routine for Mtftp4.
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
-Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
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<BR>
@@ -78,10 +78,12 @@ Mtftp4CleanOperation (
ZeroMem (&Instance->RequestOption, sizeof (MTFTP4_OPTION));
Instance->Operation = 0;
Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;
+ Instance->SentAckNo = 0;
+ Instance->WindowSize = 1;
Instance->LastBlock = 0;
Instance->ServerIp = 0;
Instance->ListeningPort = 0;
Instance->ConnectedPort = 0;
Instance->Gateway = 0;
@@ -438,10 +440,11 @@ Mtftp4Start (
// Set the operation parameters from the configuration or override data.
//
Config = &Instance->Config;
Instance->Token = Token;
Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;
+ Instance->WindowSize = MTFTP4_DEFAULT_WINDOWSIZE;
CopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));
Instance->ServerIp = NTOHL (Instance->ServerIp);
Instance->ListeningPort = Config->InitialServerPort;
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.h b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.h
index 527fd1d..733bc5d 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.h
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.h
@@ -6,12 +6,13 @@
RFC1350 - THE TFTP PROTOCOL (REVISION 2)
RFC2090 - TFTP Multicast Option
RFC2347 - TFTP Option Extension
RFC2348 - TFTP Blocksize Option
RFC2349 - TFTP Timeout Interval and Transfer Size Options
+ RFC7440 - TFTP Windowsize Option
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
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<BR>
@@ -54,10 +55,11 @@ typedef struct _MTFTP4_PROTOCOL MTFTP4_PROTOCOL;
#define MTFTP4_DEFAULT_SERVER_PORT 69
#define MTFTP4_DEFAULT_TIMEOUT 3
#define MTFTP4_DEFAULT_RETRY 5
#define MTFTP4_DEFAULT_BLKSIZE 512
+#define MTFTP4_DEFAULT_WINDOWSIZE 1
#define MTFTP4_TIME_TO_GETMAP 5
#define MTFTP4_STATE_UNCONFIGED 0
#define MTFTP4_STATE_CONFIGED 1
#define MTFTP4_STATE_DESTROY 2
@@ -119,10 +121,17 @@ struct _MTFTP4_PROTOCOL {
UINT16 BlkSize;
UINT16 LastBlock;
LIST_ENTRY Blocks;
//
+ // The last sent ack number.
+ //
+ UINT16 SentAckNo;
+
+ UINT16 WindowSize;
+
+ //
// The server's communication end point: IP and two ports. one for
// initial request, one for its selected port.
//
IP4_ADDR ServerIp;
UINT16 ListeningPort;
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c
index e40561a..da6aee0 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.c
@@ -1,9 +1,9 @@
/** @file
Routines to process MTFTP4 options.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
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<BR>
@@ -14,10 +14,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "Mtftp4Impl.h"
CHAR8 *mMtftp4SupportedOptions[MTFTP4_SUPPORTED_OPTIONS] = {
"blksize",
+ "windowsize",
"timeout",
"tsize",
"multicast"
};
@@ -479,10 +480,19 @@ Mtftp4ParseOption (
}
}
MtftpOption->Exist |= MTFTP4_MCAST_EXIST;
+ } else if (NetStringEqualNoCase (This->OptionStr, (UINT8 *) "windowsize")) {
+ Value = NetStringToU32 (This->ValueStr);
+
+ if (Value < 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MtftpOption->WindowSize = (UINT16) Value;
+ MtftpOption->Exist |= MTFTP4_WINDOWSIZE_EXIST;
} else if (Request) {
//
// Ignore the unsupported option if it is a reply, and return
// EFI_UNSUPPORTED if it's a request according to the UEFI spec.
//
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.h b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.h
index b7fdbf2..b86d77d 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.h
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Option.h
@@ -1,9 +1,9 @@
/** @file
Routines to process MTFTP4 options.
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
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<BR>
@@ -14,23 +14,25 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __EFI_MTFTP4_OPTION_H__
#define __EFI_MTFTP4_OPTION_H__
-#define MTFTP4_SUPPORTED_OPTIONS 4
+#define MTFTP4_SUPPORTED_OPTIONS 5
#define MTFTP4_OPCODE_LEN 2
#define MTFTP4_ERRCODE_LEN 2
#define MTFTP4_BLKNO_LEN 2
#define MTFTP4_DATA_HEAD_LEN 4
#define MTFTP4_BLKSIZE_EXIST 0x01
#define MTFTP4_TIMEOUT_EXIST 0x02
#define MTFTP4_TSIZE_EXIST 0x04
#define MTFTP4_MCAST_EXIST 0x08
+#define MTFTP4_WINDOWSIZE_EXIST 0x10
typedef struct {
UINT16 BlkSize;
+ UINT16 WindowSize;
UINT8 Timeout;
UINT32 Tsize;
IP4_ADDR McastIp;
UINT16 McastPort;
BOOLEAN Master;
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c
index e983d79..5454d6c 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Rrq.c
@@ -1,10 +1,10 @@
/** @file
Routines to process Rrq (download).
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
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<BR>
@@ -97,10 +97,13 @@ Mtftp4RrqSendAck (
IN UINT16 BlkNo
)
{
EFI_MTFTP4_PACKET *Ack;
NET_BUF *Packet;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
Packet = NetbufAlloc (sizeof (EFI_MTFTP4_ACK_HEADER));
if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES;
}
@@ -113,11 +116,16 @@ Mtftp4RrqSendAck (
ASSERT (Ack != NULL);
Ack->Ack.OpCode = HTONS (EFI_MTFTP4_OPCODE_ACK);
Ack->Ack.Block[0] = HTONS (BlkNo);
- return Mtftp4SendPacket (Instance, Packet);
+ Status = Mtftp4SendPacket (Instance, Packet);
+ if (!EFI_ERROR (Status)) {
+ Instance->SentAckNo = BlkNo;
+ }
+
+ return Status;
}
/**
Deliver the received data block to the user, which can be saved
@@ -156,11 +164,11 @@ Mtftp4RrqSaveBlock (
//
// This is the last block, save the block no
//
if (DataLen < Instance->BlkSize) {
- Completed = TRUE;
+ Completed = TRUE;
Instance->LastBlock = Block;
Mtftp4SetLastBlockNum (&Instance->Blocks, Block);
}
//
@@ -255,23 +263,23 @@ Mtftp4RrqHandleData (
EFI_STATUS Status;
UINT16 BlockNum;
INTN Expected;
*Completed = FALSE;
+ Status = EFI_SUCCESS;
BlockNum = NTOHS (Packet->Data.Block);
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
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->Master && (Expected != BlockNum)) {
- Mtftp4Retransmit (Instance);
- return EFI_SUCCESS;
+ return Mtftp4RrqSendAck (Instance, (UINT16) (Expected - 1));
}
Status = Mtftp4RrqSaveBlock (Instance, Packet, Len);
if (EFI_ERROR (Status)) {
@@ -307,14 +315,17 @@ Mtftp4RrqHandleData (
} else {
BlockNum = (UINT16) (Expected - 1);
}
- Mtftp4RrqSendAck (Instance, BlockNum);
+ if (Instance->WindowSize == (BlockNum - Instance->SentAckNo) || Expected < 0) {
+ Status = Mtftp4RrqSendAck (Instance, BlockNum);
+ }
+
}
- return EFI_SUCCESS;
+ return Status;
}
/**
Validate whether the options received in the server's OACK packet is valid.
@@ -347,14 +358,15 @@ Mtftp4RrqOackValid (
if ((Reply->Exist &~Request->Exist) != 0) {
return FALSE;
}
//
- // Server can only specify a smaller block size to be used and
+ // Server can only specify a smaller block size and window size to be used and
// return the timeout matches that requested.
//
if ((((Reply->Exist & MTFTP4_BLKSIZE_EXIST) != 0)&& (Reply->BlkSize > Request->BlkSize)) ||
+ (((Reply->Exist & MTFTP4_WINDOWSIZE_EXIST) != 0)&& (Reply->WindowSize > Request->WindowSize)) ||
(((Reply->Exist & MTFTP4_TIMEOUT_EXIST) != 0) && (Reply->Timeout != Request->Timeout))) {
return FALSE;
}
//
@@ -527,11 +539,11 @@ Mtftp4RrqHandleOack (
if ((Reply.Exist & MTFTP4_MCAST_EXIST) != 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->Master = Reply.Master;
if (Instance->McastIp == 0) {
@@ -596,10 +608,14 @@ Mtftp4RrqHandleOack (
// Update the parameters used.
//
if (Reply.BlkSize != 0) {
Instance->BlkSize = Reply.BlkSize;
}
+
+ if (Reply.WindowSize != 0) {
+ Instance->WindowSize = Reply.WindowSize;
+ }
if (Reply.Timeout != 0) {
Instance->Timeout = Reply.Timeout;
}
}
@@ -609,10 +625,14 @@ Mtftp4RrqHandleOack (
if (Reply.BlkSize != 0) {
Instance->BlkSize = Reply.BlkSize;
}
+ if (Reply.WindowSize != 0) {
+ Instance->WindowSize = Reply.WindowSize;
+ }
+
if (Reply.Timeout != 0) {
Instance->Timeout = Reply.Timeout;
}
}
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.c
index c625fda..83e6837 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.c
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.c
@@ -1,9 +1,9 @@
/** @file
Support routines for Mtftp.
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
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<BR>
@@ -218,19 +218,19 @@ Mtftp4RemoveBlockNum (
// transfers of unlimited size. There is no consensus, however, whether
// the counter should wrap around to zero or to one. Many implementations
// wrap to zero, because this is the simplest to implement. Here we choose
// this solution.
//
- *TotalBlock = Num;
-
+ *TotalBlock = Num;
+
if (Range->Round > 0) {
- *TotalBlock += Range->Bound + MultU64x32 ((UINTN) (Range->Round -1), (UINT32) (Range->Bound + 1)) + 1;
- }
+ *TotalBlock += Range->Bound + MultU64x32 ((UINTN) (Range->Round -1), (UINT32) (Range->Bound + 1)) + 1;
+ }
if (Range->Start > Range->Bound) {
- Range->Start = 0;
- Range->Round ++;
+ Range->Start = 0;
+ Range->Round ++;
}
if ((Range->Start > Range->End) || Completed) {
RemoveEntryList (&Range->Link);
FreePool (Range);
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.h b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.h
index 802e386..4b7e2b0 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.h
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Support.h
@@ -1,9 +1,9 @@
/** @file
Support routines for MTFTP.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
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<BR>
@@ -172,24 +172,10 @@ Mtftp4SendError (
IN UINT16 ErrCode,
IN UINT8 *ErrInfo
);
/**
- Retransmit the last packet for the instance.
-
- @param Instance The Mtftp instance
-
- @retval EFI_SUCCESS The last packet is retransmitted.
- @retval Others Failed to retransmit.
-
-**/
-EFI_STATUS
-Mtftp4Retransmit (
- IN MTFTP4_PROTOCOL *Instance
- );
-
-/**
The timer ticking function for the Mtftp service instance.
@param Event The ticking event
@param Context The Mtftp service instance
diff --git a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Wrq.c b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Wrq.c
index e825714..ea4de93 100644
--- a/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Wrq.c
+++ b/MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Wrq.c
@@ -1,9 +1,9 @@
/** @file
Routines to process Wrq (upload).
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
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<BR>
@@ -19,21 +19,23 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
/**
Build then send a MTFTP data packet for the MTFTP upload session.
@param Instance The MTFTP upload session.
@param BlockNum The block number to send.
+ @param Completed Return whether the upload has finished.
@retval EFI_OUT_OF_RESOURCES Failed to build the packet.
@retval EFI_ABORTED The consumer of this child directs to abort the
transmission by return an error through PacketNeeded.
@retval EFI_SUCCESS The data is sent.
**/
EFI_STATUS
Mtftp4WrqSendBlock (
IN OUT MTFTP4_PROTOCOL *Instance,
- IN UINT16 BlockNum
+ IN UINT16 BlockNum,
+ OUT BOOLEAN *Completed
)
{
EFI_MTFTP4_PACKET *Packet;
EFI_MTFTP4_TOKEN *Token;
NET_BUF *UdpPacket;
@@ -66,19 +68,23 @@ Mtftp4WrqSendBlock (
if (Token->Buffer != NULL) {
Start = MultU64x32 (BlockNum - 1, Instance->BlkSize);
if (Token->BufferSize < Start + Instance->BlkSize) {
DataLen = (UINT16) (Token->BufferSize - Start);
+ if (DataLen == 0) {
+ *Completed = TRUE;
+ return EFI_SUCCESS;
+ }
+
Instance->LastBlock = BlockNum;
Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
}
if (DataLen > 0) {
NetbufAllocSpace (UdpPacket, DataLen, FALSE);
CopyMem (Packet->Data.Data, (UINT8 *) Token->Buffer + Start, DataLen);
- }
-
+ }
} else {
//
// Get data from PacketNeeded
//
DataBuf = NULL;
@@ -101,10 +107,15 @@ Mtftp4WrqSendBlock (
);
return EFI_ABORTED;
}
+ if (DataLen == 0) {
+ *Completed = TRUE;
+ return EFI_SUCCESS;
+ }
+
if (DataLen < Instance->BlkSize) {
Instance->LastBlock = BlockNum;
Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
}
@@ -144,10 +155,15 @@ Mtftp4WrqHandleAck (
)
{
UINT16 AckNum;
INTN Expected;
UINT64 TotalBlock;
+
+ INTN Index;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
*Completed = FALSE;
AckNum = NTOHS (Packet->Ack.Block[0]);
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
@@ -191,11 +207,19 @@ Mtftp4WrqHandleAck (
return EFI_TFTP_ERROR;
}
}
- return Mtftp4WrqSendBlock (Instance, (UINT16) Expected);
+ for (Index = 0; Index < Instance->WindowSize; Index++) {
+ if (!EFI_ERROR (Status) && !(*Completed)) {
+ Status = Mtftp4WrqSendBlock (Instance, (UINT16) (Expected + Index), Completed);
+ } else {
+ break;
+ }
+ }
+
+ return Status;
}
/**
Check whether the received OACK is valid.
@@ -225,14 +249,15 @@ Mtftp4WrqOackValid (
if ((Reply->Exist & ~Request->Exist) != 0) {
return FALSE;
}
//
- // Server can only specify a smaller block size to be used and
+ // Server can only specify a smaller block size and window size to be used and
// return the timeout matches that requested.
//
if ((((Reply->Exist & MTFTP4_BLKSIZE_EXIST) != 0) && (Reply->BlkSize > Request->BlkSize)) ||
+ (((Reply->Exist & MTFTP4_WINDOWSIZE_EXIST) != 0)&& (Reply->WindowSize > Request->WindowSize)) ||
(((Reply->Exist & MTFTP4_TIMEOUT_EXIST) != 0) && (Reply->Timeout != Request->Timeout))) {
return FALSE;
}
return TRUE;
@@ -302,10 +327,14 @@ Mtftp4WrqHandleOack (
if (Reply.BlkSize != 0) {
Instance->BlkSize = Reply.BlkSize;
}
+ if (Reply.WindowSize != 0) {
+ Instance->WindowSize = Reply.WindowSize;
+ }
+
if (Reply.Timeout != 0) {
Instance->Timeout = Reply.Timeout;
}
//
--
1.9.5.msysgit.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.