Skip to content

Commit

Permalink
net: ena: ethtool: Add new device statistics
Browse files Browse the repository at this point in the history
The new metrics provide granular visibility along multiple network
dimensions and enable troubleshooting and remediation of issues caused
by instances exceeding network performance allowances.

The new statistics can be queried using ethtool command.

Signed-off-by: Guy Tzalik <gtzalik@amazon.com>
Signed-off-by: Sameeh Jubran <sameehj@amazon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sameeh Jubran authored and David S. Miller committed Sep 10, 2020
1 parent f1852d6 commit 713865d
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 23 deletions.
37 changes: 36 additions & 1 deletion drivers/net/ethernet/amazon/ena/ena_admin_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ enum ena_admin_completion_policy_type {
enum ena_admin_get_stats_type {
ENA_ADMIN_GET_STATS_TYPE_BASIC = 0,
ENA_ADMIN_GET_STATS_TYPE_EXTENDED = 1,
/* extra HW stats for specific network interface */
ENA_ADMIN_GET_STATS_TYPE_ENI = 2,
};

enum ena_admin_get_stats_scope {
Expand Down Expand Up @@ -410,10 +412,43 @@ struct ena_admin_basic_stats {
u32 tx_drops_high;
};

/* ENI Statistics Command. */
struct ena_admin_eni_stats {
/* The number of packets shaped due to inbound aggregate BW
* allowance being exceeded
*/
u64 bw_in_allowance_exceeded;

/* The number of packets shaped due to outbound aggregate BW
* allowance being exceeded
*/
u64 bw_out_allowance_exceeded;

/* The number of packets shaped due to PPS allowance being exceeded */
u64 pps_allowance_exceeded;

/* The number of packets shaped due to connection tracking
* allowance being exceeded and leading to failure in establishment
* of new connections
*/
u64 conntrack_allowance_exceeded;

/* The number of packets shaped due to linklocal packet rate
* allowance being exceeded
*/
u64 linklocal_allowance_exceeded;
};

struct ena_admin_acq_get_stats_resp {
struct ena_admin_acq_common_desc acq_common_desc;

struct ena_admin_basic_stats basic_stats;
union {
u64 raw[7];

struct ena_admin_basic_stats basic_stats;

struct ena_admin_eni_stats eni_stats;
} u;
};

struct ena_admin_get_set_feature_common_desc {
Expand Down
19 changes: 17 additions & 2 deletions drivers/net/ethernet/amazon/ena/ena_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -2167,6 +2167,21 @@ static int ena_get_dev_stats(struct ena_com_dev *ena_dev,
return ret;
}

int ena_com_get_eni_stats(struct ena_com_dev *ena_dev,
struct ena_admin_eni_stats *stats)
{
struct ena_com_stats_ctx ctx;
int ret;

memset(&ctx, 0x0, sizeof(ctx));
ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_ENI);
if (likely(ret == 0))
memcpy(stats, &ctx.get_resp.u.eni_stats,
sizeof(ctx.get_resp.u.eni_stats));

return ret;
}

int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
struct ena_admin_basic_stats *stats)
{
Expand All @@ -2176,8 +2191,8 @@ int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
memset(&ctx, 0x0, sizeof(ctx));
ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_BASIC);
if (likely(ret == 0))
memcpy(stats, &ctx.get_resp.basic_stats,
sizeof(ctx.get_resp.basic_stats));
memcpy(stats, &ctx.get_resp.u.basic_stats,
sizeof(ctx.get_resp.u.basic_stats));

return ret;
}
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/amazon/ena/ena_com.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,15 @@ int ena_com_get_dev_attr_feat(struct ena_com_dev *ena_dev,
int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
struct ena_admin_basic_stats *stats);

/* ena_com_get_eni_stats - Get extended network interface statistics
* @ena_dev: ENA communication layer struct
* @stats: stats return value
*
* @return: 0 on Success and negative value otherwise.
*/
int ena_com_get_eni_stats(struct ena_com_dev *ena_dev,
struct ena_admin_eni_stats *stats);

