Subject: Re: Patch to make upper-layer network protocols align as needed
To: None <thorpej@wasabisystems.com>
From: None <itojun@iijlab.net>
List: tech-net
Date: 05/22/2002 16:06:11
> > 	the "side-effect" will happen only if m_pullup() is called, or
> > 	m_pulldown() is called with off == 0 (2nd arg).  i guess we need
> > 	some check in IP6_EXTHDR_GET() macro.
>Can you cook something up for this?

	sorry for the delay, how about this?
	not sure if ALIGN() is the correct way to detect unalignedness.
	testers wanted, with align-picky archs (i have i386 only).

itojun


Index: kern/uipc_mbuf2.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/uipc_mbuf2.c,v
retrieving revision 1.9
diff -u -r1.9 uipc_mbuf2.c
--- kern/uipc_mbuf2.c	2002/04/28 00:53:34	1.9
+++ kern/uipc_mbuf2.c	2002/05/22 07:02:12
@@ -74,6 +74,8 @@
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 
+#define ALIGNED(x)	((u_long)(x) == ALIGN((x)))
+
 /*
  * ensure that [off, off + len) is contiguous on the mbuf chain "m".
  * packet chain before "off" is kept untouched.
@@ -120,6 +122,12 @@
 	sharedcluster = M_READONLY(n);
 
 	/*
+	 * if unaligned, do it in a hard way
+	 */
+	if (!ALIGNED(mtod(n, caddr_t) + off))
+		goto unaligned;
+
+	/*
 	 * the target data is on <n, off>.
 	 * if we got enough data on the mbuf "n", we're done.
 	 */
@@ -146,6 +154,7 @@
 		goto ok;
 	}
 
+unaligned:
 	/*
 	 * we need to take hlen from <n, off> and tlen from <n->m_next, 0>,
 	 * and construct contiguous mbuf with m_len == len.
@@ -171,6 +180,7 @@
 	 * we need to use m_copydata() to get data from <n->m_next, 0>.
 	 */
 	if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen &&
+	    ALIGNED(mtod(n, caddr_t) + n->m_len) &&
 	    !sharedcluster) {
 		m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len);
 		n->m_len += tlen;
@@ -178,6 +188,7 @@
 		goto ok;
 	}
 	if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen &&
+	    ALIGNED(mtod(n->m_next, caddr_t) - hlen) &&
 	    !sharedcluster) {
 		n->m_next->m_data -= hlen;
 		n->m_next->m_len += hlen;
Index: netinet/ip6.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip6.h,v
retrieving revision 1.12
diff -u -r1.12 ip6.h
--- netinet/ip6.h	2001/07/05 23:41:07	1.12
+++ netinet/ip6.h	2002/05/22 07:02:14
@@ -261,7 +261,8 @@
 do {									\
 	struct mbuf *t;							\
 	int tmp;							\
-	if ((m)->m_len >= (off) + (len))				\
+	if ((m)->m_len >= (off) + (len) &&				\
+	    (u_long)mtod((m), caddr_t) + off == ALIGN(mtod((m), caddr_t) + off)) \
 		(val) = (typ)(mtod((m), caddr_t) + (off));		\
 	else {								\
 		t = m_pulldown((m), (off), (len), &tmp);		\
@@ -279,7 +280,8 @@
 #define IP6_EXTHDR_GET0(val, typ, m, off, len) \
 do {									\
 	struct mbuf *t;							\
-	if ((off) == 0 && (m)->m_len >= len)				\
+	if ((off) == 0 && (m)->m_len >= len &&				\
+	    (u_long)mtod((m), caddr_t) == ALIGN(mtod((m), caddr_t)))	\
 		(val) = (typ)mtod((m), caddr_t);			\
 	else {								\
 		t = m_pulldown((m), (off), (len), NULL);		\