Fix inline vlan-tag handling of forwarded LRO packets from ix(4)
authorjan <jan@openbsd.org>
Thu, 27 Jul 2023 20:21:25 +0000 (20:21 +0000)
committerjan <jan@openbsd.org>
Thu, 27 Jul 2023 20:21:25 +0000 (20:21 +0000)
Implement vlan-tag parsing ether_extract_header() to use this information
to adjust the MSS calculation of LRO packets.

pointed out by mbuhl and bluhm

with tweaks from bluhm

ok bluhm@

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

index 3610ed9..80df360 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ix.c,v 1.200 2023/07/18 16:01:20 bluhm Exp $       */
+/*     $OpenBSD: if_ix.c,v 1.201 2023/07/27 20:21:25 jan Exp $ */
 
 /******************************************************************************
 
@@ -3275,6 +3275,10 @@ ixgbe_rxeof(struct rx_ring *rxr)
                                /* Calculate header size. */
                                ether_extract_headers(sendmp, &ext);
                                hdrlen = sizeof(*ext.eh);
+#if NVLAN > 0
+                               if (ext.evh)
+                                       hdrlen += ETHER_VLAN_ENCAP_LEN;
+#endif
                                if (ext.ip4)
                                        hdrlen += ext.ip4->ip_hl << 2;
                                if (ext.ip6)
index 20f7a9a..a77a0d6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ethersubr.c,v 1.290 2023/07/06 19:46:53 kn Exp $   */
+/*     $OpenBSD: if_ethersubr.c,v 1.291 2023/07/27 20:21:25 jan Exp $  */
 /*     $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $        */
 
 /*
@@ -1040,6 +1040,7 @@ ether_extract_headers(struct mbuf *mp, struct ether_extracted *ext)
        uint64_t         hlen;
        int              hoff;
        uint8_t          ipproto;
+       uint16_t         ether_type;
 
        /* Return NULL if header was not recognized. */
        memset(ext, 0, sizeof(*ext));
@@ -1048,9 +1049,20 @@ ether_extract_headers(struct mbuf *mp, struct ether_extracted *ext)
                return;
 
        ext->eh = mtod(mp, struct ether_header *);
-       switch (ntohs(ext->eh->ether_type)) {
+       ether_type = ntohs(ext->eh->ether_type);
+       hlen = sizeof(*ext->eh);
+
+#if NVLAN > 0
+       if (ether_type == ETHERTYPE_VLAN) {
+               ext->evh = mtod(mp, struct ether_vlan_header *);
+               ether_type = ntohs(ext->evh->evl_proto);
+               hlen = sizeof(*ext->evh);
+       }
+#endif
+
+       switch (ether_type) {
        case ETHERTYPE_IP:
-               m = m_getptr(mp, sizeof(*ext->eh), &hoff);
+               m = m_getptr(mp, hlen, &hoff);
                if (m == NULL || m->m_len - hoff < sizeof(*ext->ip4))
                        return;
                ext->ip4 = (struct ip *)(mtod(m, caddr_t) + hoff);
@@ -1064,7 +1076,7 @@ ether_extract_headers(struct mbuf *mp, struct ether_extracted *ext)
                break;
 #ifdef INET6
        case ETHERTYPE_IPV6:
-               m = m_getptr(mp, sizeof(*ext->eh), &hoff);
+               m = m_getptr(mp, hlen, &hoff);
                if (m == NULL || m->m_len - hoff < sizeof(*ext->ip6))
                        return;
                ext->ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + hoff);
index 9ff5bae..ed28944 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ether.h,v 1.89 2023/07/06 19:46:53 kn Exp $        */
+/*     $OpenBSD: if_ether.h,v 1.90 2023/07/27 20:21:25 jan Exp $       */
 /*     $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $    */
 
 /*
@@ -301,11 +301,12 @@ 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;
+       struct ether_header             *eh;
+       struct ether_vlan_header        *evh;
+       struct ip                       *ip4;
+       struct ip6_hdr                  *ip6;
+       struct tcphdr                   *tcp;
+       struct udphdr                   *udp;
 };
 
 void ether_extract_headers(struct mbuf *, struct ether_extracted *);