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