On Thu, Jan 19, 2023 at 12:02:29PM +0300, Vitaliy Makkoveev wrote:
> On Thu, Jan 19, 2023 at 01:55:57AM +0300, Vitaliy Makkoveev wrote:
> > > On 19 Jan 2023, at 01:39, Jan Klemkow <j.klem...@wemelug.de> wrote:
> > > 
> > > On Wed, Jan 18, 2023 at 10:50:25AM +0300, Vitaliy Makkoveev wrote:
> > >> On Tue, Jan 17, 2023 at 11:09:17PM +0100, Jan Klemkow wrote:
> > >>> 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.
> > >> 
> > >> I like code this deduplication.
> > >> 
> > >> This newly introduced function doesn't touch ifnet but only extracts
> > >> protocol headers from mbuf(9). I guess mbuf_extract_headers() or
> > >> something like is much better for name with the ern/uipc_mbuf2.c as
> > >> place.
> > > 
> > > Good Point.  Updates diff below.
> > > 
> > > +
> > > +/* Parse different TCP/IP protocol headers for a quick view inside an 
> > > mbuf. */
> > > +void
> > > +m_exract_headers(struct mbuf *mp, struct ether_header **eh, struct ip 
> > > **ip4,
> > > +    struct ip6_hdr **ip6, struct tcphdr **tcp, struct udphdr **udp)
> > > +
> > 
> > Should be m_extract_headers(). The rest of the diff looks good to me.
> > 
> 
> Please wait.
> 
> The mandatory nullification of `ip4', `ip6' and other variables passed
> to m_exract_headers() is not obvious. It is much better to return
> the integer result of extraction like m_tag_copy_chain() does.

Yes, the mandatory nullification seems to be more errorprone.  In my
opinion is the number of results it not that useful. You have to check
the retuned pointers anyway.

I moved the nullification inside of m_exract_headers().

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     19 Jan 2023 09:29:10 -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;
+       struct ip *ip;
+       struct ip6_hdr *ip6;
        int offload = 0;
        uint32_t iphlen;
        uint8_t ipproto;
 
-       *vlan_macip_lens |= (sizeof(*eh) << IXGBE_ADVTXD_MACLEN_SHIFT);
+       m_extract_headers(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    19 Jan 2023 09:29:17 -0000
@@ -2784,8 +2784,10 @@ 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;
+       struct ip *ip;
+       struct ip6_hdr *ip6;
+       struct tcphdr *th;
        uint64_t hlen;
        uint8_t ipproto;
        uint64_t offload = 0;
@@ -2800,39 +2802,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);
+       m_extract_headers(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 +2828,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: kern/uipc_mbuf2.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_mbuf2.c,v
retrieving revision 1.45
diff -u -p -r1.45 uipc_mbuf2.c
--- kern/uipc_mbuf2.c   12 Dec 2020 11:48:54 -0000      1.45
+++ kern/uipc_mbuf2.c   19 Jan 2023 09:27:44 -0000
@@ -68,6 +68,10 @@
 #include <sys/pool.h>
 #include <sys/mbuf.h>
 
+#include <net/if.h>
+#include <net/if_var.h>
+#include <netinet/if_ether.h>
+
 extern struct pool mtagpool;
 
 /* can't call it m_dup(), as freebsd[34] uses m_dup() with different arg */
@@ -386,4 +390,86 @@ struct m_tag *
 m_tag_next(struct mbuf *m, struct m_tag *t)
 {
        return (SLIST_NEXT(t, m_tag_link));
+}
+
+/* Parse different TCP/IP protocol headers for a quick view inside an mbuf. */
+void
+m_extract_headers(struct mbuf *mp, struct ether_header **eh, struct ip **ip4,
+    struct ip6_hdr **ip6, struct tcphdr **tcp, struct udphdr **udp)
+{
+       struct mbuf     *m;
+       uint64_t         hlen;
+       int              hoff;
+       uint8_t          ipproto;
+
+       /* Return NULL if header was not recognized. */
+       if (eh != NULL)
+               *eh = NULL;
+       if (ip4 != NULL)
+               *ip4 = NULL;
+       if (ip6 != NULL)
+               *ip6 = NULL;
+       if (tcp != NULL)
+               *tcp = NULL;
+       if (udp != NULL)
+               *udp = NULL;
+
+       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: sys/mbuf.h
===================================================================
RCS file: /cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.255
diff -u -p -r1.255 mbuf.h
--- sys/mbuf.h  15 Aug 2022 16:15:37 -0000      1.255
+++ sys/mbuf.h  19 Jan 2023 09:28:04 -0000
@@ -37,6 +37,14 @@
 
 #include <sys/queue.h>
 
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+struct ether_header;
+
 /*
  * Constants related to network buffer management.
  * MCLBYTES must be no larger than PAGE_SIZE (the software page size) and,
@@ -466,6 +474,8 @@ int m_tag_copy_chain(struct mbuf *, stru
 void   m_tag_init(struct mbuf *);
 struct m_tag *m_tag_first(struct mbuf *);
 struct m_tag *m_tag_next(struct mbuf *, struct m_tag *);
+void   m_extract_headers(struct mbuf *, struct ether_header **, struct ip **,
+    struct ip6_hdr **, struct tcphdr **, struct udphdr **);
 
 /* Packet tag types */
 #define PACKET_TAG_IPSEC_IN_DONE       0x0001  /* IPsec applied, in */

Reply via email to