/* ena_com_set_dev_mtu - Configure the device mtu.
* @ena_dev: ENA communication layer struct
* @mtu: mtu value
Expand Down
106 changes: 86 additions & 20 deletions drivers/net/ethernet/amazon/ena/ena_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ struct ena_stats {
.stat_offset = offsetof(struct ena_stats_##stat_type, stat) / sizeof(u64) \
}

#define ENA_STAT_HW_ENTRY(stat, stat_type) { \
.name = #stat, \
.stat_offset = offsetof(struct ena_admin_##stat_type, stat) / sizeof(u64) \
}

#define ENA_STAT_RX_ENTRY(stat) \
ENA_STAT_ENTRY(stat, rx)

Expand All @@ -58,6 +63,9 @@ struct ena_stats {
#define ENA_STAT_GLOBAL_ENTRY(stat) \
ENA_STAT_ENTRY(stat, dev)

#define ENA_STAT_ENI_ENTRY(stat) \
ENA_STAT_HW_ENTRY(stat, eni_stats)

static const struct ena_stats ena_stats_global_strings[] = {
ENA_STAT_GLOBAL_ENTRY(tx_timeout),
ENA_STAT_GLOBAL_ENTRY(suspend),
Expand All @@ -68,6 +76,14 @@ static const struct ena_stats ena_stats_global_strings[] = {
ENA_STAT_GLOBAL_ENTRY(admin_q_pause),
};

static const struct ena_stats ena_stats_eni_strings[] = {
ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded),
ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded),
ENA_STAT_ENI_ENTRY(pps_allowance_exceeded),
ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded),
ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded),
};

static const struct ena_stats ena_stats_tx_strings[] = {
ENA_STAT_TX_ENTRY(cnt),
ENA_STAT_TX_ENTRY(bytes),
Expand Down Expand Up @@ -110,10 +126,12 @@ static const struct ena_stats ena_stats_ena_com_strings[] = {
ENA_STAT_ENA_COM_ENTRY(no_completion),
};

#define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings)
#define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings)
#define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings)
#define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings)
#define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings)
#define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings)
#define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings)
#define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings)
#define ENA_STATS_ARRAY_ENI(adapter) \
(ARRAY_SIZE(ena_stats_eni_strings) * (adapter)->eni_stats_supported)

static void ena_safe_update_stat(u64 *src, u64 *dst,
struct u64_stats_sync *syncp)
Expand Down Expand Up @@ -176,11 +194,10 @@ static void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data)
}
}

static void ena_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats,
u64 *data)
static void ena_get_stats(struct ena_adapter *adapter,
u64 *data,
bool eni_stats_needed)
{
struct ena_adapter *adapter = netdev_priv(netdev);
const struct ena_stats *ena_stats;
u64 *ptr;
int i;
Expand All @@ -193,19 +210,50 @@ static void ena_get_ethtool_stats(struct net_device *netdev,
ena_safe_update_stat(ptr, data++, &adapter->syncp);
}

if (eni_stats_needed) {
ena_update_hw_stats(adapter);
for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) {
ena_stats = &ena_stats_eni_strings[i];

ptr = (u64 *)&adapter->eni_stats +
ena_stats->stat_offset;

ena_safe_update_stat(ptr, data++, &adapter->syncp);
}
}

ena_queue_stats(adapter, &data);
ena_dev_admin_queue_stats(adapter, &data);
}

static void ena_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats,
u64 *data)
{
struct ena_adapter *adapter = netdev_priv(netdev);

ena_get_stats(adapter, data, adapter->eni_stats_supported);
}

static int ena_get_sw_stats_count(struct ena_adapter *adapter)
{
return adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX)
+ ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM;
}

static int ena_get_hw_stats_count(struct ena_adapter *adapter)
{
return ENA_STATS_ARRAY_ENI(adapter);
}

int ena_get_sset_count(struct net_device *netdev, int sset)
{
struct ena_adapter *adapter = netdev_priv(netdev);

if (sset != ETH_SS_STATS)
return -EOPNOTSUPP;

return adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX)
+ ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM;
return ena_get_sw_stats_count(adapter) + ena_get_hw_stats_count(adapter);
}

static void ena_queue_strings(struct ena_adapter *adapter, u8 **data)
Expand Down Expand Up @@ -247,25 +295,43 @@ static void ena_com_dev_strings(u8 **data)
}
}

static void ena_get_strings(struct net_device *netdev, u32 sset, u8 *data)
static void ena_get_strings(struct ena_adapter *adapter,
u8 *data,
bool eni_stats_needed)
{
struct ena_adapter *adapter = netdev_priv(netdev);
const struct ena_stats *ena_stats;
int i;

if (sset != ETH_SS_STATS)
return;

for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) {
ena_stats = &ena_stats_global_strings[i];
memcpy(data, ena_stats->name, ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}

if (eni_stats_needed) {
for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) {
ena_stats = &ena_stats_eni_strings[i];
memcpy(data, ena_stats->name, ETH_GSTRING_LEN);
data += ETH_GSTRING_LEN;
}
}

ena_queue_strings(adapter, &data);
ena_com_dev_strings(&data);
}

static void ena_get_ethtool_strings(struct net_device *netdev,
u32 sset,
u8 *data)
{
struct ena_adapter *adapter = netdev_priv(netdev);

if (sset != ETH_SS_STATS)
return;

ena_get_strings(adapter, data, adapter->eni_stats_supported);
}

static int ena_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *link_ksettings)
{
Expand Down Expand Up @@ -845,7 +911,7 @@ static const struct ethtool_ops ena_ethtool_ops = {
.get_ringparam = ena_get_ringparam,
.set_ringparam = ena_set_ringparam,
.get_sset_count = ena_get_sset_count,
.get_strings = ena_get_strings,
.get_strings = ena_get_ethtool_strings,
.get_ethtool_stats = ena_get_ethtool_stats,
.get_rxnfc = ena_get_rxnfc,
.set_rxnfc = ena_set_rxnfc,
Expand Down Expand Up @@ -873,7 +939,7 @@ static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf)
int strings_num;
int i, rc;

strings_num = ena_get_sset_count(netdev, ETH_SS_STATS);
strings_num = ena_get_sw_stats_count(adapter);
if (strings_num <= 0) {
netif_err(adapter, drv, netdev, "Can't get stats num\n");
return;
Expand All @@ -893,13 +959,13 @@ static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf)
GFP_ATOMIC);
if (!data_buf) {
netif_err(adapter, drv, netdev,
"failed to allocate data buf\n");
"Failed to allocate data buf\n");
devm_kfree(&adapter->pdev->dev, strings_buf);
return;
}

ena_get_strings(netdev, ETH_SS_STATS, strings_buf);
ena_get_ethtool_stats(netdev, NULL, data_buf);
ena_get_strings(adapter, strings_buf, false);
ena_get_stats(adapter, data_buf, false);

/* If there is a buffer, dump stats, otherwise print them to dmesg */
if (buf)
Expand Down
18 changes: 18 additions & 0 deletions drivers/net/ethernet/amazon/ena/ena_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3178,6 +3178,19 @@ static void ena_config_debug_area(struct ena_adapter *adapter)
ena_com_delete_debug_area(adapter->ena_dev);
}

