etherip alignment issues

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

etherip alignment issues

Martin Brandenburg
Here's another alignment issue.

I have configured two machines as follows.

ifconfig vether0 inet ...
ifconfig etherip0 tunnel ... ...
ifconfig bridge0 add vether0 add etherip0

An amd64 machine works fine in this configuration, however armv7 and
sparc64 both have trouble. This happens very quickly after setting up
the interfaces and attempting to ping. The armv7 is running -current and
the sparc64 is running 6.0.

Some quick research points at the M_PREPEND calls in ip_etherip_output,
since etherip headers are only two bytes.

I can reproduce and get more information if necessary.

Thanks,
Martin

Here's armv7

Fatal kernel mode data abort: 'Alignment fault'
trapframe: 0xcc3c2c90
DFSR=00000801, DFAR=ca1829e6, spsr=20000113
r0 =ca182900, r1 =000008c4, r2 =0300000a, r3 =00007800
r4 =ca1829da, r5 =c56d92e8, r6 =c56d9000, r7 =c56d93e8
r8 =00000000, r9 =ca182900, r10=00000002, r11=cc3c2d24
r12=c06987d8, ssp=cc3c2ce0, slr=c0524ae8, pc =c040a13c

Stopped at      ip_etherip_output+0x158:        str     r2, [r4, #0x00c]
ddb> trace
ip_etherip_output+0x10
        scp=0xc0409ff4 rlv=0xc040a688 (etherip_start+0xe8)
        rsp=0xcc3c2d28 rfp=0xcc3c2d4c
        r10=0xc5726800 r9=0xc56f8000 r8=0xc56f8000 r7=0xc56d9198
        r6=0xc56d9000 r5=0xc56d9000 r4=0xca182900
etherip_start+0xc
        scp=0xc040a5ac rlv=0xc0403aac (if_start_locked+0x34)
        rsp=0xcc3c2d50 rfp=0xcc3c2d74
        r7=0x00000000 r6=0xc069a840 r5=0x00000003 r4=0xc56d9000
if_start_locked+0xc
        scp=0xc0403a84 rlv=0xc0407b14 (if_enqueue+0x88)
        rsp=0xcc3c2d78 rfp=0xcc3c2d9c
        r6=0x00000062 r5=0x00000012 r4=0xc56d9000
if_enqueue+0xc
        scp=0xc0407a98 rlv=0xc041a138 (bridge_ifenqueue+0x30)
        rsp=0xcc3c2da0 rfp=0xcc3c2dcc
        r7=0x00000000 r6=0x00000062 r5=0x00000000 r4=0xc5727900
bridge_ifenqueue+0xc
        scp=0xc041a114 rlv=0xc041a6fc (bridge_output+0x278)
        rsp=0xcc3c2dd0 rfp=0xcc3c2e0c
        r8=0xca182900 r7=0x00000000 r6=0xc56d9000 r5=0x00000000
        r4=0xc5727900
bridge_output+0xc
        scp=0xc041a490 rlv=0xc0409768 ($a+0xb0)
        rsp=0xcc3c2e10 rfp=0xcc3c2e54
        r10=0xcc3c2e1e r9=0xc5726aa0 r8=0xca182f00 r7=0xc5726800
        r6=0x00000008 r5=0xca182900 r4=0xca1829f0
ether_output+0xc
        scp=0xc04095a8 rlv=0xc04510a4 (arpcache+0x130)
        rsp=0xcc3c2e58 rfp=0xcc3c2eac
        r10=0xc5726800 r9=0xca182c50 r8=0xca3ed08c r7=0xca0497f8
        r6=0xca3ed09c r5=0xc07044b0 r4=0x00000001
arpcache+0xc
        scp=0xc0450f80 rlv=0xc0451578 (in_arpinput+0x280)
        rsp=0xcc3c2eb0 rfp=0xcc3c2f14
        r10=0x00000000 r9=0xca182c50 r8=0x00000001 r7=0xc5726800
        r6=0xca182c00 r5=0xca0497f8 r4=0xca182c48
in_arpinput+0xc
        scp=0xc0451304 rlv=0xc0451660 (arpintr+0x28)
        rsp=0xcc3c2f18 rfp=0xcc3c2f44
        r10=0xc069a840 r9=0x00000000 r8=0x00000000 r7=0xc0703a98
        r6=0xcc3c2f18 r5=0xc5726800 r4=0xca182c00
arpintr+0x10
        scp=0xc0451648 rlv=0xc0406e2c (if_netisr+0xc8)
        rsp=0xcc3c2f48 rfp=0xcc3c2f74
        r6=0x00000000 r5=0xc0703a98 r4=0x00040000
if_netisr+0x10
        scp=0xc0406d74 rlv=0xc03b85cc (taskq_thread+0x78)
        rsp=0xcc3c2f78 rfp=0xcc3c2fac
        r10=0xc06fbc98 r8=0xc06fbe78 r7=0xcc3c2f78 r6=0x00000001
        r5=0xc54c0040 r4=0xc03b4434
taskq_thread+0xc
        scp=0xc03b8560 rlv=0xc052b088 (proc_trampoline+0x18)
        rsp=0xcc3c2fb0 rfp=0xc0815ec4
        r7=0x00000000 r6=0x00000000 r5=0xc54c0040 r4=0xc03b8554
Bad frame pointer: 0xc0815ec4
ddb>

and here's sparc64

panic: trap type 0x34 (mem address not aligned): pc=11ffa0c npc=11ffa
10 pstate=820006<PRIV,IE>
Stopped at      Debugger+0x8:   nop
   TID    PID    UID     PRFLAGS     PFLAGS  CPU  COMMAND
*45795  45795      0     0x14000      0x210    1  softnet
trap(4007849d370, 34, 11ffa0c, 820006, 4007849db10, 0) at trap+0x360
Lslowtrap_reenter(40014464400, 14, 2, 0, 88d8, 6) at Lslowtrap_reenter+0xf8
ip_etherip_output(4000a85c800, 40014464400, 62, 4007849dc08, 4007849db10, 0) at ip_etherip_output+0xd4
etherip_start(4000a85c800, 62, 0, 0, 88d8, 6) at etherip_start+0xc4
if_start_locked(4000a85c800, 40014464400, 62, 4007849dc08, 4007849db10, 0) at if_start_locked+0x24
if_enqueue(0, 62, 0, 0, 88d8, 6) at if_enqueue+0x6c
bridge_ifenqueue(4000ae12000, 4000a85c800, 62, 4007849dc08, 4007849db10, 0) at bridge_ifenqueue+0x30
bridge_output(0, 40014464400, 0, 0, 88d8, 6) at bridge_output+0x260
if_enqueue(4000a85d800, 40014464400, 40014464400, 4007849dc08, 4007849db10, 0) at if_enqueue+0x90
ether_output(37, 40014464b00, 4007849dc08, 40014b04e70, 88d8, ffff) at ether_output+0x214
ip_output(40014464b00, 40014464b68, 4007849dbf8, 0, 0, 0) at ip_output+0x7a0
ip_send_dispatch(0, 4007849dde0, 119bfe0, 0, 40000, 20000000) at ip_send_dispatch+0x64
taskq_thread(40008b18080, 40014bded80, 168fe98, 168fc10, 0, 3b9ac800) at taskq_thread+0x6c
proc_trampoline(0, 0, 0, 0, 0, 0) at proc_trampoline+0x14

Reply | Threaded
Open this post in threaded view
|

Re: etherip alignment issues

YASUOKA Masahiko-4
Hi,

The problem doesn't repeat on my Octeon.

Can you try the diff below?

  - I assume the diff fixes the problem
  - A kernel message is added.  please let me know if it appears.

Thanks,

diff --git a/sys/net/if_etherip.c b/sys/net/if_etherip.c
index ad58c52..c0af82e 100644
--- a/sys/net/if_etherip.c
+++ b/sys/net/if_etherip.c
@@ -354,6 +354,8 @@ ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
  struct sockaddr_in *src, *dst;
  struct etherip_header *eip;
  struct ip *ip;
+ struct mbuf *m1;
+ int len;
 
  src = (struct sockaddr_in *)&sc->sc_src;
  dst = (struct sockaddr_in *)&sc->sc_dst;
@@ -370,22 +372,31 @@ ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
 
  m->m_flags &= ~(M_BCAST|M_MCAST);
 
- M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
- if (m == NULL) {
+ len = sizeof(*eip) + sizeof(*ip);
+ KASSERT(MHLEN >= len + 3);
+#if 1
+ if (M_LEADINGSPACE(m) < len)
+ printf("%s: leading space is small %d\n",
+    __func__, M_LEADINGSPACE(m));
+#endif
+
+ MGET(m1, M_DONTWAIT, m->m_type);
+ if (m1 == NULL) {
+ m_freem(m);
  etheripstat.etherip_adrops++;
  return ENOBUFS;
  }
+ m1->m_data += ETHER_ALIGN;
+ m1->m_len = len;
+ m1->m_next = m;
+ m = m1;
+
  eip = mtod(m, struct etherip_header *);
  eip->eip_ver = ETHERIP_VERSION;
  eip->eip_res = 0;
  eip->eip_pad = 0;
 
- M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
- return ENOBUFS;
- }
- ip = mtod(m, struct ip *);
+ ip = (struct ip *)(eip + 1);
  memset(ip, 0, sizeof(struct ip));
 
  ip->ip_v = IPVERSION;

Reply | Threaded
Open this post in threaded view
|

Re: etherip alignment issues

Martin Brandenburg
On Sat, 24 Sep 2016, YASUOKA Masahiko wrote:

> Hi,
>
> The problem doesn't repeat on my Octeon.
>
> Can you try the diff below?
>
>   - I assume the diff fixes the problem
>   - A kernel message is added.  please let me know if it appears.
>
> Thanks,
>

I got the message, but had another panic.

ip_etherip_output: leading space is small 2
panic: ip_output no HDR
Stopped at      Debugger+0x8:   nop
   TID    PID    UID     PRFLAGS     PFLAGS  CPU  COMMAND
 32532  32532     73    0x100010       0x80    6  syslogd
*79702  79702      0     0x14000      0x210    1  softnet
ip_output(4001491c200, 0, 0, 2, 0, 0) at ip_output+0x964
ip_etherip_output(4000ae87800, 4001491cc00, 2a, 4000ae84e8f, 0, 6) at ip_etherip_output+0x214
etherip_start(4000ae87800, 2a, 0, 0, e1, 6) at etherip_start+0xc4
if_start_locked(4000ae87800, 4001491cc00, 2a, 4000ae84e8f, 0, 6) at if_start_locked+0x24
if_enqueue(0, 2a, 0, 0, e1, 6) at if_enqueue+0x6c
bridge_ifenqueue(4000a860000, 4000ae87800, 2a, 4000ae84e8f, 0, 6) at bridge_ifenqueue+0x30
bridge_output(0, 4001491cc00, 0, 0, e1, 6) at bridge_output+0x260
if_enqueue(4000ae8a000, 4001491cc00, 2, 4000ae84e8f, 0, 6) at if_enqueue+0x90
ether_output(37, 4001491cc00, 4007849da68, 0, e1, ba) at ether_output+0x214
arpreply(4000ae8a000, 4001491cc00, 4007849db50, 4000ae84e8f, 0, 6) at arpreply+0x16c
in_arpinput(4000ae8a000, 4001491cc00, 119bfe0, 0, 40000, 20000000) at in_arpinput+0x2ec
arpintr(188aff8, 40014bded80, 168ff18, 168fc90, 0, 6) at arpintr+0x48
if_netisr(0, 4007849dde0, 119bfe0, 0, 40000, 20000000) at if_netisr+0xf0
taskq_thread(40008b18080, 40014bded80, 168ff18, 168fc90, 0, 3b9ac800) at taskq_thread+0x6c

Reply | Threaded
Open this post in threaded view
|

Re: etherip alignment issues

YASUOKA Masahiko-4
On Sat, 24 Sep 2016 13:08:18 -0400 (EDT)
Martin Brandenburg <[hidden email]> wrote:

> On Sat, 24 Sep 2016, YASUOKA Masahiko wrote:
>> The problem doesn't repeat on my Octeon.
>>
>> Can you try the diff below?
>>
>>   - I assume the diff fixes the problem
>>   - A kernel message is added.  please let me know if it appears.
>
> I got the message, but had another panic.
>
> ip_etherip_output: leading space is small 2

Thanks.  The diff was wrong.  I'm sorry.

Let me update the diff.

diff --git a/sys/net/if_etherip.c b/sys/net/if_etherip.c
index ad58c52..d3b1ed6 100644
--- a/sys/net/if_etherip.c
+++ b/sys/net/if_etherip.c
@@ -352,8 +352,9 @@ ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
 {
  struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc;
  struct sockaddr_in *src, *dst;
- struct etherip_header *eip;
+ struct etherip_header eip;
  struct ip *ip;
+ int error;
 
  src = (struct sockaddr_in *)&sc->sc_src;
  dst = (struct sockaddr_in *)&sc->sc_dst;
@@ -370,21 +371,19 @@ ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
 
  m->m_flags &= ~(M_BCAST|M_MCAST);
 
- M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
+ M_PREPEND(m, sizeof(struct ip) + sizeof(eip), M_DONTWAIT);
  if (m == NULL) {
  etheripstat.etherip_adrops++;
  return ENOBUFS;
  }
- eip = mtod(m, struct etherip_header *);
- eip->eip_ver = ETHERIP_VERSION;
- eip->eip_res = 0;
- eip->eip_pad = 0;
+ eip.eip_ver = ETHERIP_VERSION;
+ eip.eip_res = 0;
+ eip.eip_pad = 0;
+ error = m_copyback(m, sizeof(struct ip), sizeof(eip), (caddr_t)&eip,
+    M_DONTWAIT);
+ if (error != 0)
+ return error;
 
- M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
- return ENOBUFS;
- }
  ip = mtod(m, struct ip *);
  memset(ip, 0, sizeof(struct ip));
 

Reply | Threaded
Open this post in threaded view
|

Re: etherip alignment issues

Martin Brandenburg
On Sun, 25 Sep 2016, YASUOKA Masahiko wrote:

> On Sat, 24 Sep 2016 13:08:18 -0400 (EDT)
> Martin Brandenburg <[hidden email]> wrote:
> > On Sat, 24 Sep 2016, YASUOKA Masahiko wrote:
> >> The problem doesn't repeat on my Octeon.
> >>
> >> Can you try the diff below?
> >>
> >>   - I assume the diff fixes the problem
> >>   - A kernel message is added.  please let me know if it appears.
> >
> > I got the message, but had another panic.
> >
> > ip_etherip_output: leading space is small 2
>
> Thanks.  The diff was wrong.  I'm sorry.
>
> Let me update the diff.

Still panicking.

ddb{3}> show panic
trap type 0x34 (mem address not aligned): pc=11ffa68 npc=11ffa6c pstate=44820006<PRIV,IE>
ddb{3}> trace
trap(4007849d370, 34, 11ffa68, 44820006, 4007849db10, 0) at trap+0x360
Lslowtrap_reenter(0, 14, 0, 4007849d566, 2, 6) at Lslowtrap_reenter+0xf8
ip_etherip_output(4000ae96000, 4001443a600, 62, 4007849dc08, 4007849db10, 0) at ip_etherip_output+0x130
etherip_start(4000ae96000, 62, 0, 0, 292f, 6) at etherip_start+0xc4
if_start_locked(4000ae96000, 4001443a600, 62, 4007849dc08, 4007849db10, 0) at if_start_locked+0x24
if_enqueue(0, 62, 0, 0, 292f, 6) at if_enqueue+0x6c
bridge_ifenqueue(4000a860000, 4000ae96000, 62, 4007849dc08, 4007849db10, 0) at bridge_ifenqueue+0x30
bridge_output(0, 4001443a600, 0, 0, 292f, 6) at bridge_output+0x260
if_enqueue(4000ae93800, 4001443a600, 4001443a600, 4007849dc08, 4007849db10, 0) at if_enqueue+0x90
ether_output(37, 4001443ac00, 4007849dc08, 4001478bab0, 292f, ffff) at ether_output+0x214
ip_output(4001443ac00, 4001443ac68, 4007849dbf8, 0, 0, 0) at ip_output+0x7a0
ip_send_dispatch(0, 4007849dde0, 119bfe0, 0, 40000, 20000000) at ip_send_dispatch+0x64
taskq_thread(40008b18080, 40014bded80, 168fed8, 168fc50, 0, 3b9ac800) at taskq_thread+0x6c
proc_trampoline(0, 0, 0, 0, 0, 0) at proc_trampoline+0x14
ddb{3}> sc> poweroff

Reply | Threaded
Open this post in threaded view
|

Re: etherip alignment issues

YASUOKA Masahiko-4
On Sat, 24 Sep 2016 16:45:09 -0400 (EDT)
Martin Brandenburg <[hidden email]> wrote:

> On Sun, 25 Sep 2016, YASUOKA Masahiko wrote:
>
>> On Sat, 24 Sep 2016 13:08:18 -0400 (EDT)
>> Martin Brandenburg <[hidden email]> wrote:
>> > On Sat, 24 Sep 2016, YASUOKA Masahiko wrote:
>> >> The problem doesn't repeat on my Octeon.
>> >>
>> >> Can you try the diff below?
>> >>
>> >>   - I assume the diff fixes the problem
>> >>   - A kernel message is added.  please let me know if it appears.
>> >
>> > I got the message, but had another panic.
>> >
>> > ip_etherip_output: leading space is small 2
>>
>> Thanks.  The diff was wrong.  I'm sorry.
>>
>> Let me update the diff.
>
> Still panicking.

Sorry again.  Can try the diff below?

Finally I understand that any precondition about m->m_data alignment
cannot be assumed.

diff --git a/sys/net/if_etherip.c b/sys/net/if_etherip.c
index ad58c52..74dba63 100644
--- a/sys/net/if_etherip.c
+++ b/sys/net/if_etherip.c
@@ -354,6 +354,8 @@ ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
  struct sockaddr_in *src, *dst;
  struct etherip_header *eip;
  struct ip *ip;
+ struct mbuf *m1;
+ int len;
 
  src = (struct sockaddr_in *)&sc->sc_src;
  dst = (struct sockaddr_in *)&sc->sc_dst;
@@ -370,24 +372,27 @@ ip_etherip_output(struct ifnet *ifp, struct mbuf *m)
 
  m->m_flags &= ~(M_BCAST|M_MCAST);
 
- M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
+ len = sizeof(struct ip) + sizeof(struct etherip_header);
+ MGET(m1, M_DONTWAIT, m->m_type);
+ if (m1 == NULL) {
+ m_freem(m);
  return ENOBUFS;
  }
- eip = mtod(m, struct etherip_header *);
- eip->eip_ver = ETHERIP_VERSION;
- eip->eip_res = 0;
- eip->eip_pad = 0;
+ M_MOVE_PKTHDR(m1, m);
+ m1->m_next = m;
+ m = m1;
+ m->m_len = len;
+ m->m_pkthdr.len += len;
 
- M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
- return ENOBUFS;
- }
  ip = mtod(m, struct ip *);
  memset(ip, 0, sizeof(struct ip));
 
