Source-Changes-HG archive

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

[src/trunk]: src/sys Changes to allow the IPv4 and IPv6 layers to align heade...



details:   https://anonhg.NetBSD.org/src/rev/72c719bd9a59
branches:  trunk
changeset: 533455:72c719bd9a59
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sun Jun 30 22:40:32 2002 +0000

description:
Changes to allow the IPv4 and IPv6 layers to align headers themseves,
as necessary:
* Implement a new mbuf utility routine, m_copyup(), is is like
  m_pullup(), except that it always prepends and copies, rather
  than only doing so if the desired length is larger than m->m_len.
  m_copyup() also allows an offset into the destination mbuf, which
  allows space for packet headers, in the forwarding case.
* Add *_HDR_ALIGNED_P() macros for IP, IPv6, ICMP, and IGMP.  These
  macros expand to 1 if __NO_STRICT_ALIGNMENT is defined, so that
  architectures which do not have strict alignment constraints don't
  pay for the test or visit the new align-if-needed path.
* Use the new macros to check if a header needs to be aligned, or to
  assert that it already is, as appropriate.

Note: This code is still somewhat experimental.  However, the new
code path won't be visited if individual device drivers continue
to guarantee that packets are delivered to layer 3 already properly
aligned (which are rules that are already in use).

diffstat:

 sys/kern/uipc_mbuf.c     |  54 ++++++++++++++++++++++++++++++++++++++++++++++-
 sys/netinet/icmp_var.h   |   8 ++++++-
 sys/netinet/igmp.c       |   5 ++-
 sys/netinet/igmp_var.h   |   8 ++++++-
 sys/netinet/ip_flow.c    |  19 +++++++++++++---
 sys/netinet/ip_icmp.c    |   5 ++-
 sys/netinet/ip_input.c   |  26 +++++++++++++++++-----
 sys/netinet/ip_var.h     |   8 ++++++-
 sys/netinet/tcp_input.c  |   7 ++++-
 sys/netinet/tcp_var.h    |   8 ++++++-
 sys/netinet/udp_usrreq.c |   6 +++-
 sys/netinet/udp_var.h    |   8 ++++++-
 sys/netinet6/icmp6.c     |   5 ++-
 sys/netinet6/ip6_input.c |  27 +++++++++++++++++++----
 sys/netinet6/ip6_var.h   |   8 ++++++-
 sys/sys/mbuf.h           |   3 +-
 16 files changed, 171 insertions(+), 34 deletions(-)

diffs (truncated from 541 to 300 lines):

diff -r 19098b9b0770 -r 72c719bd9a59 sys/kern/uipc_mbuf.c
--- a/sys/kern/uipc_mbuf.c      Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/kern/uipc_mbuf.c      Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_mbuf.c,v 1.59 2002/03/09 01:46:33 thorpej Exp $   */
+/*     $NetBSD: uipc_mbuf.c,v 1.60 2002/06/30 22:40:32 thorpej Exp $   */
 
 /*-
  * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.59 2002/03/09 01:46:33 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.60 2002/06/30 22:40:32 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -729,6 +729,56 @@
 }
 
 /*
+ * Like m_pullup(), except a new mbuf is always allocated, and we allow
+ * the amount of empty space before the data in the new mbuf to be specified
+ * (in the event that the caller expects to prepend later).
+ */
+int MSFail;
+
+struct mbuf *
+m_copyup(struct mbuf *n, int len, int dstoff)
+{
+       struct mbuf *m;
+       int count, space;
+
+       if (len > (MHLEN - dstoff))
+               goto bad;
+       MGET(m, M_DONTWAIT, n->m_type);
+       if (m == NULL)
+               goto bad;
+       m->m_len = 0;
+       if (n->m_flags & M_PKTHDR) {
+               M_COPY_PKTHDR(m, n);
+               n->m_flags &= ~M_PKTHDR;
+       }
+       m->m_data += dstoff;
+       space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
+       do {
+               count = min(min(max(len, max_protohdr), space), n->m_len);
+               memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t),
+                   (unsigned)count);
+               len -= count;
+               m->m_len += count;
+               n->m_len -= count;
+               space -= count;
+               if (n->m_len)
+                       n->m_data += count;
+               else
+                       n = m_free(n);
+       } while (len > 0 && n);
+       if (len > 0) {
+               (void) m_free(m);
+               goto bad;
+       }
+       m->m_next = n;
+       return (m);
+ bad:
+       m_freem(n);
+       MSFail++;
+       return (NULL);
+}
+
+/*
  * Partition an mbuf chain in two pieces, returning the tail --
  * all but the first len0 bytes.  In case of failure, it returns NULL and
  * attempts to restore the chain to its original state.
diff -r 19098b9b0770 -r 72c719bd9a59 sys/netinet/icmp_var.h
--- a/sys/netinet/icmp_var.h    Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/netinet/icmp_var.h    Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: icmp_var.h,v 1.20 2002/06/09 16:33:37 itojun Exp $     */
+/*     $NetBSD: icmp_var.h,v 1.21 2002/06/30 22:40:33 thorpej Exp $    */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -83,6 +83,12 @@
 
 #ifdef _KERNEL
 struct icmpstat icmpstat;
