svn commit: r326702 - head/sys/net
Stephen Hurd
shurd at FreeBSD.org
Fri Dec 8 18:43:32 UTC 2017
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));
More information about the svn-src-all
mailing list