Commit cf954568 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sfc-per-q-stats'



Edward Cree says:

====================
sfc: per-queue stats

This series implements the netdev_stat_ops interface for per-queue
 statistics in the sfc driver, partly using existing counters that
 were originally added for ethtool -S output.

Changed in v4:
* remove RFC tags

Changed in v3:
* make TX stats count completions rather than enqueues
* add new patch #4 to account for XDP TX separately from netdev
  traffic and include it in base_stats
* move the tx_queue->old_* members out of the fastpath cachelines
* note on patch #6 that our hw_gso stats still count enqueues
* RFC since net-next is closed right now

Changed in v2:
* exclude (dedicated) XDP TXQ stats from per-queue TX stats
* explain patch #3 better
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d521db38 b3411dbd
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -134,6 +134,9 @@ void __ef100_rx_packet(struct efx_channel *channel)
		goto free_rx_buffer;
	}

	++rx_queue->rx_packets;
	rx_queue->rx_bytes += rx_buf->len;

	efx_rx_packet_gro(channel, rx_buf, channel->rx_pkt_n_frags, eh, csum);
	goto out;

@@ -149,8 +152,6 @@ static void ef100_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index)
	struct efx_channel *channel = efx_rx_queue_channel(rx_queue);
	struct efx_nic *efx = rx_queue->efx;

	++rx_queue->rx_packets;

	netif_vdbg(efx, rx_status, efx->net_dev,
		   "RX queue %d received id %x\n",
		   efx_rx_queue_index(rx_queue), index);
+109 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "net_driver.h"
#include <net/gre.h>
#include <net/udp_tunnel.h>
#include <net/netdev_queues.h>
#include "efx.h"
#include "efx_common.h"
#include "efx_channels.h"
@@ -626,6 +627,113 @@ static const struct net_device_ops efx_netdev_ops = {
	.ndo_bpf		= efx_xdp
};

static void efx_get_queue_stats_rx(struct net_device *net_dev, int idx,
				   struct netdev_queue_stats_rx *stats)
{
	struct efx_nic *efx = efx_netdev_priv(net_dev);
	struct efx_rx_queue *rx_queue;
	struct efx_channel *channel;

	channel = efx_get_channel(efx, idx);
	rx_queue = efx_channel_get_rx_queue(channel);
	/* Count only packets since last time datapath was started */
	stats->packets = rx_queue->rx_packets - rx_queue->old_rx_packets;
	stats->bytes = rx_queue->rx_bytes - rx_queue->old_rx_bytes;
	stats->hw_drops = efx_get_queue_stat_rx_hw_drops(channel) -
			  channel->old_n_rx_hw_drops;
	stats->hw_drop_overruns = channel->n_rx_nodesc_trunc -
				  channel->old_n_rx_hw_drop_overruns;
}

static void efx_get_queue_stats_tx(struct net_device *net_dev, int idx,
				   struct netdev_queue_stats_tx *stats)
{
	struct efx_nic *efx = efx_netdev_priv(net_dev);
	struct efx_tx_queue *tx_queue;
	struct efx_channel *channel;

	channel = efx_get_tx_channel(efx, idx);
	stats->packets = 0;
	stats->bytes = 0;
	stats->hw_gso_packets = 0;
	stats->hw_gso_wire_packets = 0;
	efx_for_each_channel_tx_queue(tx_queue, channel) {
		stats->packets += tx_queue->complete_packets -
				  tx_queue->old_complete_packets;
		stats->bytes += tx_queue->complete_bytes -
				tx_queue->old_complete_bytes;
		/* Note that, unlike stats->packets and stats->bytes,
		 * these count TXes enqueued, rather than completed,
		 * which may not be what users expect.
		 */
		stats->hw_gso_packets += tx_queue->tso_bursts -
					 tx_queue->old_tso_bursts;
		stats->hw_gso_wire_packets += tx_queue->tso_packets -
					      tx_queue->old_tso_packets;
	}
}

static void efx_get_base_stats(struct net_device *net_dev,
			       struct netdev_queue_stats_rx *rx,
			       struct netdev_queue_stats_tx *tx)
{
	struct efx_nic *efx = efx_netdev_priv(net_dev);
	struct efx_tx_queue *tx_queue;
	struct efx_rx_queue *rx_queue;
	struct efx_channel *channel;

	rx->packets = 0;
	rx->bytes = 0;
	rx->hw_drops = 0;
	rx->hw_drop_overruns = 0;
	tx->packets = 0;
	tx->bytes = 0;
	tx->hw_gso_packets = 0;
	tx->hw_gso_wire_packets = 0;

