Commit 4498159a authored by Michal Swiatkowski's avatar Michal Swiatkowski Committed by Tony Nguyen
Browse files

ice: count representor stats



Removing control plane VSI result in no information about slow-path
statistic. In current solution statistics need to be counted in driver.

Patch is based on similar implementation done by Simon Horman in nfp:
commit eadfa4c3 ("nfp: add stats and xmit helpers for representors")

Add const modifier to netdev parameter in ice_netdev_to_repr(). It isn't
(and shouldn't be) modified in the function.

Reviewed-by: default avatarMarcin Szycik <marcin.szycik@linux.intel.com>
Signed-off-by: default avatarMichal Swiatkowski <michal.swiatkowski@linux.intel.com>
Tested-by: default avatarSujai Buvaneswaran <sujai.buvaneswaran@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 44ba608d
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -192,13 +192,18 @@ netdev_tx_t
ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
	struct ice_repr *repr = ice_netdev_to_repr(netdev);
	unsigned int len = skb->len;
	int ret;

	skb_dst_drop(skb);
	dst_hold((struct dst_entry *)repr->dst);
	skb_dst_set(skb, (struct dst_entry *)repr->dst);
	skb->dev = repr->dst->u.port_info.lower_dev;

	return dev_queue_xmit(skb);
	ret = dev_queue_xmit(skb);
	ice_repr_inc_tx_stats(repr, len, ret);

	return ret;
}

/**
+75 −28
Original line number Diff line number Diff line
@@ -41,6 +41,47 @@ ice_repr_get_phys_port_name(struct net_device *netdev, char *buf, size_t len)
	return 0;
}

/**
 * ice_repr_inc_tx_stats - increment Tx statistic by one packet
 * @repr: repr to increment stats on
 * @len: length of the packet
 * @xmit_status: value returned by xmit function
 */
void ice_repr_inc_tx_stats(struct ice_repr *repr, unsigned int len,
			   int xmit_status)
{
	struct ice_repr_pcpu_stats *stats;

	if (unlikely(xmit_status != NET_XMIT_SUCCESS &&
		     xmit_status != NET_XMIT_CN)) {
		this_cpu_inc(repr->stats->tx_drops);
		return;
	}

	stats = this_cpu_ptr(repr->stats);
	u64_stats_update_begin(&stats->syncp);
	stats->tx_packets++;
	stats->tx_bytes += len;
	u64_stats_update_end(&stats->syncp);
}

/**
 * ice_repr_inc_rx_stats - increment Rx statistic by one packet
 * @netdev: repr netdev to increment stats on
 * @len: length of the packet
 */
void ice_repr_inc_rx_stats(struct net_device *netdev, unsigned int len)
{
	struct ice_repr *repr = ice_netdev_to_repr(netdev);
	struct ice_repr_pcpu_stats *stats;

	stats = this_cpu_ptr(repr->stats);
	u64_stats_update_begin(&stats->syncp);
	stats->rx_packets++;
	stats->rx_bytes += len;
	u64_stats_update_end(&stats->syncp);
}

/**
 * ice_repr_get_stats64 - get VF stats for VFPR use
 * @netdev: pointer to port representor netdev
@@ -76,7 +117,7 @@ ice_repr_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
 * ice_netdev_to_repr - Get port representor for given netdevice
 * @netdev: pointer to port representor netdev
 */
struct ice_repr *ice_netdev_to_repr(struct net_device *netdev)
struct ice_repr *ice_netdev_to_repr(const struct net_device *netdev)
{
	struct ice_netdev_priv *np = netdev_priv(netdev);

@@ -139,38 +180,35 @@ static int ice_repr_stop(struct net_device *netdev)
 * ice_repr_sp_stats64 - get slow path stats for port representor
 * @dev: network interface device structure
 * @stats: netlink stats structure
 *
 * RX/TX stats are being swapped here to be consistent with VF stats. In slow
 * path, port representor receives data when the corresponding VF is sending it
 * (and vice versa), TX and RX bytes/packets are effectively swapped on port
 * representor.
 */
static int
ice_repr_sp_stats64(const struct net_device *dev,
		    struct rtnl_link_stats64 *stats)
{
	struct ice_netdev_priv *np = netdev_priv(dev);
	int vf_id = np->repr->vf->vf_id;
	struct ice_tx_ring *tx_ring;
	struct ice_rx_ring *rx_ring;
	u64 pkts, bytes;

	tx_ring = np->vsi->tx_rings[vf_id];
	ice_fetch_u64_stats_per_ring(&tx_ring->ring_stats->syncp,
				     tx_ring->ring_stats->stats,
				     &pkts, &bytes);
	stats->rx_packets = pkts;
	stats->rx_bytes = bytes;

