[U-Boot] [PATCH]Fix checksum to handle odd-length packet

Greg Ren gren at ubicom.com
Wed Dec 2 23:23:45 CET 2009


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 at 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



More information about the U-Boot mailing list