Hi,

we have several drivers which have to parse the content of mbufs.  This
diff suggest a central parsing function for this.  Thus, we can reduce
redundant code.

I just start with ix(4) and ixl(4) because it was easy to test for me.
But, this could also improve em(4), igc(4), ale(4) and oce(4).

I'm not sure about the name, the api nor the place of this code.  So, if
someone has a better idea: i'm open to anything.

bye,
Jan

Index: dev/pci/if_ix.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_ix.c,v
retrieving revision 1.189
diff -u -p -r1.189 if_ix.c
--- dev/pci/if_ix.c     2 Sep 2022 14:08:09 -0000       1.189
+++ dev/pci/if_ix.c     17 Jan 2023 16:31:19 -0000
@@ -2477,23 +2477,18 @@ 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_header *eh = NULL;
+       struct ip *ip = NULL;
+       struct ip6_hdr *ip6 = NULL;
        int offload = 0;
        uint32_t iphlen;
        uint8_t ipproto;
 
-       *vlan_macip_lens |= (sizeof(*eh) << IXGBE_ADVTXD_MACLEN_SHIFT);
+       if_parse(mp, &eh, &ip, &ip6, NULL, NULL);
 
-       switch (ntohs(eh->ether_type)) {
-       case ETHERTYPE_IP: {
-               struct ip *ip;
-
-               m = m_getptr(mp, sizeof(*eh), &hoff);
-               KASSERT(m != NULL && m->m_len - hoff >= sizeof(*ip));
-               ip = (struct ip *)(mtod(m, caddr_t) + hoff);
+       *vlan_macip_lens |= (sizeof(*eh) << IXGBE_ADVTXD_MACLEN_SHIFT);
 
+       if (ip) {
                iphlen = ip->ip_hl << 2;
                ipproto = ip->ip_p;
 
@@ -2503,26 +2498,14 @@ ixgbe_csum_offload(struct mbuf *mp, uint
                }
 
                *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);
-
+       } else if (ip6) {
                iphlen = sizeof(*ip6);
                ipproto = ip6->ip6_nxt;
 
                *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
-               break;
-       }
 #endif
-
-       default:
+       } else {
                return offload;
        }
 
Index: dev/pci/if_ixl.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_ixl.c,v
retrieving revision 1.84
diff -u -p -r1.84 if_ixl.c
--- dev/pci/if_ixl.c    5 Aug 2022 13:57:16 -0000       1.84
+++ dev/pci/if_ixl.c    16 Jan 2023 23:58:05 -0000
@@ -2784,12 +2784,15 @@ ixl_load_mbuf(bus_dma_tag_t dmat, bus_dm
 static uint64_t
 ixl_tx_setup_offload(struct mbuf *m0)
 {
-       struct mbuf *m;
-       int hoff;
+       struct ether_header *eh = NULL;
+       struct ip *ip = NULL;
+       struct ip6_hdr *ip6 = NULL;
+       struct tcphdr *th = NULL;
        uint64_t hlen;
        uint8_t ipproto;
        uint64_t offload = 0;
 
+
        if (ISSET(m0->m_flags, M_VLANTAG)) {
                uint64_t vtag = m0->m_pkthdr.ether_vtag;
                offload |= IXL_TX_DESC_CMD_IL2TAG1;
@@ -2800,39 +2803,23 @@ 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);
+       if_parse(m0, &eh, &ip, &ip6, &th, NULL);
 
+       if (ip) {
                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;
-       }
-
 #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 (ip6) {
                offload |= IXL_TX_DESC_CMD_IIPT_IPV6;
 
                hlen = sizeof(*ip6);
                ipproto = ip6->ip6_nxt;
-               break;
-       }
 #endif
-       default:
+       } else {
                panic("CSUM_OUT set for non-IP packet");
                /* NOTREACHED */
        }
@@ -2842,15 +2829,12 @@ ixl_tx_setup_offload(struct mbuf *m0)
 
        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 (th == NULL)
