[PATCH net-next v5] ixgbe: implement get_queue_stats_rx

Kshitiz Bartariya posted 1 patch 1 month, 2 weeks ago
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
[PATCH net-next v5] ixgbe: implement get_queue_stats_rx
Posted by Kshitiz Bartariya 1 month, 2 weeks ago
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@zohomail.in>
---
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.5017017162150392549@zohomail.in/

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@zohomail.in/

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@zohomail.in/

v1: 
 https://lore.kernel.org/lkml/20260602100932.21838-1-kshitiz.bartariya@zohomail.in/

 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));
+	}
+
+	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)
RE: [Intel-wired-lan] [PATCH net-next v5] ixgbe: implement get_queue_stats_rx
Posted by Loktionov, Aleksandr 1 month, 1 week ago

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Kshitiz Bartariya via Intel-wired-lan
> Sent: Friday, August 14, 2026 4:15 PM
> To: Nguyen, Anthony L <anthony.l.nguyen@intel.com>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@intel.com>; andrew+netdev@lunn.ch;
> davem@davemloft.net; edumazet@google.com; kuba@kernel.org;
> pabeni@redhat.com
> Cc: Kshitiz Bartariya <kshitiz.bartariya@zohomail.in>; intel-wired-
> lan@lists.osuosl.org; netdev@vger.kernel.org; linux-
> kernel@vger.kernel.org
> 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@zohomail.in>
> ---
> 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@zohomail.in/
> 
> 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@zohomail.in/
> 
> 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@zohomail.in/
> 
> v1:
>  https://lore.kernel.org/lkml/20260602100932.21838-1-
> kshitiz.bartariya@zohomail.in/
> 
>  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)
Re: [PATCH net-next v5] ixgbe: implement get_queue_stats_rx
Posted by Jakub Kicinski 1 month, 1 week ago
On Fri, 14 Aug 2026 19:44:36 +0530 Kshitiz Bartariya wrote:
> +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));
> +	}
> +
> +	stats->bytes = bytes;

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c:9772:6: warning: variable 'bytes' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
-- 
pw-not: cr