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))