lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] [lwip] Bug in checksum routine + patch


From: psheer
Subject: [lwip-users] [lwip] Bug in checksum routine + patch
Date: Wed, 08 Jan 2003 22:35:57 -0000

Hi there

I am compiling lwIP for the ARM and I found that the checksum
routine produced wrong results. I have taken the NetBSD
checksum routine and replaced lwIP's. This works perfectly,
although I never did discover the exact problem. This may
have just been a compiler bug or an alignment bug *shrug*.

Here is the new routine:


u16_t inet_chksum_pseudo (struct pbuf *_m, struct ip_addr *src, struct ip_addr 
*dest, u8_t
proto, u16_t proto_len)
{
    struct {
        u32_t src;
        u32_t dst;
        u16_t proto;
        u16_t len;
    } pseudo = {
        (u32_t) src->addr,
        (u32_t) dest->addr,
        (u16_t) htons ((u16_t)proto),
        (u16_t) htons ((u16_t)proto_len),
    };
    struct pbuf pseudo_header;
    struct pbuf *m;
    register u16_t *w;
    register int sum = 0;
    register int mlen = 0;
    int byte_swapped = 0;
    union {
        u8_t c[2];
        u16_t s;
    } s_util __attribute__ ((packed));
    union {
        u16_t s[2];
        u32_t l;
    } l_util __attribute__ ((packed));

    pseudo_header.next = _m;
    pseudo_header.payload = &pseudo;
    pseudo_header.len = sizeof (pseudo);

    for (m = &pseudo_header; m != NULL; m = m->next) {
        if (m->len == 0)
            continue;
        w = (u16_t *) m->payload;
        if (mlen == -1) {
            /*
             * The first byte of this mbuf is the continuation
             * of a word spanning between this mbuf and the
             * last mbuf.
             *
             * s_util.c[0] is already saved when scanning previous 
             * mbuf.
             */
            s_util.c[1] = *(u8_t *) w;
            sum += s_util.s;
            w = (u16_t *) ((u8_t *) w + 1);
            mlen = m->len - 1;
        } else
            mlen = m->len;
        /*
         * Force to even boundary.
         */
        if ((1 & (long) w) && (mlen > 0)) {
            REDUCE;
            sum <<= 8;
            s_util.c[0] = *(u8_t *) w;
            w = (u16_t *) ((u8_t *) w + 1);
            mlen--;
            byte_swapped = 1;
        }
        /*
         * Unroll the loop to make overhead from
         * branches &c small.
         */
        while ((mlen -= 32) >= 0) {
            sum += w[0];
            sum += w[1];
            sum += w[2];
            sum += w[3];
            sum += w[4];
            sum += w[5];
            sum += w[6];
            sum += w[7];
            sum += w[8];
            sum += w[9];
            sum += w[10];
            sum += w[11];
            sum += w[12];
            sum += w[13];
            sum += w[14];
            sum += w[15];
            w += 16;
        }
        mlen += 32;
        while ((mlen -= 8) >= 0) {
            sum += w[0];
            sum += w[1];
            sum += w[2];
            sum += w[3];
            w += 4;
        }
        mlen += 8;
        if (mlen == 0 && byte_swapped == 0)
            continue;
        REDUCE;
        while ((mlen -= 2) >= 0) {
            sum += *w++;
        }
        if (byte_swapped) {
            REDUCE;
            sum <<= 8;
            byte_swapped = 0;
            if (mlen == -1) {
                s_util.c[1] = *(u8_t *) w;
                sum += s_util.s;
                mlen = 0;
            } else
                mlen = -1;
        } else if (mlen == -1)
            s_util.c[0] = *(u8_t *) w;
    }
    if (mlen == -1) {
        /* The last mbuf has odd # of bytes. Follow the
           standard (the odd byte may be shifted left by 8 bits
           or not as determined by endian-ness of the machine) */
        s_util.c[1] = 0;
        sum += s_util.s;
    }
    REDUCE;

    return (u16_t) (~sum & 0xffff);
}


-paul



---------------------------------------------
This message was sent using World Mail.
http://www.worldonline.co.za


[This message was sent through the lwip discussion list.]




reply via email to

[Prev in Thread] Current Thread [Next in Thread]