For LRO with ix(4) it is necessary to detect ethernet padding.
Extract ip_len and ip6_plen from the mbuf and provide it to the
drivers.
Add extended sanitity checks, like IP packet is shorter than TCP
header. This prevents offloading to network hardware with bougus
packets.
Also iphlen of extracted headers contains header length for IPv4
and IPv6, to make code in drivers simpler.
OK mglocker@
-/* $OpenBSD: if_bnxt.c,v 1.46 2024/02/13 13:58:19 bluhm Exp $ */
+/* $OpenBSD: if_bnxt.c,v 1.47 2024/02/14 22:41:48 bluhm Exp $ */
/*-
* Broadcom NetXtreme-C/E network driver.
*
if (ext.tcp) {
lflags |= TX_BD_LONG_LFLAGS_LSO;
hdrsize = sizeof(*ext.eh);
- if (ext.ip4)
- hdrsize += ext.ip4hlen;
- else if (ext.ip6)
- hdrsize += sizeof(*ext.ip6);
+ if (ext.ip4 || ext.ip6)
+ hdrsize += ext.iphlen;
else
tcpstat_inc(tcps_outbadtso);
***************************************************************************/
-/* $OpenBSD: if_em.c,v 1.372 2024/02/13 13:58:19 bluhm Exp $ */
+/* $OpenBSD: if_em.c,v 1.373 2024/02/14 22:41:48 bluhm Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
struct e1000_adv_tx_context_desc *TD;
uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0, mss_l4len_idx = 0;
int off = 0;
- uint8_t iphlen;
*olinfo_status = 0;
*cmd_type_len = 0;
vlan_macip_lens |= (sizeof(*ext.eh) << E1000_ADVTXD_MACLEN_SHIFT);
if (ext.ip4) {
- iphlen = ext.ip4hlen;
-
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) {
*olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
}
#ifdef INET6
} else if (ext.ip6) {
- iphlen = sizeof(*ext.ip6);
-
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV6;
#endif
- } else {
- iphlen = 0;
}
*cmd_type_len |= E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_IFCS;
*cmd_type_len |= E1000_ADVTXD_DCMD_DEXT;
*olinfo_status |= mp->m_pkthdr.len << E1000_ADVTXD_PAYLEN_SHIFT;
- vlan_macip_lens |= iphlen;
+ vlan_macip_lens |= ext.iphlen;
type_tucmd_mlhl |= E1000_ADVTXD_DCMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
if (ext.tcp) {
-/* $OpenBSD: if_igc.c,v 1.16 2024/02/13 13:58:19 bluhm Exp $ */
+/* $OpenBSD: if_igc.c,v 1.17 2024/02/14 22:41:48 bluhm Exp $ */
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
struct igc_adv_tx_context_desc *txdesc;
uint32_t type_tucmd_mlhl = 0;
uint32_t vlan_macip_lens = 0;
- uint32_t iphlen;
int off = 0;
vlan_macip_lens |= (sizeof(*ext.eh) << IGC_ADVTXD_MACLEN_SHIFT);
ether_extract_headers(mp, &ext);
if (ext.ip4) {
- iphlen = ext.ip4hlen;
-
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV4;
if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) {
*olinfo_status |= IGC_TXD_POPTS_IXSM << 8;
}
#ifdef INET6
} else if (ext.ip6) {
- iphlen = sizeof(*ext.ip6);
-
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV6;
#endif
} else {
return 0;
}
- vlan_macip_lens |= iphlen;
+ vlan_macip_lens |= ext.iphlen;
type_tucmd_mlhl |= IGC_ADVTXD_DCMD_DEXT | IGC_ADVTXD_DTYP_CTXT;
if (ext.tcp) {
-/* $OpenBSD: if_ix.c,v 1.207 2024/02/13 13:58:19 bluhm Exp $ */
+/* $OpenBSD: if_ix.c,v 1.208 2024/02/14 22:41:48 bluhm Exp $ */
/******************************************************************************
{
struct ether_extracted ext;
int offload = 0;
- uint32_t ethlen, iphlen;
ether_extract_headers(mp, &ext);
- ethlen = sizeof(*ext.eh);
- *vlan_macip_lens |= (ethlen << IXGBE_ADVTXD_MACLEN_SHIFT);
+ *vlan_macip_lens |= (sizeof(*ext.eh) << IXGBE_ADVTXD_MACLEN_SHIFT);
if (ext.ip4) {
- iphlen = ext.ip4hlen;
-
if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) {
*olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
offload = 1;
*type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
#ifdef INET6
} else if (ext.ip6) {
- iphlen = sizeof(*ext.ip6);
-
*type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
#endif
} else {
return offload;
}
- *vlan_macip_lens |= iphlen;
+ *vlan_macip_lens |= ext.iphlen;
if (ext.tcp) {
*type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
*mss_l4len_idx |= outlen << IXGBE_ADVTXD_MSS_SHIFT;
*mss_l4len_idx |= thlen << IXGBE_ADVTXD_L4LEN_SHIFT;
- hdrlen = ethlen + iphlen + thlen;
+ hdrlen = sizeof(*ext.eh) + ext.iphlen + thlen;
paylen = mp->m_pkthdr.len - hdrlen;
CLR(*olinfo_status, IXGBE_ADVTXD_PAYLEN_MASK
<< IXGBE_ADVTXD_PAYLEN_SHIFT);
ext.evh)
hdrlen += ETHER_VLAN_ENCAP_LEN;
#endif
- if (ext.ip4)
- hdrlen += ext.ip4hlen;
- if (ext.ip6)
- hdrlen += sizeof(*ext.ip6);
+ if (ext.ip4 || ext.ip6)
+ hdrlen += ext.iphlen;
if (ext.tcp) {
hdrlen += ext.tcphlen;
tcpstat_inc(tcps_inhwlro);
-/* $OpenBSD: if_ixl.c,v 1.96 2024/02/13 13:58:19 bluhm Exp $ */
+/* $OpenBSD: if_ixl.c,v 1.97 2024/02/14 22:41:48 bluhm Exp $ */
/*
* Copyright (c) 2013-2015, Intel Corporation
offload |= ISSET(m0->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT) ?
IXL_TX_DESC_CMD_IIPT_IPV4_CSUM :
IXL_TX_DESC_CMD_IIPT_IPV4;
-
- hlen = ext.ip4hlen;
#ifdef INET6
} else if (ext.ip6) {
offload |= IXL_TX_DESC_CMD_IIPT_IPV6;
-
- hlen = sizeof(*ext.ip6);
#endif
} else {
panic("CSUM_OUT set for non-IP packet");
/* NOTREACHED */
}
+ hlen = ext.iphlen;
offload |= (ETHER_HDR_LEN >> 1) << IXL_TX_DESC_MACLEN_SHIFT;
offload |= (hlen >> 2) << IXL_TX_DESC_IPLEN_SHIFT;
-/* $OpenBSD: if_vio.c,v 1.30 2024/02/13 13:58:19 bluhm Exp $ */
+/* $OpenBSD: if_vio.c,v 1.31 2024/02/14 22:41:48 bluhm Exp $ */
/*
* Copyright (c) 2012 Stefan Fritsch, Alexander Fiveg.
else
hdr->csum_offset = offsetof(struct udphdr, uh_sum);
- if (ext.ip4)
- hdr->csum_start += ext.ip4hlen;
-#ifdef INET6
- else if (ext.ip6)
- hdr->csum_start += sizeof(*ext.ip6);
-#endif
+ if (ext.ip4 || ext.ip6)
+ hdr->csum_start += ext.iphlen;
hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
}
-/* $OpenBSD: if_ethersubr.c,v 1.292 2024/02/13 13:58:19 bluhm Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.293 2024/02/14 22:41:48 bluhm Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
ether_extract_headers(struct mbuf *m0, struct ether_extracted *ext)
{
struct mbuf *m;
- size_t hlen;
+ size_t hlen, iplen;
int hoff;
uint8_t ipproto;
uint16_t ether_type;
ext->ip4 = NULL;
return;
}
- ext->ip4hlen = hlen;
+ iplen = ntohs(ext->ip4->ip_len);
+ if (ext->paylen < iplen) {
+ DPRINTF("paylen %u, ip4len %zu", ext->paylen, iplen);
+ ext->ip4 = NULL;
+ return;
+ }
+ if (iplen < hlen) {
+ DPRINTF("ip4len %zu, ip4hlen %zu", iplen, hlen);
+ ext->ip4 = NULL;
+ return;
+ }
+ ext->iplen = iplen;
+ ext->iphlen = hlen;
ext->paylen -= hlen;
ipproto = ext->ip4->ip_p;
ext->ip6 = NULL;
return;
}
+ iplen = hlen + ntohs(ext->ip6->ip6_plen);
+ if (ext->paylen < iplen) {
+ DPRINTF("paylen %u, ip6len %zu", ext->paylen, iplen);
+ ext->ip6 = NULL;
+ return;
+ }
+ ext->iplen = iplen;
+ ext->iphlen = hlen;
ext->paylen -= hlen;
ipproto = ext->ip6->ip6_nxt;
break;
ext->tcp = NULL;
return;
}
- if (ext->paylen < hlen) {
- DPRINTF("paylen %u, tcphlen %zu", ext->paylen, hlen);
+ if (ext->iplen - ext->iphlen < hlen) {
+ DPRINTF("iplen %u, iphlen %u, tcphlen %zu",
+ ext->iplen, ext->iphlen, hlen);
ext->tcp = NULL;
return;
}
ext->udp = (struct udphdr *)(mtod(m, caddr_t) + hoff);
hlen = sizeof(*ext->udp);
- if (ext->paylen < hlen) {
- DPRINTF("paylen %u, udphlen %zu", ext->paylen, hlen);
+ if (ext->iplen - ext->iphlen < hlen) {
+ DPRINTF("iplen %u, iphlen %u, udphlen %zu",
+ ext->iplen, ext->iphlen, hlen);
ext->udp = NULL;
return;
}
break;
}
- DNPRINTF(2, "%s%s%s%s%s%s ip4h %u, tcph %u, payl %u",
+ DNPRINTF(2, "%s%s%s%s%s%s ip %u, iph %u, tcph %u, payl %u",
ext->eh ? "eh," : "", ext->evh ? "evh," : "",
ext->ip4 ? "ip4," : "", ext->ip6 ? "ip6," : "",
ext->tcp ? "tcp," : "", ext->udp ? "udp," : "",
- ext->ip4hlen, ext->tcphlen, ext->paylen);
+ ext->iplen, ext->iphlen, ext->tcphlen, ext->paylen);
}
-/* $OpenBSD: if_ether.h,v 1.91 2024/02/13 13:58:19 bluhm Exp $ */
+/* $OpenBSD: if_ether.h,v 1.92 2024/02/14 22:41:48 bluhm Exp $ */
/* $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $ */
/*
struct ip6_hdr *ip6;
struct tcphdr *tcp;
struct udphdr *udp;
- u_int ip4hlen;
+ u_int iplen;
+ u_int iphlen;
u_int tcphlen;
u_int paylen;
};