Module Name: src Committed By: rin Date: Wed Feb 6 08:31:38 UTC 2019
Modified Files: src/sys/dev/usb: if_mue.c Log Message: Fix TSO support: - Rename mue_tx_offload() to mue_tso_prepare(). - Take care of short mbuf's (paranoia). To generate a diff of this commit: cvs rdiff -u -r1.36 -r1.37 src/sys/dev/usb/if_mue.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/if_mue.c diff -u src/sys/dev/usb/if_mue.c:1.36 src/sys/dev/usb/if_mue.c:1.37 --- src/sys/dev/usb/if_mue.c:1.36 Wed Feb 6 08:28:11 2019 +++ src/sys/dev/usb/if_mue.c Wed Feb 6 08:31:38 2019 @@ -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 int mue_open_pipes(struct mue_sof 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 @@ mue_encap(struct mue_softc *sc, struct m 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 @@ mue_encap(struct mue_softc *sc, struct m 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 @@ mue_encap(struct mue_softc *sc, struct m 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