[U-Boot] [PATCH/RFC] net: defragment IP packets

Alessandro Rubini rubini-list at gnudd.com
Fri Jul 24 10:04:49 CEST 2009


This patch add a quick and dirty defrag step in IP reception. This
allows to increase the TFTP block size and get more performance in
slow links (but at that point it should be made configurable).

The overhead is negligible, verified with an ARM9 CPU and 10MB data
file, changing the server MTU from 1500 to 800 and then 550.  However,
on a LAN connection, I didn't see advantes with using a 4k block
size with default MTU.

Signed-off-by: Alessandro Rubini <rubini at gnudd.com>
---

This patch is over mainline, without the (much appreciated) cleanup
patch that reached the list these days.

 net/net.c |   46 ++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/net/net.c b/net/net.c
index 641c37c..5034a2e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1117,6 +1117,46 @@ static void CDPStart(void)
 }
 #endif
 
+/* This only reassembles fragments that come in proper order */
+static inline IP_t *NetDefragment(IP_t *ip, int *lenp)
+{
+	static uchar pkt_buff[16384]; /*temporary arbitrary limit */
+	static int next_fragment;
+	static ushort pkt_id;
+
+	#define IPSZ 20
+	uchar *pkt = (uchar *)ip;
+	ushort ip_off;
+	int offset, len = *lenp -2;
+
+	ip_off = ntohs(ip->ip_off);
+	if (!(ip_off & (IP_OFFS | IP_FLAGS_MFRAG)))
+		return ip;
+
+	offset = (ip_off & IP_OFFS) * 8;
+	if (!offset) { /* new packet begins, discard any we might have */
+		pkt_id = ip->ip_id;
+		memcpy(pkt_buff, ip, len);
+		next_fragment = len;
+		return NULL;
+	}
+
+	/* further fragment: discard IP header */
+	offset += IPSZ;	len -= IPSZ; pkt += IPSZ;
+
+	if (ip->ip_id != pkt_id || offset != next_fragment)
+		return NULL; /* out of order */
+
+	/* further fragment: skip ip header (we miss offset_of...) */
+	memcpy(pkt_buff + next_fragment, pkt, len);
+	next_fragment += len;
+
+	if (ip_off & IP_FLAGS_MFRAG)
+		return NULL; /* more expected */
+
+	*lenp = next_fragment;
+	return (IP_t *)pkt_buff;
+}
 
 void
 NetReceive(volatile uchar * inpkt, int len)
@@ -1360,6 +1400,8 @@ NetReceive(volatile uchar * inpkt, int len)
 		break;
 
 	case PROT_IP:
+		if (!(ip = NetDefragment(ip, &len)))
+			return;
 #ifdef ET_DEBUG
 		puts ("Got IP\n");
 #endif
@@ -1378,10 +1420,6 @@ NetReceive(volatile uchar * inpkt, int len)
 		if ((ip->ip_hl_v & 0xf0) != 0x40) {
 			return;
 		}
-		/* Can't deal with fragments */
-		if (ip->ip_off & htons(IP_OFFS | IP_FLAGS_MFRAG)) {
-			return;
-		}
 		/* can't deal with headers > 20 bytes */
 		if ((ip->ip_hl_v & 0x0f) > 0x05) {
 			return;
-- 
1.6.0.2


More information about the U-Boot mailing list