	/* Count all packets on non-core queues, and packets before last
	 * datapath start on core queues.
	 */
	efx_for_each_channel(channel, efx) {
		rx_queue = efx_channel_get_rx_queue(channel);
		if (channel->channel >= net_dev->real_num_rx_queues) {
			rx->packets += rx_queue->rx_packets;
			rx->bytes += rx_queue->rx_bytes;
			rx->hw_drops += efx_get_queue_stat_rx_hw_drops(channel);
			rx->hw_drop_overruns += channel->n_rx_nodesc_trunc;
		} else {
			rx->packets += rx_queue->old_rx_packets;
			rx->bytes += rx_queue->old_rx_bytes;
			rx->hw_drops += channel->old_n_rx_hw_drops;
			rx->hw_drop_overruns += channel->old_n_rx_hw_drop_overruns;
		}
		efx_for_each_channel_tx_queue(tx_queue, channel) {
			if (channel->channel < efx->tx_channel_offset ||
			    channel->channel >= efx->tx_channel_offset +
						net_dev->real_num_tx_queues) {
				tx->packets += tx_queue->complete_packets;
				tx->bytes += tx_queue->complete_bytes;
				tx->hw_gso_packets += tx_queue->tso_bursts;
				tx->hw_gso_wire_packets += tx_queue->tso_packets;
			} else {
				tx->packets += tx_queue->old_complete_packets;
				tx->bytes += tx_queue->old_complete_bytes;
				tx->hw_gso_packets += tx_queue->old_tso_bursts;
				tx->hw_gso_wire_packets += tx_queue->old_tso_packets;
			}
			/* Include XDP TX in device-wide stats */
			tx->packets += tx_queue->complete_xdp_packets;
			tx->bytes += tx_queue->complete_xdp_bytes;
		}
	}
}

static const struct netdev_stat_ops efx_stat_ops = {
	.get_queue_stats_rx	= efx_get_queue_stats_rx,
	.get_queue_stats_tx	= efx_get_queue_stats_tx,
	.get_base_stats		= efx_get_base_stats,
};

static int efx_xdp_setup_prog(struct efx_nic *efx, struct bpf_prog *prog)
{
	struct bpf_prog *old_prog;
@@ -716,6 +824,7 @@ static int efx_register_netdev(struct efx_nic *efx)
	net_dev->watchdog_timeo = 5 * HZ;
	net_dev->irq = efx->pci_dev->irq;
	net_dev->netdev_ops = &efx_netdev_ops;
	net_dev->stat_ops = &efx_stat_ops;
	if (efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
		net_dev->priv_flags |= IFF_UNICAST_FLT;
	net_dev->ethtool_ops = &efx_ethtool_ops;
+6 −0
Original line number Diff line number Diff line
@@ -1100,6 +1100,10 @@ void efx_start_channels(struct efx_nic *efx)
			atomic_inc(&efx->active_queues);
		}

		/* reset per-queue stats */
		channel->old_n_rx_hw_drops = efx_get_queue_stat_rx_hw_drops(channel);
		channel->old_n_rx_hw_drop_overruns = channel->n_rx_nodesc_trunc;

		efx_for_each_channel_rx_queue(rx_queue, channel) {
			efx_init_rx_queue(rx_queue);
			atomic_inc(&efx->active_queues);
@@ -1209,6 +1213,8 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
						  tx_queue->pkts_compl,
						  tx_queue->bytes_compl);
		}
		tx_queue->complete_packets += tx_queue->pkts_compl;
		tx_queue->complete_bytes += tx_queue->bytes_compl;
	}

	/* Receive any packets we queued up */
+7 −0
Original line number Diff line number Diff line
@@ -43,6 +43,13 @@ struct efx_channel *efx_copy_channel(const struct efx_channel *old_channel);
void efx_start_channels(struct efx_nic *efx);
void efx_stop_channels(struct efx_nic *efx);

static inline u64 efx_get_queue_stat_rx_hw_drops(struct efx_channel *channel)
{
	return channel->n_rx_eth_crc_err + channel->n_rx_frm_trunc +
	       channel->n_rx_overlength + channel->n_rx_nodesc_trunc +
	       channel->n_rx_mport_bad;
}

void efx_init_napi_channel(struct efx_channel *channel);
void efx_init_napi(struct efx_nic *efx);
void efx_fini_napi_channel(struct efx_channel *channel);
+1 −2
Original line number Diff line number Diff line
@@ -75,7 +75,6 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
	EFX_ETHTOOL_UINT_TXQ_STAT(pio_packets),
	EFX_ETHTOOL_UINT_TXQ_STAT(cb_packets),
	EFX_ETHTOOL_ATOMIC_NIC_ERROR_STAT(rx_reset),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tobe_disc),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_ip_hdr_chksum_err),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_tcp_udp_chksum_err),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_inner_ip_hdr_chksum_err),
@@ -83,8 +82,8 @@ static const struct efx_sw_stat_desc efx_sw_stat_desc[] = {
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_outer_ip_hdr_chksum_err),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_outer_tcp_udp_chksum_err),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_eth_crc_err),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_mcast_mismatch),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_frm_trunc),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_overlength),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_events),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_merge_packets),
	EFX_ETHTOOL_UINT_CHANNEL_STAT(rx_xdp_drops),
Loading