RE: [Intel-wired-lan] [PATCH net-next v5] ixgbe: implement get_queue_stats_rx
From: Loktionov, Aleksandr
Date: Tue Aug 18 2026 - 07:22:21 EST
> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@xxxxxxxxxx> On Behalf
> Of Kshitiz Bartariya via Intel-wired-lan
> Sent: Friday, August 14, 2026 4:15 PM
> To: Nguyen, Anthony L <anthony.l.nguyen@xxxxxxxxx>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@xxxxxxxxx>; andrew+netdev@xxxxxxx;
> davem@xxxxxxxxxxxxx; edumazet@xxxxxxxxxx; kuba@xxxxxxxxxx;
> pabeni@xxxxxxxxxx
> Cc: Kshitiz Bartariya <kshitiz.bartariya@xxxxxxxxxxx>; intel-wired-
> lan@xxxxxxxxxxxxxxxx; netdev@xxxxxxxxxxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx
> Subject: [Intel-wired-lan] [PATCH net-next v5] ixgbe: implement
> get_queue_stats_rx
>
> Hook into the netdev_stat_ops interface to expose per RX queue
> statistics through the netdev generic netlink API.
>
> The following counters are filled:
> - bytes: maps directly to bytes
> - packets: maps directly to packets
> - alloc_fail: sum of alloc_rx_page_failed and alloc_rx_buff_failed
> - csum_bad: maps directly to csum_err, which is incremented for both
> IP header and L4 checksum errors in ixgbe_rx_checksum().
>
> The new per-queue stats can be observed with:
> $ ynltool qstats show scope queue
>
> Signed-off-by: Kshitiz Bartariya <kshitiz.bartariya@xxxxxxxxxxx>
> ---
> v5:
> - Added READ_ONCE() and NULL check for accessing adapter->rx_ring[i]
> - Added u64_stats_fetch_begin before reading stats from rx_ring
> Suggested by Simon Horman
>
> v4:
> - Changed comment format from // to /* */
> - Moved ixgbe_stat_ops declaration next to the ixgbe_netdev_ops
> Suggested by Jedrzej Jagielski.
> https://lore.kernel.org/lkml/19ed3cf767d.36a9bda531830.501701716215039
> 2549@xxxxxxxxxxx/
>
> v3:
> - Added bytes and packets stats counters
> - Implemented ixgbe_get_base_stats function As suggested by AI on
> https://netdev-
> ai.bots.linux.dev/sashiko/#/patchset/20260603174857.78666-1-
> kshitiz.bartariya%40zohomail.in
> https://lore.kernel.org/lkml/20260612084605.19785-1-
> kshitiz.bartariya@xxxxxxxxxxx/
>
> v2:
> Amended commit message with command to get RX queue stats as
> suggested by Jedrzej Jagielski.
> https://lore.kernel.org/lkml/20260603174857.78666-1-
> kshitiz.bartariya@xxxxxxxxxxx/
>
> v1:
> https://lore.kernel.org/lkml/20260602100932.21838-1-
> kshitiz.bartariya@xxxxxxxxxxx/
>
> drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 45
> +++++++++++++++++++
> 1 file changed, 45 insertions(+)
>
> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> index 8873a8cc4a18..560177f135ff 100644
> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
> @@ -9760,6 +9760,45 @@ static void ixgbe_get_stats64(struct net_device
> *netdev,
> stats->rx_missed_errors = netdev->stats.rx_missed_errors;
> }
>
> +static void ixgbe_get_queue_stats_rx(struct net_device *dev, int idx,
> + struct netdev_queue_stats_rx *stats) {
> + struct ixgbe_adapter *adapter = ixgbe_from_netdev(dev);
> + struct ixgbe_ring *ring = READ_ONCE(adapter->rx_ring[idx]);
> + u64 bytes, packets, alloc_rx_page_failed, alloc_rx_buff_failed,
> + csum_err;
> + unsigned int start;
> +
> + if (ring) {
> + do {
> + start = u64_stats_fetch_begin(&ring->syncp);
> + bytes = ring->stats.bytes;
> + packets = ring->stats.packets;
> + alloc_rx_page_failed =
> + ring->rx_stats.alloc_rx_page_failed;
> + alloc_rx_buff_failed =
> + ring->rx_stats.alloc_rx_buff_failed;
> + csum_err = ring->rx_stats.csum_err;
> + } while (u64_stats_fetch_retry(&ring->syncp, start));
> + }
If ring == NULL then bytes, packets, alloc_rx_page_failed, alloc_rx_buff_failed and csum_err are uninitialized UB.
> +
> + stats->bytes = bytes;
> + stats->packets = packets;
> + stats->alloc_fail = alloc_rx_page_failed +
> alloc_rx_buff_failed;
> + stats->csum_bad = csum_err;
> +}
> +
> +static void ixgbe_get_base_stats(struct net_device *dev,
> + struct netdev_queue_stats_rx *rx,
> + struct netdev_queue_stats_tx *tx)
> +{
> + /* ixgbe has no inactive queues */
> + rx->bytes = 0;
> + rx->packets = 0;
> + rx->alloc_fail = 0;
> + rx->csum_bad = 0;
> +}
> +
> static int ixgbe_ndo_get_vf_stats(struct net_device *netdev, int vf,
> struct ifla_vf_stats *vf_stats)
> {
> @@ -11117,6 +11156,11 @@ static const struct net_device_ops
> ixgbe_netdev_ops = {
> .ndo_hwtstamp_set = ixgbe_ptp_hwtstamp_set,
> };
>
> +static const struct netdev_stat_ops ixgbe_stat_ops = {
> + .get_queue_stats_rx = ixgbe_get_queue_stats_rx,
> + .get_base_stats = ixgbe_get_base_stats, };
> +
> static void ixgbe_disable_txr_hw(struct ixgbe_adapter *adapter,
> struct ixgbe_ring *tx_ring)
> {
> @@ -11663,6 +11707,7 @@ static int ixgbe_probe(struct pci_dev *pdev,
> const struct pci_device_id *ent)
> hw->phy.mdio.mdio_write = ixgbe_mdio_write;
>
> netdev->netdev_ops = &ixgbe_netdev_ops;
> + netdev->stat_ops = &ixgbe_stat_ops;
> ixgbe_set_ethtool_ops(netdev);
> netdev->watchdog_timeo = 5 * HZ;
> strscpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
> --
> 2.50.1 (Apple Git-155)