Source-Changes-HG archive

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

[src/trunk]: src/sys For controllers (eg: hme & gem) that can only perform li...



details:   https://anonhg.NetBSD.org/src/rev/c590aefef65d
branches:  trunk
changeset: 573864:c590aefef65d
user:      heas <heas%NetBSD.org@localhost>
date:      Sat Feb 12 23:25:29 2005 +0000

description:
For controllers (eg: hme & gem) that can only perform linear hardware checksums
(from an offset to the end of the packet), the pseudo-header checksum must be
calculated by software.  So, provide it in the TCP/UDP header when
M_CSUM_NO_PSEUDOHDR is set in the interface's if_csum_flags_tx.

The start offset, the end of the IP header, is also provided in the high 16
bits of pkthdr.csum_data.  Such that the driver need not examine the packet
at all.

XXX At the request of Jonathan Stone, note that sharing of if_csum_flags_tx &
    pkthdr.csum_flags for checksum quirks should be re-evaluated.

diffstat:

 sys/netinet/ip_output.c |  35 +++++++++++++++++++++++++++++++++--
 sys/sys/mbuf.h          |  23 +++++++++++++++++------
 2 files changed, 50 insertions(+), 8 deletions(-)

diffs (93 lines):

diff -r 9abd4943b369 -r c590aefef65d sys/netinet/ip_output.c
--- a/sys/netinet/ip_output.c   Sat Feb 12 23:14:03 2005 +0000
+++ b/sys/netinet/ip_output.c   Sat Feb 12 23:25:29 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_output.c,v 1.141 2005/02/12 12:31:07 manu Exp $     */
+/*     $NetBSD: ip_output.c,v 1.142 2005/02/12 23:25:29 heas Exp $     */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -98,7 +98,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.141 2005/02/12 12:31:07 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.142 2005/02/12 23:25:29 heas Exp $");
 
 #include "opt_pfil_hooks.h"
 #include "opt_inet.h"
@@ -799,6 +799,37 @@
                if (sw_csum & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
                        in_delayed_cksum(m);
                        m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
+               } else if (ifp->if_csum_flags_tx & M_CSUM_NO_PSEUDOHDR &&
+                        m->m_pkthdr.csum_flags & (M_CSUM_UDPv4|M_CSUM_TCPv4)) {
+                       /* add pseudo-header sum */
+                       uint16_t sum;
+
+                       ip = mtod(m, struct ip *);
+                       hlen = ip->ip_hl << 2;
+                       m->m_pkthdr.csum_data = (hlen << 16) |
+                                       (m->m_pkthdr.csum_data & 0xffff);
+
+                       if (ip->ip_p == IPPROTO_TCP) {
+                               sum = in_cksum_phdr(ip->ip_src.s_addr,
+                                            ip->ip_dst.s_addr,
+                                            htons(ntohs(ip->ip_len) - hlen +
+                                            IPPROTO_TCP));
+                               /* offset of TCP checksum field */
+                               hlen += (m->m_pkthdr.csum_data & 0xffff);
+                       } else if (ip->ip_p == IPPROTO_UDP) {
+                               sum = in_cksum_phdr(ip->ip_src.s_addr,
+                                            ip->ip_dst.s_addr,
+                                            htons(ntohs(ip->ip_len) - hlen +
+                                            IPPROTO_UDP));
+                               /* offset of UDP checksum field */
+                               hlen += (m->m_pkthdr.csum_data & 0xffff);
+                       }
+                       if ((hlen + sizeof(uint16_t)) > m->m_len) {
+                               /* This happens when ip options were inserted */
+                               m_copyback(m, hlen, sizeof(sum), (caddr_t)&sum);
+                       } else
+                               *(u_int16_t *)(mtod(m, caddr_t) + hlen) = sum;
+
                }
 
 #ifdef IPSEC
diff -r 9abd4943b369 -r c590aefef65d sys/sys/mbuf.h
--- a/sys/sys/mbuf.h    Sat Feb 12 23:14:03 2005 +0000
+++ b/sys/sys/mbuf.h    Sat Feb 12 23:25:29 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mbuf.h,v 1.100 2005/01/31 23:49:36 kim Exp $   */
+/*     $NetBSD: mbuf.h,v 1.101 2005/02/12 23:25:29 heas Exp $  */
 
 /*-
  * Copyright (c) 1996, 1997, 1999, 2001 The NetBSD Foundation, Inc.
@@ -171,11 +171,22 @@
 #define        M_CSUM_IPv4             0x00000040      /* IPv4 header */
 #define        M_CSUM_IPv4_BAD         0x00000080      /* IPv4 header checksum bad */
 
-/* Checksum-assist quirks: keep separate from jump-table bits. */
-#define        M_CSUM_NO_PSEUDOHDR     0x80000000      /* Rx M_CSUM_DATA does not include
-                                                * the UDP/TCP pseudo-hdr, and
-                                                * is not yet 1s-complemented.
-                                                */
+/*
+ * Checksum-assist quirks: keep separate from jump-table bits.
+ *
+ * M_CSUM_NO_PSEUDOHDR:
+ *     Rx: M_CSUM_DATA does not include the UDP/TCP pseudo-hdr, and is not yet
+ *         1s-complemented.
+ *     Tx: Set in ifnet.if_csum_flags_tx, indicates that the controller only
+ *         does linear checksums (ie: from some offset to end of the packet),
+ *         the IP module should stuff the pseudo-hdr checksum in the TCP/UDP
+ *         header.  The high 16 bits of M_CSUM_DATA is the start offset (ie:
+ *         end of the IP header).
+ *
+ * XXX The use of pkthdr.csum_flags & ifnet.if_csum_flags_{rx,tx} for
+ *     hardware checksum quirks needs further consideration.
+ */
+#define        M_CSUM_NO_PSEUDOHDR     0x80000000
 
 /*
  * Max # of pages we can attach to m_ext.  This is carefully chosen



Home | Main Index | Thread Index | Old Index