* [GIT PULL v2 net-next] netfilter: updates for net-next
From: Florian Westphal @ 2026-04-08 6:04 UTC (permalink / raw)
To: netdev
Cc: Paolo Abeni, David S. Miller, Eric Dumazet, Jakub Kicinski,
netfilter-devel, pablo
No changes since v1, I only dropped the last patch (13/13). This is also
why I am not resending the individual patches again.
The following PR contains Netfilter updates for *net-next*:
1) Fix ancient sparse warnings in nf conntrack nat modules, from
Sun Jian.
2) Fix typo in enum description, from Jelle van der Waa.
3) remove redundant refetch of netns pointer in nf_conntrack_sip.
4) add a deprecation warning for dccp match.
We can extend the deadline later if needed, but plan atm is to
remove the feature.
5) remove nf_conntrack_h323 debug code that can read out-of-bounds
with malformed messages. This code was commented out, but better
remove this.
6+7) add more netlink policy validations in netfilter.
This could theoretically cause issues when a client sends e.g.
unsupported feature flags that were previously ignored, so we
may have to relax some changes. For now, try to be stricter and
reject upfront.
8+9) minor code cleanup in nft_set_pipapo (an nftables set backend).
10) Add nftables matching support fro double-tagged vlan and pppoe
frames, from Pablo Neira Ayuso.
11) Fix up indentation of debug messages in nf_conntrack_h323 conntrack
helper, from David Laight.
12) Add a helper to iterate to next flow action and bail out if the
maximum number of actions is reached, also from Pablo.
Please, pull these changes from:
The following changes since commit b3e69fc3196fc421e26196e7792f17b0463edc6f:
Merge branch 'net-pull-gso-packet-headers-in-core-stack' (2026-04-07 19:02:18 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next.git tags/nf-next-26-04-08
for you to fetch changes up to c6f85577584b5f8414141ae389e974b8ca6a698b:
netfilter: nf_tables_offload: add nft_flow_action_entry_next() and use it (2026-04-08 07:51:31 +0200)
----------------------------------------------------------------
netfilter pull request nf-next-26-04-08
----------------------------------------------------------------
David Laight (1):
netfilter: nf_conntrack_h323: Correct indentation when H323_TRACE defined
Florian Westphal (7):
netfilter: nf_conntrack_sip: remove net variable shadowing
netfilter: add deprecation warning for dccp support
netfilter: nf_conntrack_h323: remove unreliable debug code in decode_octstr
netfilter: add more netlink-based policy range checks
netfilter: nf_tables: add netlink policy based cap on registers
netfilter: nft_set_pipapo: increment data in one step
netfilter: nft_set_pipapo_avx2: remove redundant loop in lookup_slow
Jelle van der Waa (1):
netfilter: nf_tables: Fix typo in enum description
Pablo Neira Ayuso (2):
netfilter: nft_meta: add double-tagged vlan and pppoe support
netfilter: nf_tables_offload: add nft_flow_action_entry_next() and use
it
Sun Jian (1):
netfilter: use function typedefs for __rcu NAT helper hook pointers
include/linux/netfilter/nf_conntrack_amanda.h | 15 +++--
include/linux/netfilter/nf_conntrack_ftp.h | 17 +++---
include/linux/netfilter/nf_conntrack_irc.h | 15 +++--
include/linux/netfilter/nf_conntrack_snmp.h | 11 ++--
include/linux/netfilter/nf_conntrack_tftp.h | 9 ++-
include/net/netfilter/nf_tables.h | 4 ++
include/net/netfilter/nf_tables_ipv4.h | 17 ++++--
include/net/netfilter/nf_tables_ipv6.h | 16 +++--
include/net/netfilter/nf_tables_offload.h | 10 ++++
include/uapi/linux/netfilter/nf_tables.h | 6 +-
net/netfilter/ipset/ip_set_core.c | 2 +-
net/netfilter/nf_conntrack_amanda.c | 10 +---
net/netfilter/nf_conntrack_ftp.c | 10 +---
net/netfilter/nf_conntrack_h323_asn1.c | 45 ++++++--------
net/netfilter/nf_conntrack_irc.c | 10 +---
net/netfilter/nf_conntrack_sip.c | 3 +-
net/netfilter/nf_conntrack_snmp.c | 7 +--
net/netfilter/nf_conntrack_tftp.c | 7 +--
net/netfilter/nf_dup_netdev.c | 5 +-
net/netfilter/nf_tables_api.c | 20 +++++--
net/netfilter/nf_tables_core.c | 2 +-
net/netfilter/nfnetlink_acct.c | 2 +-
net/netfilter/nfnetlink_cthelper.c | 2 +-
net/netfilter/nfnetlink_hook.c | 2 +-
net/netfilter/nfnetlink_log.c | 4 +-
net/netfilter/nfnetlink_osf.c | 2 +-
net/netfilter/nfnetlink_queue.c | 2 +-
net/netfilter/nft_bitwise.c | 6 +-
net/netfilter/nft_byteorder.c | 4 +-
net/netfilter/nft_cmp.c | 2 +-
net/netfilter/nft_compat.c | 2 +-
net/netfilter/nft_connlimit.c | 2 +-
net/netfilter/nft_ct.c | 6 +-
net/netfilter/nft_dynset.c | 3 +-
net/netfilter/nft_exthdr.c | 9 ++-
net/netfilter/nft_fib.c | 2 +-
net/netfilter/nft_hash.c | 4 +-
net/netfilter/nft_immediate.c | 6 +-
net/netfilter/nft_inner.c | 2 +-
net/netfilter/nft_limit.c | 2 +-
net/netfilter/nft_log.c | 2 +-
net/netfilter/nft_lookup.c | 4 +-
net/netfilter/nft_meta.c | 58 ++++++++++++++++++-
net/netfilter/nft_numgen.c | 2 +-
net/netfilter/nft_objref.c | 2 +-
net/netfilter/nft_osf.c | 4 +-
net/netfilter/nft_payload.c | 8 +--
net/netfilter/nft_queue.c | 2 +-
net/netfilter/nft_quota.c | 2 +-
net/netfilter/nft_range.c | 2 +-
net/netfilter/nft_rt.c | 2 +-
net/netfilter/nft_set_pipapo.c | 4 +-
net/netfilter/nft_set_pipapo.h | 3 -
net/netfilter/nft_set_pipapo_avx2.c | 32 +++-------
net/netfilter/nft_socket.c | 2 +-
net/netfilter/nft_synproxy.c | 4 +-
net/netfilter/nft_tunnel.c | 6 +-
net/netfilter/nft_xfrm.c | 6 +-
net/netfilter/xt_dccp.c | 3 +
59 files changed, 262 insertions(+), 191 deletions(-)
--
2.52.0
^ permalink raw reply
* [PATCH net-next 0/5] net: enetc: improve statistics for v1 and add statistics for v4
From: Wei Fang @ 2026-04-08 5:58 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel, imx
For ENETC v1, some standardized statistics were redundantly included in
the unstructured statistics, so remove these duplicated entries.
Previously, the unstructured statistics only contained eMAC data and
did not include pMAC data; add pMAC statistics to ensure completeness.
For ENETC v4, the driver previously reported MAC statistics only for the
internal ENETC (Pseudo MAC). Extend the implementation to provide
additional statistics for both the internal ENETC and the standalone
ENETC.
Wei Fang (5):
net: enetc: add support for the standardized counters
net: enetc: show RX drop counters only for assigned RX rings
net: enetc: remove standardized counters from enetc_pm_counters
net: enetc: add unstructured pMAC counters for ENETC v1
net: enetc: add unstructured counters for ENETC v4
drivers/net/ethernet/freescale/enetc/enetc.h | 2 +
.../net/ethernet/freescale/enetc/enetc4_hw.h | 192 ++++++++
.../ethernet/freescale/enetc/enetc_ethtool.c | 427 +++++++++++++-----
3 files changed, 519 insertions(+), 102 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH net-next 1/5] net: enetc: add support for the standardized counters
From: Wei Fang @ 2026-04-08 5:58 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel, imx
In-Reply-To: <20260408055849.1314033-1-wei.fang@nxp.com>
ENETC v4 provides 64-bit counters for IEEE 802.3 basic and mandatory
managed objects, the IETF Management Information Database (MIB) package
(RFC2665), and Remote Network Monitoring (RMON) statistics. In addition,
some ENETCs support preemption, so these ENETCs have two MACs: MAC 0 is
the express MAC (eMAC), MAC 1 is the preemptible MAC (pMAC). Both MACs
support these statistics.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
drivers/net/ethernet/freescale/enetc/enetc.h | 2 +
.../net/ethernet/freescale/enetc/enetc4_hw.h | 120 +++++++++++++++
.../ethernet/freescale/enetc/enetc_ethtool.c | 141 +++++++++++++++---
3 files changed, 245 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index aecd40aeef9c..e663bb5e614e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -264,6 +264,8 @@ struct enetc_msg_swbd {
};
#define ENETC_REV1 0x1
+#define ENETC_REV4 0x4
+
enum enetc_errata {
ENETC_ERR_VLAN_ISOL = BIT(0),
ENETC_ERR_UCMCSWP = BIT(1),
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 719c88ceb801..392992a646fb 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -196,6 +196,126 @@
#define PM_SINGLE_STEP_OFFSET_SET(o) FIELD_PREP(PM_SINGLE_STEP_OFFSET, o)
#define PM_SINGLE_STEP_EN BIT(31)
+/* Port MAC 0/1 Receive Ethernet Octets Counter */
+#define ENETC4_PM_REOCT(mac) (0x5100 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Alignment Error Counter Register */
+#define ENETC4_PM_RALN(mac) (0x5110 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Valid Pause Frame Counter */
+#define ENETC4_PM_RXPF(mac) (0x5118 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Frame Counter */
+#define ENETC4_PM_RFRM(mac) (0x5120 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Frame Check Sequence Error Counter */
+#define ENETC4_PM_RFCS(mac) (0x5128 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Multicast Frame Counter */
+#define ENETC4_PM_RMCA(mac) (0x5148 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Broadcast Frame Counter */
+#define ENETC4_PM_RBCA(mac) (0x5150 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Undersized Packet Counter */
+#define ENETC4_PM_RUND(mac) (0x5168 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive 64-Octet Packet Counter */
+#define ENETC4_PM_R64(mac) (0x5170 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive 65 to 127-Octet Packet Counter */
+#define ENETC4_PM_R127(mac) (0x5178 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive 128 to 255-Octet Packet Counter */
+#define ENETC4_PM_R255(mac) (0x5180 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive 256 to 511-Octet Packet Counter */
+#define ENETC4_PM_R511(mac) (0x5188 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive 512 to 1023-Octet Packet Counter */
+#define ENETC4_PM_R1023(mac) (0x5190 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive 1024 to 1522-Octet Packet Counter */
+#define ENETC4_PM_R1522(mac) (0x5198 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive 1523 to Max-Octet Packet Counter */
+#define ENETC4_PM_R1523X(mac) (0x51a0 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Oversized Packet Counter */
+#define ENETC4_PM_ROVR(mac) (0x51a8 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Jabber Packet Counter */
+#define ENETC4_PM_RJBR(mac) (0x51b0 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Fragment Packet Counter */
+#define ENETC4_PM_RFRG(mac) (0x51b8 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Control Packet Counter */
+#define ENETC4_PM_RCNP(mac) (0x51c0 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Dropped Not Truncated Packets Counter */
+#define ENETC4_PM_RDRNTP(mac) (0x51c8 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Ethernet Octets Counter */
+#define ENETC4_PM_TEOCT(mac) (0x5200 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Valid Pause Frame Counter */
+#define ENETC4_PM_TXPF(mac) (0x5218 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Frame Counter */
+#define ENETC4_PM_TFRM(mac) (0x5220 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Frame Error Counter */
+#define ENETC4_PM_TERR(mac) (0x5238 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Multicast Frame Counter */
+#define ENETC4_PM_TMCA(mac) (0x5248 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Broadcast Frame Counter */
+#define ENETC4_PM_TBCA(mac) (0x5250 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Undersized Packet Counter */
+#define ENETC4_PM_TUND(mac) (0x5268 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit 64-Octet Packet Counter */
+#define ENETC4_PM_T64(mac) (0x5270 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit 65 to 127-Octet Packet Counter */
+#define ENETC4_PM_T127(mac) (0x5278 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit 128 to 255-Octet Packet Counter */
+#define ENETC4_PM_T255(mac) (0x5280 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit 256 to 511-Octet Packet Counter */
+#define ENETC4_PM_T511(mac) (0x5288 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit 512 to 1023-Octet Packet Counter */
+#define ENETC4_PM_T1023(mac) (0x5290 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit 1024 to 1522-Octet Packet Counter */
+#define ENETC4_PM_T1522(mac) (0x5298 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit 1523 to TX_MTU-Octet Packet Counter */
+#define ENETC4_PM_T1523X(mac) (0x52a0 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Control Packet Counter */
+#define ENETC4_PM_TCNP(mac) (0x52c0 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Deferred Packet Counter */
+#define ENETC4_PM_TDFR(mac) (0x52d0 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Multiple Collisions Counter */
+#define ENETC4_PM_TMCOL(mac) (0x52d8 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Single Collision */
+#define ENETC4_PM_TSCOL(mac) (0x52e0 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Late Collision Counter */
+#define ENETC4_PM_TLCOL(mac) (0x52e8 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit Excessive Collisions Counter */
+#define ENETC4_PM_TECOL(mac) (0x52f0 + (mac) * 0x400)
+
/* Port MAC 0 Interface Mode Control Register */
#define ENETC4_PM_IF_MODE(mac) (0x5300 + (mac) * 0x400)
#define PM_IF_MODE_IFMODE GENMASK(2, 0)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index 7c17acaf7a38..c30a119e9142 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -320,27 +320,38 @@ static void enetc_get_ethtool_stats(struct net_device *ndev,
data[o++] = enetc_port_rd64(hw, enetc_pm_counters[i].reg);
}
-static void enetc_pause_stats(struct enetc_hw *hw, int mac,
+static void enetc_pause_stats(struct enetc_si *si, int mac,
struct ethtool_pause_stats *pause_stats)
{
- pause_stats->tx_pause_frames = enetc_port_rd64(hw, ENETC_PM_TXPF(mac));
- pause_stats->rx_pause_frames = enetc_port_rd64(hw, ENETC_PM_RXPF(mac));
+ struct enetc_hw *hw = &si->hw;
+
+ switch (si->pdev->revision) {
+ case ENETC_REV1:
+ pause_stats->tx_pause_frames = enetc_port_rd64(hw, ENETC_PM_TXPF(mac));
+ pause_stats->rx_pause_frames = enetc_port_rd64(hw, ENETC_PM_RXPF(mac));
+ break;
+ case ENETC_REV4:
+ pause_stats->tx_pause_frames = enetc_port_rd64(hw, ENETC4_PM_TXPF(mac));
+ pause_stats->rx_pause_frames = enetc_port_rd64(hw, ENETC4_PM_RXPF(mac));
+ break;
+ default:
+ break;
+ }
}
static void enetc_get_pause_stats(struct net_device *ndev,
struct ethtool_pause_stats *pause_stats)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
struct enetc_si *si = priv->si;
switch (pause_stats->src) {
case ETHTOOL_MAC_STATS_SRC_EMAC:
- enetc_pause_stats(hw, 0, pause_stats);
+ enetc_pause_stats(si, 0, pause_stats);
break;
case ETHTOOL_MAC_STATS_SRC_PMAC:
if (si->hw_features & ENETC_SI_F_QBU)
- enetc_pause_stats(hw, 1, pause_stats);
+ enetc_pause_stats(si, 1, pause_stats);
break;
case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
ethtool_aggregate_pause_stats(ndev, pause_stats);
@@ -371,11 +382,45 @@ static void enetc_mac_stats(struct enetc_hw *hw, int mac,
s->BroadcastFramesReceivedOK = enetc_port_rd64(hw, ENETC_PM_RBCA(mac));
}
-static void enetc_ctrl_stats(struct enetc_hw *hw, int mac,
+static void enetc4_mac_stats(struct enetc_hw *hw, int mac,
+ struct ethtool_eth_mac_stats *s)
+{
+ s->FramesTransmittedOK = enetc_port_rd64(hw, ENETC4_PM_TFRM(mac));
+ s->SingleCollisionFrames = enetc_port_rd64(hw, ENETC4_PM_TSCOL(mac));
+ s->MultipleCollisionFrames = enetc_port_rd64(hw, ENETC4_PM_TMCOL(mac));
+ s->FramesReceivedOK = enetc_port_rd64(hw, ENETC4_PM_RFRM(mac));
+ s->FrameCheckSequenceErrors = enetc_port_rd64(hw, ENETC4_PM_RFCS(mac));
+ s->AlignmentErrors = enetc_port_rd64(hw, ENETC4_PM_RALN(mac));
+ s->OctetsTransmittedOK = enetc_port_rd64(hw, ENETC4_PM_TEOCT(mac));
+ s->FramesWithDeferredXmissions = enetc_port_rd64(hw, ENETC4_PM_TDFR(mac));
+ s->LateCollisions = enetc_port_rd64(hw, ENETC4_PM_TLCOL(mac));
+ s->FramesAbortedDueToXSColls = enetc_port_rd64(hw, ENETC4_PM_TECOL(mac));
+ s->FramesLostDueToIntMACXmitError = enetc_port_rd64(hw, ENETC4_PM_TERR(mac));
+ s->OctetsReceivedOK = enetc_port_rd64(hw, ENETC4_PM_REOCT(mac));
+ s->FramesLostDueToIntMACRcvError = enetc_port_rd64(hw, ENETC4_PM_RDRNTP(mac));
+ s->MulticastFramesXmittedOK = enetc_port_rd64(hw, ENETC4_PM_TMCA(mac));
+ s->BroadcastFramesXmittedOK = enetc_port_rd64(hw, ENETC4_PM_TBCA(mac));
+ s->MulticastFramesReceivedOK = enetc_port_rd64(hw, ENETC4_PM_RMCA(mac));
+ s->BroadcastFramesReceivedOK = enetc_port_rd64(hw, ENETC4_PM_RBCA(mac));
+}
+
+static void enetc_ctrl_stats(struct enetc_si *si, int mac,
struct ethtool_eth_ctrl_stats *s)
{
- s->MACControlFramesTransmitted = enetc_port_rd64(hw, ENETC_PM_TCNP(mac));
- s->MACControlFramesReceived = enetc_port_rd64(hw, ENETC_PM_RCNP(mac));
+ struct enetc_hw *hw = &si->hw;
+
+ switch (si->pdev->revision) {
+ case ENETC_REV1:
+ s->MACControlFramesTransmitted = enetc_port_rd64(hw, ENETC_PM_TCNP(mac));
+ s->MACControlFramesReceived = enetc_port_rd64(hw, ENETC_PM_RCNP(mac));
+ break;
+ case ENETC_REV4:
+ s->MACControlFramesTransmitted = enetc_port_rd64(hw, ENETC4_PM_TCNP(mac));
+ s->MACControlFramesReceived = enetc_port_rd64(hw, ENETC4_PM_RCNP(mac));
+ break;
+ default:
+ break;
+ }
}
static const struct ethtool_rmon_hist_range enetc_rmon_ranges[] = {
@@ -414,20 +459,61 @@ static void enetc_rmon_stats(struct enetc_hw *hw, int mac,
s->hist_tx[6] = enetc_port_rd64(hw, ENETC_PM_T1523X(mac));
}
+static void enetc4_rmon_stats(struct enetc_hw *hw, int mac,
+ struct ethtool_rmon_stats *s)
+{
+ s->undersize_pkts = enetc_port_rd64(hw, ENETC4_PM_RUND(mac));
+ s->oversize_pkts = enetc_port_rd64(hw, ENETC4_PM_ROVR(mac));
+ s->fragments = enetc_port_rd64(hw, ENETC4_PM_RFRG(mac));
+ s->jabbers = enetc_port_rd64(hw, ENETC4_PM_RJBR(mac));
+
+ s->hist[0] = enetc_port_rd64(hw, ENETC4_PM_R64(mac));
+ s->hist[1] = enetc_port_rd64(hw, ENETC4_PM_R127(mac));
+ s->hist[2] = enetc_port_rd64(hw, ENETC4_PM_R255(mac));
+ s->hist[3] = enetc_port_rd64(hw, ENETC4_PM_R511(mac));
+ s->hist[4] = enetc_port_rd64(hw, ENETC4_PM_R1023(mac));
+ s->hist[5] = enetc_port_rd64(hw, ENETC4_PM_R1522(mac));
+ s->hist[6] = enetc_port_rd64(hw, ENETC4_PM_R1523X(mac));
+
+ s->hist_tx[0] = enetc_port_rd64(hw, ENETC4_PM_T64(mac));
+ s->hist_tx[1] = enetc_port_rd64(hw, ENETC4_PM_T127(mac));
+ s->hist_tx[2] = enetc_port_rd64(hw, ENETC4_PM_T255(mac));
+ s->hist_tx[3] = enetc_port_rd64(hw, ENETC4_PM_T511(mac));
+ s->hist_tx[4] = enetc_port_rd64(hw, ENETC4_PM_T1023(mac));
+ s->hist_tx[5] = enetc_port_rd64(hw, ENETC4_PM_T1522(mac));
+ s->hist_tx[6] = enetc_port_rd64(hw, ENETC4_PM_T1523X(mac));
+}
+
+static void enetc_get_mac_stats(struct enetc_si *si, int mac,
+ struct ethtool_eth_mac_stats *mac_stats)
+{
+ struct enetc_hw *hw = &si->hw;
+
+ switch (si->pdev->revision) {
+ case ENETC_REV1:
+ enetc_mac_stats(hw, mac, mac_stats);
+ break;
+ case ENETC_REV4:
+ enetc4_mac_stats(hw, mac, mac_stats);
+ break;
+ default:
+ break;
+ }
+}
+
static void enetc_get_eth_mac_stats(struct net_device *ndev,
struct ethtool_eth_mac_stats *mac_stats)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
struct enetc_si *si = priv->si;
switch (mac_stats->src) {
case ETHTOOL_MAC_STATS_SRC_EMAC:
- enetc_mac_stats(hw, 0, mac_stats);
+ enetc_get_mac_stats(si, 0, mac_stats);
break;
case ETHTOOL_MAC_STATS_SRC_PMAC:
if (si->hw_features & ENETC_SI_F_QBU)
- enetc_mac_stats(hw, 1, mac_stats);
+ enetc_get_mac_stats(si, 1, mac_stats);
break;
case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
ethtool_aggregate_mac_stats(ndev, mac_stats);
@@ -481,16 +567,15 @@ static void enetc_get_eth_ctrl_stats(struct net_device *ndev,
struct ethtool_eth_ctrl_stats *ctrl_stats)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
struct enetc_si *si = priv->si;
switch (ctrl_stats->src) {
case ETHTOOL_MAC_STATS_SRC_EMAC:
- enetc_ctrl_stats(hw, 0, ctrl_stats);
+ enetc_ctrl_stats(si, 0, ctrl_stats);
break;
case ETHTOOL_MAC_STATS_SRC_PMAC:
if (si->hw_features & ENETC_SI_F_QBU)
- enetc_ctrl_stats(hw, 1, ctrl_stats);
+ enetc_ctrl_stats(si, 1, ctrl_stats);
break;
case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
ethtool_aggregate_ctrl_stats(ndev, ctrl_stats);
@@ -498,23 +583,39 @@ static void enetc_get_eth_ctrl_stats(struct net_device *ndev,
}
}
+static void enetc_get_mac_rmon_stats(struct enetc_si *si, int mac,
+ struct ethtool_rmon_stats *rmon_stats)
+{
+ struct enetc_hw *hw = &si->hw;
+
+ switch (si->pdev->revision) {
+ case ENETC_REV1:
+ enetc_rmon_stats(hw, mac, rmon_stats);
+ break;
+ case ENETC_REV4:
+ enetc4_rmon_stats(hw, mac, rmon_stats);
+ break;
+ default:
+ break;
+ }
+}
+
static void enetc_get_rmon_stats(struct net_device *ndev,
struct ethtool_rmon_stats *rmon_stats,
const struct ethtool_rmon_hist_range **ranges)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
struct enetc_si *si = priv->si;
*ranges = enetc_rmon_ranges;
switch (rmon_stats->src) {
case ETHTOOL_MAC_STATS_SRC_EMAC:
- enetc_rmon_stats(hw, 0, rmon_stats);
+ enetc_get_mac_rmon_stats(si, 0, rmon_stats);
break;
case ETHTOOL_MAC_STATS_SRC_PMAC:
if (si->hw_features & ENETC_SI_F_QBU)
- enetc_rmon_stats(hw, 1, rmon_stats);
+ enetc_get_mac_rmon_stats(si, 1, rmon_stats);
break;
case ETHTOOL_MAC_STATS_SRC_AGGREGATE:
ethtool_aggregate_rmon_stats(ndev, rmon_stats);
@@ -1398,6 +1499,10 @@ const struct ethtool_ops enetc4_pf_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
+ .get_pause_stats = enetc_get_pause_stats,
+ .get_rmon_stats = enetc_get_rmon_stats,
+ .get_eth_ctrl_stats = enetc_get_eth_ctrl_stats,
+ .get_eth_mac_stats = enetc_get_eth_mac_stats,
.get_ringparam = enetc_get_ringparam,
.get_coalesce = enetc_get_coalesce,
.set_coalesce = enetc_set_coalesce,
--
2.34.1
^ permalink raw reply related
* [PATCH net-next 2/5] net: enetc: show RX drop counters only for assigned RX rings
From: Wei Fang @ 2026-04-08 5:58 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel, imx
In-Reply-To: <20260408055849.1314033-1-wei.fang@nxp.com>
For ENETC v1, each SI provides 16 RBDCR registers for RX ring drop
counters, but this does not imply that an SI actually owns 16 RX rings.
The ENETC hardware supports a total of 16 RX rings, which are assigned
to 3 SIs (1 PSI and 2 VSIs), so each SI is assigned fewer than 16 RX
rings.
The current implementation always reports 16 RX drop counters per SI,
leading to redundant output for SIs with fewer RX rings. Update the
logic to display drop counters only for the RX rings that are actually
assigned to the SI.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
.../ethernet/freescale/enetc/enetc_ethtool.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index c30a119e9142..36d1a2b810c2 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -124,22 +124,6 @@ static const struct {
{ ENETC_SITFRM, "SI tx frames" },
{ ENETC_SITUCA, "SI tx u-cast frames" },
{ ENETC_SITMCA, "SI tx m-cast frames" },
- { ENETC_RBDCR(0), "Rx ring 0 discarded frames" },
- { ENETC_RBDCR(1), "Rx ring 1 discarded frames" },
- { ENETC_RBDCR(2), "Rx ring 2 discarded frames" },
- { ENETC_RBDCR(3), "Rx ring 3 discarded frames" },
- { ENETC_RBDCR(4), "Rx ring 4 discarded frames" },
- { ENETC_RBDCR(5), "Rx ring 5 discarded frames" },
- { ENETC_RBDCR(6), "Rx ring 6 discarded frames" },
- { ENETC_RBDCR(7), "Rx ring 7 discarded frames" },
- { ENETC_RBDCR(8), "Rx ring 8 discarded frames" },
- { ENETC_RBDCR(9), "Rx ring 9 discarded frames" },
- { ENETC_RBDCR(10), "Rx ring 10 discarded frames" },
- { ENETC_RBDCR(11), "Rx ring 11 discarded frames" },
- { ENETC_RBDCR(12), "Rx ring 12 discarded frames" },
- { ENETC_RBDCR(13), "Rx ring 13 discarded frames" },
- { ENETC_RBDCR(14), "Rx ring 14 discarded frames" },
- { ENETC_RBDCR(15), "Rx ring 15 discarded frames" },
};
static const struct {
@@ -224,6 +208,7 @@ static const char rx_ring_stats[][ETH_GSTRING_LEN] = {
"Rx ring %2d recycle failures",
"Rx ring %2d redirects",
"Rx ring %2d redirect failures",
+ "Rx ring %2d discarded frames",
};
static const char tx_ring_stats[][ETH_GSTRING_LEN] = {
@@ -308,6 +293,7 @@ static void enetc_get_ethtool_stats(struct net_device *ndev,
data[o++] = priv->rx_ring[i]->stats.recycle_failures;
data[o++] = priv->rx_ring[i]->stats.xdp_redirect;
data[o++] = priv->rx_ring[i]->stats.xdp_redirect_failures;
+ data[o++] = enetc_rd(hw, ENETC_RBDCR(i));
}
if (!enetc_si_is_pf(priv->si))
--
2.34.1
^ permalink raw reply related
* [PATCH net-next 3/5] net: enetc: remove standardized counters from enetc_pm_counters
From: Wei Fang @ 2026-04-08 5:58 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel, imx
In-Reply-To: <20260408055849.1314033-1-wei.fang@nxp.com>
The standardized counters are already exposed via the get_pause_stats(),
get_rmon_stats(), get_eth_ctrl_stats() and get_eth_mac_stats()
interfaces. Keeping the same counters in enetc_pm_counters results in
redundant output.
Remove these standardized counters from enetc_pm_counters and rely on
the existing statistics interfaces to report them.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
.../ethernet/freescale/enetc/enetc_ethtool.c | 40 -------------------
1 file changed, 40 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index 36d1a2b810c2..504def405489 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -130,57 +130,17 @@ static const struct {
int reg;
char name[ETH_GSTRING_LEN] __nonstring;
} enetc_pm_counters[] = {
- { ENETC_PM_REOCT(0), "MAC rx ethernet octets" },
- { ENETC_PM_RALN(0), "MAC rx alignment errors" },
- { ENETC_PM_RXPF(0), "MAC rx valid pause frames" },
- { ENETC_PM_RFRM(0), "MAC rx valid frames" },
- { ENETC_PM_RFCS(0), "MAC rx fcs errors" },
{ ENETC_PM_RVLAN(0), "MAC rx VLAN frames" },
{ ENETC_PM_RERR(0), "MAC rx frame errors" },
{ ENETC_PM_RUCA(0), "MAC rx unicast frames" },
- { ENETC_PM_RMCA(0), "MAC rx multicast frames" },
- { ENETC_PM_RBCA(0), "MAC rx broadcast frames" },
{ ENETC_PM_RDRP(0), "MAC rx dropped packets" },
{ ENETC_PM_RPKT(0), "MAC rx packets" },
- { ENETC_PM_RUND(0), "MAC rx undersized packets" },
- { ENETC_PM_R64(0), "MAC rx 64 byte packets" },
- { ENETC_PM_R127(0), "MAC rx 65-127 byte packets" },
- { ENETC_PM_R255(0), "MAC rx 128-255 byte packets" },
- { ENETC_PM_R511(0), "MAC rx 256-511 byte packets" },
- { ENETC_PM_R1023(0), "MAC rx 512-1023 byte packets" },
- { ENETC_PM_R1522(0), "MAC rx 1024-1522 byte packets" },
- { ENETC_PM_R1523X(0), "MAC rx 1523 to max-octet packets" },
- { ENETC_PM_ROVR(0), "MAC rx oversized packets" },
- { ENETC_PM_RJBR(0), "MAC rx jabber packets" },
- { ENETC_PM_RFRG(0), "MAC rx fragment packets" },
- { ENETC_PM_RCNP(0), "MAC rx control packets" },
- { ENETC_PM_RDRNTP(0), "MAC rx fifo drop" },
- { ENETC_PM_TEOCT(0), "MAC tx ethernet octets" },
{ ENETC_PM_TOCT(0), "MAC tx octets" },
- { ENETC_PM_TCRSE(0), "MAC tx carrier sense errors" },
- { ENETC_PM_TXPF(0), "MAC tx valid pause frames" },
- { ENETC_PM_TFRM(0), "MAC tx frames" },
{ ENETC_PM_TFCS(0), "MAC tx fcs errors" },
{ ENETC_PM_TVLAN(0), "MAC tx VLAN frames" },
- { ENETC_PM_TERR(0), "MAC tx frame errors" },
{ ENETC_PM_TUCA(0), "MAC tx unicast frames" },
- { ENETC_PM_TMCA(0), "MAC tx multicast frames" },
- { ENETC_PM_TBCA(0), "MAC tx broadcast frames" },
{ ENETC_PM_TPKT(0), "MAC tx packets" },
{ ENETC_PM_TUND(0), "MAC tx undersized packets" },
- { ENETC_PM_T64(0), "MAC tx 64 byte packets" },
- { ENETC_PM_T127(0), "MAC tx 65-127 byte packets" },
- { ENETC_PM_T255(0), "MAC tx 128-255 byte packets" },
- { ENETC_PM_T511(0), "MAC tx 256-511 byte packets" },
- { ENETC_PM_T1023(0), "MAC tx 512-1023 byte packets" },
- { ENETC_PM_T1522(0), "MAC tx 1024-1522 byte packets" },
- { ENETC_PM_T1523X(0), "MAC tx 1523 to max-octet packets" },
- { ENETC_PM_TCNP(0), "MAC tx control packets" },
- { ENETC_PM_TDFR(0), "MAC tx deferred packets" },
- { ENETC_PM_TMCOL(0), "MAC tx multiple collisions" },
- { ENETC_PM_TSCOL(0), "MAC tx single collisions" },
- { ENETC_PM_TLCOL(0), "MAC tx late collisions" },
- { ENETC_PM_TECOL(0), "MAC tx excessive collisions" },
};
static const struct {
--
2.34.1
^ permalink raw reply related
* [PATCH net-next 4/5] net: enetc: add unstructured pMAC counters for ENETC v1
From: Wei Fang @ 2026-04-08 5:58 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel, imx
In-Reply-To: <20260408055849.1314033-1-wei.fang@nxp.com>
The ENETC v1 has two MACs (eMAC and pMAC) to support preemption. The
existing unstructured counters include the eMAC counters, but not the
pMAC counters. So add pMAC counters to improve statistical coverage.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
.../ethernet/freescale/enetc/enetc_ethtool.c | 77 ++++++++++++++-----
1 file changed, 56 insertions(+), 21 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index 504def405489..bdc5916e4400 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -129,18 +129,35 @@ static const struct {
static const struct {
int reg;
char name[ETH_GSTRING_LEN] __nonstring;
-} enetc_pm_counters[] = {
- { ENETC_PM_RVLAN(0), "MAC rx VLAN frames" },
- { ENETC_PM_RERR(0), "MAC rx frame errors" },
- { ENETC_PM_RUCA(0), "MAC rx unicast frames" },
- { ENETC_PM_RDRP(0), "MAC rx dropped packets" },
- { ENETC_PM_RPKT(0), "MAC rx packets" },
- { ENETC_PM_TOCT(0), "MAC tx octets" },
- { ENETC_PM_TFCS(0), "MAC tx fcs errors" },
- { ENETC_PM_TVLAN(0), "MAC tx VLAN frames" },
- { ENETC_PM_TUCA(0), "MAC tx unicast frames" },
- { ENETC_PM_TPKT(0), "MAC tx packets" },
- { ENETC_PM_TUND(0), "MAC tx undersized packets" },
+} enetc_emac_counters[] = {
+ { ENETC_PM_RVLAN(0), "eMAC rx VLAN frames" },
+ { ENETC_PM_RERR(0), "eMAC rx frame errors" },
+ { ENETC_PM_RUCA(0), "eMAC rx unicast frames" },
+ { ENETC_PM_RDRP(0), "eMAC rx dropped packets" },
+ { ENETC_PM_RPKT(0), "eMAC rx packets" },
+ { ENETC_PM_TOCT(0), "eMAC tx octets" },
+ { ENETC_PM_TFCS(0), "eMAC tx fcs errors" },
+ { ENETC_PM_TVLAN(0), "eMAC tx VLAN frames" },
+ { ENETC_PM_TUCA(0), "eMAC tx unicast frames" },
+ { ENETC_PM_TPKT(0), "eMAC tx packets" },
+ { ENETC_PM_TUND(0), "eMAC tx undersized packets" },
+};
+
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN] __nonstring;
+} enetc_pmac_counters[] = {
+ { ENETC_PM_RVLAN(1), "pMAC rx VLAN frames" },
+ { ENETC_PM_RERR(1), "pMAC rx frame errors" },
+ { ENETC_PM_RUCA(1), "pMAC rx unicast frames" },
+ { ENETC_PM_RDRP(1), "pMAC rx dropped packets" },
+ { ENETC_PM_RPKT(1), "pMAC rx packets" },
+ { ENETC_PM_TOCT(1), "pMAC tx octets" },
+ { ENETC_PM_TFCS(1), "pMAC tx fcs errors" },
+ { ENETC_PM_TVLAN(1), "pMAC tx VLAN frames" },
+ { ENETC_PM_TUCA(1), "pMAC tx unicast frames" },
+ { ENETC_PM_TPKT(1), "pMAC tx packets" },
+ { ENETC_PM_TUND(1), "pMAC tx undersized packets" },
};
static const struct {
@@ -181,6 +198,7 @@ static const char tx_ring_stats[][ETH_GSTRING_LEN] = {
static int enetc_get_sset_count(struct net_device *ndev, int sset)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_si *si = priv->si;
int len;
if (sset != ETH_SS_STATS)
@@ -190,11 +208,14 @@ static int enetc_get_sset_count(struct net_device *ndev, int sset)
ARRAY_SIZE(tx_ring_stats) * priv->num_tx_rings +
ARRAY_SIZE(rx_ring_stats) * priv->num_rx_rings;
- if (!enetc_si_is_pf(priv->si))
+ if (!enetc_si_is_pf(si))
return len;
len += ARRAY_SIZE(enetc_port_counters);
- len += ARRAY_SIZE(enetc_pm_counters);
+ len += ARRAY_SIZE(enetc_emac_counters);
+
+ if (si->hw_features & ENETC_SI_F_QBU)
+ len += ARRAY_SIZE(enetc_pmac_counters);
return len;
}
@@ -202,6 +223,7 @@ static int enetc_get_sset_count(struct net_device *ndev, int sset)
static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
+ struct enetc_si *si = priv->si;
int i, j;
switch (stringset) {
@@ -215,14 +237,20 @@ static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
for (j = 0; j < ARRAY_SIZE(rx_ring_stats); j++)
ethtool_sprintf(&data, rx_ring_stats[j], i);
- if (!enetc_si_is_pf(priv->si))
+ if (!enetc_si_is_pf(si))
break;
for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
ethtool_cpy(&data, enetc_port_counters[i].name);
- for (i = 0; i < ARRAY_SIZE(enetc_pm_counters); i++)
- ethtool_cpy(&data, enetc_pm_counters[i].name);
+ for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
+ ethtool_cpy(&data, enetc_emac_counters[i].name);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ break;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
+ ethtool_cpy(&data, enetc_pmac_counters[i].name);
break;
}
@@ -232,7 +260,8 @@ static void enetc_get_ethtool_stats(struct net_device *ndev,
struct ethtool_stats *stats, u64 *data)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
- struct enetc_hw *hw = &priv->si->hw;
+ struct enetc_si *si = priv->si;
+ struct enetc_hw *hw = &si->hw;
int i, o = 0;
for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++)
@@ -256,14 +285,20 @@ static void enetc_get_ethtool_stats(struct net_device *ndev,
data[o++] = enetc_rd(hw, ENETC_RBDCR(i));
}
- if (!enetc_si_is_pf(priv->si))
+ if (!enetc_si_is_pf(si))
return;
for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg);
- for (i = 0; i < ARRAY_SIZE(enetc_pm_counters); i++)
- data[o++] = enetc_port_rd64(hw, enetc_pm_counters[i].reg);
+ for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
+ data[o++] = enetc_port_rd64(hw, enetc_emac_counters[i].reg);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
+ data[o++] = enetc_port_rd64(hw, enetc_pmac_counters[i].reg);
}
static void enetc_pause_stats(struct enetc_si *si, int mac,
--
2.34.1
^ permalink raw reply related
* [PATCH net-next 5/5] net: enetc: add unstructured counters for ENETC v4
From: Wei Fang @ 2026-04-08 5:58 UTC (permalink / raw)
To: claudiu.manoil, vladimir.oltean, xiaoning.wang, andrew+netdev,
davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel, imx
In-Reply-To: <20260408055849.1314033-1-wei.fang@nxp.com>
Like ENETC v1, ENETC v4 also has many non-standard counters, so these
counters are added to improve statistical coverage.
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
.../net/ethernet/freescale/enetc/enetc4_hw.h | 72 +++++++
.../ethernet/freescale/enetc/enetc_ethtool.c | 187 +++++++++++++++---
2 files changed, 234 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 392992a646fb..f18437556a0e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -64,6 +64,9 @@
#define ENETC4_PPAUONTR 0x108
#define ENETC4_PPAUOFFTR 0x10c
+/* Port ingress congestion DRa (a=0,1,2,3) discard count register */
+#define ENETC4_PICDRDCR(a) ((a) * 0x10 + 0x140)
+
/* Port Station interface promiscuous MAC mode register */
#define ENETC4_PSIPMMR 0x200
#define PSIPMMR_SI_MAC_UP(a) BIT(a) /* a = SI index */
@@ -72,6 +75,12 @@
/* Port Station interface promiscuous VLAN mode register */
#define ENETC4_PSIPVMR 0x204
+/* Port broadcast frames dropped due to MAC filtering register */
+#define ENETC4_PBFDSIR 0x208
+
+/* Port frame drop MAC source address pruning register */
+#define ENETC4_PFDMSAPR 0x20c
+
/* Port RSS key register n. n = 0,1,2,...,9 */
#define ENETC4_PRSSKR(n) ((n) * 0x4 + 0x250)
@@ -79,6 +88,12 @@
#define ENETC4_PSIMAFCAPR 0x280
#define PSIMAFCAPR_NUM_MAC_AFTE GENMASK(11, 0)
+/* Port unicast frames dropped due to MAC filtering register */
+#define ENETC4_PUFDMFR 0x284
+
+/* Port multicast frames dropped due to MAC filtering register */
+#define ENETC4_PMFDMFR 0x288
+
/* Port station interface VLAN filtering capability register */
#define ENETC4_PSIVLANFCAPR 0x2c0
#define PSIVLANFCAPR_NUM_VLAN_FTE GENMASK(11, 0)
@@ -87,6 +102,15 @@
#define ENETC4_PSIVLANFMR 0x2c4
#define PSIVLANFMR_VS BIT(0)
+/* Port unicast frames dropped VLAN filtering register */
+#define ENETC4_PUFDVFR 0x2d0
+
+/* Port multicast frames dropped VLAN filtering register */
+#define ENETC4_PMFDVFR 0x2d4
+
+/* Port broadcast frames dropped VLAN filtering register */
+#define ENETC4_PBFDVFR 0x2d8
+
/* Port Station interface a primary MAC address registers */
#define ENETC4_PSIPMAR0(a) ((a) * 0x80 + 0x2000)
#define ENETC4_PSIPMAR1(a) ((a) * 0x80 + 0x2004)
@@ -141,6 +165,18 @@
#define ENETC4_PSR 0x4104
#define PSR_RX_BUSY BIT(1)
+/* Port Rx discard count register */
+#define ENETC4_PRXDCR 0x41c0
+
+/* Port Rx discard count read-reset register */
+#define ENETC4_PRXDCRRR 0x41c4
+
+/* Port Rx discard count reason register 0 */
+#define ENETC4_PRXDCRR0 0x41c8
+
+/* Port Rx discard count reason register 1 */
+#define ENETC4_PRXDCRR1 0x41cc
+
/* Port traffic class a transmit maximum SDU register */
#define ENETC4_PTCTMSDUR(a) ((a) * 0x20 + 0x4208)
#define PTCTMSDUR_MAXSDU GENMASK(15, 0)
@@ -199,6 +235,9 @@
/* Port MAC 0/1 Receive Ethernet Octets Counter */
#define ENETC4_PM_REOCT(mac) (0x5100 + (mac) * 0x400)
+/* Port MAC 0/1 Receive Octets Counter */
+#define ENETC4_PM_ROCT(mac) (0x5108 + (mac) * 0x400)
+
/* Port MAC 0/1 Receive Alignment Error Counter Register */
#define ENETC4_PM_RALN(mac) (0x5110 + (mac) * 0x400)
@@ -211,12 +250,27 @@
/* Port MAC 0/1 Receive Frame Check Sequence Error Counter */
#define ENETC4_PM_RFCS(mac) (0x5128 + (mac) * 0x400)
+/* Port MAC 0/1 Receive VLAN Frame Counter */
+#define ENETC4_PM_RVLAN(mac) (0x5130 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Frame Error Counter */
+#define ENETC4_PM_RERR(mac) (0x5138 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Unicast Frame Counter */
+#define ENETC4_PM_RUCA(mac) (0x5140 + (mac) * 0x400)
+
/* Port MAC 0/1 Receive Multicast Frame Counter */
#define ENETC4_PM_RMCA(mac) (0x5148 + (mac) * 0x400)
/* Port MAC 0/1 Receive Broadcast Frame Counter */
#define ENETC4_PM_RBCA(mac) (0x5150 + (mac) * 0x400)
+/* Port MAC 0/1 Receive Dropped Packets Counter */
+#define ENETC4_PM_RDRP(mac) (0x5158 + (mac) * 0x400)
+
+/* Port MAC 0/1 Receive Packets Counter */
+#define ENETC4_PM_RPKT(mac) (0x5160 + (mac) * 0x400)
+
/* Port MAC 0/1 Receive Undersized Packet Counter */
#define ENETC4_PM_RUND(mac) (0x5168 + (mac) * 0x400)
@@ -259,21 +313,36 @@
/* Port MAC 0/1 Transmit Ethernet Octets Counter */
#define ENETC4_PM_TEOCT(mac) (0x5200 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Octets Counter */
+#define ENETC4_PM_TOCT(mac) (0x5208 + (mac) * 0x400)
+
/* Port MAC 0/1 Transmit Valid Pause Frame Counter */
#define ENETC4_PM_TXPF(mac) (0x5218 + (mac) * 0x400)
/* Port MAC 0/1 Transmit Frame Counter */
#define ENETC4_PM_TFRM(mac) (0x5220 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Frame Check Sequence Error Counter */
+#define ENETC4_PM_TFCS(mac) (0x5228 + (mac) * 0x400)
+
+/* Port MAC 0/1 Transmit VLAN Frame Counter */
+#define ENETC4_PM_TVLAN(mac) (0x5230 + (mac) * 0x400)
+
/* Port MAC 0/1 Transmit Frame Error Counter */
#define ENETC4_PM_TERR(mac) (0x5238 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Unicast Frame Counter */
+#define ENETC4_PM_TUCA(mac) (0x5240 + (mac) * 0x400)
+
/* Port MAC 0/1 Transmit Multicast Frame Counter */
#define ENETC4_PM_TMCA(mac) (0x5248 + (mac) * 0x400)
/* Port MAC 0/1 Transmit Broadcast Frame Counter */
#define ENETC4_PM_TBCA(mac) (0x5250 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Packets Counter */
+#define ENETC4_PM_TPKT(mac) (0x5260 + (mac) * 0x400)
+
/* Port MAC 0/1 Transmit Undersized Packet Counter */
#define ENETC4_PM_TUND(mac) (0x5268 + (mac) * 0x400)
@@ -316,6 +385,9 @@
/* Port MAC 0/1 Transmit Excessive Collisions Counter */
#define ENETC4_PM_TECOL(mac) (0x52f0 + (mac) * 0x400)
+/* Port MAC 0/1 Transmit Invalid Octets Counter */
+#define ENETC4_PM_TIOCT(mac) (0x52f8 + (mac) * 0x400)
+
/* Port MAC 0 Interface Mode Control Register */
#define ENETC4_PM_IF_MODE(mac) (0x5300 + (mac) * 0x400)
#define PM_IF_MODE_IFMODE GENMASK(2, 0)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
index bdc5916e4400..71f376ef1be1 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -177,6 +177,65 @@ static const struct {
{ ENETC_PICDR(3), "ICM DR3 discarded frames" },
};
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN] __nonstring;
+} enetc4_emac_counters[] = {
+ { ENETC4_PM_ROCT(0), "eMAC rx octets" },
+ { ENETC4_PM_RVLAN(0), "eMAC rx VLAN frames" },
+ { ENETC4_PM_RERR(0), "eMAC rx frame errors" },
+ { ENETC4_PM_RUCA(0), "eMAC rx unicast frames" },
+ { ENETC4_PM_RDRP(0), "eMAC rx dropped packets" },
+ { ENETC4_PM_RPKT(0), "eMAC rx packets" },
+ { ENETC4_PM_TOCT(0), "eMAC tx octets" },
+ { ENETC4_PM_TVLAN(0), "eMAC tx VLAN frames" },
+ { ENETC4_PM_TFCS(0), "eMAC tx fcs errors" },
+ { ENETC4_PM_TUCA(0), "eMAC tx unicast frames" },
+ { ENETC4_PM_TPKT(0), "eMAC tx packets" },
+ { ENETC4_PM_TUND(0), "eMAC tx undersized packets" },
+ { ENETC4_PM_TIOCT(0), "eMAC tx invalid octets" },
+};
+
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN] __nonstring;
+} enetc4_pmac_counters[] = {
+ { ENETC4_PM_ROCT(1), "pMAC rx octets" },
+ { ENETC4_PM_RVLAN(1), "pMAC rx VLAN frames" },
+ { ENETC4_PM_RERR(1), "pMAC rx frame errors" },
+ { ENETC4_PM_RUCA(1), "pMAC rx unicast frames" },
+ { ENETC4_PM_RDRP(1), "pMAC rx dropped packets" },
+ { ENETC4_PM_RPKT(1), "pMAC rx packets" },
+ { ENETC4_PM_TOCT(1), "pMAC tx octets" },
+ { ENETC4_PM_TVLAN(1), "pMAC tx VLAN frames" },
+ { ENETC4_PM_TFCS(1), "pMAC tx fcs errors" },
+ { ENETC4_PM_TUCA(1), "pMAC tx unicast frames" },
+ { ENETC4_PM_TPKT(1), "pMAC tx packets" },
+ { ENETC4_PM_TUND(1), "pMAC tx undersized packets" },
+ { ENETC4_PM_TIOCT(1), "pMAC tx invalid octets" },
+};
+
+static const struct {
+ int reg;
+ char name[ETH_GSTRING_LEN] __nonstring;
+} enetc4_port_counters[] = {
+ { ENETC4_PICDRDCR(0), "ICM DR0 discarded frames" },
+ { ENETC4_PICDRDCR(1), "ICM DR1 discarded frames" },
+ { ENETC4_PICDRDCR(2), "ICM DR2 discarded frames" },
+ { ENETC4_PICDRDCR(3), "ICM DR3 discarded frames" },
+ { ENETC4_PUFDMFR, "MAC filter discarded unicast" },
+ { ENETC4_PMFDMFR, "MAC filter discarded multicast" },
+ { ENETC4_PBFDSIR, "MAC filter discarded broadcast" },
+ { ENETC4_PFDMSAPR, "MAC SA pruning discarded frames" },
+ { ENETC4_PUFDVFR, "VLAN filter discarded unicast" },
+ { ENETC4_PMFDVFR, "VLAN filter discarded multicast" },
+ { ENETC4_PBFDVFR, "VLAN filter discarded broadcast" },
+ { ENETC4_PRXDCR, "MAC rx discarded frames" },
+ { ENETC4_PRXDCRRR, "MAC rx discard read-reset" },
+ { ENETC4_PRXDCRR0, "MAC rx discard reason 0" },
+ { ENETC4_PRXDCRR1, "MAC rx discard reason 1" },
+};
+
static const char rx_ring_stats[][ETH_GSTRING_LEN] = {
"Rx ring %2d frames",
"Rx ring %2d alloc errors",
@@ -211,15 +270,62 @@ static int enetc_get_sset_count(struct net_device *ndev, int sset)
if (!enetc_si_is_pf(si))
return len;
- len += ARRAY_SIZE(enetc_port_counters);
- len += ARRAY_SIZE(enetc_emac_counters);
+ if (is_enetc_rev1(si)) {
+ len += ARRAY_SIZE(enetc_port_counters);
+ len += ARRAY_SIZE(enetc_emac_counters);
+ if (si->hw_features & ENETC_SI_F_QBU)
+ len += ARRAY_SIZE(enetc_pmac_counters);
+ } else {
+ len += ARRAY_SIZE(enetc4_port_counters);
- if (si->hw_features & ENETC_SI_F_QBU)
- len += ARRAY_SIZE(enetc_pmac_counters);
+ if (enetc_is_pseudo_mac(si))
+ return len;
+
+ len += ARRAY_SIZE(enetc4_emac_counters);
+ if (si->hw_features & ENETC_SI_F_QBU)
+ len += ARRAY_SIZE(enetc4_pmac_counters);
+ }
return len;
}
+static void enetc_get_pf_strings(struct enetc_si *si, u8 *data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
+ ethtool_cpy(&data, enetc_port_counters[i].name);
+
+ for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
+ ethtool_cpy(&data, enetc_emac_counters[i].name);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
+ ethtool_cpy(&data, enetc_pmac_counters[i].name);
+}
+
+static void enetc4_get_pf_strings(struct enetc_si *si, u8 *data)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_port_counters); i++)
+ ethtool_cpy(&data, enetc4_port_counters[i].name);
+
+ if (enetc_is_pseudo_mac(si))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_emac_counters); i++)
+ ethtool_cpy(&data, enetc4_emac_counters[i].name);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_pmac_counters); i++)
+ ethtool_cpy(&data, enetc4_pmac_counters[i].name);
+}
+
static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -240,20 +346,52 @@ static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
if (!enetc_si_is_pf(si))
break;
- for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
- ethtool_cpy(&data, enetc_port_counters[i].name);
+ if (is_enetc_rev1(si))
+ enetc_get_pf_strings(si, data);
+ else
+ enetc4_get_pf_strings(si, data);
- for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
- ethtool_cpy(&data, enetc_emac_counters[i].name);
+ break;
+ }
+}
- if (!(si->hw_features & ENETC_SI_F_QBU))
- break;
+static void enetc_pf_get_ethtool_stats(struct enetc_si *si, int *o, u64 *data)
+{
+ struct enetc_hw *hw = &si->hw;
+ int i;
- for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
- ethtool_cpy(&data, enetc_pmac_counters[i].name);
+ for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
+ data[(*o)++] = enetc_port_rd(hw, enetc_port_counters[i].reg);
- break;
- }
+ for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
+ data[(*o)++] = enetc_port_rd64(hw, enetc_emac_counters[i].reg);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
+ data[(*o)++] = enetc_port_rd64(hw, enetc_pmac_counters[i].reg);
+}
+
+static void enetc4_pf_get_ethtool_stats(struct enetc_si *si, int *o, u64 *data)
+{
+ struct enetc_hw *hw = &si->hw;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_port_counters); i++)
+ data[(*o)++] = enetc_port_rd(hw, enetc4_port_counters[i].reg);
+
+ if (enetc_is_pseudo_mac(si))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_emac_counters); i++)
+ data[(*o)++] = enetc_port_rd64(hw, enetc4_emac_counters[i].reg);
+
+ if (!(si->hw_features & ENETC_SI_F_QBU))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(enetc4_pmac_counters); i++)
+ data[(*o)++] = enetc_port_rd64(hw, enetc4_pmac_counters[i].reg);
}
static void enetc_get_ethtool_stats(struct net_device *ndev,
@@ -288,17 +426,10 @@ static void enetc_get_ethtool_stats(struct net_device *ndev,
if (!enetc_si_is_pf(si))
return;
- for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++)
- data[o++] = enetc_port_rd(hw, enetc_port_counters[i].reg);
-
- for (i = 0; i < ARRAY_SIZE(enetc_emac_counters); i++)
- data[o++] = enetc_port_rd64(hw, enetc_emac_counters[i].reg);
-
- if (!(si->hw_features & ENETC_SI_F_QBU))
- return;
-
- for (i = 0; i < ARRAY_SIZE(enetc_pmac_counters); i++)
- data[o++] = enetc_port_rd64(hw, enetc_pmac_counters[i].reg);
+ if (is_enetc_rev1(si))
+ enetc_pf_get_ethtool_stats(si, &o, data);
+ else
+ enetc4_pf_get_ethtool_stats(si, &o, data);
}
static void enetc_pause_stats(struct enetc_si *si, int mac,
@@ -1438,6 +1569,9 @@ const struct ethtool_ops enetc4_ppm_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
+ .get_sset_count = enetc_get_sset_count,
+ .get_strings = enetc_get_strings,
+ .get_ethtool_stats = enetc_get_ethtool_stats,
.get_eth_mac_stats = enetc_ppm_get_eth_mac_stats,
.get_rx_ring_count = enetc_get_rx_ring_count,
.get_rxfh_key_size = enetc_get_rxfh_key_size,
@@ -1480,6 +1614,9 @@ const struct ethtool_ops enetc4_pf_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
ETHTOOL_COALESCE_MAX_FRAMES |
ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
+ .get_sset_count = enetc_get_sset_count,
+ .get_strings = enetc_get_strings,
+ .get_ethtool_stats = enetc_get_ethtool_stats,
.get_pause_stats = enetc_get_pause_stats,
.get_rmon_stats = enetc_get_rmon_stats,
.get_eth_ctrl_stats = enetc_get_eth_ctrl_stats,
--
2.34.1
^ permalink raw reply related
* Re: [Intel-wired-lan] [PATCH net] ice: fix VF queue configuration with low MTU values
From: Paul Menzel @ 2026-04-08 6:24 UTC (permalink / raw)
To: Jose Ignacio Tornos Martinez
Cc: intel-wired-lan, netdev, Tony Nguyen, Przemek Kitszel,
Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Jacob Keller, Aleksandr Loktionov,
Michal Swiatkowski, Dave Ertman, Michal Kubiak, stable
In-Reply-To: <20260406145641.1020623-1-jtornosm@redhat.com>
Dear Jose,
Thank you for the patch.
Am 06.04.26 um 16:56 schrieb Jose Ignacio Tornos Martinez:
> The ice driver's VF queue configuration validation rejects
> databuffer_size values below 1024 bytes, which prevents VFs from
> using MTU values below 871 bytes.
>
> The iavf driver calculates databuffer_size based on the MTU using:
> databuffer_size = ALIGN(MTU + LIBETH_RX_LL_LEN, 128)
>
> where LIBETH_RX_LL_LEN = 26 (ETH_HLEN + 2*VLAN_HLEN + ETH_FCS_LEN).
>
> For MTU values below 871:
> MTU 870: 870 + 26 = 896, aligned to 128 = 896 (< 1024, rejected)
> MTU 871: 871 + 26 = 897, aligned to 128 = 1024 (>= 1024, accepted)
>
> The 1024-byte minimum seems unnecessarily restrictive, because the hardware
> supports databuffer_size as low as 128 bytes (the alignment boundary),
> which should allow MTU values down to the standard minimum of 68 bytes.
>
> I haven't found the reason why the limit was configured in the commit
> 9c7dd7566d18 ("ice: add validation in OP_CONFIG_VSI_QUEUES VF message"), so
> with no more information and since it is working, change the minimum
> databuffer_size validation from 1024 to 128 bytes to allow standard low
> MTU values while still preventing invalid configurations.
Should you resend, having the reproducer script would be nice to have.
> Fixes: 9c7dd7566d18 ("ice: add validation in OP_CONFIG_VSI_QUEUES VF message")
> cc: stable@vger.kernel.org
> Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
> ---
> drivers/net/ethernet/intel/ice/virt/queues.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/intel/ice/virt/queues.c b/drivers/net/ethernet/intel/ice/virt/queues.c
> index f73d5a3e83d4..31be2f76181c 100644
> --- a/drivers/net/ethernet/intel/ice/virt/queues.c
> +++ b/drivers/net/ethernet/intel/ice/virt/queues.c
> @@ -840,7 +840,7 @@ int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
>
> if (qpi->rxq.databuffer_size != 0 &&
> (qpi->rxq.databuffer_size > ((16 * 1024) - 128) ||
> - qpi->rxq.databuffer_size < 1024))
> + qpi->rxq.databuffer_size < 128))
> goto error_param;
>
> ring->rx_buf_len = qpi->rxq.databuffer_size;
Either way:
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Kind regards,
Paul
^ permalink raw reply
* Re: [PATCH] ppp: require CAP_NET_ADMIN in target netns for unattached ioctls
From: Qingfang Deng @ 2026-04-08 6:28 UTC (permalink / raw)
To: Taegu Ha, netdev
Cc: linux-ppp, gnault, jaco, richardbgobert, ericwouds,
Cyrill Gorcunov, Matteo Croce
In-Reply-To: <20260408042345.1011-1-hataegu0826@gmail.com>
Hi,
Added Cc: Cyrill, and Matteo
On 2026/4/8 12:23, Taegu Ha wrote:
> /dev/ppp open is currently authorized against file->f_cred->user_ns,
> while unattached administrative ioctls operate on current->nsproxy->net_ns.
>
> As a result, a local unprivileged user can create a new user namespace
> with CLONE_NEWUSER, gain CAP_NET_ADMIN only in that new user namespace,
> and still issue PPPIOCNEWUNIT, PPPIOCATTACH, or PPPIOCATTCHAN against
> an inherited network namespace.
>
> Require CAP_NET_ADMIN in the user namespace that owns the target network
> namespace before handling these unattached PPP administrative ioctls.
>
> This preserves normal pppd operation in the network namespace it is
> actually privileged in, while rejecting the userns-only inherited-netns
> case.
>
> Fixes: 273ec51dd7ce ("net: ppp_generic - introduce net-namespace functionality v2")
For fixes, you should set the target tree to "net" in the patch subject,
using:
git format-patch --subject-prefix="PATCH net"
> Reported-by: Taegu Ha <hataegu0826@gmail.com>
Minor nit: Reported-by tag is not needed if it's the same user as Signed-off-by.
> Signed-off-by: Taegu Ha <hataegu0826@gmail.com>
> ---
> drivers/net/ppp/ppp_generic.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
> index e9b41777be80..99a8557188c0 100644
> --- a/drivers/net/ppp/ppp_generic.c
> +++ b/drivers/net/ppp/ppp_generic.c
> @@ -1059,6 +1059,9 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
>
> switch (cmd) {
> case PPPIOCNEWUNIT:
> + if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
> + return -EPERM;
> +
These three identical checks can be combined into one and placed before
the switch statement.
> /* Create a new ppp unit */
> if (get_user(unit, p))
> break;
> @@ -1073,6 +1076,9 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
> break;
>
> case PPPIOCATTACH:
> + if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
> + return -EPERM;
> +
> /* Attach to an existing ppp unit */
> if (get_user(unit, p))
> break;
> @@ -1089,6 +1095,9 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
> break;
>
> case PPPIOCATTCHAN:
> + if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
> + return -EPERM;
> +
> if (get_user(unit, p))
> break;
> err = -ENXIO;
^ permalink raw reply
* RE: [Intel-wired-lan] [PATCH iwl-net 2/2] idpf: fix skb datapath queue based scheduling crashes and timeouts
From: Loktionov, Aleksandr @ 2026-04-08 6:37 UTC (permalink / raw)
To: Hay, Joshua A, intel-wired-lan@lists.osuosl.org; +Cc: netdev@vger.kernel.org
In-Reply-To: <20260406233236.3585504-3-joshua.a.hay@intel.com>
> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Joshua Hay
> Sent: Tuesday, April 7, 2026 1:33 AM
> To: intel-wired-lan@lists.osuosl.org
> Cc: netdev@vger.kernel.org
> Subject: [Intel-wired-lan] [PATCH iwl-net 2/2] idpf: fix skb datapath
> queue based scheduling crashes and timeouts
>
> The splitq Tx resource checks were assuming that the queues were using
> flow based scheduling and checking the refillqs for free buffers.
> However, the Tx refillqs are not allocated when using queue based
> scheduling resulting in a NULL ptr dereference. Adjust the Tx resource
> checks to only check available descriptor resources when using queue
> based scheduling. Because queue based scheduling does not have any
> notion of descriptor only completions, there cannot be any packets in
> flight, meaning there is no need to check for pending completions.
>
> The driver also only supported 8 byte completion descriptors in the
> skb datapath previously. However, currently the FW only supports 4
> byte completion descriptors when using queue based scheduling. This
> meant we were skipping over completions, resulting in Tx timeouts.
> Add support to process both 4 and 8 byte completion descriptors,
> depending on the scheduling mode. Cache the next_to_clean completion
> descriptor in the completion queue struct, and fetch this descriptor
> before the start of each cleaning loop. Access the next descriptor in
> the loop by calculating the index based on raw byte count.
>
> Fixes: 0c3f135e840d ("idpf: stop Tx if there are insufficient buffer
> resources")
> Fixes: 1c325aac10a8 ("idpf: configure resources for TX queues")
> Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
> Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
> ---
> drivers/net/ethernet/intel/idpf/idpf_txrx.c | 49 +++++++++++++-------
> - drivers/net/ethernet/intel/idpf/idpf_txrx.h | 6 ++-
> 2 files changed, 36 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> index f6b3b15364ff..4fc0bb14c5b1 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
> @@ -270,11 +270,9 @@ static int idpf_tx_desc_alloc(const struct
> idpf_vport *vport, static int idpf_compl_desc_alloc(const struct
> idpf_vport *vport,
> struct idpf_compl_queue *complq)
> {
...
>
> /**
> * struct idpf_sw_queue
> --
> 2.39.2
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
^ permalink raw reply
* [syzbot ci] Re: net_sched: fix skb memory leak in deferred qdisc drops
From: syzbot ci @ 2026-04-08 6:45 UTC (permalink / raw)
To: damilola, davem, edumazet, fmancera, horms, kuba, netdev, pabeni
Cc: syzbot, syzkaller-bugs
In-Reply-To: <20260407170214.4157-2-fmancera@suse.de>
syzbot ci has tested the following series
[v1] net_sched: fix skb memory leak in deferred qdisc drops
https://lore.kernel.org/all/20260407170214.4157-2-fmancera@suse.de
* [PATCH net] net_sched: fix skb memory leak in deferred qdisc drops
and found the following issue:
WARNING: suspicious RCU usage in cake_dequeue
Full report is available here:
https://ci.syzbot.org/series/90acbb62-3e93-4bb7-af7a-51d555f5956b
***
WARNING: suspicious RCU usage in cake_dequeue
tree: net
URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/netdev/net.git
base: a9b8b18364fffce4c451e6f6fd218fa4ab646705
arch: amd64
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
config: https://ci.syzbot.org/builds/a5e0fad0-c9c8-4102-b2af-b4d1c7947ee3/config
syz repro: https://ci.syzbot.org/findings/b1dd239a-f59f-414f-8bde-578258899e94/syz_repro
=============================
WARNING: suspicious RCU usage
syzkaller #0 Not tainted
-----------------------------
./include/net/sch_generic.h:581 suspicious rcu_dereference_check() usage!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1
2 locks held by syz.0.51/6016:
#0: ffffffff8e75e640 (rcu_read_lock_bh){....}-{1:3}, at: local_bh_disable include/linux/bottom_half.h:20 [inline]
#0: ffffffff8e75e640 (rcu_read_lock_bh){....}-{1:3}, at: rcu_read_lock_bh include/linux/rcupdate.h:903 [inline]
#0: ffffffff8e75e640 (rcu_read_lock_bh){....}-{1:3}, at: __dev_queue_xmit+0x277/0x3890 net/core/dev.c:4778
#1: ffff8881ad9e8170 (&sch->root_lock_key#31){+...}-{3:3}, at: spin_lock include/linux/spinlock.h:341 [inline]
#1: ffff8881ad9e8170 (&sch->root_lock_key#31){+...}-{3:3}, at: __dev_xmit_skb net/core/dev.c:4241 [inline]
#1: ffff8881ad9e8170 (&sch->root_lock_key#31){+...}-{3:3}, at: __dev_queue_xmit+0xbf2/0x3890 net/core/dev.c:4819
stack backtrace:
CPU: 1 UID: 0 PID: 6016 Comm: syz.0.51 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
lockdep_rcu_suspicious+0x13f/0x1d0 kernel/locking/lockdep.c:6876
qdisc_root_sleeping include/net/sch_generic.h:581 [inline]
qdisc_dequeue_drop include/net/sch_generic.h:1173 [inline]
cake_dequeue+0x23a7/0x4e50 net/sched/sch_cake.c:2240
dequeue_skb net/sched/sch_generic.c:297 [inline]
qdisc_restart net/sched/sch_generic.c:402 [inline]
__qdisc_run+0x26c/0x15d0 net/sched/sch_generic.c:420
qdisc_run include/net/pkt_sched.h:120 [inline]
__dev_xmit_skb net/core/dev.c:4286 [inline]
__dev_queue_xmit+0x1bad/0x3890 net/core/dev.c:4819
packet_snd net/packet/af_packet.c:3076 [inline]
packet_sendmsg+0x3eb6/0x50f0 net/packet/af_packet.c:3108
sock_sendmsg_nosec net/socket.c:727 [inline]
__sock_sendmsg net/socket.c:742 [inline]
__sys_sendto+0x672/0x710 net/socket.c:2206
__do_sys_sendto net/socket.c:2213 [inline]
__se_sys_sendto net/socket.c:2209 [inline]
__x64_sys_sendto+0xde/0x100 net/socket.c:2209
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f077b39c819
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f077c28c028 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 00007f077b615fa0 RCX: 00007f077b39c819
RDX: 000000000000fc13 RSI: 0000200000000800 RDI: 0000000000000003
RBP: 00007f077b432c91 R08: 0000000000000000 R09: fffffffffffffef0
R10: 0000000000000880 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f077b616038 R14: 00007f077b615fa0 R15: 00007fffceb20038
</TASK>
***
If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
Tested-by: syzbot@syzkaller.appspotmail.com
---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.
To test a patch for this bug, please reply with `#syz test`
(should be on a separate line).
The patch should be attached to the email.
Note: arguments like custom git repos and branches are not supported.
^ permalink raw reply
* [PATCH net v2] ppp: require CAP_NET_ADMIN in target netns for unattached ioctls
From: Taegu Ha @ 2026-04-08 6:51 UTC (permalink / raw)
To: netdev
Cc: linux-ppp, qingfang.deng, gnault, jaco, richardbgobert, ericwouds,
Taegu Ha
/dev/ppp open is currently authorized against file->f_cred->user_ns,
while unattached administrative ioctls operate on current->nsproxy->net_ns.
As a result, a local unprivileged user can create a new user namespace
with CLONE_NEWUSER, gain CAP_NET_ADMIN only in that new user namespace,
and still issue PPPIOCNEWUNIT, PPPIOCATTACH, or PPPIOCATTCHAN against
an inherited network namespace.
Require CAP_NET_ADMIN in the user namespace that owns the target network
namespace before handling these unattached PPP administrative ioctls.
This preserves normal pppd operation in the network namespace it is
actually privileged in, while rejecting the userns-only inherited-netns
case.
Fixes: 273ec51dd7ce ("net: ppp_generic - introduce net-namespace functionality v2")
Signed-off-by: Taegu Ha <hataegu0826@gmail.com>
---
drivers/net/ppp/ppp_generic.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index e9b41777be80..4435c594f587 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -1057,6 +1057,12 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
struct ppp_net *pn;
int __user *p = (int __user *)arg;
+ if ((cmd == PPPIOCNEWUNIT ||
+ cmd == PPPIOCATTACH ||
+ cmd == PPPIOCATTCHAN) &&
+ !ns_capable(net->user_ns, CAP_NET_ADMIN))
+ return -EPERM;
+
switch (cmd) {
case PPPIOCNEWUNIT:
/* Create a new ppp unit */
--
2.43.0
^ permalink raw reply related
* [PATCH 0/3] io_uring: fix resource leak issues
From: KobaK @ 2026-04-08 6:54 UTC (permalink / raw)
To: Jens Axboe, Pavel Begunkov
Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel, Koba Ko
From: Koba Ko <kobak@nvidia.com>
Three resource leak fixes found by code audit:
1. memmap: pinned pages and pages array leak on WARN_ON path in
io_region_pin_pages() — mr->pages is never assigned so the caller's
cleanup is a no-op.
2. rsrc: kfree() used instead of io_cache_free() in
io_buffer_register_bvec() error path — bypasses cache return.
3. zcrx: io_import_umem() leaves live pinned pages in a partially
initialized struct on io_account_mem() failure, and
io_release_area_mem() is not idempotent (missing pages = NULL),
creating a double-free hazard.
Koba Ko (3):
io_uring: fix pinned pages and pages array leak in
io_region_pin_pages()
io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec
error path
io_uring/zcrx: fix resource leak and double-free hazard in
io_import_umem
io_uring/memmap.c | 5 ++++-
io_uring/rsrc.c | 2 +-
io_uring/zcrx.c | 19 +++++++++++++------
3 files changed, 18 insertions(+), 8 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH 1/3] io_uring: fix pinned pages and pages array leak in io_region_pin_pages()
From: KobaK @ 2026-04-08 6:54 UTC (permalink / raw)
To: Jens Axboe, Pavel Begunkov
Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel, Koba Ko
In-Reply-To: <20260408065408.2017967-1-kobak@nvidia.com>
From: Koba Ko <kobak@nvidia.com>
When io_pin_pages() succeeds but the subsequent nr_pages sanity check
fires (WARN_ON_ONCE), the function returns -EFAULT without unpinning the
user pages or freeing the kvmalloc'd pages array. The caller's cleanup
via io_free_region() won't help either, because mr->pages was never
assigned — so the entire cleanup block is skipped.
Add unpin_user_pages() and kvfree() before the error return to prevent
the leak.
Fixes: a90558b36ccee ("io_uring/memmap: helper for pinning region pages")
Signed-off-by: Koba Ko <kobak@nvidia.com>
---
io_uring/memmap.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/io_uring/memmap.c b/io_uring/memmap.c
index e6958968975a8..9f0d3750ce3bc 100644
--- a/io_uring/memmap.c
+++ b/io_uring/memmap.c
@@ -141,8 +141,11 @@ static int io_region_pin_pages(struct io_mapped_region *mr,
pages = io_pin_pages(reg->user_addr, size, &nr_pages);
if (IS_ERR(pages))
return PTR_ERR(pages);
- if (WARN_ON_ONCE(nr_pages != mr->nr_pages))
+ if (WARN_ON_ONCE(nr_pages != mr->nr_pages)) {
+ unpin_user_pages(pages, nr_pages);
+ kvfree(pages);
return -EFAULT;
+ }
mr->pages = pages;
mr->flags |= IO_REGION_F_USER_PROVIDED;
--
2.43.0
^ permalink raw reply related
* [PATCH 2/3] io_uring/rsrc: use io_cache_free for node in io_buffer_register_bvec error path
From: KobaK @ 2026-04-08 6:54 UTC (permalink / raw)
To: Jens Axboe, Pavel Begunkov
Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel, Koba Ko
In-Reply-To: <20260408065408.2017967-1-kobak@nvidia.com>
From: Koba Ko <kobak@nvidia.com>
io_buffer_register_bvec() allocates the rsrc node via
io_rsrc_node_alloc() which pulls from ctx->node_cache. On imu allocation
failure, the node is freed with raw kfree() instead of
io_cache_free(&ctx->node_cache, node), bypassing the cache return path
and wasting a reuse opportunity. Every other error path in this file
correctly uses io_cache_free for nodes.
Fixes: 27cb27b6d5ea4 ("io_uring: add support for kernel registered bvecs")
Signed-off-by: Koba Ko <kobak@nvidia.com>
---
io_uring/rsrc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index 1b96ab5e98c99..6f46cf9cd13d7 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -961,7 +961,7 @@ int io_buffer_register_bvec(struct io_uring_cmd *cmd, struct request *rq,
*/
imu = io_alloc_imu(ctx, blk_rq_nr_phys_segments(rq));
if (!imu) {
- kfree(node);
+ io_cache_free(&ctx->node_cache, node);
ret = -ENOMEM;
goto unlock;
}
--
2.43.0
^ permalink raw reply related
* [PATCH 3/3] io_uring/zcrx: fix resource leak and double-free hazard in io_import_umem
From: KobaK @ 2026-04-08 6:54 UTC (permalink / raw)
To: Jens Axboe, Pavel Begunkov
Cc: Keith Busch, Ming Lei, io-uring, netdev, linux-kernel, Koba Ko
In-Reply-To: <20260408065408.2017967-1-kobak@nvidia.com>
From: Koba Ko <kobak@nvidia.com>
io_import_umem() has two problems:
1. When io_account_mem() fails, the function returns an error but leaves
live pinned pages and sg_table in the mem struct without cleaning them
up. The caller happens to handle this today via io_zcrx_free_area() ->
io_release_area_mem(), but the contract is fragile.
2. io_release_area_mem() doesn't NULL out mem->pages after kvfree(),
making it unsafe to call twice. Since io_zcrx_free_area() always
calls it during teardown, any earlier cleanup call would cause a
double-free.
Fix both: populate mem fields before io_account_mem() so
io_release_area_mem() can do a proper cleanup on failure, and add
mem->pages = NULL in io_release_area_mem() to make it idempotent.
Fixes: 262ab205180d2 ("io_uring/zcrx: account area memory")
Signed-off-by: Koba Ko <kobak@nvidia.com>
---
io_uring/zcrx.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c
index 62d693287457f..c9ed1139c7bcd 100644
--- a/io_uring/zcrx.c
+++ b/io_uring/zcrx.c
@@ -188,6 +188,8 @@ static unsigned long io_count_account_pages(struct page **pages, unsigned nr_pag
return res;
}
+static void io_release_area_mem(struct io_zcrx_mem *mem);
+
static int io_import_umem(struct io_zcrx_ifq *ifq,
struct io_zcrx_mem *mem,
struct io_uring_zcrx_area_reg *area_reg)
@@ -213,16 +215,20 @@ static int io_import_umem(struct io_zcrx_ifq *ifq,
return ret;
}
- mem->account_pages = io_count_account_pages(pages, nr_pages);
- ret = io_account_mem(ifq->user, ifq->mm_account, mem->account_pages);
- if (ret < 0)
- mem->account_pages = 0;
-
mem->sgt = &mem->page_sg_table;
mem->pages = pages;
mem->nr_folios = nr_pages;
mem->size = area_reg->len;
- return ret;
+
+ mem->account_pages = io_count_account_pages(pages, nr_pages);
+ ret = io_account_mem(ifq->user, ifq->mm_account, mem->account_pages);
+ if (ret < 0) {
+ mem->account_pages = 0;
+ io_release_area_mem(mem);
+ return ret;
+ }
+
+ return 0;
}
static void io_release_area_mem(struct io_zcrx_mem *mem)
@@ -236,6 +242,7 @@ static void io_release_area_mem(struct io_zcrx_mem *mem)
sg_free_table(mem->sgt);
mem->sgt = NULL;
kvfree(mem->pages);
+ mem->pages = NULL;
}
}
--
2.43.0
^ permalink raw reply related
* RE: [PATCH v4 net-next 03/14] net: enetc: add pre-boot initialization for i.MX94 switch
From: Wei Fang @ 2026-04-08 6:55 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, f.fainelli@gmail.com, Frank Li,
chleroy@kernel.org, horms@kernel.org, linux@armlinux.org.uk,
andrew@lunn.ch, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev
In-Reply-To: <20260403011723.1795349-1-kuba@kernel.org>
> > +static int imx94_switch_link_config(struct netc_blk_ctrl *priv,
> > + struct device_node *np,
> > + bool *swp2_en)
> > +{
> > + struct device_node *ports;
> > + int port_id, err = 0;
>
> Since of_property_read_u32() expects a u32 pointer, does passing a
> signed int pointer here trigger an incompatible pointer types warning
> during compilation?
>
Okay, I will change port_id to u32 type.
> > +
> > + ports = netc_get_switch_ports(np);
> > + if (!ports)
> > + return -ENODEV;
> > +
> > + for_each_available_child_of_node_scoped(ports, child) {
> > + if (of_property_read_u32(child, "reg", &port_id) < 0) {
>
> If the device tree provides a reg value with the MSB set, port_id
> would be evaluated as a negative number.
>
> [ ... ]
> > static int imx94_netcmix_init(struct platform_device *pdev)
> > {
> > struct netc_blk_ctrl *priv = platform_get_drvdata(pdev);
> > struct device_node *np = pdev->dev.of_node;
> > + bool enetc0_en = false, swp2_en = false;
> > u32 val;
> > int err;
> >
> > for_each_child_of_node_scoped(np, child) {
> > for_each_child_of_node_scoped(child, gchild) {
> > - if (!of_device_is_compatible(gchild, "pci1131,e101"))
> > - continue;
> > -
> > - err = imx94_enetc_link_config(priv, gchild);
> > - if (err)
> > - return err;
> > + if (of_device_is_compatible(gchild, "pci1131,e101")) {
> > + err = imx94_enetc_link_config(priv, gchild,
> > + &enetc0_en);
> > + if (err)
> > + return err;
> > + } else if (of_device_is_compatible(gchild,
> > + "pci1131,eef2")) {
>
> Is it possible for the switch node to be disabled in the device tree?
>
> If so, should we check of_device_is_available() for gchild before proceeding,
> similar to how it is checked for enetc0_en?
The switch may be owned by a guest OS, in this case, the switch node of the
host OS will be disabled, but we still hope that the host OS could do some
configurations for the switch, as the netc_blk_ctrl is owned by host OS, so
we cannot check of_device_is_available() for the switch node.
>
> Without checking availability, if the disabled switch lacks a ports subnode,
> imx94_switch_link_config() might return -ENODEV and abort the entire probe.
This is the expected behavior, only one of swp2 and enetc0 can be enabled,
as they share the same parallel interface. If all of them are enabled, the driver
will detect this incorrect DTS configuration and return a failure.
> Alternatively, if the disabled switch node has a ports subnode with an
> available port 2, it could spuriously set swp2_en = true and cause a false
> conflict with ENETC 0.
>
> > + err = imx94_switch_link_config(priv, gchild,
> > + &swp2_en);
> > + if (err)
> > + return err;
> > + }
> > }
> > }
^ permalink raw reply
* Re: [PATCH net-next v2] net: bcmasp: Switch to page pool for RX path
From: Nicolai Buchwitz @ 2026-04-08 6:58 UTC (permalink / raw)
To: Florian Fainelli
Cc: netdev, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Justin Chen, Vikas Gupta,
Rajashekar Hudumula, Bhargava Marreddy, Arnd Bergmann,
Markus Blöchl, Heiner Kallweit, Fernando Fernandez Mancera,
linux-kernel, bcm-kernel-feedback-list
In-Reply-To: <20260408001813.635679-1-florian.fainelli@broadcom.com>
On 8.4.2026 02:18, Florian Fainelli wrote:
> This shows an improvement of 1.9% in reducing the CPU cycles and data
> cache misses.
>
> Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
> ---
> Changes in v2:
>
> - addressed Nicolai's comments by setting the .netdev and .napi members
> and dropped the useless comment and .dma_dir initialization
> [...]
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
^ permalink raw reply
* Re: [PATCH net-next 1/2] tcp: rehash onto different ECMP path on retransmit timeout
From: Neil Spring @ 2026-04-08 6:59 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, ncardwell, kuniyu, davem, dsahern, kuba, pabeni, horms,
shuah, linux-kselftest, Ido Schimmel
In-Reply-To: <CANn89iKEgkbS=FEssas9upr4kTpAuH2PRehthBC4Oc4bBfW8hQ@mail.gmail.com>
Thanks Eric for looking at this; sorry for the duplicate email as I
failed to reply all; comments below.
On Tue, Apr 7, 2026 at 6:09=E2=80=AFPM Eric Dumazet <edumazet@google.com> w=
rote:
> On Tue, Apr 7, 2026 at 5:28=E2=80=AFPM Neil Spring <ntspring@meta.com> wr=
ote:
> >
> > Add sk_dst_reset() alongside sk_rethink_txhash() in the RTO, PLB,
> > and spurious-retrans paths so that the next transmit triggers a fresh
> > route lookup. Propagate sk_txhash into fl6->mp_hash in
> > inet6_csk_route_req() and inet6_csk_route_socket() so
> > fib6_select_path() uses the socket's current hash for ECMP selection.
> >
> > The ir_iif update in tcp_check_req() covers both IPv4 and IPv6
> > because it was cleaner than gating on address family; IPv4 is
> > otherwise unaltered, and not having autoflowlabel in IPv4 means
> > I wouldn't expect a new path on timeout.
> >
> > It is possible that PLB does not need this (that there are other
> > methods of reacting to local congestion); I added the sk_dst_reset
> > for consistency.
> >
> > Signed-off-by: Neil Spring <ntspring@meta.com>
> > ---
> > net/ipv4/tcp_input.c | 4 +++-
> > net/ipv4/tcp_minisocks.c | 9 +++++++++
> > net/ipv4/tcp_plb.c | 1 +
> > net/ipv4/tcp_timer.c | 1 +
> > net/ipv6/inet6_connection_sock.c | 8 ++++++++
> > 5 files changed, 22 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> > index 7171442c3ed7..3d42ab45066c 100644
> > --- a/net/ipv4/tcp_input.c
> > +++ b/net/ipv4/tcp_input.c
> > @@ -5014,8 +5014,10 @@ static void tcp_rcv_spurious_retrans(struct sock=
*sk,
> > skb->protocol =3D=3D htons(ETH_P_IPV6) &&
> > (tcp_sk(sk)->inet_conn.icsk_ack.lrcv_flowlabel !=3D
> > ntohl(ip6_flowlabel(ipv6_hdr(skb)))) &&
> > - sk_rethink_txhash(sk))
> > + sk_rethink_txhash(sk)) {
> > NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDUPLICATEDATAR=
EHASH);
> > + sk_dst_reset(sk);
> > + }
> >
> > /* Save last flowlabel after a spurious retrans. */
> > tcp_save_lrcv_flowlabel(sk, skb);
> > diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
> > index 199f0b579e89..ef4b3771e9d8 100644
> > --- a/net/ipv4/tcp_minisocks.c
> > +++ b/net/ipv4/tcp_minisocks.c
> > @@ -750,6 +750,15 @@ struct sock *tcp_check_req(struct sock *sk, struct=
sk_buff *skb,
> > * Reset timer after retransmitting SYNACK, similar to
> > * the idea of fast retransmit in recovery.
> > */
> > +
>
> What is the following part doing?
> tcp_v6_init_req() uses something quite different before setting ir_iif
> A comment explaining the rationale would be nice.
Comment added in v2. The behavior I thought I observed was that the
ir_iif goes into fl6->flowi6_oif in inet6_csk_route_req(), limiting options
to any next hop on that interface, so if we received a retransmitted syn
on a new interface, we should try to use the new interface for the
response.
>
> > +#if IS_ENABLED(CONFIG_IPV6)
> > + if (sk->sk_family =3D=3D AF_INET6)
> > + inet_rsk(req)->ir_iif =3D tcp_v6_iif(skb);
> > + else
> > +#endif
> > + inet_rsk(req)->ir_iif =3D
> > + inet_request_bound_dev_if(sk, skb);
> > +
> > if (!tcp_oow_rate_limited(sock_net(sk), skb,
> > LINUX_MIB_TCPACKSKIPPEDSYNREC=
V,
> > &tcp_rsk(req)->last_oow_ack_t=
ime)) {
> > diff --git a/net/ipv4/tcp_plb.c b/net/ipv4/tcp_plb.c
> > index 68ccdb9a5412..d7cc00a58e53 100644
> > --- a/net/ipv4/tcp_plb.c
> > +++ b/net/ipv4/tcp_plb.c
> > @@ -79,6 +79,7 @@ void tcp_plb_check_rehash(struct sock *sk, struct tcp=
_plb_state *plb)
> > return;
> >
> > sk_rethink_txhash(sk);
> > + sk_dst_reset(sk);
> > plb->consec_cong_rounds =3D 0;
> > tcp_sk(sk)->plb_rehash++;
> > NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPLBREHASH);
> > diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
> > index ea99988795e7..acc22fc532c2 100644
> > --- a/net/ipv4/tcp_timer.c
> > +++ b/net/ipv4/tcp_timer.c
> > @@ -299,6 +299,7 @@ static int tcp_write_timeout(struct sock *sk)
> > if (sk_rethink_txhash(sk)) {
> > tp->timeout_rehash++;
> > __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPTIMEOUTREHAS=
H);
> > + sk_dst_reset(sk);
> > }
> >
> > return 0;
> > diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connecti=
on_sock.c
> > index 37534e116899..2fe753bb38b4 100644
> > --- a/net/ipv6/inet6_connection_sock.c
> > +++ b/net/ipv6/inet6_connection_sock.c
> > @@ -48,6 +48,11 @@ struct dst_entry *inet6_csk_route_req(const struct s=
ock *sk,
> > fl6->flowi6_uid =3D sk_uid(sk);
> > security_req_classify_flow(req, flowi6_to_flowi_common(fl6));
> >
> > + if (req->num_retrans)
> > + fl6->mp_hash =3D jhash_1word(req->num_retrans,
> > + (__force u32)ireq->ir_rmt_po=
rt)
> > + >> 1;
>
> Why not setting mp_hash to sk_txhash ?
To be honest, I was trying to avoid adding #include <tcp.h> to the top of
inet6_connection_sock.c, which is needed to get tcp_rsk(req)->txhash, but
that does make better code, using that in v2.
> Why are you using ">> 1" ?
The >> 1 is due to rt6_multipath_hash returning its computed
value shifted right one before going into mp_hash in route.c sites.
I understood mp_hash can't have the high bit set and still work
due to fib6_select_path treating it as a signed integer when comparing
to fib_nh_upper_bound.
> rt6_multipath_hash() seems to be bypassed, it might be time to add a
> comment there
> explaining that mp_hash needs to be 31-bit only...
>
> Perhaps use rt6_multipath_hash() and expand it to use a socket pointer
> to retrieve sk->sk_txhash when/if possible
> instead of yet another flow dissection.
I think thyour comment above (grabbing txhash) avoids the dissection.
>
> > +
> > if (!dst) {
> > dst =3D ip6_dst_lookup_flow(sock_net(sk), sk, fl6, fina=
l_p);
> > if (IS_ERR(dst))
> > @@ -70,6 +75,9 @@ struct dst_entry *inet6_csk_route_socket(struct sock =
*sk,
> > fl6->saddr =3D np->saddr;
> > fl6->flowlabel =3D np->flow_label;
> > IP6_ECN_flow_xmit(sk, fl6->flowlabel);
> > +
> > + if (sk->sk_txhash)
> > + fl6->mp_hash =3D sk->sk_txhash >> 1;
>
> Seems inconsistent, and same question about the right shift.
Adding comment and standardizing on
* tcp_rsk(req)->txhash >> 1 for request sockets,
* sk->sk_txhash >> 1 for established sockets.
>
>
> > fl6->flowi6_oif =3D sk->sk_bound_dev_if;
> > fl6->flowi6_mark =3D sk->sk_mark;
> > fl6->fl6_sport =3D inet->inet_sport;
> > --
> > 2.52.0
> >
On Tue, Apr 7, 2026 at 6:09 PM Eric Dumazet <edumazet@google.com> wrote:
>
> >
> On Tue, Apr 7, 2026 at 5:28 PM Neil Spring <ntspring@meta.com> wrote:
> >
> > Add sk_dst_reset() alongside sk_rethink_txhash() in the RTO, PLB,
> > and spurious-retrans paths so that the next transmit triggers a fresh
> > route lookup. Propagate sk_txhash into fl6->mp_hash in
> > inet6_csk_route_req() and inet6_csk_route_socket() so
> > fib6_select_path() uses the socket's current hash for ECMP selection.
> >
> > The ir_iif update in tcp_check_req() covers both IPv4 and IPv6
> > because it was cleaner than gating on address family; IPv4 is
> > otherwise unaltered, and not having autoflowlabel in IPv4 means
> > I wouldn't expect a new path on timeout.
> >
> > It is possible that PLB does not need this (that there are other
> > methods of reacting to local congestion); I added the sk_dst_reset
> > for consistency.
> >
> > Signed-off-by: Neil Spring <ntspring@meta.com>
> > ---
> > net/ipv4/tcp_input.c | 4 +++-
> > net/ipv4/tcp_minisocks.c | 9 +++++++++
> > net/ipv4/tcp_plb.c | 1 +
> > net/ipv4/tcp_timer.c | 1 +
> > net/ipv6/inet6_connection_sock.c | 8 ++++++++
> > 5 files changed, 22 insertions(+), 1 deletion(-)
> >
> > diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> > index 7171442c3ed7..3d42ab45066c 100644
> > --- a/net/ipv4/tcp_input.c
> > +++ b/net/ipv4/tcp_input.c
> > @@ -5014,8 +5014,10 @@ static void tcp_rcv_spurious_retrans(struct sock *sk,
> > skb->protocol == htons(ETH_P_IPV6) &&
> > (tcp_sk(sk)->inet_conn.icsk_ack.lrcv_flowlabel !=
> > ntohl(ip6_flowlabel(ipv6_hdr(skb)))) &&
> > - sk_rethink_txhash(sk))
> > + sk_rethink_txhash(sk)) {
> > NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDUPLICATEDATAREHASH);
> > + sk_dst_reset(sk);
> > + }
> >
> > /* Save last flowlabel after a spurious retrans. */
> > tcp_save_lrcv_flowlabel(sk, skb);
> > diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
> > index 199f0b579e89..ef4b3771e9d8 100644
> > --- a/net/ipv4/tcp_minisocks.c
> > +++ b/net/ipv4/tcp_minisocks.c
> > @@ -750,6 +750,15 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
> > * Reset timer after retransmitting SYNACK, similar to
> > * the idea of fast retransmit in recovery.
> > */
> > +
>
> What is the following part doing?
> tcp_v6_init_req() uses something quite different before setting ir_iif
> A comment explaining the rationale would be nice.
>
> > +#if IS_ENABLED(CONFIG_IPV6)
> > + if (sk->sk_family == AF_INET6)
> > + inet_rsk(req)->ir_iif = tcp_v6_iif(skb);
> > + else
> > +#endif
> > + inet_rsk(req)->ir_iif =
> > + inet_request_bound_dev_if(sk, skb);
> > +
> > if (!tcp_oow_rate_limited(sock_net(sk), skb,
> > LINUX_MIB_TCPACKSKIPPEDSYNRECV,
> > &tcp_rsk(req)->last_oow_ack_time)) {
> > diff --git a/net/ipv4/tcp_plb.c b/net/ipv4/tcp_plb.c
> > index 68ccdb9a5412..d7cc00a58e53 100644
> > --- a/net/ipv4/tcp_plb.c
> > +++ b/net/ipv4/tcp_plb.c
> > @@ -79,6 +79,7 @@ void tcp_plb_check_rehash(struct sock *sk, struct tcp_plb_state *plb)
> > return;
> >
> > sk_rethink_txhash(sk);
> > + sk_dst_reset(sk);
> > plb->consec_cong_rounds = 0;
> > tcp_sk(sk)->plb_rehash++;
> > NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPLBREHASH);
> > diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
> > index ea99988795e7..acc22fc532c2 100644
> > --- a/net/ipv4/tcp_timer.c
> > +++ b/net/ipv4/tcp_timer.c
> > @@ -299,6 +299,7 @@ static int tcp_write_timeout(struct sock *sk)
> > if (sk_rethink_txhash(sk)) {
> > tp->timeout_rehash++;
> > __NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPTIMEOUTREHASH);
> > + sk_dst_reset(sk);
> > }
> >
> > return 0;
> > diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
> > index 37534e116899..2fe753bb38b4 100644
> > --- a/net/ipv6/inet6_connection_sock.c
> > +++ b/net/ipv6/inet6_connection_sock.c
> > @@ -48,6 +48,11 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,
> > fl6->flowi6_uid = sk_uid(sk);
> > security_req_classify_flow(req, flowi6_to_flowi_common(fl6));
> >
> > + if (req->num_retrans)
> > + fl6->mp_hash = jhash_1word(req->num_retrans,
> > + (__force u32)ireq->ir_rmt_port)
> > + >> 1;
>
> Why not setting mp_hash to sk_txhash ?
>
> Why are you using ">> 1" ?
>
> rt6_multipath_hash() seems to be bypassed, it might be time to add a
> comment there
> explaining that mp_hash needs to be 31-bit only...
>
> Perhaps use rt6_multipath_hash() and expand it to use a socket pointer
> to retrieve sk->sk_txhash when/if possible
> instead of yet another flow dissection.
>
> > +
> > if (!dst) {
> > dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
> > if (IS_ERR(dst))
> > @@ -70,6 +75,9 @@ struct dst_entry *inet6_csk_route_socket(struct sock *sk,
> > fl6->saddr = np->saddr;
> > fl6->flowlabel = np->flow_label;
> > IP6_ECN_flow_xmit(sk, fl6->flowlabel);
> > +
> > + if (sk->sk_txhash)
> > + fl6->mp_hash = sk->sk_txhash >> 1;
>
> Seems inconsistent, and same question about the right shift.
>
>
> > fl6->flowi6_oif = sk->sk_bound_dev_if;
> > fl6->flowi6_mark = sk->sk_mark;
> > fl6->fl6_sport = inet->inet_sport;
> > --
> > 2.52.0
> >
^ permalink raw reply
* RE: [PATCH v4 net-next 04/14] net: enetc: add basic operations to the FDB table
From: Wei Fang @ 2026-04-08 7:04 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Claudiu Manoil, Vladimir Oltean, Clark Wang,
andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
pabeni@redhat.com, robh@kernel.org, krzk+dt@kernel.org,
conor+dt@kernel.org, f.fainelli@gmail.com, Frank Li,
chleroy@kernel.org, horms@kernel.org, linux@armlinux.org.uk,
andrew@lunn.ch, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, devicetree@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org, imx@lists.linux.dev
In-Reply-To: <20260403011727.1795379-1-kuba@kernel.org>
> > @@ -116,6 +158,31 @@ static inline int ntmp_rsst_query_entry(struct
> ntmp_user *user,
> > return 0;
> > }
> >
> > +static inline int ntmp_fdbt_add_entry(struct ntmp_user *user, u32 *entry_id,
> > + const struct fdbt_keye_data *keye,
> > + const struct fdbt_cfge_data *data)
> > +{
> > + return 0;
> > +}
>
> If CONFIG_NXP_NETC_LIB is disabled, will returning 0 here cause callers to
> falsely assume the operation succeeded and proceed to use an uninitialized
> entry_id pointer? Would it be safer to return an error code such as
> -EOPNOTSUPP for stubs that have output parameters?
>
The ntmp_fdbt_add_entry() is only called by the netc switch driver,
and the driver will select CONFIG_NXP_NETC_LIB option, so actually
this inline function is not used by any drivers. I suppose such inline
functions could be removed. Thanks.
^ permalink raw reply
* [PATCH net-next v2 0/2] tcp: rehash onto different ECMP path on retransmit timeout
From: Neil Spring @ 2026-04-08 7:05 UTC (permalink / raw)
To: netdev; +Cc: edumazet, davem, kuba
In-Reply-To: <20260408002802.2448424-1-ntspring@meta.com>
Make TCP retransmission timeouts select a different ECMP path for IPv6.
Currently sk_rethink_txhash() changes the socket's txhash on RTO, but the
cached route is reused and the new hash is not propagated into the ECMP
path selection logic. This series adds sk_dst_reset() alongside
sk_rethink_txhash() to force a fresh route lookup, and sets fl6->mp_hash
from sk_txhash so fib6_select_path() picks a path based on the new hash.
Three selftest scenarios verify the behavior: SYN retransmission, SYN/ACK
retransmission (server-side), and midstream RTO on an established
connection.
Changes since v1:
- Use tcp_rsk(req)->txhash instead of jhash_1word(req->num_retrans, ...)
for ECMP path selection in inet6_csk_route_req(), making the request
socket path consistent with the established socket path (Eric Dumazet)
- Add comments explaining the >> 1 shift for 31-bit mp_hash range
- Add comment explaining the ir_iif update rationale in tcp_check_req()
- Use socat -u (unidirectional) in selftest to avoid SIGPIPE race
- Increase tcp_syn_retries and tcp_syn_linear_timeouts to 25 for
better rehash coverage; add tcp_synack_retries=10 on the server
Neil Spring (2):
tcp: rehash onto different ECMP path on retransmit timeout
selftests: net: add ECMP rehash test
net/ipv4/tcp_input.c | 4 +-
net/ipv4/tcp_minisocks.c | 13 +
net/ipv4/tcp_plb.c | 1 +
net/ipv4/tcp_timer.c | 1 +
net/ipv6/inet6_connection_sock.c | 11 +
tools/testing/selftests/net/Makefile | 1 +
tools/testing/selftests/net/ecmp_rehash.sh | 361 +++++++++++++++++++++
7 files changed, 391 insertions(+), 1 deletion(-)
create mode 100755 tools/testing/selftests/net/ecmp_rehash.sh
--
2.52.0
^ permalink raw reply
* [PATCH net-next v2 1/2] tcp: rehash onto different ECMP path on retransmit timeout
From: Neil Spring @ 2026-04-08 7:05 UTC (permalink / raw)
To: netdev; +Cc: edumazet, davem, kuba
In-Reply-To: <20260408070514.1840227-1-ntspring@meta.com>
Add sk_dst_reset() alongside sk_rethink_txhash() in the RTO, PLB,
and spurious-retrans paths so that the next transmit triggers a fresh
route lookup. Propagate sk_txhash into fl6->mp_hash in
inet6_csk_route_req() and inet6_csk_route_socket() so
fib6_select_path() uses the socket's current hash for ECMP selection.
The ir_iif update in tcp_check_req() covers both IPv4 and IPv6
because it was cleaner than gating on address family; IPv4 is
otherwise unaltered, and not having autoflowlabel in IPv4 means
I wouldn't expect a new path on timeout.
It is possible that PLB does not need this (that there are other
methods of reacting to local congestion); I added the sk_dst_reset
for consistency.
Signed-off-by: Neil Spring <ntspring@meta.com>
---
net/ipv4/tcp_input.c | 4 +++-
net/ipv4/tcp_minisocks.c | 13 +++++++++++++
net/ipv4/tcp_plb.c | 1 +
net/ipv4/tcp_timer.c | 1 +
net/ipv6/inet6_connection_sock.c | 11 +++++++++++
5 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 7171442c3ed7..3d42ab45066c 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5014,8 +5014,10 @@ static void tcp_rcv_spurious_retrans(struct sock *sk,
skb->protocol == htons(ETH_P_IPV6) &&
(tcp_sk(sk)->inet_conn.icsk_ack.lrcv_flowlabel !=
ntohl(ip6_flowlabel(ipv6_hdr(skb)))) &&
- sk_rethink_txhash(sk))
+ sk_rethink_txhash(sk)) {
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPDUPLICATEDATAREHASH);
+ sk_dst_reset(sk);
+ }
/* Save last flowlabel after a spurious retrans. */
tcp_save_lrcv_flowlabel(sk, skb);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 199f0b579e89..27edf71effc2 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -750,6 +750,19 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
* Reset timer after retransmitting SYNACK, similar to
* the idea of fast retransmit in recovery.
*/
+
+ /* Update ir_iif to match the interface the retransmitted
+ * SYN arrived on; inet6_csk_route_req() uses this as
+ * flowi6_oif, constraining ECMP path for the SYN/ACK.
+ */
+#if IS_ENABLED(CONFIG_IPV6)
+ if (sk->sk_family == AF_INET6)
+ inet_rsk(req)->ir_iif = tcp_v6_iif(skb);
+ else
+#endif
+ inet_rsk(req)->ir_iif =
+ inet_request_bound_dev_if(sk, skb);
+
if (!tcp_oow_rate_limited(sock_net(sk), skb,
LINUX_MIB_TCPACKSKIPPEDSYNRECV,
&tcp_rsk(req)->last_oow_ack_time)) {
diff --git a/net/ipv4/tcp_plb.c b/net/ipv4/tcp_plb.c
index 68ccdb9a5412..d7cc00a58e53 100644
--- a/net/ipv4/tcp_plb.c
+++ b/net/ipv4/tcp_plb.c
@@ -79,6 +79,7 @@ void tcp_plb_check_rehash(struct sock *sk, struct tcp_plb_state *plb)
return;
sk_rethink_txhash(sk);
+ sk_dst_reset(sk);
plb->consec_cong_rounds = 0;
tcp_sk(sk)->plb_rehash++;
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPLBREHASH);
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index ea99988795e7..acc22fc532c2 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -299,6 +299,7 @@ static int tcp_write_timeout(struct sock *sk)
if (sk_rethink_txhash(sk)) {
tp->timeout_rehash++;
__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPTIMEOUTREHASH);
+ sk_dst_reset(sk);
}
return 0;
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 37534e116899..3fd7acbe2c49 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -14,6 +14,7 @@
#include <linux/ipv6.h>
#include <linux/jhash.h>
#include <linux/slab.h>
+#include <linux/tcp.h>
#include <net/addrconf.h>
#include <net/inet_connection_sock.h>
@@ -48,6 +49,12 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,
fl6->flowi6_uid = sk_uid(sk);
security_req_classify_flow(req, flowi6_to_flowi_common(fl6));
+ /* Use the request socket's txhash (re-rolled by tcp_rtx_synack())
+ * for ECMP path selection; >> 1 for 31-bit mp_hash range.
+ */
+ if (tcp_rsk(req)->txhash)
+ fl6->mp_hash = tcp_rsk(req)->txhash >> 1;
+
if (!dst) {
dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
if (IS_ERR(dst))
@@ -70,6 +77,10 @@ struct dst_entry *inet6_csk_route_socket(struct sock *sk,
fl6->saddr = np->saddr;
fl6->flowlabel = np->flow_label;
IP6_ECN_flow_xmit(sk, fl6->flowlabel);
+
+ /* >> 1 for 31-bit mp_hash range matching nhc_upper_bound. */
+ if (sk->sk_txhash)
+ fl6->mp_hash = sk->sk_txhash >> 1;
fl6->flowi6_oif = sk->sk_bound_dev_if;
fl6->flowi6_mark = sk->sk_mark;
fl6->fl6_sport = inet->inet_sport;
--
2.52.0
^ permalink raw reply related
* [PATCH net-next v2 2/2] selftests: net: add ECMP rehash test
From: Neil Spring @ 2026-04-08 7:05 UTC (permalink / raw)
To: netdev; +Cc: edumazet, davem, kuba
In-Reply-To: <20260408070514.1840227-1-ntspring@meta.com>
Add ecmp_rehash.sh to exercise TCP ECMP path re-selection on
retransmission timeout. Three tests cover client SYN rehash, server
SYN/ACK rehash, and midstream RTO rehash of an established connection
over a two-path ECMP topology with one leg blocked by tc.
The SYN test retries 26 times, so has a false negative probability
of ~(1/2)^25 ≈ 3e-8.
Signed-off-by: Neil Spring <ntspring@meta.com>
---
tools/testing/selftests/net/Makefile | 1 +
tools/testing/selftests/net/ecmp_rehash.sh | 361 +++++++++++++++++++++
2 files changed, 362 insertions(+)
create mode 100755 tools/testing/selftests/net/ecmp_rehash.sh
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 6bced3ed798b..acc61a51d7e2 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -25,6 +25,7 @@ TEST_PROGS := \
cmsg_time.sh \
double_udp_encap.sh \
drop_monitor_tests.sh \
+ ecmp_rehash.sh \
fcnal-ipv4.sh \
fcnal-ipv6.sh \
fcnal-other.sh \
diff --git a/tools/testing/selftests/net/ecmp_rehash.sh b/tools/testing/selftests/net/ecmp_rehash.sh
new file mode 100755
index 000000000000..a468ccf22d4f
--- /dev/null
+++ b/tools/testing/selftests/net/ecmp_rehash.sh
@@ -0,0 +1,361 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test ECMP path re-selection on TCP retransmission timeout.
+#
+# Two namespaces connected by two parallel veth pairs with a 2-way ECMP
+# route. When a TCP path is blocked (via tc drop), RTO triggers
+# sk_rethink_txhash() + sk_dst_reset(), causing the next route lookup
+# to select the other ECMP path.
+#
+# False negative: ~(1/2)^25 ≈ 3e-8. With tcp_syn_retries=25 and
+# tcp_syn_linear_timeouts=25 there are 26 SYN attempts at 1-second
+# intervals, each choosing one of 2 paths uniformly.
+
+source lib.sh
+
+SUBNETS=(a b)
+PORT=9900
+
+ALL_TESTS="
+ test_ecmp_rto_rehash
+ test_ecmp_synack_rehash
+ test_ecmp_midstream_rehash
+"
+
+link_tx_packets_get()
+{
+ local ns=$1; shift
+ local dev=$1; shift
+
+ ip netns exec "$ns" cat "/sys/class/net/$dev/statistics/tx_packets"
+}
+
+# Return the number of packets matched by the tc filter action on a device.
+# When tc drops packets via "action drop", the device's tx_packets is not
+# incremented (packet never reaches veth_xmit), but the tc action maintains
+# its own counter.
+tc_filter_pkt_count()
+{
+ local ns=$1; shift
+ local dev=$1; shift
+
+ ip netns exec "$ns" tc -s filter show dev "$dev" parent 1: 2>/dev/null |
+ awk '/Sent .* pkt/ { for (i=1;i<=NF;i++) if ($i=="pkt") { print $(i-1); exit } }'
+}
+
+# Read TcpTimeoutRehash counter from /proc/net/netstat in a namespace.
+# This counter increments in tcp_write_timeout() on every RTO that triggers
+# sk_rethink_txhash().
+get_timeout_rehash_count()
+{
+ local ns=$1; shift
+
+ ip netns exec "$ns" awk '
+ /^TcpExt:/ {
+ if (!h) { split($0, n); h=1 }
+ else {
+ split($0, v)
+ for (i in n)
+ if (n[i] == "TcpTimeoutRehash") print v[i]
+ }
+ }
+ ' /proc/net/netstat
+}
+
+# Block TCP (IPv6 next-header = 6) egress, allowing ICMPv6 through.
+block_tcp()
+{
+ local ns=$1; shift
+ local dev=$1; shift
+
+ ip netns exec "$ns" tc qdisc add dev "$dev" root handle 1: prio
+ ip netns exec "$ns" tc filter add dev "$dev" parent 1: \
+ protocol ipv6 prio 1 u32 match u8 0x06 0xff at 6 action drop
+}
+
+unblock_tcp()
+{
+ local ns=$1; shift
+ local dev=$1; shift
+
+ ip netns exec "$ns" tc qdisc del dev "$dev" root 2>/dev/null
+}
+
+# Return success when both devices have dropped at least one TCP packet.
+both_devs_attempted()
+{
+ local ns=$1; shift
+ local dev0=$1; shift
+ local dev1=$1; shift
+
+ local c0 c1
+ c0=$(tc_filter_pkt_count "$ns" "$dev0")
+ c1=$(tc_filter_pkt_count "$ns" "$dev1")
+ [ "${c0:-0}" -ge 1 ] && [ "${c1:-0}" -ge 1 ]
+}
+
+setup()
+{
+ setup_ns NS1 NS2
+
+ local ns
+ for ns in "$NS1" "$NS2"; do
+ ip netns exec "$ns" sysctl -qw net.ipv6.conf.all.accept_dad=0
+ ip netns exec "$ns" sysctl -qw net.ipv6.conf.default.accept_dad=0
+ ip netns exec "$ns" sysctl -qw net.ipv6.conf.all.forwarding=1
+ ip netns exec "$ns" sysctl -qw net.core.txrehash=1
+ done
+
+ local i sub
+ for i in 0 1; do
+ sub=${SUBNETS[$i]}
+ ip link add "veth${i}a" type veth peer name "veth${i}b"
+ ip link set "veth${i}a" netns "$NS1"
+ ip link set "veth${i}b" netns "$NS2"
+ ip -n "$NS1" addr add "fd00:${sub}::1/64" dev "veth${i}a"
+ ip -n "$NS2" addr add "fd00:${sub}::2/64" dev "veth${i}b"
+ ip -n "$NS1" link set "veth${i}a" up
+ ip -n "$NS2" link set "veth${i}b" up
+ done
+
+ ip -n "$NS1" addr add fd00:ff::1/128 dev lo
+ ip -n "$NS2" addr add fd00:ff::2/128 dev lo
+
+ # Allow many SYN retries at 1-second intervals (linear, no
+ # exponential backoff) so the rehash test has enough attempts
+ # to exercise both ECMP paths. tcp_syn_retries is a pure
+ # retransmission count (not time-based for SYN_SENT), so with
+ # linear 1-second intervals it also sets the total lifetime.
+ ip netns exec "$NS1" sysctl -qw net.ipv4.tcp_syn_retries=25
+ ip netns exec "$NS1" sysctl -qw net.ipv4.tcp_syn_linear_timeouts=25
+
+ # Keep the server's request socket alive during the blocking
+ # period so SYN/ACK retransmits continue.
+ ip netns exec "$NS2" sysctl -qw net.ipv4.tcp_synack_retries=10
+
+ ip -n "$NS1" -6 route add fd00:ff::2/128 \
+ nexthop via fd00:a::2 dev veth0a \
+ nexthop via fd00:b::2 dev veth1a
+
+ ip -n "$NS2" -6 route add fd00:ff::1/128 \
+ nexthop via fd00:a::1 dev veth0b \
+ nexthop via fd00:b::1 dev veth1b
+
+ for i in 0 1; do
+ sub=${SUBNETS[$i]}
+ ip netns exec "$NS1" \
+ ping -6 -c1 -W5 "fd00:${sub}::2" &>/dev/null
+ ip netns exec "$NS2" \
+ ping -6 -c1 -W5 "fd00:${sub}::1" &>/dev/null
+ done
+
+ if ! ip netns exec "$NS1" ping -6 -c1 -W5 fd00:ff::2 &>/dev/null; then
+ echo "Basic connectivity check failed"
+ return $ksft_skip
+ fi
+}
+
+# Block ALL paths, start a connection, wait until SYNs have been dropped
+# on both interfaces (proving rehash steered the SYN to a new path), then
+# unblock so the connection completes.
+test_ecmp_rto_rehash()
+{
+ RET=0
+
+ block_tcp "$NS1" veth0a
+ defer unblock_tcp "$NS1" veth0a
+ block_tcp "$NS1" veth1a
+ defer unblock_tcp "$NS1" veth1a
+
+ ip netns exec "$NS2" socat \
+ "TCP6-LISTEN:$PORT,bind=[fd00:ff::2],reuseaddr,fork" \
+ EXEC:"echo ESTABLISH_OK" &
+ defer kill_process $!
+
+ wait_local_port_listen "$NS2" $PORT tcp
+
+ local rehash_before
+ rehash_before=$(get_timeout_rehash_count "$NS1")
+
+ # Start the connection in the background; it will retry SYNs at
+ # 1-second intervals until an unblocked path is found.
+ # Use -u (unidirectional) to only receive from the server;
+ # sending data back would risk SIGPIPE if the server's EXEC
+ # child has already exited.
+ ip netns exec "$NS1" socat -u \
+ "TCP6:[fd00:ff::2]:$PORT,bind=[fd00:ff::1],connect-timeout=60" \
+ STDOUT >"/tmp/ecmp_rto_$$" 2>&1 &
+ local client_pid=$!
+ defer kill_process $client_pid
+
+ # Wait until both paths have seen at least one dropped SYN.
+ # This proves sk_rethink_txhash() rehashed the connection from
+ # one ECMP path to the other.
+ slowwait 30 both_devs_attempted "$NS1" veth0a veth1a
+ check_err $? "SYNs did not appear on both paths (rehash not working)"
+ if [ $RET -ne 0 ]; then
+ log_test "ECMP RTO rehash: establish with blocked paths"
+ return
+ fi
+
+ # Unblock both paths and let the next SYN retransmit succeed.
+ unblock_tcp "$NS1" veth0a
+ unblock_tcp "$NS1" veth1a
+
+ local rc=0
+ wait $client_pid || rc=$?
+
+ local result
+ result=$(cat "/tmp/ecmp_rto_$$" 2>/dev/null)
+ rm -f "/tmp/ecmp_rto_$$"
+
+ if [[ "$result" != *"ESTABLISH_OK"* ]]; then
+ check_err 1 "connection failed after unblocking (rc=$rc): $result"
+ fi
+
+ local rehash_after
+ rehash_after=$(get_timeout_rehash_count "$NS1")
+ if [ "$rehash_after" -le "$rehash_before" ]; then
+ check_err 1 "TcpTimeoutRehash counter did not increment"
+ fi
+
+ log_test "ECMP RTO rehash: establish with blocked paths"
+}
+
+# Block the server's return paths so SYN/ACKs are dropped. The client
+# retransmits SYNs at 1-second intervals; each duplicate SYN arriving at
+# the server updates ir_iif to match the new arrival interface, so the
+# retransmitted SYN/ACK routes back via the interface the SYN arrived on.
+test_ecmp_synack_rehash()
+{
+ RET=0
+ local port=$((PORT + 2))
+
+ block_tcp "$NS2" veth0b
+ defer unblock_tcp "$NS2" veth0b
+ block_tcp "$NS2" veth1b
+ defer unblock_tcp "$NS2" veth1b
+
+ ip netns exec "$NS2" socat \
+ "TCP6-LISTEN:$port,bind=[fd00:ff::2],reuseaddr,fork" \
+ EXEC:"echo SYNACK_OK" &
+ defer kill_process $!
+
+ wait_local_port_listen "$NS2" $port tcp
+
+ # Start the connection; SYNs reach the server (client egress is
+ # open) but SYN/ACKs are dropped on the server's return path.
+ ip netns exec "$NS1" socat -u \
+ "TCP6:[fd00:ff::2]:$port,bind=[fd00:ff::1],connect-timeout=60" \
+ STDOUT >"/tmp/ecmp_synack_$$" 2>&1 &
+ local client_pid=$!
+ defer kill_process $client_pid
+
+ # Wait until both server-side interfaces have dropped at least
+ # one SYN/ACK, proving the server rehashed its return path.
+ slowwait 30 both_devs_attempted "$NS2" veth0b veth1b
+ check_err $? "SYN/ACKs did not appear on both return paths"
+ if [ $RET -ne 0 ]; then
+ log_test "ECMP SYN/ACK rehash: blocked return path"
+ return
+ fi
+
+ # Unblock and let the connection complete.
+ unblock_tcp "$NS2" veth0b
+ unblock_tcp "$NS2" veth1b
+
+ local rc=0
+ wait $client_pid || rc=$?
+
+ local result
+ result=$(cat "/tmp/ecmp_synack_$$" 2>/dev/null)
+ rm -f "/tmp/ecmp_synack_$$"
+
+ if [[ "$result" != *"SYNACK_OK"* ]]; then
+ check_err 1 "connection failed after unblocking (rc=$rc): $result"
+ fi
+
+ log_test "ECMP SYN/ACK rehash: blocked return path"
+}
+
+# Establish a data transfer with both paths open, then block the
+# active path. Verify the transfer continues via rehash and that
+# TcpTimeoutRehash incremented.
+test_ecmp_midstream_rehash()
+{
+ RET=0
+ local port=$((PORT + 1))
+
+ ip netns exec "$NS2" socat -u \
+ "TCP6-LISTEN:$port,bind=[fd00:ff::2],reuseaddr" - >/dev/null &
+ defer kill_process $!
+
+ wait_local_port_listen "$NS2" $port tcp
+
+ local base_tx0 base_tx1
+ base_tx0=$(link_tx_packets_get "$NS1" veth0a)
+ base_tx1=$(link_tx_packets_get "$NS1" veth1a)
+
+ ip netns exec "$NS1" bash -c "
+ for i in \$(seq 1 40); do
+ dd if=/dev/zero bs=10k count=1 2>/dev/null
+ sleep 0.25
+ done | timeout 60 socat - 'TCP6:[fd00:ff::2]:$port,bind=[fd00:ff::1]'
+ " &>/dev/null &
+ local client_pid=$!
+ defer kill_process $client_pid
+
+ busywait $BUSYWAIT_TIMEOUT until_counter_is \
+ ">= $((base_tx0 + base_tx1 + 20))" \
+ link_tx_packets_total "$NS1"
+ check_err $? "no TX activity detected"
+ if [ $RET -ne 0 ]; then
+ log_test "ECMP midstream rehash: block active path"
+ return
+ fi
+
+ # Find the active path and block it.
+ local cur0 cur1 active_idx
+ cur0=$(link_tx_packets_get "$NS1" veth0a)
+ cur1=$(link_tx_packets_get "$NS1" veth1a)
+ if [ $((cur0 - base_tx0)) -ge $((cur1 - base_tx1)) ]; then
+ active_idx=0
+ else
+ active_idx=1
+ fi
+
+ local rehash_before
+ rehash_before=$(get_timeout_rehash_count "$NS1")
+
+ block_tcp "$NS1" "veth${active_idx}a"
+ defer unblock_tcp "$NS1" "veth${active_idx}a"
+
+ local rc=0
+ wait $client_pid || rc=$?
+
+ check_err $rc "data transfer failed after blocking veth${active_idx}a"
+
+ local rehash_after
+ rehash_after=$(get_timeout_rehash_count "$NS1")
+ if [ "$rehash_after" -le "$rehash_before" ]; then
+ check_err 1 "TcpTimeoutRehash counter did not increment"
+ fi
+
+ log_test "ECMP midstream rehash: block active path"
+}
+
+link_tx_packets_total()
+{
+ local ns=$1; shift
+
+ echo $(( $(link_tx_packets_get "$ns" veth0a) +
+ $(link_tx_packets_get "$ns" veth1a) ))
+}
+
+require_command socat
+
+trap cleanup_all_ns EXIT
+setup || exit $?
+tests_run
+exit $EXIT_STATUS
--
2.52.0
^ permalink raw reply related
* Re: [PATCH net-next v4 1/2] dt-bindings: net: ti: k3-am654-cpsw-nuss: Add ti,j722s-cpsw-nuss compatible
From: Krzysztof Kozlowski @ 2026-04-08 7:06 UTC (permalink / raw)
To: Nora Schiffer
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Nishanth Menon, Vignesh Raghavendra, Tero Kristo,
Siddharth Vadapalli, Roger Quadros, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, netdev, devicetree,
linux-kernel, linux-arm-kernel, linux
In-Reply-To: <191e9f7e3a6c14eabe891a98c5fb646766479c0a.1775558273.git.nora.schiffer@ew.tq-group.com>
On Tue, Apr 07, 2026 at 12:48:01PM +0200, Nora Schiffer wrote:
> The J722S CPSW3G is mostly identical to the AM64's, but additionally
> supports SGMII. The AM64 compatible ti,am642-cpsw-nuss is used as a
> fallback.
>
> Signed-off-by: Nora Schiffer <nora.schiffer@ew.tq-group.com>
> ---
>
> v2: keep ti,am642-cpsw-nuss as a fallback
> v3: resubmission for net-next, no changes
> v4: remove redundant items: level
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v4 2/5] dt-bindings: phy: ti: phy-gmii-sel: Add ti,j722s-phy-gmii-sel compatible
From: Krzysztof Kozlowski @ 2026-04-08 7:06 UTC (permalink / raw)
To: Nora Schiffer
Cc: Nishanth Menon, Vignesh Raghavendra, Tero Kristo, Vinod Koul,
Neil Armstrong, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Siddharth Vadapalli, Roger Quadros,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, netdev,
devicetree, linux-kernel, linux-phy, linux-arm-kernel, linux
In-Reply-To: <b67c8b0bc9cc918667e9329d79f617d033d025d5.1775559102.git.nora.schiffer@ew.tq-group.com>
On Tue, Apr 07, 2026 at 01:42:34PM +0200, Nora Schiffer wrote:
> The J722S gmii-sel is mostly identical to the AM64's, but additionally
> supports SGMII. The AM64 compatible ti,am654-phy-gmii-sel is used as a
> fallback.
>
> Signed-off-by: Nora Schiffer <nora.schiffer@ew.tq-group.com>
> ---
> .../bindings/phy/ti,phy-gmii-sel.yaml | 23 +++++++++++--------
> 1 file changed, 14 insertions(+), 9 deletions(-)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox