Mon Mar 16 12:02:00 2009 UTC ()
Fix a bug in calculation of checksum deduction:
- To get 16 bit one's complement value from uint32_t variable,
  higher 16 bits should be ignored.
- RFC 1624 describes methods to recalculate checksum field in headers,
  i.e. one's complement of one's complement sum that could be 0x0000,
  but we don't have to use the strategy to deduct one's complement sum
  itself which won't be zero but should be 0xffff.

Found on debugging mec(4) on sgimips O2.


(tsutsui)
diff -r1.82 -r1.83 src/sys/dev/ic/gem.c
diff -r1.72 -r1.73 src/sys/dev/ic/hme.c

cvs diff -r1.82 -r1.83 src/sys/dev/ic/gem.c (expand / switch to unified diff)

--- src/sys/dev/ic/gem.c 2009/03/14 21:04:19 1.82
+++ src/sys/dev/ic/gem.c 2009/03/16 12:02:00 1.83
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gem.c,v 1.82 2009/03/14 21:04:19 dsl Exp $ */ 1/* $NetBSD: gem.c,v 1.83 2009/03/16 12:02:00 tsutsui Exp $ */
2 2
3/* 3/*
4 * 4 *
5 * Copyright (C) 2001 Eduardo Horvath. 5 * Copyright (C) 2001 Eduardo Horvath.
6 * Copyright (c) 2001-2003 Thomas Moestl 6 * Copyright (c) 2001-2003 Thomas Moestl
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 * 30 *
31 */ 31 */
32 32
33/* 33/*
34 * Driver for Apple GMAC, Sun ERI and Sun GEM Ethernet controllers 34 * Driver for Apple GMAC, Sun ERI and Sun GEM Ethernet controllers
35 * See `GEM Gigabit Ethernet ASIC Specification' 35 * See `GEM Gigabit Ethernet ASIC Specification'
36 * http://www.sun.com/processors/manuals/ge.pdf 36 * http://www.sun.com/processors/manuals/ge.pdf
37 */ 37 */
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.82 2009/03/14 21:04:19 dsl Exp $"); 40__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.83 2009/03/16 12:02:00 tsutsui Exp $");
41 41
42#include "opt_inet.h" 42#include "opt_inet.h"
43#include "bpfilter.h" 43#include "bpfilter.h"
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/systm.h> 46#include <sys/systm.h>
47#include <sys/callout.h> 47#include <sys/callout.h>
48#include <sys/mbuf.h> 48#include <sys/mbuf.h>
49#include <sys/syslog.h> 49#include <sys/syslog.h>
50#include <sys/malloc.h> 50#include <sys/malloc.h>
51#include <sys/kernel.h> 51#include <sys/kernel.h>
52#include <sys/socket.h> 52#include <sys/socket.h>
53#include <sys/ioctl.h> 53#include <sys/ioctl.h>
@@ -1834,29 +1834,28 @@ gem_rint(struct gem_softc *sc) @@ -1834,29 +1834,28 @@ gem_rint(struct gem_softc *sc)
1834 optsum = 0; 1834 optsum = 0;
1835 temp = hlen - sizeof(struct ip); 1835 temp = hlen - sizeof(struct ip);
1836 opts = (uint16_t *) ((char *) ip + 1836 opts = (uint16_t *) ((char *) ip +
1837 sizeof(struct ip)); 1837 sizeof(struct ip));
1838 1838
1839 while (temp > 1) { 1839 while (temp > 1) {
1840 optsum += ntohs(*opts++); 1840 optsum += ntohs(*opts++);
1841 temp -= 2; 1841 temp -= 2;
1842 } 1842 }
1843 while (optsum >> 16) 1843 while (optsum >> 16)
1844 optsum = (optsum >> 16) + 1844 optsum = (optsum >> 16) +
1845 (optsum & 0xffff); 1845 (optsum & 0xffff);
1846 1846
1847 /* Deduct ip opts sum from hwsum (rfc 1624). */ 1847 /* Deduct ip opts sum from hwsum. */
1848 m->m_pkthdr.csum_data = 1848 m->m_pkthdr.csum_data += (uint16_t)~optsum;
1849 ~((~m->m_pkthdr.csum_data) - ~optsum); 
1850 1849
1851 while (m->m_pkthdr.csum_data >> 16) 1850 while (m->m_pkthdr.csum_data >> 16)
1852 m->m_pkthdr.csum_data = 1851 m->m_pkthdr.csum_data =
1853 (m->m_pkthdr.csum_data >> 16) + 1852 (m->m_pkthdr.csum_data >> 16) +
1854 (m->m_pkthdr.csum_data & 1853 (m->m_pkthdr.csum_data &
1855 0xffff); 1854 0xffff);
1856 } 1855 }
1857 1856
1858 m->m_pkthdr.csum_flags |= M_CSUM_DATA | 1857 m->m_pkthdr.csum_flags |= M_CSUM_DATA |
1859 M_CSUM_NO_PSEUDOHDR; 1858 M_CSUM_NO_PSEUDOHDR;
1860 } else 1859 } else
1861swcsum: 1860swcsum:
1862 m->m_pkthdr.csum_flags = 0; 1861 m->m_pkthdr.csum_flags = 0;

