Module Name: src
Committed By: tsutsui
Date: Sat Sep 18 16:43:51 UTC 2010
Modified Files:
src/sys/arch/mips/mips: in_cksum.c
Log Message:
Fix wrong checksum calculations of 32 bit unaligned two byte payloads.
Analyzed in PR port-mips/43882, but applied slightly different patch.
Also put some changes for readability.
Note netbsd-5 doesn't use this MD version but netbsd-4 needs a pullup.
(though it's unclear if it's really faster even on modern aggressive gcc4)
To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/mips/mips/in_cksum.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/mips/mips/in_cksum.c
diff -u src/sys/arch/mips/mips/in_cksum.c:1.13 src/sys/arch/mips/mips/in_cksum.c:1.14
--- src/sys/arch/mips/mips/in_cksum.c:1.13 Wed Jan 24 13:08:11 2007
+++ src/sys/arch/mips/mips/in_cksum.c Sat Sep 18 16:43:50 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: in_cksum.c,v 1.13 2007/01/24 13:08:11 hubertf Exp $ */
+/* $NetBSD: in_cksum.c,v 1.14 2010/09/18 16:43:50 tsutsui Exp $ */
/*
* Copyright (c) 1993 Regents of the University of California.
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in_cksum.c,v 1.13 2007/01/24 13:08:11 hubertf Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in_cksum.c,v 1.14 2010/09/18 16:43:50 tsutsui Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -56,11 +56,10 @@
#include <machine/endian.h>
union memptr {
- unsigned int *i;
- unsigned long *l;
- unsigned long u;
- unsigned short *s;
- unsigned char *c;
+ uint32_t *l;
+ uintptr_t u;
+ uint16_t *s;
+ uint8_t *c;
};
static inline uint32_t fastsum(union memptr, int, unsigned int, int);
@@ -83,10 +82,6 @@
/* Align to 32 bits. */
if (buf.u & 0x3) {
- /* Skip to the end for very small mbufs */
- if (n < 3)
- goto verylittleleft;
-
/*
* 16-bit-align.
* If buf is odd-byte-aligned, add the byte and toggle
@@ -107,6 +102,9 @@
n -= 1;
odd_aligned = !odd_aligned;
}
+ /* Skip to the end for very small mbufs */
+ if (n <= 2)
+ goto postunaligned;
/* 32-bit-align */
if (buf.u & 0x2) {
@@ -198,7 +196,7 @@
notmuchleft:
high = hilo = 0;
- while (n >= 4) {
+ while (n >= sizeof(uint32_t)) {
w0 = *(buf.l++);
hilo += w0;
high += w0 >> 16;
@@ -208,19 +206,21 @@
sum += hilo;
sum += high;
- while (n > 1) {
- n -= sizeof(*buf.s);
+ postunaligned:
+ /* handle post 32bit unaligned payloads */
+ if (n >= sizeof(uint16_t)) {
sum += *(buf.s++);
+ n -= sizeof(uint16_t);
}
- verylittleleft:
- /* handle trailing byte and short (possibly) unaligned payloads */
- while (n-- > 0) {
+ /* handle a trailing odd byte */
+ if (n > 0) {
#if BYTE_ORDER == BIG_ENDIAN
sum += *(buf.c++) << 8;
#else
sum += *(buf.c++);
#endif
+ n = 0;
}
/*