+ eip = (struct etherip_header *)(ip + 1);
+
+ eip->eip_ver = ETHERIP_VERSION;
+ eip->eip_res = 0;
+ eip->eip_pad = 0;
+
  ip->ip_v = IPVERSION;
  ip->ip_hl = sizeof(struct ip) >> 2;
  ip->ip_id = htons(ip_randomid());
@@ -514,6 +519,8 @@ ip6_etherip_output(struct ifnet *ifp, struct mbuf *m)
  struct sockaddr_in6 *src, *dst;
  struct etherip_header *eip;
  struct ip6_hdr *ip6;
+ struct mbuf *m1;
+ int len;
 
  src = (struct sockaddr_in6 *)&sc->sc_src;
  dst = (struct sockaddr_in6 *)&sc->sc_dst;
@@ -530,22 +537,24 @@ ip6_etherip_output(struct ifnet *ifp, struct mbuf *m)
 
  m->m_flags &= ~(M_BCAST|M_MCAST);
 
- M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
+ MGET(m1, M_DONTWAIT, m->m_type);
+ if (m1 == NULL) {
+ m_freem(m);
  return ENOBUFS;
  }
- eip = mtod(m, struct etherip_header *);
+ M_MOVE_PKTHDR(m1, m);
+ m1->m_next = m;
+ m = m1;
+ m->m_len = len;
+ m->m_pkthdr.len += len;
+
+ ip6 = mtod(m, struct ip6_hdr *);
+ eip = (struct etherip_header *)(ip6 + 1);
+
  eip->eip_ver = ETHERIP_VERSION;
  eip->eip_res = 0;
  eip->eip_pad = 0;
 
