mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-13 22:25:03 +00:00
nfp: add ethtool statistics for representors
Representors may be associated with both VFs or more importantly with physical ports. Allow vNIC and MAC statistics to be read with ethtool -S on representors. In case of vNICs we reuse the vNIC statistic helper, we just need to swap RX and TX to give statistics the "switch perspective." Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ef0ec676a7
commit
899a37ade8
2 changed files with 71 additions and 4 deletions
|
@ -180,6 +180,7 @@ static const struct nfp_et_stat nfp_mac_et_stats[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NN_ET_GLOBAL_STATS_LEN ARRAY_SIZE(nfp_net_et_stats)
|
#define NN_ET_GLOBAL_STATS_LEN ARRAY_SIZE(nfp_net_et_stats)
|
||||||
|
#define NN_ET_SWITCH_STATS_LEN 9
|
||||||
#define NN_ET_RVEC_GATHER_STATS 7
|
#define NN_ET_RVEC_GATHER_STATS 7
|
||||||
|
|
||||||
static void nfp_net_get_nspinfo(struct nfp_app *app, char *version)
|
static void nfp_net_get_nspinfo(struct nfp_app *app, char *version)
|
||||||
|
@ -497,11 +498,24 @@ nfp_vnic_get_hw_stats_count(unsigned int rx_rings, unsigned int tx_rings)
|
||||||
|
|
||||||
static u8 *
|
static u8 *
|
||||||
nfp_vnic_get_hw_stats_strings(u8 *data, unsigned int rx_rings,
|
nfp_vnic_get_hw_stats_strings(u8 *data, unsigned int rx_rings,
|
||||||
unsigned int tx_rings)
|
unsigned int tx_rings, bool repr)
|
||||||
{
|
{
|
||||||
int i;
|
int swap_off, i;
|
||||||
|
|
||||||
for (i = 0; i < NN_ET_GLOBAL_STATS_LEN; i++)
|
BUILD_BUG_ON(NN_ET_GLOBAL_STATS_LEN < NN_ET_SWITCH_STATS_LEN * 2);
|
||||||
|
/* If repr is true first add SWITCH_STATS_LEN and then subtract it
|
||||||
|
* effectively swapping the RX and TX statistics (giving us the RX
|
||||||
|
* and TX from perspective of the switch).
|
||||||
|
*/
|
||||||
|
swap_off = repr * NN_ET_SWITCH_STATS_LEN;
|
||||||
|
|
||||||
|
for (i = 0; i < NN_ET_SWITCH_STATS_LEN; i++)
|
||||||
|
data = nfp_pr_et(data, nfp_net_et_stats[i + swap_off].name);
|
||||||
|
|
||||||
|
for (i = NN_ET_SWITCH_STATS_LEN; i < NN_ET_SWITCH_STATS_LEN * 2; i++)
|
||||||
|
data = nfp_pr_et(data, nfp_net_et_stats[i - swap_off].name);
|
||||||
|
|
||||||
|
for (i = NN_ET_SWITCH_STATS_LEN * 2; i < NN_ET_GLOBAL_STATS_LEN; i++)
|
||||||
data = nfp_pr_et(data, nfp_net_et_stats[i].name);
|
data = nfp_pr_et(data, nfp_net_et_stats[i].name);
|
||||||
|
|
||||||
for (i = 0; i < tx_rings; i++) {
|
for (i = 0; i < tx_rings; i++) {
|
||||||
|
@ -589,7 +603,8 @@ static void nfp_net_get_strings(struct net_device *netdev,
|
||||||
case ETH_SS_STATS:
|
case ETH_SS_STATS:
|
||||||
data = nfp_vnic_get_sw_stats_strings(netdev, data);
|
data = nfp_vnic_get_sw_stats_strings(netdev, data);
|
||||||
data = nfp_vnic_get_hw_stats_strings(data, nn->dp.num_rx_rings,
|
data = nfp_vnic_get_hw_stats_strings(data, nn->dp.num_rx_rings,
|
||||||
nn->dp.num_tx_rings);
|
nn->dp.num_tx_rings,
|
||||||
|
false);
|
||||||
data = nfp_mac_get_stats_strings(netdev, data);
|
data = nfp_mac_get_stats_strings(netdev, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -622,6 +637,50 @@ static int nfp_net_get_sset_count(struct net_device *netdev, int sset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nfp_port_get_strings(struct net_device *netdev,
|
||||||
|
u32 stringset, u8 *data)
|
||||||
|
{
|
||||||
|
struct nfp_port *port = nfp_port_from_netdev(netdev);
|
||||||
|
|
||||||
|
switch (stringset) {
|
||||||
|
case ETH_SS_STATS:
|
||||||
|
if (nfp_port_is_vnic(port))
|
||||||
|
data = nfp_vnic_get_hw_stats_strings(data, 0, 0, true);
|
||||||
|
else
|
||||||
|
data = nfp_mac_get_stats_strings(netdev, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nfp_port_get_stats(struct net_device *netdev, struct ethtool_stats *stats,
|
||||||
|
u64 *data)
|
||||||
|
{
|
||||||
|
struct nfp_port *port = nfp_port_from_netdev(netdev);
|
||||||
|
|
||||||
|
if (nfp_port_is_vnic(port))
|
||||||
|
data = nfp_vnic_get_hw_stats(data, port->vnic, 0, 0);
|
||||||
|
else
|
||||||
|
data = nfp_mac_get_stats(netdev, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nfp_port_get_sset_count(struct net_device *netdev, int sset)
|
||||||
|
{
|
||||||
|
struct nfp_port *port = nfp_port_from_netdev(netdev);
|
||||||
|
unsigned int count;
|
||||||
|
|
||||||
|
switch (sset) {
|
||||||
|
case ETH_SS_STATS:
|
||||||
|
if (nfp_port_is_vnic(port))
|
||||||
|
count = nfp_vnic_get_hw_stats_count(0, 0);
|
||||||
|
else
|
||||||
|
count = nfp_mac_get_stats_count(netdev);
|
||||||
|
return count;
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* RX network flow classification (RSS, filters, etc)
|
/* RX network flow classification (RSS, filters, etc)
|
||||||
*/
|
*/
|
||||||
static u32 ethtool_flow_to_nfp_flag(u32 flow_type)
|
static u32 ethtool_flow_to_nfp_flag(u32 flow_type)
|
||||||
|
@ -1085,6 +1144,9 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
|
||||||
const struct ethtool_ops nfp_port_ethtool_ops = {
|
const struct ethtool_ops nfp_port_ethtool_ops = {
|
||||||
.get_drvinfo = nfp_app_get_drvinfo,
|
.get_drvinfo = nfp_app_get_drvinfo,
|
||||||
.get_link = ethtool_op_get_link,
|
.get_link = ethtool_op_get_link,
|
||||||
|
.get_strings = nfp_port_get_strings,
|
||||||
|
.get_ethtool_stats = nfp_port_get_stats,
|
||||||
|
.get_sset_count = nfp_port_get_sset_count,
|
||||||
.set_dump = nfp_app_set_dump,
|
.set_dump = nfp_app_set_dump,
|
||||||
.get_dump_flag = nfp_app_get_dump_flag,
|
.get_dump_flag = nfp_app_get_dump_flag,
|
||||||
.get_dump_data = nfp_app_get_dump_data,
|
.get_dump_data = nfp_app_get_dump_data,
|
||||||
|
|
|
@ -116,6 +116,11 @@ extern const struct switchdev_ops nfp_port_switchdev_ops;
|
||||||
int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
|
int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
|
||||||
void *type_data);
|
void *type_data);
|
||||||
|
|
||||||
|
static inline bool nfp_port_is_vnic(const struct nfp_port *port)
|
||||||
|
{
|
||||||
|
return port->type == NFP_PORT_PF_PORT || port->type == NFP_PORT_VF_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
|
struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
|
||||||
struct nfp_port *
|
struct nfp_port *
|
||||||
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id);
|
nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id);
|
||||||
|
|
Loading…
Reference in a new issue