From owner-svn-src-all@freebsd.org Tue Dec 5 21:00:35 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 75439E816DA; Tue, 5 Dec 2017 21:00:35 +0000 (UTC) (envelope-from shurd@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id CCA966F731; Tue, 5 Dec 2017 21:00:33 +0000 (UTC) (envelope-from shurd@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vB5L0VcZ006615; Tue, 5 Dec 2017 21:00:31 GMT (envelope-from shurd@FreeBSD.org) Received: (from shurd@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vB5L0VnS006611; Tue, 5 Dec 2017 21:00:31 GMT (envelope-from shurd@FreeBSD.org) Message-Id: <201712052100.vB5L0VnS006611@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: shurd set sender to shurd@FreeBSD.org using -f From: Stephen Hurd Date: Tue, 5 Dec 2017 21:00:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r326578 - in head/sys: dev/bnxt net X-SVN-Group: head X-SVN-Commit-Author: shurd X-SVN-Commit-Paths: in head/sys: dev/bnxt net X-SVN-Commit-Revision: 326578 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Dec 2017 21:00:35 -0000 Author: shurd Date: Tue Dec 5 21:00:31 2017 New Revision: 326578 URL: https://svnweb.freebsd.org/changeset/base/326578 Log: iflib: Support to padding Ethernet frames to a min size Some bnxt devices do not correctly send frames smaller than 52 bytes (without CRC), so add a quirk that will pad frames to an arbitrary size before passing off to the encap routine. Reported by: Bhargava Chenna Marreddy Sponsored by: Limelight Networks Differential Revision: https://reviews.freebsd.org/D13269 Modified: head/sys/dev/bnxt/bnxt.h head/sys/dev/bnxt/if_bnxt.c head/sys/net/iflib.c head/sys/net/iflib.h Modified: head/sys/dev/bnxt/bnxt.h ============================================================================== --- head/sys/dev/bnxt/bnxt.h Tue Dec 5 20:43:24 2017 (r326577) +++ head/sys/dev/bnxt/bnxt.h Tue Dec 5 21:00:31 2017 (r326578) @@ -236,6 +236,8 @@ __FBSDID("$FreeBSD$"); ifmedia_add(softc->media, IFM_ETHER | (ifm_speed), 0, NULL); \ } while(0) +#define BNXT_MIN_FRAME_SIZE 52 /* Frames must be padded to this size for some A0 chips */ + /* NVRAM access */ enum bnxt_nvm_directory_type { BNX_DIR_TYPE_UNUSED = 0, Modified: head/sys/dev/bnxt/if_bnxt.c ============================================================================== --- head/sys/dev/bnxt/if_bnxt.c Tue Dec 5 20:43:24 2017 (r326577) +++ head/sys/dev/bnxt/if_bnxt.c Tue Dec 5 21:00:31 2017 (r326578) @@ -298,7 +298,7 @@ static struct if_shared_ctx bnxt_sctx_init = { .isc_magic = IFLIB_MAGIC, .isc_driver = &bnxt_iflib_driver, .isc_nfl = 2, // Number of Free Lists - .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ, + .isc_flags = IFLIB_HAS_RXCQ | IFLIB_HAS_TXCQ | IFLIB_NEED_ETHER_PAD, .isc_q_align = PAGE_SIZE, .isc_tx_maxsize = BNXT_TSO_SIZE, .isc_tx_maxsegsize = BNXT_TSO_SIZE, @@ -793,6 +793,7 @@ bnxt_attach_pre(if_ctx_t ctx) scctx->isc_tx_tso_size_max = BNXT_TSO_SIZE; scctx->isc_tx_tso_segsize_max = BNXT_TSO_SIZE; scctx->isc_vectors = softc->func.max_cp_rings; + scctx->isc_min_frame_size = BNXT_MIN_FRAME_SIZE; scctx->isc_txrx = &bnxt_txrx; if (scctx->isc_nrxd[0] < Modified: head/sys/net/iflib.c ============================================================================== --- head/sys/net/iflib.c Tue Dec 5 20:43:24 2017 (r326577) +++ head/sys/net/iflib.c Tue Dec 5 21:00:31 2017 (r326578) @@ -627,11 +627,14 @@ SYSCTL_INT(_net_iflib, OID_AUTO, txq_drain_encapfail, static int iflib_encap_load_mbuf_fail; +static int iflib_encap_pad_mbuf_fail; static int iflib_encap_txq_avail_fail; static int iflib_encap_txd_encap_fail; SYSCTL_INT(_net_iflib, OID_AUTO, encap_load_mbuf_fail, CTLFLAG_RD, &iflib_encap_load_mbuf_fail, 0, "# busdma load failures"); +SYSCTL_INT(_net_iflib, OID_AUTO, encap_pad_mbuf_fail, CTLFLAG_RD, + &iflib_encap_pad_mbuf_fail, 0, "# runt frame pad failures"); SYSCTL_INT(_net_iflib, OID_AUTO, encap_txq_avail_fail, CTLFLAG_RD, &iflib_encap_txq_avail_fail, 0, "# txq avail failures"); SYSCTL_INT(_net_iflib, OID_AUTO, encap_txd_encap_fail, CTLFLAG_RD, @@ -684,9 +687,10 @@ iflib_debug_reset(void) iflib_fl_refills = iflib_fl_refills_large = iflib_tx_frees = iflib_txq_drain_flushing = iflib_txq_drain_oactive = iflib_txq_drain_notready = iflib_txq_drain_encapfail = - iflib_encap_load_mbuf_fail = iflib_encap_txq_avail_fail = - iflib_encap_txd_encap_fail = iflib_task_fn_rxs = iflib_rx_intr_enables = - iflib_fast_intrs = iflib_intr_link = iflib_intr_msix = iflib_rx_unavail = + iflib_encap_load_mbuf_fail = iflib_encap_pad_mbuf_fail = + iflib_encap_txq_avail_fail = iflib_encap_txd_encap_fail = + iflib_task_fn_rxs = iflib_rx_intr_enables = iflib_fast_intrs = + iflib_intr_link = iflib_intr_msix = iflib_rx_unavail = iflib_rx_ctx_inactive = iflib_rx_zero_len = iflib_rx_if_input = iflib_rx_mbuf_null = iflib_rxd_flush = 0; } @@ -3103,6 +3107,35 @@ calc_next_txd(iflib_txq_t txq, int cidx, uint8_t qid) return (next < end ? next : start); } +/* + * Pad an mbuf to ensure a minimum ethernet frame size. + * min_frame_size is the frame size (less CRC) to pad the mbuf to + */ +static __noinline int +iflib_ether_pad(device_t dev, struct mbuf *m_head, uint16_t min_frame_size) +{ + /* + * 18 is enough bytes to pad an ARP packet to 46 bytes, and + * and ARP message is the smallest common payload I can think of + */ + static char pad[18]; /* just zeros */ + int n; + + for (n = min_frame_size - m_head->m_pkthdr.len; + n > 0; n -= sizeof(pad)) + if (!m_append(m_head, min(n, sizeof(pad)), pad)) + break; + + if (n > 0) { + m_freem(m_head); + device_printf(dev, "cannot pad short frame\n"); + DBG_COUNTER_INC(encap_pad_mbuf_fail); + return (ENOBUFS); + } + + return 0; +} + static int iflib_encap(iflib_txq_t txq, struct mbuf **m_headp) { @@ -3157,6 +3190,12 @@ iflib_encap(iflib_txq_t txq, struct mbuf **m_headp) max_segs = scctx->isc_tx_nsegments; } m_head = *m_headp; + if ((sctx->isc_flags & IFLIB_NEED_ETHER_PAD) && + __predict_false(m_head->m_pkthdr.len < scctx->isc_min_frame_size)) { + err = iflib_ether_pad(ctx->ifc_dev, m_head, scctx->isc_min_frame_size); + if (err) + return err; + } pkt_info_zero(&pi); pi.ipi_mflags = (m_head->m_flags & (M_VLANTAG|M_BCAST|M_MCAST)); Modified: head/sys/net/iflib.h ============================================================================== --- head/sys/net/iflib.h Tue Dec 5 20:43:24 2017 (r326577) +++ head/sys/net/iflib.h Tue Dec 5 21:00:31 2017 (r326578) @@ -217,6 +217,8 @@ typedef struct if_softc_ctx { iflib_intr_mode_t isc_intr; uint16_t isc_max_frame_size; /* set at init time by driver */ + uint16_t isc_min_frame_size; /* set at init time by driver, only used if + IFLIB_NEED_ETHER_PAD is set. */ uint32_t isc_pause_frames; /* set by driver for iflib_timer to detect */ pci_vendor_info_t isc_vendor_info; /* set by iflib prior to attach_pre */ int isc_disable_msix; @@ -314,6 +316,10 @@ typedef enum { * Driver needs csum zeroed for offloading */ #define IFLIB_NEED_ZERO_CSUM 0x80 +/* + * Driver needs frames padded to some minimum length + */ +#define IFLIB_NEED_ETHER_PAD 0x100