[Top][All Lists]
[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.]
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lwip-users] [lwip] Bug in checksum routine + patch,
psheer <=