On Thu, Jan 13, 2022 at 12:43:57PM -0700, Theo de Raadt wrote:
> > - m_getptr() returns the correct mbuf and offset to the header.  I
> >   think we can assume that a single IPv6 header, that our stack has
> >   created, is in contiguous memory.  The IPv4 case just above makes
> >   the same assumption.
> 
> And if the assumption is not met due to interations between various
> tunnel or encapsulation layers... then panic the kernel?  That is OK?

It was OK for IPv4 during more than 6 years.

1.118        (mikeb    20-Mar-15):              m = m_getptr(mp, ehdrlen, 
&ipoff);
1.118        (mikeb    20-Mar-15):              KASSERT(m != NULL && m->m_len - 
ipoff >= sizeof(*ip));
1.118        (mikeb    20-Mar-15):              ip = (struct ip *)(m->m_data + 
ipoff);

But to be safe we can use a combination of simple access in the hot
path and m_copydata() in rare cases.

Untested and IPv4-only.  If you like it, Jan can do it with IPv6
tomorrow.

bluhm

Index: dev/pci/if_ix.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_ix.c,v
retrieving revision 1.180
diff -u -p -r1.180 if_ix.c
--- dev/pci/if_ix.c     27 Jul 2021 01:44:55 -0000      1.180
+++ dev/pci/if_ix.c     13 Jan 2022 20:14:33 -0000
@@ -2437,12 +2437,9 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, 
 #else
        struct ether_header *eh;
 #endif
-       struct ip *ip;
 #ifdef notyet
        struct ip6_hdr *ip6;
 #endif
-       struct mbuf *m;
-       int     ipoff;
        uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0;
        int     ehdrlen, ip_hlen = 0;
        uint16_t etype;
@@ -2511,16 +2508,23 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, 
        vlan_macip_lens |= ehdrlen << IXGBE_ADVTXD_MACLEN_SHIFT;
 
        switch (etype) {
-       case ETHERTYPE_IP:
+       case ETHERTYPE_IP: {
+               struct ip *ip, ipdata;
+
                if (mp->m_pkthdr.len < ehdrlen + sizeof(*ip))
                        return (-1);
-               m = m_getptr(mp, ehdrlen, &ipoff);
-               KASSERT(m != NULL && m->m_len - ipoff >= sizeof(*ip));
-               ip = (struct ip *)(m->m_data + ipoff);
+               if ((mtod(mp, unsigned long) & ALIGNBYTES) == 0 &&
+                   mp->m_len >= ehdrlen + sizeof(*ip)) {
+                       ip = (struct ip *)(mp->m_data + ehdrlen);
+               } else {
+                       m_copydata(mp, ehdrlen, sizeof(ipdata), &ipdata);
+                       ip = &ipdata;
+               }
                ip_hlen = ip->ip_hl << 2;
                ipproto = ip->ip_p;
                type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
                break;
+       }
 #ifdef notyet
        case ETHERTYPE_IPV6:
                if (mp->m_pkthdr.len < ehdrlen + sizeof(*ip6))

Reply via email to