+                       break;
+
                offload |= IXL_TX_DESC_CMD_L4T_EOFT_TCP;
                offload |= (uint64_t)th->th_off << IXL_TX_DESC_L4LEN_SHIFT;
                break;
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.683
diff -u -p -r1.683 if.c
--- net/if.c    23 Nov 2022 16:57:37 -0000      1.683
+++ net/if.c    16 Jan 2023 23:20:21 -0000
@@ -96,6 +96,10 @@
 #include <net/netisr.h>
 
 #include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
 #include <netinet/if_ether.h>
 #include <netinet/igmp.h>
 #ifdef MROUTING
@@ -3352,6 +3356,75 @@ if_rxr_ioctl(struct if_rxrinfo *ifri, co
        ifr.ifr_info = *rxr;
 
        return (if_rxr_info_ioctl(ifri, 1, &ifr));
+}
+
+void
+if_parse(struct mbuf *mp, struct ether_header **eh, struct ip **ip4,
+    struct ip6_hdr **ip6, struct tcphdr **tcp, struct udphdr **udp)
+{
+       struct mbuf             *m;
+       int                      hoff;
+       uint8_t                  ipproto;
+       uint64_t                 hlen;
+
+       if (eh == NULL)
+               return;
+
+       *eh = mtod(mp, struct ether_header *);
+       switch (ntohs((*eh)->ether_type)) {
+       case ETHERTYPE_IP:
+               if (ip4 == NULL)
+                       return;
+
+               m = m_getptr(mp, sizeof(**eh), &hoff);
+               KASSERT(m != NULL && m->m_len - hoff >= sizeof(**ip4));
+               *ip4 = (struct ip *)(mtod(m, caddr_t) + hoff);
+
+               hlen = (*ip4)->ip_hl << 2;
+               ipproto = (*ip4)->ip_p;
+
+               break;
+
+#ifdef INET6
+       case ETHERTYPE_IPV6:
+               if (ip6 == NULL)
+                       return;
+
+               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);
+
+               hlen = sizeof(**ip6);
+               ipproto = (*ip6)->ip6_nxt;
+
+               break;
+#endif
+
+       default:
+               return;
+       }
+
+       switch (ipproto) {
+       case IPPROTO_TCP:
+               if (tcp == NULL)
+                       return;
+
+               m = m_getptr(m, hoff + hlen, &hoff);
+               KASSERT(m != NULL && m->m_len - hoff >= sizeof(**tcp));
+               *tcp = (struct tcphdr *)(mtod(m, caddr_t) + hoff);
+               break;
+
+       case IPPROTO_UDP:
+               if (udp == NULL)
+                       return;
+
+               m = m_getptr(m, hoff + hlen, &hoff);
+               KASSERT(m != NULL && m->m_len - hoff >= sizeof(**udp));
+               *udp = (struct udphdr *)(mtod(m, caddr_t) + hoff);
+               break;
+       }
+
+       return;
 }
 
 /*
Index: net/if_var.h
===================================================================
RCS file: /cvs/src/sys/net/if_var.h,v
retrieving revision 1.122
diff -u -p -r1.122 if_var.h
--- net/if_var.h        23 Nov 2022 14:50:59 -0000      1.122
+++ net/if_var.h        16 Jan 2023 21:50:06 -0000
@@ -317,6 +317,13 @@ int                niq_enlist(struct niqueue *, struct
 
 extern struct ifnet_head ifnetlist;
 
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netinet/if_ether.h>
+
 void   if_start(struct ifnet *);
 int    if_enqueue(struct ifnet *, struct mbuf *);
 int    if_enqueue_ifq(struct ifnet *, struct mbuf *);
@@ -371,6 +378,8 @@ u_int       if_rxr_get(struct if_rxring *, u_i
 int    if_rxr_info_ioctl(struct if_rxrinfo *, u_int, struct if_rxring_info *);
 int    if_rxr_ioctl(struct if_rxrinfo *, const char *, u_int,
            struct if_rxring *);
+void   if_parse(struct mbuf *, struct ether_header **, struct ip **,
+    struct ip6_hdr **, struct tcphdr **, struct udphdr **);
 
 void   if_counters_alloc(struct ifnet *);
 void   if_counters_free(struct ifnet *);

Reply via email to