git: 87cd7c333f7c - stable/15 - iflib: report output drops and handle ENOBUFS properly
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 29 Oct 2026 06:02:55 UTC
The branch stable/15 has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=87cd7c333f7c6307a9a207be038079b51a1bcd16
commit 87cd7c333f7c6307a9a207be038079b51a1bcd16
Author: Andrew Gallatin <gallatin@FreeBSD.org>
AuthorDate: 2025-09-10 13:17:35 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-10-29 05:22:34 +0000
iflib: report output drops and handle ENOBUFS properly
- Fix an mbuf leak with iflib.simple_tx=1 when we run out of tx descs
in iflib_encap(). It seems odd to free the mbuf in iflib_encap(),
but that routine consumes mbufs for other reasons, and it seemed
safest to free there rather than have the simple tx routine parse
return values to determine what needed to be freed.
- Increment counters for output drops when ENOBUFS is encountered
and output errors when other transmit errors are encountered for both
the simple and normal tx routines.
- Performed driver changes so that iflib drivers now add the generic
output drop and output error counters to their private counters in their
ifdi_get_counter routines.
Reviewed by: kbowling, markj
Differential Revision: https://reviews.freebsd.org/D52369
Sponsored by: Netflix
(cherry picked from commit 6577e32ea2c7868c275eae6d1c68f1c37d418c71)
---
sys/dev/axgbe/if_axgbe_pci.c | 3 ++-
sys/dev/e1000/if_em.c | 4 ++--
sys/dev/enetc/if_enetc.c | 3 ++-
sys/dev/ice/ice_lib.c | 6 ++++--
sys/dev/igc/if_igc.c | 4 ++--
sys/dev/ixgbe/if_ix.c | 2 --
sys/dev/ixl/if_ixl.c | 4 ++--
sys/net/iflib.c | 15 +++++++++++++++
8 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/sys/dev/axgbe/if_axgbe_pci.c b/sys/dev/axgbe/if_axgbe_pci.c
index 51db5ce54df7..00b4c6c1d451 100644
--- a/sys/dev/axgbe/if_axgbe_pci.c
+++ b/sys/dev/axgbe/if_axgbe_pci.c
@@ -2413,7 +2413,8 @@ axgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt)
case IFCOUNTER_OPACKETS:
return (pstats->txframecount_gb);
case IFCOUNTER_OERRORS:
- return (pstats->txframecount_gb - pstats->txframecount_g);
+ return (if_get_counter_default(ifp, cnt) +
+ pstats->txframecount_gb - pstats->txframecount_g);
case IFCOUNTER_IBYTES:
return (pstats->rxoctetcount_gb);
case IFCOUNTER_OBYTES:
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 6cd7ebce5f0f..74da82296b59 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -6864,8 +6864,8 @@ em_if_get_counter(if_ctx_t ctx, ift_counter cnt)
stats->ruc + stats->roc +
stats->mpc + stats->cexterr);
case IFCOUNTER_OERRORS:
- return (stats->ecol + stats->latecol +
- sc->watchdog_events);
+ return (if_get_counter_default(ifp, cnt) +
+ stats->ecol + stats->latecol + sc->watchdog_events);
default:
return (if_get_counter_default(ifp, cnt));
}
diff --git a/sys/dev/enetc/if_enetc.c b/sys/dev/enetc/if_enetc.c
index dcc6d4585991..55fec66266fe 100644
--- a/sys/dev/enetc/if_enetc.c
+++ b/sys/dev/enetc/if_enetc.c
@@ -1347,7 +1347,8 @@ enetc_get_counter(if_ctx_t ctx, ift_counter cnt)
case IFCOUNTER_IERRORS:
return (ENETC_PORT_RD8(sc, ENETC_PM0_RERR));
case IFCOUNTER_OERRORS:
- return (ENETC_PORT_RD8(sc, ENETC_PM0_TERR));
+ return (if_get_counter_default(ifp, cnt) +
+ ENETC_PORT_RD8(sc, ENETC_PM0_TERR));
default:
return (if_get_counter_default(ifp, cnt));
}
diff --git a/sys/dev/ice/ice_lib.c b/sys/dev/ice/ice_lib.c
index 3965196f728d..e84895393175 100644
--- a/sys/dev/ice/ice_lib.c
+++ b/sys/dev/ice/ice_lib.c
@@ -7823,7 +7823,8 @@ ice_get_ifnet_counter(struct ice_vsi *vsi, ift_counter counter)
case IFCOUNTER_OPACKETS:
return (es->tx_unicast + es->tx_multicast + es->tx_broadcast);
case IFCOUNTER_OERRORS:
- return (es->tx_errors);
+ return (if_get_counter_default(vsi->sc->ifp, counter) +
+ es->tx_errors);
case IFCOUNTER_COLLISIONS:
return (0);
case IFCOUNTER_IBYTES:
@@ -7837,7 +7838,8 @@ ice_get_ifnet_counter(struct ice_vsi *vsi, ift_counter counter)
case IFCOUNTER_IQDROPS:
return (es->rx_discards);
case IFCOUNTER_OQDROPS:
- return (hs->tx_dropped_link_down);
+ return (if_get_counter_default(vsi->sc->ifp, counter) +
+ hs->tx_dropped_link_down);
case IFCOUNTER_NOPROTO:
return (es->rx_unknown_protocol);
default:
diff --git a/sys/dev/igc/if_igc.c b/sys/dev/igc/if_igc.c
index 1cf866dba374..3734bb09508e 100644
--- a/sys/dev/igc/if_igc.c
+++ b/sys/dev/igc/if_igc.c
@@ -3171,8 +3171,8 @@ igc_if_get_counter(if_ctx_t ctx, ift_counter cnt)
sc->stats.ruc + sc->stats.rfc + sc->stats.roc +
sc->stats.mpc);
case IFCOUNTER_OERRORS:
- return (sc->stats.ecol + sc->stats.latecol +
- sc->watchdog_events);
+ return (if_get_counter_default(ifp, cnt) +
+ sc->stats.ecol + sc->stats.latecol + sc->watchdog_events);
default:
return (if_get_counter_default(ifp, cnt));
}
diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index 0f6604693432..ada3cead1dd1 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -1549,8 +1549,6 @@ ixgbe_if_get_counter(if_ctx_t ctx, ift_counter cnt)
return (0);
case IFCOUNTER_IQDROPS:
return (sc->iqdrops);
- case IFCOUNTER_OQDROPS:
- return (0);
case IFCOUNTER_IERRORS:
return (sc->ierrors);
default:
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index 892e663588ad..ed7163c9eba4 100644
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -1899,7 +1899,7 @@ ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt)
case IFCOUNTER_OPACKETS:
return (vsi->opackets);
case IFCOUNTER_OERRORS:
- return (vsi->oerrors);
+ return (if_get_counter_default(ifp, cnt) + vsi->oerrors);
case IFCOUNTER_COLLISIONS:
/* Collisions are by standard impossible in 40G/10G Ethernet */
return (0);
@@ -1914,7 +1914,7 @@ ixl_if_get_counter(if_ctx_t ctx, ift_counter cnt)
case IFCOUNTER_IQDROPS:
return (vsi->iqdrops);
case IFCOUNTER_OQDROPS:
- return (vsi->oqdrops);
+ return (if_get_counter_default(ifp, cnt) + vsi->oqdrops);
case IFCOUNTER_NOPROTO:
return (vsi->noproto);
default:
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index c008d915fd6d..e27479b9f529 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -3740,6 +3740,12 @@ defrag:
bus_dmamap_unload(buf_tag, map);
DBG_COUNTER_INC(encap_txq_avail_fail);
DBG_COUNTER_INC(encap_txd_encap_fail);
+ if (ctx->ifc_sysctl_simple_tx) {
+ *m_headp = m_head = iflib_remove_mbuf(txq);
+ m_freem(*m_headp);
+ DBG_COUNTER_INC(tx_frees);
+ *m_headp = NULL;
+ }
if ((txq->ift_task.gt_task.ta_flags & TASK_ENQUEUED) == 0)
GROUPTASK_ENQUEUE(&txq->ift_task);
return (ENOBUFS);
@@ -4412,6 +4418,10 @@ iflib_if_transmit(if_t ifp, struct mbuf *m)
ifmp_ring_check_drainage(txq->ift_br, TX_BATCH_SIZE);
m_freem(m);
DBG_COUNTER_INC(tx_frees);
+ if (err == ENOBUFS)
+ if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
+ else
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
return (err);
@@ -7524,6 +7534,11 @@ iflib_simple_transmit(if_t ifp, struct mbuf *m)
bytes_sent += m->m_pkthdr.len;
mcast_sent += !!(m->m_flags & M_MCAST);
(void)iflib_txd_db_check(txq, true);
+ } else {
+ if (error == ENOBUFS)
+ if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
+ else
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
(void)iflib_completed_tx_reclaim(txq, RECLAIM_THRESH(ctx));
mtx_unlock(&txq->ift_mtx);