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 via email to