- M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
- return ENOBUFS;
- }
- ip6 = mtod(m, struct ip6_hdr *);
  ip6->ip6_flow = 0;
  ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
  ip6->ip6_vfc |= IPV6_VERSION;

Reply | Threaded
Open this post in threaded view
|

Re: etherip alignment issues

YASUOKA Masahiko-3
Hi,

I could repeat the problem on my octeon.  Tested the diff on it.

ok?

Use a new mbufs for a tunnel header to make sure it is aligned correctly.

Index: sys/net/if_etherip.c
===================================================================
RCS file: /cvs/src/sys/net/if_etherip.c,v
retrieving revision 1.7
diff -u -p -r1.7 if_etherip.c
--- sys/net/if_etherip.c 13 Apr 2016 11:41:15 -0000 1.7
+++ sys/net/if_etherip.c 26 Sep 2016 01:20:08 -0000
@@ -354,6 +354,7 @@ ip_etherip_output(struct ifnet *ifp, str
  struct sockaddr_in *src, *dst;
  struct etherip_header *eip;
  struct ip *ip;
+ struct mbuf *m0;
 
  src = (struct sockaddr_in *)&sc->sc_src;
  dst = (struct sockaddr_in *)&sc->sc_dst;
@@ -370,24 +371,25 @@ ip_etherip_output(struct ifnet *ifp, str
 
  m->m_flags &= ~(M_BCAST|M_MCAST);
 
- M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
+ MGETHDR(m0, M_DONTWAIT, MT_HEADER);
+ if (m0 == NULL) {
+ m_freem(m);
  return ENOBUFS;
  }
- eip = mtod(m, struct etherip_header *);
- eip->eip_ver = ETHERIP_VERSION;
- eip->eip_res = 0;
- eip->eip_pad = 0;
+ M_MOVE_HDR(m0, m);
+ m0->m_len = sizeof(struct ip) + sizeof(struct etherip_header);
+ m0->m_pkthdr.len += m0->m_len;
+ m0->m_next = m;
+ m = m0;
 
- M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
- return ENOBUFS;
- }
  ip = mtod(m, struct ip *);
  memset(ip, 0, sizeof(struct ip));
 
+ eip = (struct etherip_header *)(ip + 1);
+ eip->eip_ver = ETHERIP_VERSION;
+ eip->eip_res = 0;
+ eip->eip_pad = 0;
+
  ip->ip_v = IPVERSION;
  ip->ip_hl = sizeof(struct ip) >> 2;
  ip->ip_id = htons(ip_randomid());
@@ -514,6 +516,7 @@ ip6_etherip_output(struct ifnet *ifp, st
  struct sockaddr_in6 *src, *dst;
  struct etherip_header *eip;
  struct ip6_hdr *ip6;
+ struct mbuf *m0;
 
  src = (struct sockaddr_in6 *)&sc->sc_src;
  dst = (struct sockaddr_in6 *)&sc->sc_dst;
@@ -530,22 +533,24 @@ ip6_etherip_output(struct ifnet *ifp, st
 
  m->m_flags &= ~(M_BCAST|M_MCAST);
 
- M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
+ MGETHDR(m0, M_DONTWAIT, MT_HEADER);
+ if (m0 == NULL) {
+ m_freem(m);
  return ENOBUFS;
  }
- eip = mtod(m, struct etherip_header *);
+ M_MOVE_PKTHDR(m0, m);
+ m0->m_len = sizeof(struct ip6_hdr) + sizeof(struct etherip_header);
+ m0->m_pkthdr.len += m0->m_len;
+ m0->m_next = m;
+ m = m0;
+
+ ip6 = mtod(m, struct ip6_hdr *);
+
+ eip = (struct etherip_header *)(ip6 + 1);
  eip->eip_ver = ETHERIP_VERSION;
  eip->eip_res = 0;
  eip->eip_pad = 0;
 
- M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
- if (m == NULL) {
- etheripstat.etherip_adrops++;
- return ENOBUFS;
- }
- ip6 = mtod(m, struct ip6_hdr *);
  ip6->ip6_flow = 0;
  ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
  ip6->ip6_vfc |= IPV6_VERSION;

Reply | Threaded
Open this post in threaded view
|

Re: etherip alignment issues

Martin Brandenburg
On Mon, 26 Sep 2016, YASUOKA Masahiko wrote:

> Hi,
>
> I could repeat the problem on my octeon.  Tested the diff on it.
>
> ok?
>
> Use a new mbufs for a tunnel header to make sure it is aligned correctly.

I have tested this latest diff and can confirm it also works on sparc64.

Martin