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

Greg Ren gren at ubicom.com
Thu Dec 3 17:18:58 CET 2009


Thanks.

It was not a clean solution as I only experimented on our processor
which is big-endian.

The fact is that the original code is not endianess proof. It was coded
for big-endian processors.

Greg Ren


-----Original Message-----
From: Joakim Tjernlund [mailto:joakim.tjernlund at transmode.se] 
Sent: Thursday, December 03, 2009 6:41 AM
To: Wolfgang Denk
Cc: Greg Ren; u-boot at lists.denx.de
Subject: Re: [U-Boot] [PATCH]Fix checksum to handle odd-length packet

Wolfgang Denk <wd at denx.de> wrote on 03/12/2009 15:08:24:

> Dear Joakim Tjernlund,
>
> In message <OFDFF8A95F.374EB267-ONC1257681.0042613C-C1257681.
> 004485DD at transmode.se> you wrote:
> >
> > > > +       if (len == 1) {
> > > > +               xsum += (*p & 0xff00);
> > >
> > > I doubt that this code is endianess-clean.
> >
> > Nope, I would think some thing like this would work better:
> >       count = len >> 1; /* div by 2 */
> >    for(p--; count; --count)
> >      xsum += *++p;
> >
> >    if (len & 1) /* Odd */
> >      xsum += *(u_char *)(++p);   /* one byte only */
>
> It probably depends on the definition of "better" ;-)
>
> Running this test code:
>
> -----------------------------------------
> #include <stdio.h>
> #include <string.h>
>
> #define LENGTH   6
>
> int main (void)
> {
>    char string[LENGTH] = { 1, 2, 3, 4, 5, 0, };
>    unsigned short array[LENGTH/2];
>    unsigned short *p;
>    unsigned short xsum, xsum1, xsum2;

ulong, not short :)

>    int i, count;
>
>    memcpy (array, string, LENGTH);
>
>    count = LENGTH / 2;
>
>    xsum = 0;
>    p = array;
>
>    while (count > 1) {
>       printf ("Adding 0x%04x\n", *p);
>       xsum += *p++;
>       --count;
>    }
    for(p--; count; --count)
      xsum += *++p;

    if (LENGTH & 1) /* Odd */
      xsum += *(unsigned char *)(++p);   /* one byte only */

>
>    xsum1 = xsum + (*p & 0xff00);
ehh, this has to go.


>
>    xsum2 = xsum + *(unsigned char *)(p);

You are not folding the sum, unsure if that has any significans

>
>    printf ("*p = 0x%04x\n", *p);
>    printf ("xsum = %04x,  xsum1 = %04x,  xsum2 = %04x\n",
>       xsum, xsum1, xsum2);
>
>    return (0);
> }
> -----------------------------------------
>
> on a little endian system gives:
>
>    -> ./f-le
>    Adding 0x0201
>    Adding 0x0403
>    *p = 0x0005
>    xsum = 0604,  xsum1 = 0604,  xsum2 = 0609
>
> while running it on a big endian system gives
>
>    -> ./f-be
>    Adding 0x0102
>    Adding 0x0304
>    *p = 0x0500
>    xsum = 0406,  xsum1 = 0906,  xsum2 = 040b
>
> I don't know what you consider to be the exact result,  but  fact  is
> that  even if we ignore byte swapping, none of the implementations is
> endianess clean.
>
> Of course, there is a chance that I mis-implemented your suggestion.
>
> Best regards,
>
> Wolfgang Denk
>
> --
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
>        There is enough for the need of everyone in this world,
>        but not for the greed of everyone.     - Mahatma Gandhi
>



More information about the U-Boot mailing list