Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Fix TSO support:



details:   https://anonhg.NetBSD.org/src/rev/13b0c7e8fe45
branches:  trunk
changeset: 996678:13b0c7e8fe45
user:      rin <rin%NetBSD.org@localhost>
date:      Wed Feb 06 08:31:38 2019 +0000

description:
Fix TSO support:
- Rename mue_tx_offload() to mue_tso_prepare().
- Take care of short mbuf's (paranoia).

diffstat:

 sys/dev/usb/if_mue.c |  56 +++++++++++++++++++++++++++++++++++----------------
 1 files changed, 38 insertions(+), 18 deletions(-)

diffs (117 lines):

diff -r 7cc01cd83882 -r 13b0c7e8fe45 sys/dev/usb/if_mue.c
--- a/sys/dev/usb/if_mue.c      Wed Feb 06 08:28:11 2019 +0000
+++ b/sys/dev/usb/if_mue.c      Wed Feb 06 08:31:38 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_mue.c,v 1.36 2019/02/06 08:28:11 rin Exp $  */
+/*     $NetBSD: if_mue.c,v 1.37 2019/02/06 08:31:38 rin Exp $  */
 /*     $OpenBSD: if_mue.c,v 1.3 2018/08/04 16:42:46 jsg Exp $  */
 
 /*
@@ -20,7 +20,7 @@
 /* Driver for Microchip LAN7500/LAN7800 chipsets. */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mue.c,v 1.36 2019/02/06 08:28:11 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mue.c,v 1.37 2019/02/06 08:31:38 rin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -146,7 +146,7 @@
 static void    mue_startup_rx_pipes(struct mue_softc *);
 
 static int     mue_encap(struct mue_softc *, struct mbuf *, int);
-static void    mue_tx_offload(struct mue_softc *, struct mbuf *);
+static int     mue_prepare_tso(struct mue_softc *, struct mbuf *);
 
 static void    mue_setmulti(struct mue_softc *);
 static void    mue_sethwcsum(struct mue_softc *);
@@ -1230,7 +1230,7 @@
        usbd_status err;
        struct mue_txbuf_hdr hdr;
        uint32_t tx_cmd_a, tx_cmd_b;
-       int csum, len;
+       int csum, len, rv;
        bool tso, ipe, tpe;
 
        csum = m->m_pkthdr.csum_flags;
@@ -1260,7 +1260,9 @@
                        tx_cmd_b = MUE_TX_MSS_MIN;
                tx_cmd_b <<= MUE_TX_CMD_B_MSS_SHIFT;
                KASSERT((tx_cmd_b & ~MUE_TX_CMD_B_MSS_MASK) == 0);
-               mue_tx_offload(sc, m);
+               rv = mue_prepare_tso(sc, m);
+               if (__predict_false(rv))
+                       return rv;
        } else {
                if (ipe)
                        tx_cmd_a |= MUE_TX_CMD_A_IPE;
@@ -1292,38 +1294,56 @@
        return 0;
 }
 
-static void
-mue_tx_offload(struct mue_softc *sc, struct mbuf *m)
+/*
+ * L3 length field should be cleared.
+ */
+static int
+mue_prepare_tso(struct mue_softc *sc, struct mbuf *m)
 {
        struct ether_header *eh;
        struct ip *ip;
        struct ip6_hdr *ip6;
+       uint16_t type, len = 0;
        int off;
 
-       eh = mtod(m, struct ether_header *);
-       switch (htons(eh->ether_type)) {
+       if (__predict_true(m->m_len >= sizeof(*eh))) {
+               eh = mtod(m, struct ether_header *);
+               type = eh->ether_type;
+       } else
+               m_copydata(m, offsetof(struct ether_header, ether_type),
+                   sizeof(type), &type);
+       switch (type = htons(type)) {
        case ETHERTYPE_IP:
        case ETHERTYPE_IPV6:
                off = ETHER_HDR_LEN;
                break;
        case ETHERTYPE_VLAN:
-               /* XXX not yet supported */
                off = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
                break;
        default:
-               /* XXX */
-               panic("%s: unsupported ethertype\n", __func__);
-               /* NOTREACHED */
+               if (usbd_ratecheck(&sc->mue_tx_notice))
+                       MUE_PRINTF(sc, "dropping invalid frame "
+                           "type 0x%04hx csum_flags 0x%08x\n", 
+                           type, m->m_pkthdr.csum_flags);
+               return EINVAL;
        }
 
-       /* Packet length should be cleared. */
        if (m->m_pkthdr.csum_flags & M_CSUM_TSOv4) {
-               ip = (void *)(mtod(m, char *) + off);
-               ip->ip_len = 0;
+               if (__predict_true(m->m_len >= off + sizeof(*ip))) {
+                       ip = (void *)(mtod(m, char *) + off);
+                       ip->ip_len = 0;
+               } else
+                       m_copyback(m, off + offsetof(struct ip, ip_len),
+                           sizeof(len), &len);
        } else {
-               ip6 = (void *)(mtod(m, char *) + off);
-               ip6->ip6_plen = 0;
+               if (__predict_true(m->m_len >= off + sizeof(*ip6))) {
+                       ip6 = (void *)(mtod(m, char *) + off);
+                       ip6->ip6_plen = 0;
+               } else
+                       m_copyback(m, off + offsetof(struct ip6_hdr, ip6_plen),
+                           sizeof(len), &len);
        }
+       return 0;
 }
 
 static void



Home | Main Index | Thread Index | Old Index