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;