Hi,

We have a lot of redundant code on the network device driver layer, that
parses the content of mbufs for ethernet, ip and tcp header.  This diff
introduces a new function if_parse_packet() to centralize this feature.
It just refactors ix(4) and ixl(4) code because, I could test this cards
and won't blowup this diff.  But, igc(3), ale(4) and oce(4) could also
be improved with this.  Beside of refactoring, we'll need this kind of
code in ix(4) and other drivers for better checksum and TSO support.

I'm not sure about the correct naming or place for this helper function.
Thus, nitpicking and bike shading is welcome. :)

bye,
Jan

Index: dev/pci/if_ix.c
===================================================================
RCS file: /mount/openbsd/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     24 Oct 2022 13:51:22 -0000
@@ -2477,25 +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;
        int offload = 0;
-       uint32_t iphlen;
        uint8_t ipproto;
 
-       *vlan_macip_lens |= (sizeof(*eh) << IXGBE_ADVTXD_MACLEN_SHIFT);
+       struct if_hdr hdr;
 
-       switch (ntohs(eh->ether_type)) {
-       case ETHERTYPE_IP: {
-               struct ip *ip;
+       if_parse_packet(mp, &hdr);
 
-               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 |= (hdr.l2len << IXGBE_ADVTXD_MACLEN_SHIFT);
 
-               iphlen = ip->ip_hl << 2;
-               ipproto = ip->ip_p;
+       switch (ntohs(hdr.eth->ether_type)) {
+       case ETHERTYPE_IP: {
+               ipproto = hdr.ip4->ip_p;
 
                if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) {
                        *olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
@@ -2508,15 +2501,7 @@ ixgbe_csum_offload(struct mbuf *mp, uint
 
 #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;
-
+               ipproto = hdr.ip6->ip6_nxt;
                *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
                break;
        }
@@ -2526,7 +2511,7 @@ ixgbe_csum_offload(struct mbuf *mp, uint
                return offload;
        }
 
-       *vlan_macip_lens |= iphlen;
+       *vlan_macip_lens |= hdr.l3len;
 
        switch (ipproto) {
        case IPPROTO_TCP:
Index: dev/pci/if_ixgb.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/dev/pci/if_ixgb.h,v
retrieving revision 1.19
diff -u -p -r1.19 if_ixgb.h
--- dev/pci/if_ixgb.h   24 Nov 2015 17:11:39 -0000      1.19
+++ dev/pci/if_ixgb.h   24 Oct 2022 13:27:43 -0000
@@ -54,6 +54,7 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #include <netinet/in.h>
 #include <netinet/ip.h>
+#include <netinet/ip6.h>
 #include <netinet/if_ether.h>
 #include <netinet/tcp.h>
 #include <netinet/udp.h>
Index: dev/pci/if_ixl.c
===================================================================
RCS file: /mount/openbsd/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    24 Oct 2022 16:34:29 -0000
@@ -2784,11 +2784,12 @@ 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;
-       uint64_t hlen;
        uint8_t ipproto;
        uint64_t offload = 0;
+       struct if_hdr hdr;
+
+       memset(&hdr, 0, sizeof(hdr));
+       if_parse_packet(m0, &hdr);
 
        if (ISSET(m0->m_flags, M_VLANTAG)) {
                uint64_t vtag = m0->m_pkthdr.ether_vtag;
@@ -2800,35 +2801,20 @@ 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)) {
+       switch (ntohs(hdr.eth->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);
-
                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;
+               ipproto = hdr.ip4->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);
- 
                offload |= IXL_TX_DESC_CMD_IIPT_IPV6;
-
-               hlen = sizeof(*ip6);
-               ipproto = ip6->ip6_nxt;
+               ipproto = hdr.ip6->ip6_nxt;
                break;
        }
 #endif
@@ -2838,21 +2824,15 @@ 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;
+       offload |= (hdr.l3len >> 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);
- 
                offload |= IXL_TX_DESC_CMD_L4T_EOFT_TCP;
-               offload |= (uint64_t)th->th_off << IXL_TX_DESC_L4LEN_SHIFT;
+               offload |= (uint64_t)hdr.tcp->th_off << IXL_TX_DESC_L4LEN_SHIFT;
                break;
        }
 
Index: net/if.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/net/if.c,v
retrieving revision 1.665
diff -u -p -r1.665 if.c
--- net/if.c    8 Sep 2022 10:22:06 -0000       1.665
+++ net/if.c    24 Oct 2022 15:40:33 -0000
@@ -3364,6 +3364,54 @@ if_rxr_ioctl(struct if_rxrinfo *ifri, co
        return (if_rxr_info_ioctl(ifri, 1, &ifr));
 }
 
+void
+if_parse_packet(struct mbuf *mp, struct if_hdr *hdr)
+{
+       struct mbuf *m;
+       int hoff;
+       uint8_t ipproto;
+       memset(hdr, 0, sizeof *hdr);
+
+       hdr->eth = mtod(mp, struct ether_header *);
+       hdr->l2len = sizeof(*hdr->eth);
+
+       switch (ntohs(hdr->eth->ether_type)) {
+       case ETHERTYPE_IP: {
+               m = m_getptr(mp, hdr->l2len, &hoff);
+               KASSERT(m != NULL && m->m_len - hoff >= sizeof(*hdr->ip4));
+               hdr->ip4 = (struct ip *)(mtod(m, caddr_t) + hoff);
+               hdr->l3len = hdr->ip4->ip_hl << 2;
+               ipproto = hdr->ip4->ip_p;
+               break;
+       }
+
+#ifdef INET6
+       case ETHERTYPE_IPV6: {
+               m = m_getptr(mp, hdr->l2len, &hoff);
+               KASSERT(m != NULL && m->m_len - hoff >= sizeof(*hdr->ip6));
+               hdr->ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff);
+               hdr->l3len = sizeof(*hdr->ip6);
+               ipproto = hdr->ip6->ip6_nxt;
+               break;
+       }
+#endif
+
+       default:
+               return;
+       }
+
+       switch (ipproto) {
+       case IPPROTO_TCP:
+               m = m_getptr(mp, hdr->l2len + hdr->l3len, &hoff);
+               KASSERT(m != NULL && m->m_len - hoff >= sizeof(*hdr->tcp));
+               hdr->tcp = (struct tcphdr *)(mtod(m, caddr_t) + hoff);
+               hdr->l4len = hdr->tcp->th_off << 2;
+               break;
+       case IPPROTO_UDP:
+               break;
+       }
+}
+
 /*
  * Network stack input queues.
  */
Index: net/if.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/net/if.h,v
retrieving revision 1.209
diff -u -p -r1.209 if.h
--- net/if.h    27 Jun 2022 15:11:23 -0000      1.209
+++ net/if.h    24 Oct 2022 13:33:10 -0000
@@ -36,6 +36,12 @@
 #define _NET_IF_H_
 
 #include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
 
 /*
  * Length of interface external name, including terminating '\0'.
@@ -527,6 +533,16 @@ struct socket;
 struct ifnet;
 struct ifq_ops;
 
+struct if_hdr {
+       struct ether_header     *eth;
+       struct ip               *ip4;
+       struct ip6_hdr          *ip6;
+       struct tcphdr           *tcp;
+       int                      l2len;
+       int                      l3len;
+       int                      l4len;
+};
+
 void   if_alloc_sadl(struct ifnet *);
 void   if_free_sadl(struct ifnet *);
 void   if_attach(struct ifnet *);
@@ -556,6 +572,7 @@ void        if_congestion(void);
 int    if_congested(void);
 __dead void    unhandled_af(int);
 int    if_setlladdr(struct ifnet *, const uint8_t *);
+void   if_parse_packet(struct mbuf *, struct if_hdr *);
 struct taskq * net_tq(unsigned int);
 
 #endif /* _KERNEL */

Reply via email to