int ena_update_hw_stats(struct ena_adapter *adapter)
{
int rc = 0;

rc = ena_com_get_eni_stats(adapter->ena_dev, &adapter->eni_stats);
if (rc) {
dev_info_once(&adapter->pdev->dev, "Failed to get ENI stats\n");
return rc;
}

return 0;
}

static void ena_get_stats64(struct net_device *netdev,
struct rtnl_link_stats64 *stats)
{
Expand Down Expand Up @@ -4296,6 +4309,11 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

ena_config_debug_area(adapter);

if (!ena_update_hw_stats(adapter))
adapter->eni_stats_supported = true;
else
adapter->eni_stats_supported = false;

memcpy(adapter->netdev->perm_addr, adapter->mac_addr, netdev->addr_len);

netif_carrier_off(netdev);
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/amazon/ena/ena_netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ struct ena_adapter {

struct u64_stats_sync syncp;
struct ena_stats_dev dev_stats;
struct ena_admin_eni_stats eni_stats;
bool eni_stats_supported;

/* last queue index that was checked for uncompleted tx packets */
u32 last_monitored_tx_qid;
Expand All @@ -422,6 +424,8 @@ void ena_dump_stats_to_dmesg(struct ena_adapter *adapter);

void ena_dump_stats_to_buf(struct ena_adapter *adapter, u8 *buf);

int ena_update_hw_stats(struct ena_adapter *adapter);

int ena_update_queue_sizes(struct ena_adapter *adapter,
u32 new_tx_size,
u32 new_rx_size);
Expand Down

0 comments on commit 713865d

Please sign in to comment.