
Hi all:
I am new to u-boot and got assignment to debug some networking issue. I traced the checksum failure and was able to fix it with the patch below.
This change fixes: 1. The checksum generation failure for odd-length packet. 2. Do not ignore the LSB of checksum value - (Again, I am new to this. Maybe someone can educate me about the idea of ignoring one bit of checksum)
The patch is a git commit log from my local git reposite.
Thanks for your time and advice.
% git show cffd5fb03e0c3f116cce9f3ff825c5445a1eca3f commit cffd5fb03e0c3f116cce9f3ff825c5445a1eca3f Author: gren gren@ubicom.com Date: Wed Dec 2 13:07:53 2009 -0800
Fix issue with checksum failure of odd-length packets
diff --git a/net/net.c b/net/net.c old mode 100644 new mode 100755 index 5637cf5..5bbee04 --- a/net/net.c +++ b/net/net.c @@ -703,14 +703,14 @@ int PingSend(void) ip->ip_sum = 0; NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */ NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */ - ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); + ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP);
s = &ip->udp_src; /* XXX ICMP starts here */ s[0] = htons(0x0800); /* echo-request, code */ s[1] = 0; /* checksum */ s[2] = 0; /* identifier */ s[3] = htons(PingSeqNo++); /* sequence number */ - s[1] = ~NetCksum((uchar *)s, 8/2); + s[1] = ~NetCksum((uchar *)s, 8);
/* size of the waiting packet */ NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8; @@ -1363,7 +1363,7 @@ NetReceive(volatile uchar * inpkt, int len) if ((ip->ip_hl_v & 0x0f) > 0x05) { return; } - if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) { + if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP)) { puts ("checksum bad\n"); return; } @@ -1420,12 +1420,12 @@ NetReceive(volatile uchar * inpkt, int len) ip->ip_off = 0; NetCopyIP((void*)&ip->ip_dst, &ip->ip_src); NetCopyIP((void*)&ip->ip_src, &NetOurIP); - ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP >> 1); + ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP);
icmph->type = ICMP_ECHO_REPLY; icmph->checksum = 0; icmph->checksum = ~NetCksum((uchar *)icmph, - (len - IP_HDR_SIZE_NO_UDP) >> 1); + (len - IP_HDR_SIZE_NO_UDP)); (void) eth_send((uchar *)et, ETHER_HDR_SIZE + len); return; #endif @@ -1577,7 +1577,7 @@ static int net_check_prereq (proto_t protocol) int NetCksumOk(uchar * ptr, int len) { - return !((NetCksum(ptr, len) + 1) & 0xfffe); + return (NetCksum(ptr, len) == 0xffff); }
@@ -1588,8 +1588,13 @@ NetCksum(uchar * ptr, int len) ushort *p = (ushort *)ptr;
xsum = 0; - while (len-- > 0) + while (len > 1) { xsum += *p++; + len -= 2; + } + if (len == 1) { + xsum += (*p & 0xff00); + } xsum = (xsum & 0xffff) + (xsum >> 16); xsum = (xsum & 0xffff) + (xsum >> 16); return (xsum & 0xffff); @@ -1663,7 +1668,7 @@ NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len) ip->udp_dst = htons(dport); ip->udp_len = htons(8 + len); ip->udp_xsum = 0; - ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); + ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP); }
void copy_filename (char *dst, char *src, int size)
Regards
Greg Ren SW Engineer Phone: (408)649-2703 195 Baypointe Pkwy. San Jose CA 95134