+
+#ifdef __NO_STRICT_ALIGNMENT
+#define        ICMP_HDR_ALIGNED_P(ic)  1
+#else
+#define        ICMP_HDR_ALIGNED_P(ic)  ((((vaddr_t) (ic)) & 3) == 0)
 #endif
+#endif /* _KERNEL_ */
 
 #endif /* _NETINET_ICMP_VAR_H_ */
diff -r 19098b9b0770 -r 72c719bd9a59 sys/netinet/igmp.c
--- a/sys/netinet/igmp.c        Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/netinet/igmp.c        Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: igmp.c,v 1.29 2002/06/09 16:33:37 itojun Exp $ */
+/*     $NetBSD: igmp.c,v 1.30 2002/06/30 22:40:33 thorpej Exp $        */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: igmp.c,v 1.29 2002/06/09 16:33:37 itojun Exp $");
+__KERNEL_RCSID(0, "$NetBSD: igmp.c,v 1.30 2002/06/30 22:40:33 thorpej Exp $");
 
 #include "opt_mrouting.h"
 
@@ -180,6 +180,7 @@
        m->m_data += iphlen;
        m->m_len -= iphlen;
        igmp = mtod(m, struct igmp *);
+       /* No need to assert alignment here. */
        if (in_cksum(m, ip->ip_len - iphlen)) {
                ++igmpstat.igps_rcv_badsum;
                m_freem(m);
diff -r 19098b9b0770 -r 72c719bd9a59 sys/netinet/igmp_var.h
--- a/sys/netinet/igmp_var.h    Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/netinet/igmp_var.h    Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: igmp_var.h,v 1.13 2002/05/29 01:33:45 itojun Exp $     */
+/*     $NetBSD: igmp_var.h,v 1.14 2002/06/30 22:40:33 thorpej Exp $    */
 
 /*
  * Copyright (c) 1988 Stephen Deering.
@@ -75,6 +75,12 @@
  */
 #define        IGMP_RANDOM_DELAY(X)    (arc4random() % (X) + 1)
 
+#ifdef __NO_STRICT_ALIGNMENT
+#define        IGMP_HDR_ALIGNED_P(ig)  1
+#else
+#define        IGMP_HDR_ALIGNED_P(ig)  ((((vaddr_t) (ig)) & 3) == 0)
+#endif
+
 void   igmp_init __P((void));
 void   igmp_input __P((struct mbuf *, ...));
 void   igmp_joingroup __P((struct in_multi *));
diff -r 19098b9b0770 -r 72c719bd9a59 sys/netinet/ip_flow.c
--- a/sys/netinet/ip_flow.c     Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/netinet/ip_flow.c     Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_flow.c,v 1.24 2002/06/09 16:33:40 itojun Exp $      */
+/*     $NetBSD: ip_flow.c,v 1.25 2002/06/30 22:40:34 thorpej Exp $     */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.24 2002/06/09 16:33:40 itojun Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_flow.c,v 1.25 2002/06/30 22:40:34 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -143,7 +143,7 @@
 ipflow_fastforward(
        struct mbuf *m)
 {
-       struct ip *ip;
+       struct ip *ip, ip_store;
        struct ipflow *ipf;
        struct rtentry *rt;
        struct sockaddr *dst;
@@ -166,7 +166,12 @@
        /*
         * IP header with no option and valid version and length
         */
-       ip = mtod(m, struct ip *);
+       if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)))
+               ip = mtod(m, struct ip *);
+       else {
+               memcpy(&ip_store, mtod(m, caddr_t), sizeof(ip_store));
+               ip = &ip_store;
+       }
        iplen = ntohs(ip->ip_len);
        if (ip->ip_v != IPVERSION || ip->ip_hl != (sizeof(struct ip) >> 2) ||
            iplen < sizeof(struct ip) || iplen > m->m_pkthdr.len)