cvs diff -r1.72 -r1.73 src/sys/dev/ic/hme.c (expand / switch to unified diff)

--- src/sys/dev/ic/hme.c 2009/03/14 21:04:20 1.72
+++ src/sys/dev/ic/hme.c 2009/03/16 12:02:00 1.73
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: hme.c,v 1.72 2009/03/14 21:04:20 dsl Exp $ */ 1/* $NetBSD: hme.c,v 1.73 2009/03/16 12:02:00 tsutsui Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Paul Kranenburg. 8 * by Paul Kranenburg.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -24,27 +24,27 @@ @@ -24,27 +24,27 @@
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * HME Ethernet module driver. 33 * HME Ethernet module driver.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: hme.c,v 1.72 2009/03/14 21:04:20 dsl Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: hme.c,v 1.73 2009/03/16 12:02:00 tsutsui Exp $");
38 38
39/* #define HMEDEBUG */ 39/* #define HMEDEBUG */
40 40
41#include "opt_inet.h" 41#include "opt_inet.h"
42#include "bpfilter.h" 42#include "bpfilter.h"
43#include "rnd.h" 43#include "rnd.h"
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/systm.h> 46#include <sys/systm.h>
47#include <sys/kernel.h> 47#include <sys/kernel.h>
48#include <sys/mbuf.h> 48#include <sys/mbuf.h>
49#include <sys/syslog.h> 49#include <sys/syslog.h>
50#include <sys/socket.h> 50#include <sys/socket.h>
@@ -787,29 +787,28 @@ hme_get(struct hme_softc *sc, int ri, u_ @@ -787,29 +787,28 @@ hme_get(struct hme_softc *sc, int ri, u_
787 uint32_t optsum; 787 uint32_t optsum;
788 788
789 optsum = 0; 789 optsum = 0;
790 temp = hlen - sizeof(struct ip); 790 temp = hlen - sizeof(struct ip);
791 opts = (uint16_t *)((char *)ip + sizeof(struct ip)); 791 opts = (uint16_t *)((char *)ip + sizeof(struct ip));
792 792
793 while (temp > 1) { 793 while (temp > 1) {
794 optsum += ntohs(*opts++); 794 optsum += ntohs(*opts++);
795 temp -= 2; 795 temp -= 2;
796 } 796 }
797 while (optsum >> 16) 797 while (optsum >> 16)
798 optsum = (optsum >> 16) + (optsum & 0xffff); 798 optsum = (optsum >> 16) + (optsum & 0xffff);
799 799
800 /* Deduct the ip opts sum from the hwsum (rfc 1624). */ 800 /* Deduct the ip opts sum from the hwsum. */
801 m0->m_pkthdr.csum_data = ~((~m0->m_pkthdr.csum_data) - 801 m0->m_pkthdr.csum_data += (uint16_t)~optsum;
802 ~optsum); 
803 802
804 while (m0->m_pkthdr.csum_data >> 16) 803 while (m0->m_pkthdr.csum_data >> 16)
805 m0->m_pkthdr.csum_data = 804 m0->m_pkthdr.csum_data =
806 (m0->m_pkthdr.csum_data >> 16) + 805 (m0->m_pkthdr.csum_data >> 16) +
807 (m0->m_pkthdr.csum_data & 0xffff); 806 (m0->m_pkthdr.csum_data & 0xffff);
808 } 807 }
809 808
810 m0->m_pkthdr.csum_flags |= M_CSUM_DATA | M_CSUM_NO_PSEUDOHDR; 809 m0->m_pkthdr.csum_flags |= M_CSUM_DATA | M_CSUM_NO_PSEUDOHDR;
811 } else 810 } else
812swcsum: 811swcsum:
813 m0->m_pkthdr.csum_flags = 0; 812 m0->m_pkthdr.csum_flags = 0;
814#endif 813#endif
815 814