
Josh & Frank,
Sorry again for dropping the ball on this one. This is a useful feature that we should add to U-boot, but I'm concerned about the memory footprint.
Josh Boyer wrote:
From: Frank Haverkamp haver@vnet.ibm.com
http://tools.ietf.org/html/rfc2348 describes the TFTP block size option which allows larger packtes than the 512 byte default. This reduces the number of TFTP ACKs significantly and improves performance.
To get the most benefit out of the tftp block size option the support of defragementation of IP/UDP packet is helpful. The current implemenation should work even with packets received out of order. To enable the large packet size the user should set "tftp_block_size" so a value like 16352.
We experimented with different packet sizes and found that more than those 16KiB do not contribute much to the performance anymore. Therefor I limited the defragmentation buffer to 16KiB no too waste memory.
Signed-off-by: Frank Haverkamp haver@vnet.ibm.com Signed-off-by: Josh Boyer jwboyer@linux.vnet.ibm.com
include/net.h | 17 ++++++ net/net.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- net/tftp.c | 22 ++++++++ net/tftp.h | 10 +++ 4 files changed, 185 insertions(+), 20 deletions(-)
--- u-boot.git.orig/include/net.h +++ u-boot.git/include/net.h @@ -200,6 +200,13 @@ typedef struct { ushort udp_xsum; /* Checksum */ } IP_t;
+#define IP_OFFS 0x1FFF /* ip offset *= 8 */ +#define IP_OFFS_SHIFT 3 /* in 8 byte steps */ +#define IP_FLAGS 0xE000 /* first 3 bits */ +#define IP_FLAGS_RES 0x8000 /* reserved */ +#define IP_FLAGS_DFRAG 0x4000 /* don't fragments */ +#define IP_FLAGS_MFRAG 0x2000 /* more fragments */
#define IP_HDR_SIZE_NO_UDP (sizeof (IP_t) - 8) #define IP_HDR_SIZE (sizeof (IP_t))
@@ -282,6 +289,16 @@ typedef struct icmphdr { #define PKTSIZE_ALIGN 1536 /*#define PKTSIZE 608*/
- /*
- IP/UDP Fragmentation support
- MAX possible UDP packet size is 64 KiB, if there is memory available.
- */
+#define NET_ETH_MTU 1500 +#define NET_FRAG_BUF_SIZE (16 * 1024) /* MAX is 64 KiB */ +#define NET_UDP_FRAG_SIZE (NET_ETH_MTU - IP_HDR_SIZE_NO_UDP) /* 1480 */ +#define NET_FRAG_BUF_USED (NET_FRAG_BUF_SIZE / NET_UDP_FRAG_SIZE + 1)
/*
- Maximum receive ring size; that is, the number of packets
- we can buffer before overflow happens. Basically, this just
--- u-boot.git.orig/net/net.c +++ u-boot.git/net/net.c @@ -192,6 +192,15 @@ volatile uchar PktBuf[(PKTBUFSRX+1) * PK
volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */
+/* Packet fragmentation support */ +static uint16_t ip_id = 0; /* sequence number */ +static uint16_t udp_len = 0; +static uint16_t udp_src = 0; +static uint16_t udp_dst = 0; +static int max_idx = 0; +static uchar NetFragBuf[NET_FRAG_BUF_SIZE];
Allocating a 16k buffer should be optional. Please consider wrapping this feature in a CONFIG.
+static char NetFragBufUsed[NET_FRAG_BUF_USED] = { 0, };
static rxhand_f *packetHandler; /* Current RX packet handler */ static thand_f *timeHandler; /* Current timeout handler */ static ulong timeStart; /* Time base value */ @@ -288,6 +297,13 @@ NetLoop(proto_t protocol) { bd_t *bd = gd->bd;
- /* Packet fragmentation support */
- ip_id = udp_len = udp_src = udp_dst = max_idx = 0;
- memset(NetFragBuf, 0xFF, sizeof(NetFragBuf));
- memset(NetFragBufUsed, 0, sizeof(NetFragBufUsed));
- printf("NetFragBuf @ %08x max tftp_block_size=%d udp_frag_size=%d\n",
NetFragBuf, TFTP_BLOCK_SIZE_MAX, NET_UDP_FRAG_SIZE);
I get a compiler warning here that a simple cast should fix: net.c: In function 'NetLoop': net.c:300: warning: format '%08x' expects type 'unsigned int', but argument 2 has type 'uchar *'
regards, Ben