@@ -234,6 +239,12 @@
                ip->ip_sum += htons(IPTTLDEC << 8);
 
        /*
+        * Done modifying the header; copy it back, if necessary.
+        */
+       if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0)
+               memcpy(mtod(m, caddr_t), &ip_store, sizeof(ip_store));
+
+       /*
         * Trim the packet in case it's too long..
         */
        if (m->m_pkthdr.len > iplen) {
diff -r 19098b9b0770 -r 72c719bd9a59 sys/netinet/ip_icmp.c
--- a/sys/netinet/ip_icmp.c     Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/netinet/ip_icmp.c     Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_icmp.c,v 1.68 2002/06/13 16:25:54 itojun Exp $      */
+/*     $NetBSD: ip_icmp.c,v 1.69 2002/06/30 22:40:34 thorpej Exp $     */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -105,7 +105,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.68 2002/06/13 16:25:54 itojun Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.69 2002/06/30 22:40:34 thorpej Exp $");
 
 #include "opt_ipsec.h"
 
@@ -419,6 +419,7 @@
        m->m_len -= hlen;
        m->m_data += hlen;
        icp = mtod(m, struct icmp *);
+       /* Don't need to assert alignment, here. */
        if (in_cksum(m, icmplen)) {
                icmpstat.icps_checksum++;
                goto freeit;
diff -r 19098b9b0770 -r 72c719bd9a59 sys/netinet/ip_input.c
--- a/sys/netinet/ip_input.c    Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/netinet/ip_input.c    Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_input.c,v 1.153 2002/06/13 16:25:54 itojun Exp $    */
+/*     $NetBSD: ip_input.c,v 1.154 2002/06/30 22:40:34 thorpej Exp $   */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.153 2002/06/13 16:25:54 itojun Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.154 2002/06/30 22:40:34 thorpej Exp $");
 
 #include "opt_gateway.h"
 #include "opt_pfil_hooks.h"
@@ -420,10 +420,24 @@
        if (TAILQ_FIRST(&in_ifaddr) == 0)
                goto bad;
        ipstat.ips_total++;
-       if (m->m_len < sizeof (struct ip) &&
-           (m = m_pullup(m, sizeof (struct ip))) == 0) {
-               ipstat.ips_toosmall++;
-               return;
+       /*
+        * If the IP header is not aligned, slurp it up into a new
+        * mbuf with space for link headers, in the event we forward
+        * it.  Otherwise, if it is aligned, make sure the entire
+        * base IP header is in the first mbuf of the chain.
+        */
+       if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) {
+               if ((m = m_copyup(m, sizeof(struct ip),
+                                 (max_linkhdr + 3) & ~3)) == NULL) {
+                       /* XXXJRT new stat, please */
+                       ipstat.ips_toosmall++;
+                       return;
+               }
+       } else if (__predict_false(m->m_len < sizeof (struct ip))) {
+               if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
+                       ipstat.ips_toosmall++;
+                       return;
+               }
        }
        ip = mtod(m, struct ip *);
        if (ip->ip_v != IPVERSION) {
diff -r 19098b9b0770 -r 72c719bd9a59 sys/netinet/ip_var.h
--- a/sys/netinet/ip_var.h      Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/netinet/ip_var.h      Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_var.h,v 1.47 2002/05/07 02:59:38 matt Exp $ */
+/*     $NetBSD: ip_var.h,v 1.48 2002/06/30 22:40:35 thorpej Exp $      */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -183,6 +183,12 @@
 #define        IP_ALLOWBROADCAST       SO_BROADCAST    /* can send broadcast packets */
 #define        IP_MTUDISC              0x0400          /* Path MTU Discovery; set DF */
 
+#ifdef __NO_STRICT_ALIGNMENT
+#define        IP_HDR_ALIGNED_P(ip)    1
+#else
+#define        IP_HDR_ALIGNED_P(ip)    ((((vaddr_t) (ip)) & 3) == 0)
+#endif
+
 extern struct ipstat ipstat;           /* ip statistics */
 extern LIST_HEAD(ipqhead, ipq) ipq;    /* ip reass. queue */
 extern u_int16_t ip_id;                        /* ip packet ctr, for ids */
diff -r 19098b9b0770 -r 72c719bd9a59 sys/netinet/tcp_input.c
--- a/sys/netinet/tcp_input.c   Sun Jun 30 22:05:16 2002 +0000
+++ b/sys/netinet/tcp_input.c   Sun Jun 30 22:40:32 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tcp_input.c,v 1.145 2002/06/29 04:13:21 yamt Exp $     */
+/*     $NetBSD: tcp_input.c,v 1.146 2002/06/30 22:40:35 thorpej Exp $  */



Home | Main Index | Thread Index | Old Index