Configuring an EtherIP tunnel on a sparc64 machine, then attempting to send layer-3 traffic over it, panics the kernel. Here is a sample configuration: hme0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=b<RXCSUM,TXCSUM,VLAN_MTU> ether 08:00:20:f5:65:bb inet 128.238.9.196 netmask 0xffffff00 broadcast 128.238.9.255 media: Ethernet autoselect (100baseTX <full-duplex>) status: active ath0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500 ether 00:18:e7:32:b7:bd media: IEEE 802.11 Wireless Ethernet autoselect <hostap> (autoselect <hostap>) status: associated ssid acm channel 1 (2412 Mhz 11g) bssid 00:18:e7:32:b7:bd authmode OPEN privacy ON deftxkey 1 wepkey 1:104-bit txpower 31.5 scanvalid 60 bgscan bgscanintvl 300 bgscanidle 250 roam:rssi11g 7 roam:rate11g 5 protmode CTS burst dtimperiod 1 lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3 inet6 ::1 prefixlen 128 inet 127.0.0.1 netmask 0xff000000 bridge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 ether 3a:d6:0d:f7:8a:0b id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15 maxage 20 holdcnt 6 proto rstp maxaddr 100 timeout 1200 root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0 member: gif0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP> ifmaxaddr 0 port 5 priority 128 path cost 55 member: ath0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP> ifmaxaddr 0 port 2 priority 128 path cost 370370 gif0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1280 tunnel inet 128.238.9.196 --> 128.238.9.199 inet 10.0.0.2 --> 10.0.0.1 netmask 0xffffff00 If I were to assign an IP address to bridge0 and attempt to do anything with it, or if I attempt to send any layer-3 traffic to 10.0.0.1, the kernel panics. Note that the above machine's main purpose is to bridge traffic between the ath0 device and the endpoint of the gif0 tunnel, and the machine itself generates no layer-3 traffic over the EtherIP tunnel, so it's fine if left alone. The problem does not appear on i386. Here is a backtrace: Unread portion of the kernel message buffer: panic: trap: memory address not aligned cpuid = 1 Uptime: 7m24s Dumping 768 MB (2 chunks) chunk at 0: 536870912 bytes | #0 0x00000000c029a0d8 in doadump () at /usr/src/sys/kern/kern_shutdown.c:243 243 savectx(&dumppcb); (kgdb) where #0 0x00000000c029a0d8 in doadump () at /usr/src/sys/kern/kern_shutdown.c:243 #1 0x00000000c029aab8 in boot (howto=260) at /usr/src/sys/kern/kern_shutdown.c:418 #2 0x00000000c029adbc in panic (fmt=0xc06af798 "trap: %s") at /usr/src/sys/kern/kern_shutdown.c:574 #3 0x00000000c0580928 in trap (tf=0xe06dac10) at /usr/src/sys/sparc64/sparc64/trap.c:378 #4 0x00000000c0070fe0 in tl1_trap () #5 0x00000000c03a49d0 in ip_output (m=0xfffff80001756000, opt=0x0, ro=0x0, flags=-1066005504, imo=0x201, inp=0x0) at /usr/src/sys/netinet/ip_output.c:152 #6 0x00000000c039beb4 in in_rtalloc_ign (ro=0xfffff80001829172, ignflags=0, fibnum=22098760) at /usr/src/sys/netinet/in_rmx.c:446 #7 0x00000000c0396b68 in in_gif_output (ifp=Variable "ifp" is not available. ) at /usr/src/sys/netinet/in_gif.c:230 #8 0x00000000c03518bc in gif_output (ifp=0xfffff80001078800, m=0xfffff80001829100, dst=0xe06db078, rt=0xfffff800016e00f8) at /usr/src/sys/net/if_gif.c:455 #9 0x00000000c03a55f8 in ip_output (m=0xfffff80001829100, opt=Variable "opt" is not available. ) at /usr/src/sys/netinet/ip_output.c:554 #10 0x00000000c03a7690 in rip_output (m=0xfffff80001829100, so=Variable "so" is not available. ) at /usr/src/sys/netinet/raw_ip.c:414 #11 0x00000000c03a7754 in rip_send (so=0xfffff80001670000, flags=0, m=0xfffff80001829100, nam=0xfffff80001552640, control=0x0, td=0xfffff80001756000) at /usr/src/sys/netinet/raw_ip.c:885 #12 0x00000000c03040ac in sosend_generic (so=0xfffff80001670000, addr=0xfffff80001552640, uio=0xe06db4a8, top=0xfffff80001829100, control=0x0, flags=Variable "flags" is not available. ) at /usr/src/sys/kern/uipc_socket.c:1246 #13 0x00000000c02ff974 in sosend (so=0xfffff80001670000, addr=0xfffff80001552640, uio=0xe06db4a8, top=0x0, control=0x0, flags=0, td=0xfffff80001756000) at /usr/src/sys/kern/uipc_socket.c:1288 #14 0x00000000c03070a4 in kern_sendit (td=0xfffff80001756000, s=3, mp=0xe06db680, flags=0, control=0x0, segflg=Variable "segflg" is not available. ) at /usr/src/sys/kern/uipc_syscalls.c:805 #15 0x00000000c0309f94 in sendit (td=0xfffff80001756000, s=3, mp=0xe06db680, flags=0) at /usr/src/sys/kern/uipc_syscalls.c:742 #16 0x00000000c030a0cc in sendto (td=0xfffff80001756000, uap=0xe06db770) at /usr/src/sys/kern/uipc_syscalls.c:857 #17 0x00000000c0580c4c in syscall (tf=0xe06db880) at /usr/src/sys/sparc64/sparc64/trap.c:610 #18 0x00000000c0070dc0 in tl0_intr () #19 0x0000000000000000 in ?? () How-To-Repeat: Attempt to send layer-3 traffic over an EtherIP tunnel on sparc64. ping(8) will do the trick.
Could you please give the patch at following URL a try? http://people.freebsd.org/~marius/gif_etherip_align.diff Thanks, Marius
The patch fixes it, and I've also tested it on i386 to make sure it doesn't cause any trouble there. Thanks! -Boris
On Mon, Feb 23, 2009 at 12:53:53AM -0500, Boris Kochergin wrote: > The patch fixes it, and I've also tested it on i386 to make sure it > doesn't cause any trouble there. Thanks! > Hi Andrew, are you okay with the following patch? http://people.freebsd.org/~marius/gif_etherip_align.diff Marius
Author: marius Date: Sat Mar 7 19:08:58 2009 New Revision: 189494 URL: http://svn.freebsd.org/changeset/base/189494 Log: On architectures with strict alignment requirements compensate the misalignment of the IP header that prepending the EtherIP header might have caused. PR: 131921 MFC after: 1 week Modified: head/sys/net/if_gif.h head/sys/netinet/in_gif.c head/sys/netinet6/in6_gif.c Modified: head/sys/net/if_gif.h ============================================================================== --- head/sys/net/if_gif.h Sat Mar 7 18:57:03 2009 (r189493) +++ head/sys/net/if_gif.h Sat Mar 7 19:08:58 2009 (r189494) @@ -100,6 +100,8 @@ struct etherip_header { #define ETHERIP_VER_VERS_MASK 0x0f #define ETHERIP_VER_RSVD_MASK 0xf0 #define ETHERIP_VERSION 0x03 +/* mbuf adjust factor to force 32-bit alignment of IP header */ +#define ETHERIP_ALIGN 2 /* Prototypes */ void gif_input(struct mbuf *, int, struct ifnet *); Modified: head/sys/netinet/in_gif.c ============================================================================== --- head/sys/netinet/in_gif.c Sat Mar 7 18:57:03 2009 (r189493) +++ head/sys/netinet/in_gif.c Sat Mar 7 19:08:58 2009 (r189494) @@ -102,7 +102,7 @@ in_gif_output(struct ifnet *ifp, int fam struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst; struct ip iphdr; /* capsule IP header, host byte ordered */ struct etherip_header eiphdr; - int proto, error; + int error, len, proto; u_int8_t tos; GIF_LOCK_ASSERT(sc); @@ -186,13 +186,27 @@ in_gif_output(struct ifnet *ifp, int fam &iphdr.ip_tos, &tos); /* prepend new IP header */ - M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); - if (m && m->m_len < sizeof(struct ip)) - m = m_pullup(m, sizeof(struct ip)); + len = sizeof(struct ip); +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) + len += ETHERIP_ALIGN; +#endif + M_PREPEND(m, len, M_DONTWAIT); + if (m != NULL && m->m_len < len) + m = m_pullup(m, len); if (m == NULL) { printf("ENOBUFS in in_gif_output %d\n", __LINE__); return ENOBUFS; } +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) { + len = mtod(m, vm_offset_t) & 3; + KASSERT(len == 0 || len == ETHERIP_ALIGN, + ("in_gif_output: unexpected misalignment")); + m->m_data += len; + m->m_len -= ETHERIP_ALIGN; + } +#endif bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); M_SETFIB(m, sc->gif_fibnum); Modified: head/sys/netinet6/in6_gif.c ============================================================================== --- head/sys/netinet6/in6_gif.c Sat Mar 7 18:57:03 2009 (r189493) +++ head/sys/netinet6/in6_gif.c Sat Mar 7 19:08:58 2009 (r189494) @@ -98,7 +98,7 @@ in6_gif_output(struct ifnet *ifp, struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst; struct ip6_hdr *ip6; struct etherip_header eiphdr; - int proto, error; + int error, len, proto; u_int8_t itos, otos; GIF_LOCK_ASSERT(sc); @@ -166,13 +166,27 @@ in6_gif_output(struct ifnet *ifp, } /* prepend new IP header */ - M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); - if (m && m->m_len < sizeof(struct ip6_hdr)) - m = m_pullup(m, sizeof(struct ip6_hdr)); + len = sizeof(struct ip6_hdr); +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) + len += ETHERIP_ALIGN; +#endif + M_PREPEND(m, len, M_DONTWAIT); + if (m != NULL && m->m_len < len) + m = m_pullup(m, len); if (m == NULL) { printf("ENOBUFS in in6_gif_output %d\n", __LINE__); return ENOBUFS; } +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) { + len = mtod(m, vm_offset_t) & 3; + KASSERT(len == 0 || len == ETHERIP_ALIGN, + ("in6_gif_output: unexpected misalignment")); + m->m_data += len; + m->m_len -= ETHERIP_ALIGN; + } +#endif ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = 0; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Wed Mar 18 22:12:54 2009 New Revision: 189996 URL: http://svn.freebsd.org/changeset/base/189996 Log: MFC: r189494 On architectures with strict alignment requirements compensate the misalignment of the IP header that prepending the EtherIP header might have caused. PR: 131921 Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/net/if_gif.h stable/7/sys/netinet/in_gif.c stable/7/sys/netinet6/in6_gif.c Modified: stable/7/sys/net/if_gif.h ============================================================================== --- stable/7/sys/net/if_gif.h Wed Mar 18 21:57:35 2009 (r189995) +++ stable/7/sys/net/if_gif.h Wed Mar 18 22:12:54 2009 (r189996) @@ -100,6 +100,8 @@ struct etherip_header { #define ETHERIP_VER_VERS_MASK 0x0f #define ETHERIP_VER_RSVD_MASK 0xf0 #define ETHERIP_VERSION 0x03 +/* mbuf adjust factor to force 32-bit alignment of IP header */ +#define ETHERIP_ALIGN 2 /* Prototypes */ void gif_input(struct mbuf *, int, struct ifnet *); Modified: stable/7/sys/netinet/in_gif.c ============================================================================== --- stable/7/sys/netinet/in_gif.c Wed Mar 18 21:57:35 2009 (r189995) +++ stable/7/sys/netinet/in_gif.c Wed Mar 18 22:12:54 2009 (r189996) @@ -98,7 +98,7 @@ in_gif_output(struct ifnet *ifp, int fam struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst; struct ip iphdr; /* capsule IP header, host byte ordered */ struct etherip_header eiphdr; - int proto, error; + int error, len, proto; u_int8_t tos; GIF_LOCK_ASSERT(sc); @@ -182,13 +182,27 @@ in_gif_output(struct ifnet *ifp, int fam &iphdr.ip_tos, &tos); /* prepend new IP header */ - M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); - if (m && m->m_len < sizeof(struct ip)) - m = m_pullup(m, sizeof(struct ip)); + len = sizeof(struct ip); +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) + len += ETHERIP_ALIGN; +#endif + M_PREPEND(m, len, M_DONTWAIT); + if (m != NULL && m->m_len < len) + m = m_pullup(m, len); if (m == NULL) { printf("ENOBUFS in in_gif_output %d\n", __LINE__); return ENOBUFS; } +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) { + len = mtod(m, vm_offset_t) & 3; + KASSERT(len == 0 || len == ETHERIP_ALIGN, + ("in_gif_output: unexpected misalignment")); + m->m_data += len; + m->m_len -= ETHERIP_ALIGN; + } +#endif bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); M_SETFIB(m, sc->gif_fibnum); Modified: stable/7/sys/netinet6/in6_gif.c ============================================================================== --- stable/7/sys/netinet6/in6_gif.c Wed Mar 18 21:57:35 2009 (r189995) +++ stable/7/sys/netinet6/in6_gif.c Wed Mar 18 22:12:54 2009 (r189996) @@ -96,7 +96,7 @@ in6_gif_output(struct ifnet *ifp, struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst; struct ip6_hdr *ip6; struct etherip_header eiphdr; - int proto, error; + int error, len, proto; u_int8_t itos, otos; GIF_LOCK_ASSERT(sc); @@ -164,13 +164,27 @@ in6_gif_output(struct ifnet *ifp, } /* prepend new IP header */ - M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); - if (m && m->m_len < sizeof(struct ip6_hdr)) - m = m_pullup(m, sizeof(struct ip6_hdr)); + len = sizeof(struct ip6_hdr); +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) + len += ETHERIP_ALIGN; +#endif + M_PREPEND(m, len, M_DONTWAIT); + if (m != NULL && m->m_len < len) + m = m_pullup(m, len); if (m == NULL) { printf("ENOBUFS in in6_gif_output %d\n", __LINE__); return ENOBUFS; } +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) { + len = mtod(m, vm_offset_t) & 3; + KASSERT(len == 0 || len == ETHERIP_ALIGN, + ("in6_gif_output: unexpected misalignment")); + m->m_data += len; + m->m_len -= ETHERIP_ALIGN; + } +#endif ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = 0; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Wed Mar 18 22:13:29 2009 New Revision: 189997 URL: http://svn.freebsd.org/changeset/base/189997 Log: MFC: r189494 On architectures with strict alignment requirements compensate the misalignment of the IP header that prepending the EtherIP header might have caused. PR: 131921 Modified: stable/6/sys/ (props changed) stable/6/sys/contrib/pf/ (props changed) stable/6/sys/dev/cxgb/ (props changed) stable/6/sys/net/if_gif.h stable/6/sys/netinet/in_gif.c stable/6/sys/netinet6/in6_gif.c Modified: stable/6/sys/net/if_gif.h ============================================================================== --- stable/6/sys/net/if_gif.h Wed Mar 18 22:12:54 2009 (r189996) +++ stable/6/sys/net/if_gif.h Wed Mar 18 22:13:29 2009 (r189997) @@ -99,6 +99,8 @@ struct etherip_header { #define ETHERIP_VER_VERS_MASK 0x0f #define ETHERIP_VER_RSVD_MASK 0xf0 #define ETHERIP_VERSION 0x03 +/* mbuf adjust factor to force 32-bit alignment of IP header */ +#define ETHERIP_ALIGN 2 /* Prototypes */ void gif_input(struct mbuf *, int, struct ifnet *); Modified: stable/6/sys/netinet/in_gif.c ============================================================================== --- stable/6/sys/netinet/in_gif.c Wed Mar 18 22:12:54 2009 (r189996) +++ stable/6/sys/netinet/in_gif.c Wed Mar 18 22:13:29 2009 (r189997) @@ -101,7 +101,7 @@ in_gif_output(ifp, family, m) struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst; struct ip iphdr; /* capsule IP header, host byte ordered */ struct etherip_header eiphdr; - int proto, error; + int error, len, proto; u_int8_t tos; GIF_LOCK_ASSERT(sc); @@ -185,13 +185,27 @@ in_gif_output(ifp, family, m) &iphdr.ip_tos, &tos); /* prepend new IP header */ - M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); - if (m && m->m_len < sizeof(struct ip)) - m = m_pullup(m, sizeof(struct ip)); + len = sizeof(struct ip); +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) + len += ETHERIP_ALIGN; +#endif + M_PREPEND(m, len, M_DONTWAIT); + if (m != NULL && m->m_len < len) + m = m_pullup(m, len); if (m == NULL) { printf("ENOBUFS in in_gif_output %d\n", __LINE__); return ENOBUFS; } +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) { + len = mtod(m, vm_offset_t) & 3; + KASSERT(len == 0 || len == ETHERIP_ALIGN, + ("in_gif_output: unexpected misalignment")); + m->m_data += len; + m->m_len -= ETHERIP_ALIGN; + } +#endif bcopy(&iphdr, mtod(m, struct ip *), sizeof(struct ip)); if (dst->sin_family != sin_dst->sin_family || Modified: stable/6/sys/netinet6/in6_gif.c ============================================================================== --- stable/6/sys/netinet6/in6_gif.c Wed Mar 18 22:12:54 2009 (r189996) +++ stable/6/sys/netinet6/in6_gif.c Wed Mar 18 22:13:29 2009 (r189997) @@ -96,7 +96,7 @@ in6_gif_output(ifp, family, m) struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst; struct ip6_hdr *ip6; struct etherip_header eiphdr; - int proto, error; + int error, len, proto; u_int8_t itos, otos; GIF_LOCK_ASSERT(sc); @@ -164,13 +164,27 @@ in6_gif_output(ifp, family, m) } /* prepend new IP header */ - M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); - if (m && m->m_len < sizeof(struct ip6_hdr)) - m = m_pullup(m, sizeof(struct ip6_hdr)); + len = sizeof(struct ip6_hdr); +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) + len += ETHERIP_ALIGN; +#endif + M_PREPEND(m, len, M_DONTWAIT); + if (m != NULL && m->m_len < len) + m = m_pullup(m, len); if (m == NULL) { printf("ENOBUFS in in6_gif_output %d\n", __LINE__); return ENOBUFS; } +#ifndef __NO_STRICT_ALIGNMENT + if (family == AF_LINK) { + len = mtod(m, vm_offset_t) & 3; + KASSERT(len == 0 || len == ETHERIP_ALIGN, + ("in6_gif_output: unexpected misalignment")); + m->m_data += len; + m->m_len -= ETHERIP_ALIGN; + } +#endif ip6 = mtod(m, struct ip6_hdr *); ip6->ip6_flow = 0; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
State Changed From-To: open->closed close