Skip to content

Commit

Permalink
ice: count representor stats
Browse files Browse the repository at this point in the history
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 eadfa4c ("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: Marcin Szycik <marcin.szycik@linux.intel.com>
Signed-off-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Tested-by: Sujai Buvaneswaran <sujai.buvaneswaran@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
  • Loading branch information
Michal Swiatkowski authored and Tony Nguyen committed Mar 25, 2024
1 parent 44ba608 commit 4498159
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 30 deletions.
7 changes: 6 additions & 1 deletion drivers/net/ethernet/intel/ice/ice_eswitch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down
103 changes: 75 additions & 28 deletions drivers/net/ethernet/intel/ice/ice_repr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
16 changes: 15 additions & 1 deletion drivers/net/ethernet/intel/ice/ice_repr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
};
Expand All @@ -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 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/ice/ice_txrx_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 4498159

Please sign in to comment.