	rx_ring = np->vsi->rx_rings[vf_id];
	ice_fetch_u64_stats_per_ring(&rx_ring->ring_stats->syncp,
				     rx_ring->ring_stats->stats,
				     &pkts, &bytes);
	stats->tx_packets = pkts;
	stats->tx_bytes = bytes;
	stats->tx_dropped = rx_ring->ring_stats->rx_stats.alloc_page_failed +
			    rx_ring->ring_stats->rx_stats.alloc_buf_failed;

	struct ice_repr *repr = ice_netdev_to_repr(dev);
	int i;

	for_each_possible_cpu(i) {
		u64 tbytes, tpkts, tdrops, rbytes, rpkts;
		struct ice_repr_pcpu_stats *repr_stats;
		unsigned int start;

		repr_stats = per_cpu_ptr(repr->stats, i);
		do {
			start = u64_stats_fetch_begin(&repr_stats->syncp);
			tbytes = repr_stats->tx_bytes;
			tpkts = repr_stats->tx_packets;
			tdrops = repr_stats->tx_drops;
			rbytes = repr_stats->rx_bytes;
			rpkts = repr_stats->rx_packets;
		} while (u64_stats_fetch_retry(&repr_stats->syncp, start));

		stats->tx_bytes += tbytes;
		stats->tx_packets += tpkts;
		stats->tx_dropped += tdrops;
		stats->rx_bytes += rbytes;
		stats->rx_packets += rpkts;
	}
	return 0;
}

@@ -291,6 +329,7 @@ static void ice_repr_remove_node(struct devlink_port *devlink_port)
 */
static void ice_repr_rem(struct ice_repr *repr)
{
	free_percpu(repr->stats);
	free_netdev(repr->netdev);
	kfree(repr);
}
@@ -344,6 +383,12 @@ ice_repr_add(struct ice_pf *pf, struct ice_vsi *src_vsi, const u8 *parent_mac)
		goto err_alloc;
	}

	repr->stats = netdev_alloc_pcpu_stats(struct ice_repr_pcpu_stats);
	if (!repr->stats) {
		err = -ENOMEM;
		goto err_stats;
	}

	repr->src_vsi = src_vsi;
	repr->id = src_vsi->vsi_num;
	np = netdev_priv(repr->netdev);
@@ -353,6 +398,8 @@ ice_repr_add(struct ice_pf *pf, struct ice_vsi *src_vsi, const u8 *parent_mac)

	return repr;

err_stats:
	free_netdev(repr->netdev);
err_alloc:
	kfree(repr);
	return ERR_PTR(err);
+15 −1
Original line number Diff line number Diff line
@@ -6,12 +6,22 @@

#include <net/dst_metadata.h>

struct ice_repr_pcpu_stats {
	struct u64_stats_sync syncp;
	u64 rx_packets;
	u64 rx_bytes;
	u64 tx_packets;
	u64 tx_bytes;
	u64 tx_drops;
};

struct ice_repr {
	struct ice_vsi *src_vsi;
	struct ice_vf *vf;
	struct net_device *netdev;
	struct metadata_dst *dst;
	struct ice_esw_br_port *br_port;
	struct ice_repr_pcpu_stats __percpu *stats;
	u32 id;
	u8 parent_mac[ETH_ALEN];
};
@@ -22,8 +32,12 @@ void ice_repr_rem_vf(struct ice_repr *repr);
void ice_repr_start_tx_queues(struct ice_repr *repr);
void ice_repr_stop_tx_queues(struct ice_repr *repr);

struct ice_repr *ice_netdev_to_repr(struct net_device *netdev);
struct ice_repr *ice_netdev_to_repr(const struct net_device *netdev);
bool ice_is_port_repr_netdev(const struct net_device *netdev);

struct ice_repr *ice_repr_get_by_vsi(struct ice_vsi *vsi);

void ice_repr_inc_tx_stats(struct ice_repr *repr, unsigned int len,
			   int xmit_status);
void ice_repr_inc_rx_stats(struct net_device *netdev, unsigned int len);
#endif
+2 −0
Original line number Diff line number Diff line
@@ -240,6 +240,8 @@ ice_process_skb_fields(struct ice_rx_ring *rx_ring,
		struct net_device *netdev = ice_eswitch_get_target(rx_ring,
								   rx_desc);

		if (ice_is_port_repr_netdev(netdev))
			ice_repr_inc_rx_stats(netdev, skb->len);
		skb->protocol = eth_type_trans(skb, netdev);
	} else {
		skb->protocol = eth_type_trans(skb, rx_ring->netdev);