Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Dec 2017 18:43:31 +0000 (UTC)
From:      Stephen Hurd <shurd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r326702 - head/sys/net
Message-ID:  <201712081843.vB8IhVdA064251@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: shurd
Date: Fri Dec  8 18:43:31 2017
New Revision: 326702
URL: https://svnweb.freebsd.org/changeset/base/326702

Log:
  Handle read-only mbufs in iflib ether pad function
  
  If ethernet padding is enabled, and a read-only mbuf is passed,
  it would modify the mbuf using m_append(). Instead, call m_dup() and
  append to the new packet.
  
  Reported by:	Pyun YongHyeon
  Sponsored by:	Limelight Networks
  Differential Revision:	https://reviews.freebsd.org/D13414

Modified:
  head/sys/net/iflib.c

Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c	Fri Dec  8 18:04:43 2017	(r326701)
+++ head/sys/net/iflib.c	Fri Dec  8 18:43:31 2017	(r326702)
@@ -3112,7 +3112,7 @@ calc_next_txd(iflib_txq_t txq, int cidx, uint8_t qid)
  * 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)
+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
@@ -3120,14 +3120,25 @@ iflib_ether_pad(device_t dev, struct mbuf *m_head, uin
 	 */
 	static char pad[18];	/* just zeros */
 	int n;
+	struct mbuf *new_head;
 
-	for (n = min_frame_size - m_head->m_pkthdr.len;
+	if (!M_WRITABLE(*m_head)) {
+		new_head = m_dup(*m_head, M_NOWAIT);
+		if (new_head == NULL) {
+			device_printf(dev, "cannot pad short frame, m_dup() failed");
+			return ENOMEM;
+		}
+		m_freem(*m_head);
+		*m_head = new_head;
+	}
+
+	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))
+		if (!m_append(*m_head, min(n, sizeof(pad)), pad))
 			break;
 
 	if (n > 0) {
-		m_freem(m_head);
+		m_freem(*m_head);
 		device_printf(dev, "cannot pad short frame\n");
 		DBG_COUNTER_INC(encap_pad_mbuf_fail);
 		return (ENOBUFS);
@@ -3189,13 +3200,13 @@ iflib_encap(iflib_txq_t txq, struct mbuf **m_headp)
 		desc_tag = txq->ift_desc_tag;
 		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);
+		err = iflib_ether_pad(ctx->ifc_dev, m_headp, scctx->isc_min_frame_size);
 		if (err)
 			return err;
 	}
+	m_head = *m_headp;
 
 	pkt_info_zero(&pi);
 	pi.ipi_mflags = (m_head->m_flags & (M_VLANTAG|M_BCAST|M_MCAST));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201712081843.vB8IhVdA064251>