Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic Perform a s/w checksum for packets that are not t...



details:   https://anonhg.NetBSD.org/src/rev/6f0f0cbc642d
branches:  trunk
changeset: 574597:6f0f0cbc642d
user:      heas <heas%NetBSD.org@localhost>
date:      Sat Mar 05 18:36:23 2005 +0000

description:
Perform a s/w checksum for packets that are not the same length as the length
field of the IP header (ip->ip-len) indicates they should be.  This handles
the case where an ethernet frame has been padded to meet the minimum ethernet
frame length or erroneously (my cisco switch unnecessarily adds 4 bytes to its
SYN).  This padding will be included in the hardware checksum and may be
non-zero, thus making it incorrect.
Also, clear csum_flags when we want a s/w checksum, since we may have started
down the h/w checksum path and determined that it was not usable.

While here, clean-up a few WS nits and ifdef INET the hardware checksum code.

diffstat:

 sys/dev/ic/hme.c |  34 +++++++++++++++++++++-------------
 1 files changed, 21 insertions(+), 13 deletions(-)

diffs (124 lines):

diff -r 8e14cd5447ec -r 6f0f0cbc642d sys/dev/ic/hme.c
--- a/sys/dev/ic/hme.c  Sat Mar 05 18:32:59 2005 +0000
+++ b/sys/dev/ic/hme.c  Sat Mar 05 18:36:23 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hme.c,v 1.48 2005/02/27 00:27:01 perry Exp $   */
+/*     $NetBSD: hme.c,v 1.49 2005/03/05 18:36:23 heas Exp $    */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hme.c,v 1.48 2005/02/27 00:27:01 perry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hme.c,v 1.49 2005/03/05 18:36:23 heas Exp $");
 
 /* #define HMEDEBUG */
 
@@ -510,8 +510,7 @@
        bus_space_write_4(t, mac, HME_MACI_LTCNT, 0);
        bus_space_write_4(t, mac, HME_MACI_TXSIZE,
            (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) ?
-           ETHER_VLAN_ENCAP_LEN + ETHER_MAX_LEN :
-            ETHER_MAX_LEN);
+           ETHER_VLAN_ENCAP_LEN + ETHER_MAX_LEN : ETHER_MAX_LEN);
        sc->sc_ec_capenable = sc->sc_ethercom.ec_capenable;
 
        /* Load station MAC address */
@@ -541,9 +540,7 @@
        bus_space_write_4(t, erx, HME_ERXI_RING, sc->sc_rb.rb_rxddma);
        bus_space_write_4(t, mac, HME_MACI_RXSIZE,
            (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) ?
-           ETHER_VLAN_ENCAP_LEN + ETHER_MAX_LEN :
-            ETHER_MAX_LEN);
-
+           ETHER_VLAN_ENCAP_LEN + ETHER_MAX_LEN : ETHER_MAX_LEN);
 
        /* step 8. Global Configuration & Interrupt Mask */
        bus_space_write_4(t, seb, HME_SEBI_IMASK,
@@ -610,10 +607,12 @@
        v |= HME_ERX_CFG_DMAENABLE;
 
        /* set h/w rx checksum start offset (# of half-words) */
+#ifdef INET
        v |= (((ETHER_HDR_LEN + sizeof(struct ip) +
                ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) ?
                ETHER_VLAN_ENCAP_LEN : 0)) / 2) << HME_ERX_CFG_CSUMSHIFT) &
                HME_ERX_CFG_CSUMSTART;
+#endif
        bus_space_write_4(t, erx, HME_ERXI_CFG, v);
 
        /* step 11. XIF Configuration */
@@ -754,6 +753,8 @@
                }
        }
 
+#ifdef INET
+       /* hardware checksum */
        if (ifp->if_csum_flags_rx & (M_CSUM_TCPv4 | M_CSUM_TCPv4)) {
                struct ether_header *eh;
                struct ip *ip;
@@ -783,10 +784,13 @@
                if (hlen < sizeof(struct ip))
                        goto swcsum;
 
-               /* too short, truncated, fragment */
-               if ((ntohs(ip->ip_len) < hlen) || (ntohs(ip->ip_len) > pktlen)
+               /*
+                * bail if too short, has random trailing garbage, truncated,
+                * fragment, or has ethernet pad.
+                */
+               if ((ntohs(ip->ip_len) < hlen) || (ntohs(ip->ip_len) != pktlen)
                    || (ntohs(ip->ip_off) & (IP_MF | IP_OFFMASK)))
-                       goto swcsum;
+                       goto swcsum;
 
                switch (ip->ip_p) {
                case IPPROTO_TCP:
@@ -808,7 +812,7 @@
                        m0->m_pkthdr.csum_flags = M_CSUM_UDPv4;
                        break;
                default:
-                       goto swcsum;
+                       goto swcsum;
                }
 
                /* w/ M_CSUM_NO_PSEUDOHDR, the uncomplemented sum is expected */
@@ -822,7 +826,7 @@
                        temp = hlen - sizeof(struct ip);
                        opts = (uint16_t *) ((caddr_t) ip + sizeof(struct ip));
 
-                       while (temp > 1) {
+                       while (temp > 1) {
                                optsum += ntohs(*opts++);
                                temp -= 2;
                        }
@@ -841,8 +845,10 @@
 
                m0->m_pkthdr.csum_flags |= M_CSUM_DATA | M_CSUM_NO_PSEUDOHDR;
        }
+swcsum:
+               m0->m_pkthdr.csum_flags = 0;
+#endif
 
-swcsum:
        return (m0);
 
 bad:
@@ -928,6 +934,7 @@
                        bpf_mtap(ifp->if_bpf, m);
 #endif
 
+#ifdef INET
                /* collect bits for h/w csum, before hme_put frees the mbuf */
                if (ifp->if_csum_flags_tx & (M_CSUM_TCPv4 | M_CSUM_UDPv4) &&
                    m->m_pkthdr.csum_flags & (M_CSUM_TCPv4 | M_CSUM_UDPv4)) {
@@ -954,6 +961,7 @@
                                  (offset << HME_XD_TXCSSTUFFSHIFT) |
                                  (start << HME_XD_TXCSSTARTSHIFT);
                } else
+#endif
                        txflags = 0;
 
                /*



Home | Main Index | Thread Index | Old Index