backing "consolidate mbuf header parsing on device driver layer"
authorderaadt <deraadt@openbsd.org>
Thu, 26 Jan 2023 07:32:39 +0000 (07:32 +0000)
committerderaadt <deraadt@openbsd.org>
Thu, 26 Jan 2023 07:32:39 +0000 (07:32 +0000)
easily repeatable ASSERT happens seconds after starting compiles over nfs.

sys/dev/pci/if_ix.c
sys/dev/pci/if_ixl.c
sys/net/if_ethersubr.c
sys/netinet/if_ether.h

index 21d4820..32e0c60 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ix.c,v 1.190 2023/01/24 22:35:46 jan Exp $ */
+/*     $OpenBSD: if_ix.c,v 1.191 2023/01/26 07:32:39 deraadt Exp $     */
 
 /******************************************************************************
 
@@ -2477,16 +2477,25 @@ 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_extracted ext;
+       struct ether_header *eh = mtod(mp, struct ether_header *);
+       struct mbuf *m;
+       int hoff;
        int offload = 0;
        uint32_t iphlen;
+       uint8_t ipproto;
 
-       ether_extract_headers(mp, &ext);
+       *vlan_macip_lens |= (sizeof(*eh) << IXGBE_ADVTXD_MACLEN_SHIFT);
 
-       *vlan_macip_lens |= (sizeof(*ext.eh) << IXGBE_ADVTXD_MACLEN_SHIFT);
+       switch (ntohs(eh->ether_type)) {
+       case ETHERTYPE_IP: {
+               struct ip *ip;
 
-       if (ext.ip4) {
-               iphlen = ext.ip4->ip_hl << 2;
+               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 (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) {
                        *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
@@ -2494,30 +2503,46 @@ ixgbe_csum_offload(struct mbuf *mp, uint32_t *vlan_macip_lens,
                }
 
                *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4;
+               break;
+       }
+
 #ifdef INET6
-       } else if (ext.ip6) {
-               iphlen = sizeof(*ext.ip6);
+       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;
 
                *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
+               break;
+       }
 #endif
-       } else {
+
+       default:
                return offload;
        }
 
        *vlan_macip_lens |= iphlen;
 
-       if (ext.tcp) {
+       switch (ipproto) {
+       case IPPROTO_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;
                }
-       } else if (ext.udp) {
+               break;
+       case IPPROTO_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;
index 8d27207..c565f70 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ixl.c,v 1.85 2023/01/24 22:35:46 jan Exp $ */
+/*     $OpenBSD: if_ixl.c,v 1.86 2023/01/26 07:32:39 deraadt Exp $ */
 
 /*
  * Copyright (c) 2013-2015, Intel Corporation
@@ -2784,8 +2784,10 @@ 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 ether_extracted ext;
+       struct mbuf *m;
+       int hoff;
        uint64_t hlen;
+       uint8_t ipproto;
        uint64_t offload = 0;
 
        if (ISSET(m0->m_flags, M_VLANTAG)) {
@@ -2798,21 +2800,39 @@ ixl_tx_setup_offload(struct mbuf *m0)
            M_IPV4_CSUM_OUT|M_TCP_CSUM_OUT|M_UDP_CSUM_OUT))
                return (offload);
 
-       ether_extract_headers(m0, &ext);
+       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);
 
-       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 = ext.ip4->ip_hl << 2;
+               hlen = ip->ip_hl << 2;
+               ipproto = ip->ip_p;
+               break;
+       }
+
 #ifdef INET6
-       } else if (ext.ip6) {
+       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);
                offload |= IXL_TX_DESC_CMD_IIPT_IPV6;
 
-               hlen = sizeof(*ext.ip6);
+               hlen = sizeof(*ip6);
+               ipproto = ip6->ip6_nxt;
+               break;
+       }
 #endif
-       } else {
+       default:
                panic("CSUM_OUT set for non-IP packet");
                /* NOTREACHED */
        }
@@ -2820,12 +2840,30 @@ 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;
 
-       if (ext.tcp && ISSET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) {
+       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);
                offload |= IXL_TX_DESC_CMD_L4T_EOFT_TCP;
-               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 |= (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 |= IXL_TX_DESC_CMD_L4T_EOFT_UDP;
-               offload |= (sizeof(*ext.udp) >> 2) << IXL_TX_DESC_L4LEN_SHIFT;
+               offload |= (sizeof(struct udphdr) >> 2) <<
+                   IXL_TX_DESC_L4LEN_SHIFT;
+               break;
        }
 
        return (offload);
index 9c28a1c..c0c2187 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ethersubr.c,v 1.285 2023/01/24 22:35:47 jan Exp $  */
+/*     $OpenBSD: if_ethersubr.c,v 1.286 2023/01/26 07:32:40 deraadt Exp $      */
 /*     $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $        */
 
 /*
@@ -98,10 +98,6 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 #include <netinet/ip_ipsp.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/tcp.h>
-#include <netinet/udp.h>
 
 #if NBPFILTER > 0
 #include <net/bpf.h>
@@ -1038,56 +1034,3 @@ 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;
-       }
-}
index a90bacb..4758b38 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ether.h,v 1.85 2023/01/24 22:35:47 jan Exp $       */
+/*     $OpenBSD: if_ether.h,v 1.86 2023/01/26 07:32:40 deraadt Exp $   */
 /*     $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $    */
 
 /*
@@ -297,16 +297,6 @@ 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