* [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW
@ 2025-02-26 21:09 Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 1/9] eth: bnxt: use napi_consume_skb() Jakub Kicinski
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
Some workloads want to be able to track bandwidth utilization on
the scale of 10s of msecs. bnxt uses HW stats and async stats
updates, with update frequency controlled via ethtool -C.
Updating all HW stats more often than 100 msec is both hard for
the device and consumes PCIe bandwidth. Switch to maintaining
basic Rx / Tx packet and byte counters in SW.
Tested with drivers/net/stats.py:
# Totals: pass:7 fail:0 xfail:0 xpass:0 skip:0 error:0
Manually tested by comparing the ethtool -S stats (which continues
to show HW stats) with qstats, and total interface stats.
With and without HW-GRO, and with XDP on / off.
Stopping and starting the interface also doesn't corrupt the values.
Jakub Kicinski (9):
eth: bnxt: use napi_consume_skb()
eth: bnxt: don't run xdp programs on fallback traffic
eth: bnxt: rename ring_err_stats -> ring_drv_stats
eth: bnxt: snapshot driver stats
eth: bnxt: don't use ifdef to check for CONFIG_INET in GRO
eth: bnxt: consolidate the GRO-but-not-really paths in bnxt_gro_skb()
eth: bnxt: maintain rx pkt/byte stats in SW
eth: bnxt: maintain tx pkt/byte stats in SW
eth: bnxt: count xdp xmit packets
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 31 ++-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 240 ++++++++++++------
.../net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 14 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 15 ++
4 files changed, 208 insertions(+), 92 deletions(-)
--
2.48.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH net-next 1/9] eth: bnxt: use napi_consume_skb()
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
@ 2025-02-26 21:09 ` Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 2/9] eth: bnxt: don't run xdp programs on fallback traffic Jakub Kicinski
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
Use napi_consume_skb() to improve skb recycling.
__bnxt_tx_int() already has the real NAPI passed in budget.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 15c57a06ecaf..f6a26f6f85bb 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -855,7 +855,7 @@ static bool __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
next_tx_int:
cons = NEXT_TX(cons);
- dev_consume_skb_any(skb);
+ napi_consume_skb(skb, budget);
}
WRITE_ONCE(txr->tx_cons, cons);
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 2/9] eth: bnxt: don't run xdp programs on fallback traffic
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 1/9] eth: bnxt: use napi_consume_skb() Jakub Kicinski
@ 2025-02-26 21:09 ` Jakub Kicinski
2025-02-27 3:35 ` Michael Chan
2025-02-26 21:09 ` [PATCH net-next 3/9] eth: bnxt: rename ring_err_stats -> ring_drv_stats Jakub Kicinski
` (6 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
The XDP program attached to the PF should not be executed
on the fallback traffic. Compile tested only.
Well behaved drivers (nfp) do not execute XDP on fallback
traffic, but perhaps this is a matter of opinion rather than
a hard rule, therefore I'm not considering this a fix.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index f6a26f6f85bb..53b689800e1c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -2036,7 +2036,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
{
struct bnxt_napi *bnapi = cpr->bnapi;
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
- struct net_device *dev = bp->dev;
+ struct net_device *dev;
struct rx_cmp *rxcmp;
struct rx_cmp_ext *rxcmp1;
u32 tmp_raw_cons = *raw_cons;
@@ -2159,6 +2159,10 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
len = flags >> RX_CMP_LEN_SHIFT;
dma_addr = rx_buf->mapping;
+ dev = bp->dev;
+ if (cmp_type == CMP_TYPE_RX_L2_CMP)
+ dev = bnxt_get_pkt_dev(bp, RX_CMP_CFA_CODE(rxcmp1));
+
if (bnxt_xdp_attached(bp, rxr)) {
bnxt_xdp_buff_init(bp, rxr, cons, data_ptr, len, &xdp);
if (agg_bufs) {
@@ -2171,7 +2175,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
xdp_active = true;
}
- if (xdp_active) {
+ if (xdp_active && dev == bp->dev) {
if (bnxt_rx_xdp(bp, rxr, cons, &xdp, data, &data_ptr, &len, event)) {
rc = 1;
goto next_rx;
@@ -2239,8 +2243,6 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
skb_set_hash(skb, le32_to_cpu(rxcmp->rx_cmp_rss_hash), type);
}
- if (cmp_type == CMP_TYPE_RX_L2_CMP)
- dev = bnxt_get_pkt_dev(bp, RX_CMP_CFA_CODE(rxcmp1));
skb->protocol = eth_type_trans(skb, dev);
if (skb->dev->features & BNXT_HW_FEATURE_VLAN_ALL_RX) {
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 3/9] eth: bnxt: rename ring_err_stats -> ring_drv_stats
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 1/9] eth: bnxt: use napi_consume_skb() Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 2/9] eth: bnxt: don't run xdp programs on fallback traffic Jakub Kicinski
@ 2025-02-26 21:09 ` Jakub Kicinski
2025-02-27 4:55 ` Przemek Kitszel
2025-02-26 21:09 ` [PATCH net-next 4/9] eth: bnxt: snapshot driver stats Jakub Kicinski
` (5 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
We will soon store non-error stats to the ring struct.
Rename them to "drv" stats, as these are all maintained
by the driver (even if partially based on info from descriptors).
Pure rename using sed.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 8 ++++----
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 14 +++++++-------
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 14 +++++++-------
3 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index e85b5ce94f58..34f23ddd4d71 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1136,7 +1136,7 @@ struct bnxt_sw_stats {
struct bnxt_cmn_sw_stats cmn;
};
-struct bnxt_total_ring_err_stats {
+struct bnxt_total_ring_drv_stats {
u64 rx_total_l4_csum_errors;
u64 rx_total_resets;
u64 rx_total_buf_errors;
@@ -2538,7 +2538,7 @@ struct bnxt {
u8 pri2cos_idx[8];
u8 pri2cos_valid;
- struct bnxt_total_ring_err_stats ring_err_stats_prev;
+ struct bnxt_total_ring_drv_stats ring_drv_stats_prev;
u16 hwrm_max_req_len;
u16 hwrm_max_ext_req_len;
@@ -2936,8 +2936,8 @@ int bnxt_half_open_nic(struct bnxt *bp);
void bnxt_half_close_nic(struct bnxt *bp);
void bnxt_reenable_sriov(struct bnxt *bp);
void bnxt_close_nic(struct bnxt *, bool, bool);
-void bnxt_get_ring_err_stats(struct bnxt *bp,
- struct bnxt_total_ring_err_stats *stats);
+void bnxt_get_ring_drv_stats(struct bnxt *bp,
+ struct bnxt_total_ring_drv_stats *stats);
bool bnxt_rfs_capable(struct bnxt *bp, bool new_rss_ctx);
int bnxt_dbg_hwrm_rd_reg(struct bnxt *bp, u32 reg_off, u16 num_words,
u32 *reg_buf);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 53b689800e1c..29515d6c6cdd 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -12940,7 +12940,7 @@ static void __bnxt_close_nic(struct bnxt *bp, bool irq_re_init,
/* Save ring stats before shutdown */
if (bp->bnapi && irq_re_init) {
bnxt_get_ring_stats(bp, &bp->net_stats_prev);
- bnxt_get_ring_err_stats(bp, &bp->ring_err_stats_prev);
+ bnxt_get_ring_drv_stats(bp, &bp->ring_drv_stats_prev);
}
if (irq_re_init) {
bnxt_free_irq(bp);
@@ -13190,8 +13190,8 @@ bnxt_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
clear_bit(BNXT_STATE_READ_STATS, &bp->state);
}
-static void bnxt_get_one_ring_err_stats(struct bnxt *bp,
- struct bnxt_total_ring_err_stats *stats,
+static void bnxt_get_one_ring_drv_stats(struct bnxt *bp,
+ struct bnxt_total_ring_drv_stats *stats,
struct bnxt_cp_ring_info *cpr)
{
struct bnxt_sw_stats *sw_stats = cpr->sw_stats;
@@ -13210,13 +13210,13 @@ static void bnxt_get_one_ring_err_stats(struct bnxt *bp,
stats->total_missed_irqs += sw_stats->cmn.missed_irqs;
}
-void bnxt_get_ring_err_stats(struct bnxt *bp,
- struct bnxt_total_ring_err_stats *stats)
+void bnxt_get_ring_drv_stats(struct bnxt *bp,
+ struct bnxt_total_ring_drv_stats *stats)
{
int i;
for (i = 0; i < bp->cp_nr_rings; i++)
- bnxt_get_one_ring_err_stats(bp, stats, &bp->bnapi[i]->cp_ring);
+ bnxt_get_one_ring_drv_stats(bp, stats, &bp->bnapi[i]->cp_ring);
}
static bool bnxt_mc_list_updated(struct bnxt *bp, u32 *rx_mask)
@@ -15642,7 +15642,7 @@ static void bnxt_get_base_stats(struct net_device *dev,
rx->packets = bp->net_stats_prev.rx_packets;
rx->bytes = bp->net_stats_prev.rx_bytes;
- rx->alloc_fail = bp->ring_err_stats_prev.rx_total_oom_discards;
+ rx->alloc_fail = bp->ring_drv_stats_prev.rx_total_oom_discards;
tx->packets = bp->net_stats_prev.tx_packets;
tx->bytes = bp->net_stats_prev.tx_bytes;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index 9c5820839514..df726a31192b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -340,7 +340,7 @@ enum {
RX_NETPOLL_DISCARDS,
};
-static const char *const bnxt_ring_err_stats_arr[] = {
+static const char *const bnxt_ring_drv_stats_arr[] = {
"rx_total_l4_csum_errors",
"rx_total_resets",
"rx_total_buf_errors",
@@ -500,7 +500,7 @@ static const struct {
BNXT_TX_STATS_PRI_ENTRIES(tx_packets),
};
-#define BNXT_NUM_RING_ERR_STATS ARRAY_SIZE(bnxt_ring_err_stats_arr)
+#define BNXT_NUM_RING_ERR_STATS ARRAY_SIZE(bnxt_ring_drv_stats_arr)
#define BNXT_NUM_PORT_STATS ARRAY_SIZE(bnxt_port_stats_arr)
#define BNXT_NUM_STATS_PRI \
(ARRAY_SIZE(bnxt_rx_bytes_pri_arr) + \
@@ -594,7 +594,7 @@ static bool is_tx_ring(struct bnxt *bp, int ring_num)
static void bnxt_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *buf)
{
- struct bnxt_total_ring_err_stats ring_err_stats = {0};
+ struct bnxt_total_ring_drv_stats ring_drv_stats = {0};
struct bnxt *bp = netdev_priv(dev);
u64 *curr, *prev;
u32 tpa_stats;
@@ -643,11 +643,11 @@ static void bnxt_get_ethtool_stats(struct net_device *dev,
buf[j] = sw[k];
}
- bnxt_get_ring_err_stats(bp, &ring_err_stats);
+ bnxt_get_ring_drv_stats(bp, &ring_drv_stats);
skip_ring_stats:
- curr = &ring_err_stats.rx_total_l4_csum_errors;
- prev = &bp->ring_err_stats_prev.rx_total_l4_csum_errors;
+ curr = &ring_drv_stats.rx_total_l4_csum_errors;
+ prev = &bp->ring_drv_stats_prev.rx_total_l4_csum_errors;
for (i = 0; i < BNXT_NUM_RING_ERR_STATS; i++, j++, curr++, prev++)
buf[j] = *curr + *prev;
@@ -753,7 +753,7 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
}
}
for (i = 0; i < BNXT_NUM_RING_ERR_STATS; i++)
- ethtool_puts(&buf, bnxt_ring_err_stats_arr[i]);
+ ethtool_puts(&buf, bnxt_ring_drv_stats_arr[i]);
if (bp->flags & BNXT_FLAG_PORT_STATS)
for (i = 0; i < BNXT_NUM_PORT_STATS; i++) {
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 4/9] eth: bnxt: snapshot driver stats
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
` (2 preceding siblings ...)
2025-02-26 21:09 ` [PATCH net-next 3/9] eth: bnxt: rename ring_err_stats -> ring_drv_stats Jakub Kicinski
@ 2025-02-26 21:09 ` Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 5/9] eth: bnxt: don't use ifdef to check for CONFIG_INET in GRO Jakub Kicinski
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
Subsequent commits will add datapath stats which need u64_stats
protection. Make current readers work on a snapshot, so it's
easier to extend this code without much duplication.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 31 +++++++++++++++--------
1 file changed, 21 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 29515d6c6cdd..32a2fbc6615b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -13092,6 +13092,12 @@ static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EOPNOTSUPP;
}
+static void bnxt_drv_stat_snapshot(const struct bnxt_sw_stats *sw_stats,
+ struct bnxt_sw_stats *snapshot)
+{
+ memcpy(snapshot, sw_stats, sizeof(*snapshot));
+}
+
static void bnxt_get_ring_stats(struct bnxt *bp,
struct rtnl_link_stats64 *stats)
{
@@ -13100,8 +13106,11 @@ static void bnxt_get_ring_stats(struct bnxt *bp,
for (i = 0; i < bp->cp_nr_rings; i++) {
struct bnxt_napi *bnapi = bp->bnapi[i];
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
+ struct bnxt_sw_stats sw_stats;
u64 *sw = cpr->stats.sw_stats;
+ bnxt_drv_stat_snapshot(cpr->sw_stats, &sw_stats);
+
stats->rx_packets += BNXT_GET_RING_STATS64(sw, rx_ucast_pkts);
stats->rx_packets += BNXT_GET_RING_STATS64(sw, rx_mcast_pkts);
stats->rx_packets += BNXT_GET_RING_STATS64(sw, rx_bcast_pkts);
@@ -13126,8 +13135,8 @@ static void bnxt_get_ring_stats(struct bnxt *bp,
stats->tx_dropped += BNXT_GET_RING_STATS64(sw, tx_error_pkts);
stats->rx_dropped +=
- cpr->sw_stats->rx.rx_netpoll_discards +
- cpr->sw_stats->rx.rx_oom_discards;
+ sw_stats.rx.rx_netpoll_discards +
+ sw_stats.rx.rx_oom_discards;
}
}
@@ -13194,20 +13203,22 @@ static void bnxt_get_one_ring_drv_stats(struct bnxt *bp,
struct bnxt_total_ring_drv_stats *stats,
struct bnxt_cp_ring_info *cpr)
{
- struct bnxt_sw_stats *sw_stats = cpr->sw_stats;
u64 *hw_stats = cpr->stats.sw_stats;
+ struct bnxt_sw_stats sw_stats;
- stats->rx_total_l4_csum_errors += sw_stats->rx.rx_l4_csum_errors;
- stats->rx_total_resets += sw_stats->rx.rx_resets;
- stats->rx_total_buf_errors += sw_stats->rx.rx_buf_errors;
- stats->rx_total_oom_discards += sw_stats->rx.rx_oom_discards;
- stats->rx_total_netpoll_discards += sw_stats->rx.rx_netpoll_discards;
+ bnxt_drv_stat_snapshot(cpr->sw_stats, &sw_stats);
+
+ stats->rx_total_l4_csum_errors += sw_stats.rx.rx_l4_csum_errors;
+ stats->rx_total_resets += sw_stats.rx.rx_resets;
+ stats->rx_total_buf_errors += sw_stats.rx.rx_buf_errors;
+ stats->rx_total_oom_discards += sw_stats.rx.rx_oom_discards;
+ stats->rx_total_netpoll_discards += sw_stats.rx.rx_netpoll_discards;
stats->rx_total_ring_discards +=
BNXT_GET_RING_STATS64(hw_stats, rx_discard_pkts);
- stats->tx_total_resets += sw_stats->tx.tx_resets;
+ stats->tx_total_resets += sw_stats.tx.tx_resets;
stats->tx_total_ring_discards +=
BNXT_GET_RING_STATS64(hw_stats, tx_discard_pkts);
- stats->total_missed_irqs += sw_stats->cmn.missed_irqs;
+ stats->total_missed_irqs += sw_stats.cmn.missed_irqs;
}
void bnxt_get_ring_drv_stats(struct bnxt *bp,
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 5/9] eth: bnxt: don't use ifdef to check for CONFIG_INET in GRO
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
` (3 preceding siblings ...)
2025-02-26 21:09 ` [PATCH net-next 4/9] eth: bnxt: snapshot driver stats Jakub Kicinski
@ 2025-02-26 21:09 ` Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 6/9] eth: bnxt: consolidate the GRO-but-not-really paths in bnxt_gro_skb() Jakub Kicinski
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
Use IS_ENABLED(CONFIG_INET) to make the code easier to refactor.
Now all packets which did not go thru GRO will exit in the same
branch.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 32a2fbc6615b..497bc81ecdb9 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1740,12 +1740,11 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp,
struct rx_tpa_end_cmp_ext *tpa_end1,
struct sk_buff *skb)
{
-#ifdef CONFIG_INET
int payload_off;
u16 segs;
segs = TPA_END_TPA_SEGS(tpa_end);
- if (segs == 1)
+ if (segs == 1 || !IS_ENABLED(CONFIG_INET))
return skb;
NAPI_GRO_CB(skb)->count = segs;
@@ -1759,7 +1758,6 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp,
skb = bp->gro_func(tpa_info, payload_off, TPA_END_GRO_TS(tpa_end), skb);
if (likely(skb))
tcp_gro_complete(skb);
-#endif
return skb;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 6/9] eth: bnxt: consolidate the GRO-but-not-really paths in bnxt_gro_skb()
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
` (4 preceding siblings ...)
2025-02-26 21:09 ` [PATCH net-next 5/9] eth: bnxt: don't use ifdef to check for CONFIG_INET in GRO Jakub Kicinski
@ 2025-02-26 21:10 ` Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 7/9] eth: bnxt: maintain rx pkt/byte stats in SW Jakub Kicinski
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:10 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
bnxt_tpa_end() skips calling bnxt_gro_skb() if it determines that GRO
should not be performed. For ease of packet counting pass the gro bool
into bnxt_gro_skb(), this way we have a single branch thru which all
non-GRO packets coming out of bnxt_tpa_end() should pass.
bnxt_gro_skb() is a static inline with a single caller, it will
be inlined so there is no concern about adding an extra call.
seg count will now be extracted every time, but tpa_end is touched
by bnxt_tpa_end(), the field extraction will make no practical
difference.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 497bc81ecdb9..113989b9b8cb 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1735,6 +1735,7 @@ static struct sk_buff *bnxt_gro_func_5730x(struct bnxt_tpa_info *tpa_info,
}
static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp,
+ bool gro,
struct bnxt_tpa_info *tpa_info,
struct rx_tpa_end_cmp *tpa_end,
struct rx_tpa_end_cmp_ext *tpa_end1,
@@ -1744,7 +1745,7 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp,
u16 segs;
segs = TPA_END_TPA_SEGS(tpa_end);
- if (segs == 1 || !IS_ENABLED(CONFIG_INET))
+ if (!gro || segs == 1 || !IS_ENABLED(CONFIG_INET))
return skb;
NAPI_GRO_CB(skb)->count = segs;
@@ -1917,10 +1918,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
(tpa_info->flags2 & RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3;
}
- if (gro)
- skb = bnxt_gro_skb(bp, tpa_info, tpa_end, tpa_end1, skb);
-
- return skb;
+ return bnxt_gro_skb(bp, gro, tpa_info, tpa_end, tpa_end1, skb);
}
static void bnxt_tpa_agg(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 7/9] eth: bnxt: maintain rx pkt/byte stats in SW
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
` (5 preceding siblings ...)
2025-02-26 21:10 ` [PATCH net-next 6/9] eth: bnxt: consolidate the GRO-but-not-really paths in bnxt_gro_skb() Jakub Kicinski
@ 2025-02-26 21:10 ` Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 8/9] eth: bnxt: maintain tx " Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 9/9] eth: bnxt: count xdp xmit packets Jakub Kicinski
8 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:10 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
Some workloads want to be able to track bandwidth utilization on
the scale of 10s of msecs. Updating all HW stats at this rate is
both hard and wasteful of PCIe bandwidth.
Maintain basic Rx pkt/byte counters in software. ethtool -S will still
show the HW stats, but qstats and rtnl stats will show SW statistics.
We need to take care of HW-GRO, XDP and VF representors. Per netdev
qstat definition Rx stats should reflect packets passed to XDP (if
active, otherwise to the stack). XDP and GRO do not interoperate
in bnxt, so we need to count the packets in a few places.
Add a helper and call it where needed.
Do not count VF representor traffic as traffic for the main netdev.
The stats are added towards the end of the struct since ethtool
code expects existing members to be first.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 7 ++
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 96 +++++++++++++++--------
2 files changed, 72 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 34f23ddd4d71..1607a4a28bf0 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -1118,8 +1118,12 @@ struct bnxt_rx_sw_stats {
u64 rx_l4_csum_errors;
u64 rx_resets;
u64 rx_buf_errors;
+ /* non-ethtool stats follow */
u64 rx_oom_discards;
u64 rx_netpoll_discards;
+ u64 rx_packets;
+ u64 rx_bytes;
+ struct u64_stats_sync syncp;
};
struct bnxt_tx_sw_stats {
@@ -1146,6 +1150,9 @@ struct bnxt_total_ring_drv_stats {
u64 tx_total_resets;
u64 tx_total_ring_discards;
u64 total_missed_irqs;
+ /* non-ethtool stats follow */
+ u64 rx_total_packets;
+ u64 rx_total_bytes;
};
struct bnxt_stats_mem {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 113989b9b8cb..b74495e0e5d5 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -886,6 +886,24 @@ static bool bnxt_separate_head_pool(void)
return PAGE_SIZE > BNXT_RX_PAGE_SIZE;
}
+static void bnxt_rx_pkt_cnt(struct bnxt *bp, struct bnxt_napi *bnapi,
+ struct net_device *dev,
+ int segs, int len, int payload_off)
+{
+ struct bnxt_sw_stats *sw_stats = bnapi->cp_ring.sw_stats;
+
+ /* Packet is for a representor */
+ if (bp->dev != dev)
+ return;
+
+ u64_stats_update_begin(&sw_stats->rx.syncp);
+ sw_stats->rx.rx_packets += segs;
+ sw_stats->rx.rx_bytes += len;
+ if (segs > 1)
+ sw_stats->rx.rx_bytes += (segs - 1) * payload_off;
+ u64_stats_update_end(&sw_stats->rx.syncp);
+}
+
static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
struct bnxt_rx_ring_info *rxr,
unsigned int *offset,
@@ -1735,6 +1753,7 @@ static struct sk_buff *bnxt_gro_func_5730x(struct bnxt_tpa_info *tpa_info,
}
static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp,
+ struct bnxt_napi *bnapi,
bool gro,
struct bnxt_tpa_info *tpa_info,
struct rx_tpa_end_cmp *tpa_end,
@@ -1742,11 +1761,15 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp,
struct sk_buff *skb)
{
int payload_off;
+ int full_len;
u16 segs;
+ full_len = skb->len - skb_mac_offset(skb);
segs = TPA_END_TPA_SEGS(tpa_end);
- if (!gro || segs == 1 || !IS_ENABLED(CONFIG_INET))
+ if (!gro || segs == 1 || !IS_ENABLED(CONFIG_INET)) {
+ bnxt_rx_pkt_cnt(bp, bnapi, skb->dev, 1, full_len, 0);
return skb;
+ }
NAPI_GRO_CB(skb)->count = segs;
skb_shinfo(skb)->gso_size =
@@ -1757,8 +1780,11 @@ static inline struct sk_buff *bnxt_gro_skb(struct bnxt *bp,
else
payload_off = TPA_END_PAYLOAD_OFF(tpa_end);
skb = bp->gro_func(tpa_info, payload_off, TPA_END_GRO_TS(tpa_end), skb);
- if (likely(skb))
+ if (likely(skb)) {
tcp_gro_complete(skb);
+ bnxt_rx_pkt_cnt(bp, bnapi, skb->dev,
+ segs, full_len, payload_off);
+ }
return skb;
}
@@ -1918,7 +1944,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
(tpa_info->flags2 & RX_CMP_FLAGS2_T_L4_CS_CALC) >> 3;
}
- return bnxt_gro_skb(bp, gro, tpa_info, tpa_end, tpa_end1, skb);
+ return bnxt_gro_skb(bp, bnapi, gro, tpa_info, tpa_end, tpa_end1, skb);
}
static void bnxt_tpa_agg(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
@@ -2045,6 +2071,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
struct sk_buff *skb;
struct xdp_buff xdp;
u32 flags, misc;
+ u32 frag_len;
u32 cmpl_ts;
void *data;
int rc = 0;
@@ -2162,16 +2189,19 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
if (bnxt_xdp_attached(bp, rxr)) {
bnxt_xdp_buff_init(bp, rxr, cons, data_ptr, len, &xdp);
if (agg_bufs) {
- u32 frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp,
- cp_cons, agg_bufs,
- false);
+ frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp,
+ cp_cons, agg_bufs,
+ false);
if (!frag_len)
goto oom_next_rx;
+ } else {
+ frag_len = 0;
}
xdp_active = true;
}
if (xdp_active && dev == bp->dev) {
+ bnxt_rx_pkt_cnt(bp, bnapi, dev, 1, len + frag_len, 0);
if (bnxt_rx_xdp(bp, rxr, cons, &xdp, data, &data_ptr, &len, event)) {
rc = 1;
goto next_rx;
@@ -2274,6 +2304,10 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
}
}
}
+
+ if (!xdp_active) /* XDP packets counted before calling XDP */
+ bnxt_rx_pkt_cnt(bp, bnapi, dev,
+ 1, skb->len - skb_mac_offset(skb), 0);
bnxt_deliver_skb(bp, bnapi, skb);
rc = 1;
@@ -5114,6 +5148,8 @@ static int bnxt_alloc_stats(struct bnxt *bp)
if (!cpr->sw_stats)
return -ENOMEM;
+ u64_stats_init(&cpr->sw_stats->rx.syncp);
+
cpr->stats.len = size;
rc = bnxt_alloc_stats_mem(bp, &cpr->stats, !i);
if (rc)
@@ -13091,7 +13127,14 @@ static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static void bnxt_drv_stat_snapshot(const struct bnxt_sw_stats *sw_stats,
struct bnxt_sw_stats *snapshot)
{
- memcpy(snapshot, sw_stats, sizeof(*snapshot));
+ unsigned int seq_rx;
+
+ do {
+ seq_rx = u64_stats_fetch_begin(&sw_stats->rx.syncp);
+
+ memcpy(snapshot, sw_stats, sizeof(*snapshot));
+
+ } while (u64_stats_fetch_retry(&sw_stats->rx.syncp, seq_rx));
}
static void bnxt_get_ring_stats(struct bnxt *bp,
@@ -13107,18 +13150,13 @@ static void bnxt_get_ring_stats(struct bnxt *bp,
bnxt_drv_stat_snapshot(cpr->sw_stats, &sw_stats);
- stats->rx_packets += BNXT_GET_RING_STATS64(sw, rx_ucast_pkts);
- stats->rx_packets += BNXT_GET_RING_STATS64(sw, rx_mcast_pkts);
- stats->rx_packets += BNXT_GET_RING_STATS64(sw, rx_bcast_pkts);
+ stats->rx_packets += sw_stats.rx.rx_packets;
+ stats->rx_bytes += sw_stats.rx.rx_bytes;
stats->tx_packets += BNXT_GET_RING_STATS64(sw, tx_ucast_pkts);
stats->tx_packets += BNXT_GET_RING_STATS64(sw, tx_mcast_pkts);
stats->tx_packets += BNXT_GET_RING_STATS64(sw, tx_bcast_pkts);
- stats->rx_bytes += BNXT_GET_RING_STATS64(sw, rx_ucast_bytes);
- stats->rx_bytes += BNXT_GET_RING_STATS64(sw, rx_mcast_bytes);
- stats->rx_bytes += BNXT_GET_RING_STATS64(sw, rx_bcast_bytes);
-
stats->tx_bytes += BNXT_GET_RING_STATS64(sw, tx_ucast_bytes);
stats->tx_bytes += BNXT_GET_RING_STATS64(sw, tx_mcast_bytes);
stats->tx_bytes += BNXT_GET_RING_STATS64(sw, tx_bcast_bytes);
@@ -13209,6 +13247,8 @@ static void bnxt_get_one_ring_drv_stats(struct bnxt *bp,
stats->rx_total_buf_errors += sw_stats.rx.rx_buf_errors;
stats->rx_total_oom_discards += sw_stats.rx.rx_oom_discards;
stats->rx_total_netpoll_discards += sw_stats.rx.rx_netpoll_discards;
+ stats->rx_total_packets += sw_stats.rx.rx_packets;
+ stats->rx_total_bytes += sw_stats.rx.rx_bytes;
stats->rx_total_ring_discards +=
BNXT_GET_RING_STATS64(hw_stats, rx_discard_pkts);
stats->tx_total_resets += sw_stats.tx.tx_resets;
@@ -15601,23 +15641,17 @@ static void bnxt_get_queue_stats_rx(struct net_device *dev, int i,
struct netdev_queue_stats_rx *stats)
{
struct bnxt *bp = netdev_priv(dev);
- struct bnxt_cp_ring_info *cpr;
- u64 *sw;
+ struct bnxt_sw_stats *sw_stats;
+ unsigned int seq;
- cpr = &bp->bnapi[i]->cp_ring;
- sw = cpr->stats.sw_stats;
+ sw_stats = bp->bnapi[i]->cp_ring.sw_stats;
- stats->packets = 0;
- stats->packets += BNXT_GET_RING_STATS64(sw, rx_ucast_pkts);
- stats->packets += BNXT_GET_RING_STATS64(sw, rx_mcast_pkts);
- stats->packets += BNXT_GET_RING_STATS64(sw, rx_bcast_pkts);
-
- stats->bytes = 0;
- stats->bytes += BNXT_GET_RING_STATS64(sw, rx_ucast_bytes);
- stats->bytes += BNXT_GET_RING_STATS64(sw, rx_mcast_bytes);
- stats->bytes += BNXT_GET_RING_STATS64(sw, rx_bcast_bytes);
-
- stats->alloc_fail = cpr->sw_stats->rx.rx_oom_discards;
+ do {
+ seq = u64_stats_fetch_begin(&sw_stats->rx.syncp);
+ stats->packets = sw_stats->rx.rx_packets;
+ stats->bytes = sw_stats->rx.rx_bytes;
+ stats->alloc_fail = sw_stats->rx.rx_oom_discards;
+ } while (u64_stats_fetch_retry(&sw_stats->rx.syncp, seq));
}
static void bnxt_get_queue_stats_tx(struct net_device *dev, int i,
@@ -15647,8 +15681,8 @@ static void bnxt_get_base_stats(struct net_device *dev,
{
struct bnxt *bp = netdev_priv(dev);
- rx->packets = bp->net_stats_prev.rx_packets;
- rx->bytes = bp->net_stats_prev.rx_bytes;
+ rx->packets = bp->ring_drv_stats_prev.rx_total_packets;
+ rx->bytes = bp->ring_drv_stats_prev.rx_total_bytes;
rx->alloc_fail = bp->ring_drv_stats_prev.rx_total_oom_discards;
tx->packets = bp->net_stats_prev.tx_packets;
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 8/9] eth: bnxt: maintain tx pkt/byte stats in SW
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
` (6 preceding siblings ...)
2025-02-26 21:10 ` [PATCH net-next 7/9] eth: bnxt: maintain rx pkt/byte stats in SW Jakub Kicinski
@ 2025-02-26 21:10 ` Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 9/9] eth: bnxt: count xdp xmit packets Jakub Kicinski
8 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:10 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
Some workloads want to be able to track bandwidth utilization on
the scale of 10s of msecs. Updating all HW stats at this rate is
both hard and wasteful of PCIe bandwidth.
Maintain basic Tx pkt/byte counters in software. ethtool -S will still
show the HW stats, but qstats and rtnl stats will show SW statistics.
We need to take care of TSO and VF representors, record relevant
state in tx_buf to avoid touching potentially cold skb. Use existing
holes in the struct (no size change). Note that according to TX_BD_HSIZE
max header size is 255, so u8 should be enough.
It's not obvious whether VF representor traffic should be counted,
on one hand it doesn't belong to the local interface. On the other
it does go thru normal queuing so Qdisc will show it. I opted to
_not_ count it.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 11 +++-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 70 ++++++++++++++---------
2 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 1607a4a28bf0..e542e39bf84c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -877,11 +877,14 @@ struct bnxt_sw_tx_bd {
struct sk_buff *skb;
struct xdp_frame *xdpf;
};
+ struct page *page;
DEFINE_DMA_UNMAP_ADDR(mapping);
DEFINE_DMA_UNMAP_LEN(len);
- struct page *page;
+ u16 extra_segs;
+ u8 hdr_size;
u8 is_ts_pkt;
u8 is_push;
+ u8 is_vfr;
u8 action;
unsigned short nr_frags;
union {
@@ -1128,6 +1131,10 @@ struct bnxt_rx_sw_stats {
struct bnxt_tx_sw_stats {
u64 tx_resets;
+ /* non-ethtool stats follow */
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
};
struct bnxt_cmn_sw_stats {
@@ -1153,6 +1160,8 @@ struct bnxt_total_ring_drv_stats {
/* non-ethtool stats follow */
u64 rx_total_packets;
u64 rx_total_bytes;
+ u64 tx_total_packets;
+ u64 tx_total_bytes;
};
struct bnxt_stats_mem {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index b74495e0e5d5..19f823f1079b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -514,6 +514,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
vlan_tag_flags = 0;
cfa_action = bnxt_xmit_get_cfa_action(skb);
+ tx_buf->is_vfr = !!cfa_action;
if (skb_vlan_tag_present(skb)) {
vlan_tag_flags = TX_BD_CFA_META_KEY_VLAN |
skb_vlan_tag_get(skb);
@@ -675,6 +676,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
length = skb_shinfo(skb)->gso_size;
txbd1->tx_bd_mss = cpu_to_le32(length);
length += hdr_len;
+
+ tx_buf->hdr_size = hdr_len;
+ tx_buf->extra_segs = skb_shinfo(skb)->gso_segs - 1;
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
txbd1->tx_bd_hsize_lflags |=
cpu_to_le32(TX_BD_FLAGS_TCP_UDP_CHKSUM);
@@ -784,6 +788,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (txr->kick_pending)
bnxt_txr_db_kick(bp, txr, txr->tx_prod);
txr->tx_buf_ring[txr->tx_prod].skb = NULL;
+ txr->tx_buf_ring[txr->tx_prod].extra_segs = 0;
+ txr->tx_buf_ring[txr->tx_prod].hdr_size = 0;
+ txr->tx_buf_ring[txr->tx_prod].is_vfr = 0;
dev_core_stats_tx_dropped_inc(dev);
return NETDEV_TX_OK;
}
@@ -793,11 +800,12 @@ static bool __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
int budget)
{
struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
+ struct bnxt_sw_stats *sw_stats = txr->bnapi->cp_ring.sw_stats;
struct pci_dev *pdev = bp->pdev;
+ int adj_bytes = 0, tx_bytes = 0;
+ int adj_pkts = 0, tx_pkts = 0;
u16 hw_cons = txr->tx_hw_cons;
- unsigned int tx_bytes = 0;
u16 cons = txr->tx_cons;
- int tx_pkts = 0;
bool rc = false;
while (RING_TX(bp, cons) != hw_cons) {
@@ -823,8 +831,18 @@ static bool __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
cons = NEXT_TX(cons);
tx_pkts++;
tx_bytes += skb->len;
+ if (!tx_buf->is_vfr) {
+ adj_pkts += tx_buf->extra_segs;
+ adj_bytes += tx_buf->extra_segs * tx_buf->hdr_size;
+ } else {
+ adj_pkts--;
+ adj_bytes -= skb->len;
+ }
tx_buf->skb = NULL;
+ tx_buf->extra_segs = 0;
+ tx_buf->hdr_size = 0;
tx_buf->is_ts_pkt = 0;
+ tx_buf->is_vfr = 0;
if (tx_buf->is_push) {
tx_buf->is_push = 0;
@@ -860,6 +878,11 @@ static bool __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
WRITE_ONCE(txr->tx_cons, cons);
+ u64_stats_update_begin(&sw_stats->tx.syncp);
+ sw_stats->tx.tx_packets += tx_pkts + adj_pkts;
+ sw_stats->tx.tx_bytes += tx_bytes + adj_bytes;
+ u64_stats_update_end(&sw_stats->tx.syncp);
+
__netif_txq_completed_wake(txq, tx_pkts, tx_bytes,
bnxt_tx_avail(bp, txr), bp->tx_wake_thresh,
READ_ONCE(txr->dev_state) == BNXT_DEV_STATE_CLOSING);
@@ -5149,6 +5172,7 @@ static int bnxt_alloc_stats(struct bnxt *bp)
return -ENOMEM;
u64_stats_init(&cpr->sw_stats->rx.syncp);
+ u64_stats_init(&cpr->sw_stats->tx.syncp);
cpr->stats.len = size;
rc = bnxt_alloc_stats_mem(bp, &cpr->stats, !i);
@@ -13127,14 +13151,16 @@ static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static void bnxt_drv_stat_snapshot(const struct bnxt_sw_stats *sw_stats,
struct bnxt_sw_stats *snapshot)
{
- unsigned int seq_rx;
+ unsigned int seq_rx, seq_tx;
do {
seq_rx = u64_stats_fetch_begin(&sw_stats->rx.syncp);
+ seq_tx = u64_stats_fetch_begin(&sw_stats->tx.syncp);
memcpy(snapshot, sw_stats, sizeof(*snapshot));
- } while (u64_stats_fetch_retry(&sw_stats->rx.syncp, seq_rx));
+ } while (u64_stats_fetch_retry(&sw_stats->rx.syncp, seq_rx) ||
+ u64_stats_fetch_retry(&sw_stats->tx.syncp, seq_tx));
}
static void bnxt_get_ring_stats(struct bnxt *bp,
@@ -13153,13 +13179,8 @@ static void bnxt_get_ring_stats(struct bnxt *bp,
stats->rx_packets += sw_stats.rx.rx_packets;
stats->rx_bytes += sw_stats.rx.rx_bytes;
- stats->tx_packets += BNXT_GET_RING_STATS64(sw, tx_ucast_pkts);
- stats->tx_packets += BNXT_GET_RING_STATS64(sw, tx_mcast_pkts);
- stats->tx_packets += BNXT_GET_RING_STATS64(sw, tx_bcast_pkts);
-
- stats->tx_bytes += BNXT_GET_RING_STATS64(sw, tx_ucast_bytes);
- stats->tx_bytes += BNXT_GET_RING_STATS64(sw, tx_mcast_bytes);
- stats->tx_bytes += BNXT_GET_RING_STATS64(sw, tx_bcast_bytes);
+ stats->tx_packets += sw_stats.tx.tx_packets;
+ stats->tx_bytes += sw_stats.tx.tx_bytes;
stats->rx_missed_errors +=
BNXT_GET_RING_STATS64(sw, rx_discard_pkts);
@@ -13251,6 +13272,8 @@ static void bnxt_get_one_ring_drv_stats(struct bnxt *bp,
stats->rx_total_bytes += sw_stats.rx.rx_bytes;
stats->rx_total_ring_discards +=
BNXT_GET_RING_STATS64(hw_stats, rx_discard_pkts);
+ stats->tx_total_packets += sw_stats.tx.tx_packets;
+ stats->tx_total_bytes += sw_stats.tx.tx_bytes;
stats->tx_total_resets += sw_stats.tx.tx_resets;
stats->tx_total_ring_discards +=
BNXT_GET_RING_STATS64(hw_stats, tx_discard_pkts);
@@ -15658,21 +15681,16 @@ static void bnxt_get_queue_stats_tx(struct net_device *dev, int i,
struct netdev_queue_stats_tx *stats)
{
struct bnxt *bp = netdev_priv(dev);
- struct bnxt_napi *bnapi;
- u64 *sw;
+ struct bnxt_sw_stats *sw_stats;
+ unsigned int seq;
- bnapi = bp->tx_ring[bp->tx_ring_map[i]].bnapi;
- sw = bnapi->cp_ring.stats.sw_stats;
+ sw_stats = bp->tx_ring[bp->tx_ring_map[i]].bnapi->cp_ring.sw_stats;
- stats->packets = 0;
- stats->packets += BNXT_GET_RING_STATS64(sw, tx_ucast_pkts);
- stats->packets += BNXT_GET_RING_STATS64(sw, tx_mcast_pkts);
- stats->packets += BNXT_GET_RING_STATS64(sw, tx_bcast_pkts);
-
- stats->bytes = 0;
- stats->bytes += BNXT_GET_RING_STATS64(sw, tx_ucast_bytes);
- stats->bytes += BNXT_GET_RING_STATS64(sw, tx_mcast_bytes);
- stats->bytes += BNXT_GET_RING_STATS64(sw, tx_bcast_bytes);
+ do {
+ seq = u64_stats_fetch_begin(&sw_stats->tx.syncp);
+ stats->packets = sw_stats->tx.tx_packets;
+ stats->bytes = sw_stats->tx.tx_bytes;
+ } while (u64_stats_fetch_retry(&sw_stats->tx.syncp, seq));
}
static void bnxt_get_base_stats(struct net_device *dev,
@@ -15685,8 +15703,8 @@ static void bnxt_get_base_stats(struct net_device *dev,
rx->bytes = bp->ring_drv_stats_prev.rx_total_bytes;
rx->alloc_fail = bp->ring_drv_stats_prev.rx_total_oom_discards;
- tx->packets = bp->net_stats_prev.tx_packets;
- tx->bytes = bp->net_stats_prev.tx_bytes;
+ tx->packets = bp->ring_drv_stats_prev.tx_total_packets;
+ tx->bytes = bp->ring_drv_stats_prev.tx_total_bytes;
}
static const struct netdev_stat_ops bnxt_stat_ops = {
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH net-next 9/9] eth: bnxt: count xdp xmit packets
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
` (7 preceding siblings ...)
2025-02-26 21:10 ` [PATCH net-next 8/9] eth: bnxt: maintain tx " Jakub Kicinski
@ 2025-02-26 21:10 ` Jakub Kicinski
8 siblings, 0 replies; 12+ messages in thread
From: Jakub Kicinski @ 2025-02-26 21:10 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, michael.chan,
pavan.chebbi, Jakub Kicinski
Count XDP_TX and XDP_REDIRECT packets. Since the Tx rings are separate
we count the packets sent to the base stats, not per-queues stats.
The XDP stats are protected by the Rx syncp since they are in NAPI
context. Feels slightly less ugly than having a Tx stats in Rx struct.
But neither is ideal.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.h | 7 +++++-
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 23 +++++++++++++++++--
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 15 ++++++++++++
3 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index e542e39bf84c..6db34f8b8fa6 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -880,7 +880,10 @@ struct bnxt_sw_tx_bd {
struct page *page;
DEFINE_DMA_UNMAP_ADDR(mapping);
DEFINE_DMA_UNMAP_LEN(len);
- u16 extra_segs;
+ union {
+ u16 extra_segs;
+ u16 xdp_len;
+ };
u8 hdr_size;
u8 is_ts_pkt;
u8 is_push;
@@ -1134,6 +1137,8 @@ struct bnxt_tx_sw_stats {
/* non-ethtool stats follow */
u64 tx_packets;
u64 tx_bytes;
+ u64 xdp_packets; /* under rx syncp */
+ u64 xdp_bytes; /* under rx syncp */
struct u64_stats_sync syncp;
};
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 19f823f1079b..ca68f677368e 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -13181,6 +13181,8 @@ static void bnxt_get_ring_stats(struct bnxt *bp,
stats->tx_packets += sw_stats.tx.tx_packets;
stats->tx_bytes += sw_stats.tx.tx_bytes;
+ stats->tx_packets += sw_stats.tx.xdp_packets;
+ stats->tx_bytes += sw_stats.tx.xdp_bytes;
stats->rx_missed_errors +=
BNXT_GET_RING_STATS64(sw, rx_discard_pkts);
@@ -13272,8 +13274,9 @@ static void bnxt_get_one_ring_drv_stats(struct bnxt *bp,
stats->rx_total_bytes += sw_stats.rx.rx_bytes;
stats->rx_total_ring_discards +=
BNXT_GET_RING_STATS64(hw_stats, rx_discard_pkts);
- stats->tx_total_packets += sw_stats.tx.tx_packets;
- stats->tx_total_bytes += sw_stats.tx.tx_bytes;
+ stats->tx_total_packets +=
+ sw_stats.tx.tx_packets + sw_stats.tx.xdp_packets;
+ stats->tx_total_bytes += sw_stats.tx.tx_bytes + sw_stats.tx.xdp_bytes;
stats->tx_total_resets += sw_stats.tx.tx_resets;
stats->tx_total_ring_discards +=
BNXT_GET_RING_STATS64(hw_stats, tx_discard_pkts);
@@ -15698,6 +15701,7 @@ static void bnxt_get_base_stats(struct net_device *dev,
struct netdev_queue_stats_tx *tx)
{
struct bnxt *bp = netdev_priv(dev);
+ int i;
rx->packets = bp->ring_drv_stats_prev.rx_total_packets;
rx->bytes = bp->ring_drv_stats_prev.rx_total_bytes;
@@ -15705,6 +15709,21 @@ static void bnxt_get_base_stats(struct net_device *dev,
tx->packets = bp->ring_drv_stats_prev.tx_total_packets;
tx->bytes = bp->ring_drv_stats_prev.tx_total_bytes;
+
+ for (i = 0; i < bp->cp_nr_rings; i++) {
+ struct bnxt_sw_stats *sw_stats = bp->bnapi[i]->cp_ring.sw_stats;
+ unsigned int seq;
+ u64 pkts, bytes;
+
+ do {
+ seq = u64_stats_fetch_begin(&sw_stats->rx.syncp);
+ pkts = sw_stats->tx.xdp_packets;
+ bytes = sw_stats->tx.xdp_bytes;
+ } while (u64_stats_fetch_retry(&sw_stats->rx.syncp, seq));
+
+ tx->packets += pkts;
+ tx->bytes += bytes;
+ }
}
static const struct netdev_stat_ops bnxt_stat_ops = {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
index e6c64e4bd66c..d4cd36f227b9 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
@@ -38,6 +38,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
if (xdp && xdp_buff_has_frags(xdp)) {
sinfo = xdp_get_shared_info_from_buff(xdp);
num_frags = sinfo->nr_frags;
+ tx_buf->xdp_len += sinfo->xdp_frags_size;
}
/* fill up the first buffer */
@@ -47,6 +48,8 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
if (xdp)
tx_buf->page = virt_to_head_page(xdp->data);
+ tx_buf->xdp_len += len;
+
txbd = &txr->tx_desc_ring[TX_RING(bp, prod)][TX_IDX(prod)];
flags = (len << TX_BD_LEN_SHIFT) |
((num_frags + 1) << TX_BD_FLAGS_BD_CNT_SHIFT) |
@@ -120,9 +123,11 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp,
void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{
+ struct bnxt_sw_stats *sw_stats = bnapi->cp_ring.sw_stats;
struct bnxt_tx_ring_info *txr = bnapi->tx_ring[0];
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
u16 tx_hw_cons = txr->tx_hw_cons;
+ unsigned int pkts = 0, bytes = 0;
bool rx_doorbell_needed = false;
struct bnxt_sw_tx_bd *tx_buf;
u16 tx_cons = txr->tx_cons;
@@ -135,6 +140,10 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
while (RING_TX(bp, tx_cons) != tx_hw_cons) {
tx_buf = &txr->tx_buf_ring[RING_TX(bp, tx_cons)];
+ pkts++;
+ bytes += tx_buf->xdp_len;
+ tx_buf->xdp_len = 0;
+
if (tx_buf->action == XDP_REDIRECT) {
struct pci_dev *pdev = bp->pdev;
@@ -163,6 +172,12 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
tx_cons = NEXT_TX(tx_cons);
}
+ /* Note: Rx sync here, because Rx == NAPI context */
+ u64_stats_update_begin(&sw_stats->rx.syncp);
+ sw_stats->tx.xdp_packets += pkts;
+ sw_stats->tx.xdp_bytes += bytes;
+ u64_stats_update_end(&sw_stats->rx.syncp);
+
bnapi->events &= ~BNXT_TX_CMP_EVENT;
WRITE_ONCE(txr->tx_cons, tx_cons);
if (rx_doorbell_needed) {
--
2.48.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 2/9] eth: bnxt: don't run xdp programs on fallback traffic
2025-02-26 21:09 ` [PATCH net-next 2/9] eth: bnxt: don't run xdp programs on fallback traffic Jakub Kicinski
@ 2025-02-27 3:35 ` Michael Chan
0 siblings, 0 replies; 12+ messages in thread
From: Michael Chan @ 2025-02-27 3:35 UTC (permalink / raw)
To: Jakub Kicinski, Andrew Gospodarek
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms,
pavan.chebbi
[-- Attachment #1: Type: text/plain, Size: 1364 bytes --]
On Wed, Feb 26, 2025 at 1:10 PM Jakub Kicinski <kuba@kernel.org> wrote:
> @@ -2159,6 +2159,10 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
> len = flags >> RX_CMP_LEN_SHIFT;
> dma_addr = rx_buf->mapping;
>
> + dev = bp->dev;
> + if (cmp_type == CMP_TYPE_RX_L2_CMP)
> + dev = bnxt_get_pkt_dev(bp, RX_CMP_CFA_CODE(rxcmp1));
> +
> if (bnxt_xdp_attached(bp, rxr)) {
> bnxt_xdp_buff_init(bp, rxr, cons, data_ptr, len, &xdp);
> if (agg_bufs) {
> @@ -2171,7 +2175,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
> xdp_active = true;
> }
>
> - if (xdp_active) {
> + if (xdp_active && dev == bp->dev) {
If we skip the XDP program, we still need to do this check in
bnxt_rx_xdp() because we may be using the XDP TX ring:
tx_avail = bnxt_tx_avail(bp, txr);
/* If the tx ring is not full, we must not update the rx producer yet
* because we may still be transmitting on some BDs.
*/
if (tx_avail != bp->tx_ring_size)
*event &= ~BNXT_RX_EVENT;
> if (bnxt_rx_xdp(bp, rxr, cons, &xdp, data, &data_ptr, &len, event)) {
> rc = 1;
> goto next_rx;
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 4209 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 3/9] eth: bnxt: rename ring_err_stats -> ring_drv_stats
2025-02-26 21:09 ` [PATCH net-next 3/9] eth: bnxt: rename ring_err_stats -> ring_drv_stats Jakub Kicinski
@ 2025-02-27 4:55 ` Przemek Kitszel
0 siblings, 0 replies; 12+ messages in thread
From: Przemek Kitszel @ 2025-02-27 4:55 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, davem, edumazet, pabeni, andrew+netdev, horms,
michael.chan, pavan.chebbi
On 2/26/25 22:09, Jakub Kicinski wrote:
> We will soon store non-error stats to the ring struct.
> Rename them to "drv" stats, as these are all maintained
> by the driver (even if partially based on info from descriptors).
>
> Pure rename using sed.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
> @@ -340,7 +340,7 @@ enum {
> RX_NETPOLL_DISCARDS,
> };
>
> -static const char *const bnxt_ring_err_stats_arr[] = {
> +static const char *const bnxt_ring_drv_stats_arr[] = {
> "rx_total_l4_csum_errors",
> "rx_total_resets",
> "rx_total_buf_errors",
> @@ -500,7 +500,7 @@ static const struct {
> BNXT_TX_STATS_PRI_ENTRIES(tx_packets),
> };
>
> -#define BNXT_NUM_RING_ERR_STATS ARRAY_SIZE(bnxt_ring_err_stats_arr)
> +#define BNXT_NUM_RING_ERR_STATS ARRAY_SIZE(bnxt_ring_drv_stats_arr)
s/BNXT_NUM_RING_ERR_STATS/BNXT_NUM_RING_DRV_STATS/?
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-02-27 4:55 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-26 21:09 [PATCH net-next 0/9] eth: bnxt: maintain basic pkt/byte counters in SW Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 1/9] eth: bnxt: use napi_consume_skb() Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 2/9] eth: bnxt: don't run xdp programs on fallback traffic Jakub Kicinski
2025-02-27 3:35 ` Michael Chan
2025-02-26 21:09 ` [PATCH net-next 3/9] eth: bnxt: rename ring_err_stats -> ring_drv_stats Jakub Kicinski
2025-02-27 4:55 ` Przemek Kitszel
2025-02-26 21:09 ` [PATCH net-next 4/9] eth: bnxt: snapshot driver stats Jakub Kicinski
2025-02-26 21:09 ` [PATCH net-next 5/9] eth: bnxt: don't use ifdef to check for CONFIG_INET in GRO Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 6/9] eth: bnxt: consolidate the GRO-but-not-really paths in bnxt_gro_skb() Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 7/9] eth: bnxt: maintain rx pkt/byte stats in SW Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 8/9] eth: bnxt: maintain tx " Jakub Kicinski
2025-02-26 21:10 ` [PATCH net-next 9/9] eth: bnxt: count xdp xmit packets Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).