From: jan Date: Tue, 24 Jan 2023 22:35:46 +0000 (+0000) Subject: consolidate mbuf header parsing on device driver layer X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=77e41592ba5ea10bc1ba289df030553e7a1233a1;p=openbsd consolidate mbuf header parsing on device driver layer with tweaks from mvs@, mpi@ and dlg@ ok mvs@, dlg@ --- diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c index b59ec28d9f1..21d48208954 100644 --- a/sys/dev/pci/if_ix.c +++ b/sys/dev/pci/if_ix.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ix.c,v 1.189 2022/09/02 14:08:09 jan Exp $ */ +/* $OpenBSD: if_ix.c,v 1.190 2023/01/24 22:35:46 jan Exp $ */ /****************************************************************************** @@ -2477,25 +2477,16 @@ static inline int ixgbe_csum_offload(struct mbuf *mp, uint32_t *vlan_macip_lens, uint32_t *type_tucmd_mlhl, uint32_t *olinfo_status) { - struct ether_header *eh = mtod(mp, struct ether_header *); - struct mbuf *m; - int hoff; + struct ether_extracted ext; int offload = 0; uint32_t iphlen; - uint8_t ipproto; - *vlan_macip_lens |= (sizeof(*eh) << IXGBE_ADVTXD_MACLEN_SHIFT); + ether_extract_headers(mp, &ext); - switch (ntohs(eh->ether_type)) { - case ETHERTYPE_IP: { - struct ip *ip; + *vlan_macip_lens |= (sizeof(*ext.eh) << IXGBE_ADVTXD_MACLEN_SHIFT); - m = m_getptr(mp, sizeof(*eh), &hoff); - KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ip)); - ip = (struct ip *)(mtod(m, caddr_t) + hoff); - - iphlen = ip->ip_hl << 2; - ipproto = ip->ip_p; + if (ext.ip4) { + iphlen = ext.ip4->ip_hl << 2; if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) { *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8; @@ -2503,46 +2494,30 @@ ixgbe_csum_offload(struct mbuf *mp, uint32_t *vlan_macip_lens, } *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; - break; - } - #ifdef INET6 - case ETHERTYPE_IPV6: { - struct ip6_hdr *ip6; - - m = m_getptr(mp, sizeof(*eh), &hoff); - KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ip6)); - ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff); - - iphlen = sizeof(*ip6); - ipproto = ip6->ip6_nxt; + } else if (ext.ip6) { + iphlen = sizeof(*ext.ip6); *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6; - break; - } #endif - - default: + } else { return offload; } *vlan_macip_lens |= iphlen; - switch (ipproto) { - case IPPROTO_TCP: + if (ext.tcp) { *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; if (ISSET(mp->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) { *olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8; offload = 1; } - break; - case IPPROTO_UDP: + } else if (ext.udp) { *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP; if (ISSET(mp->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) { *olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8; offload = 1; } - break; } return offload; diff --git a/sys/dev/pci/if_ixl.c b/sys/dev/pci/if_ixl.c index 8af9473bc25..8d2720765bd 100644 --- a/sys/dev/pci/if_ixl.c +++ b/sys/dev/pci/if_ixl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ixl.c,v 1.84 2022/08/05 13:57:16 bluhm Exp $ */ +/* $OpenBSD: if_ixl.c,v 1.85 2023/01/24 22:35:46 jan Exp $ */ /* * Copyright (c) 2013-2015, Intel Corporation @@ -2784,10 +2784,8 @@ ixl_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m) static uint64_t ixl_tx_setup_offload(struct mbuf *m0) { - struct mbuf *m; - int hoff; + struct ether_extracted ext; uint64_t hlen; - uint8_t ipproto; uint64_t offload = 0; if (ISSET(m0->m_flags, M_VLANTAG)) { @@ -2800,39 +2798,21 @@ ixl_tx_setup_offload(struct mbuf *m0) M_IPV4_CSUM_OUT|M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) return (offload); - switch (ntohs(mtod(m0, struct ether_header *)->ether_type)) { - case ETHERTYPE_IP: { - struct ip *ip; - - m = m_getptr(m0, ETHER_HDR_LEN, &hoff); - KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ip)); - ip = (struct ip *)(mtod(m, caddr_t) + hoff); + ether_extract_headers(m0, &ext); + if (ext.ip4) { 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 = ip->ip_hl << 2; - ipproto = ip->ip_p; - break; - } - + hlen = ext.ip4->ip_hl << 2; #ifdef INET6 - case ETHERTYPE_IPV6: { - struct ip6_hdr *ip6; - - m = m_getptr(m0, ETHER_HDR_LEN, &hoff); - KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ip6)); - ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff); - + } else if (ext.ip6) { offload |= IXL_TX_DESC_CMD_IIPT_IPV6; - hlen = sizeof(*ip6); - ipproto = ip6->ip6_nxt; - break; - } + hlen = sizeof(*ext.ip6); #endif - default: + } else { panic("CSUM_OUT set for non-IP packet"); /* NOTREACHED */ } @@ -2840,30 +2820,12 @@ ixl_tx_setup_offload(struct mbuf *m0) offload |= (ETHER_HDR_LEN >> 1) << IXL_TX_DESC_MACLEN_SHIFT; offload |= (hlen >> 2) << IXL_TX_DESC_IPLEN_SHIFT; - switch (ipproto) { - case IPPROTO_TCP: { - struct tcphdr *th; - - if (!ISSET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) - break; - - m = m_getptr(m, hoff + hlen, &hoff); - KASSERT(m != NULL && m->m_len - hoff >= sizeof(*th)); - th = (struct tcphdr *)(mtod(m, caddr_t) + hoff); - + if (ext.tcp && ISSET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) { offload |= IXL_TX_DESC_CMD_L4T_EOFT_TCP; - offload |= (uint64_t)th->th_off << IXL_TX_DESC_L4LEN_SHIFT; - break; - } - - case IPPROTO_UDP: - if (!ISSET(m0->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) - break; - + offload |= (uint64_t)ext.tcp->th_off << IXL_TX_DESC_L4LEN_SHIFT; + } else if (ext.udp && ISSET(m0->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) { offload |= IXL_TX_DESC_CMD_L4T_EOFT_UDP; - offload |= (sizeof(struct udphdr) >> 2) << - IXL_TX_DESC_L4LEN_SHIFT; - break; + offload |= (sizeof(*ext.udp) >> 2) << IXL_TX_DESC_L4LEN_SHIFT; } return (offload); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 3fb702c453f..9c28a1c172e 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.284 2022/06/29 09:08:07 mvs Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.285 2023/01/24 22:35:47 jan Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -98,6 +98,10 @@ didn't get a copy, you may request one from . #include #include #include +#include +#include +#include +#include #if NBPFILTER > 0 #include @@ -1034,3 +1038,56 @@ ether_e64_to_addr(struct ether_addr *ea, uint64_t e64) e64 >>= 8; } while (i > 0); } + +/* Parse different TCP/IP protocol headers for a quick view inside an mbuf. */ +void +ether_extract_headers(struct mbuf *mp, struct ether_extracted *ext) +{ + struct mbuf *m; + uint64_t hlen; + int hoff; + uint8_t ipproto; + + /* Return NULL if header was not recognized. */ + memset(ext, 0, sizeof *ext); + + ext->eh = mtod(mp, struct ether_header *); + switch (ntohs(ext->eh->ether_type)) { + case ETHERTYPE_IP: + m = m_getptr(mp, sizeof(*ext->eh), &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ext->ip4)); + ext->ip4 = (struct ip *)(mtod(m, caddr_t) + hoff); + + hlen = ext->ip4->ip_hl << 2; + ipproto = ext->ip4->ip_p; + + break; +#ifdef INET6 + case ETHERTYPE_IPV6: + m = m_getptr(mp, sizeof(*ext->eh), &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ext->ip6)); + ext->ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff); + + hlen = sizeof(*ext->ip6); + ipproto = ext->ip6->ip6_nxt; + + break; +#endif + default: + return; + } + + switch (ipproto) { + case IPPROTO_TCP: + m = m_getptr(m, hoff + hlen, &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ext->tcp)); + ext->tcp = (struct tcphdr *)(mtod(m, caddr_t) + hoff); + break; + + case IPPROTO_UDP: + m = m_getptr(m, hoff + hlen, &hoff); + KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ext->udp)); + ext->udp = (struct udphdr *)(mtod(m, caddr_t) + hoff); + break; + } +} diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h index 8b66114f9a5..a90bacbf5cf 100644 --- a/sys/netinet/if_ether.h +++ b/sys/netinet/if_ether.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ether.h,v 1.84 2022/12/27 20:13:03 patrick Exp $ */ +/* $OpenBSD: if_ether.h,v 1.85 2023/01/24 22:35:47 jan Exp $ */ /* $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $ */ /* @@ -297,6 +297,16 @@ const struct ether_brport * uint64_t ether_addr_to_e64(const struct ether_addr *); void ether_e64_to_addr(struct ether_addr *, uint64_t); +struct ether_extracted { + struct ether_header *eh; + struct ip *ip4; + struct ip6_hdr *ip6; + struct tcphdr *tcp; + struct udphdr *udp; +}; + +void ether_extract_headers(struct mbuf *, struct ether_extracted *); + /* * Ethernet multicast address structure. There is one of these for each * multicast address or range of multicast addresses that we are supposed