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

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
......@@ -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;
}
/**
......
......@@ -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);
......
......@@ -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
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment