From f1852d64ba0af0e6916e81f16349dbf75f5dd9b0 Mon Sep 17 00:00:00 2001 From: Sameeh Jubran Date: Thu, 10 Sep 2020 13:07:10 +0000 Subject: [PATCH 1/4] net: ena: ethtool: convert stat_offset to 64 bit resolution The type of all stat fields is u64, therefore when iterating over stat fields in a stats struct, it makes sense to use an offset in 64 bit resolution. Doing so allows us to drop some of the casting that is currently used when referencing stats. Signed-off-by: Sameeh Jubran Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_ethtool.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 430275bc0d04..291d169dde48 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -41,12 +41,12 @@ struct ena_stats { #define ENA_STAT_ENA_COM_ENTRY(stat) { \ .name = #stat, \ - .stat_offset = offsetof(struct ena_com_stats_admin, stat) \ + .stat_offset = offsetof(struct ena_com_stats_admin, stat) / sizeof(u64) \ } #define ENA_STAT_ENTRY(stat, stat_type) { \ .name = #stat, \ - .stat_offset = offsetof(struct ena_stats_##stat_type, stat) \ + .stat_offset = offsetof(struct ena_stats_##stat_type, stat) / sizeof(u64) \ } #define ENA_STAT_RX_ENTRY(stat) \ @@ -141,8 +141,7 @@ static void ena_queue_stats(struct ena_adapter *adapter, u64 **data) for (j = 0; j < ENA_STATS_ARRAY_TX; j++) { ena_stats = &ena_stats_tx_strings[j]; - ptr = (u64 *)((uintptr_t)&ring->tx_stats + - (uintptr_t)ena_stats->stat_offset); + ptr = (u64 *)&ring->tx_stats + ena_stats->stat_offset; ena_safe_update_stat(ptr, (*data)++, &ring->syncp); } @@ -153,8 +152,8 @@ static void ena_queue_stats(struct ena_adapter *adapter, u64 **data) for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { ena_stats = &ena_stats_rx_strings[j]; - ptr = (u64 *)((uintptr_t)&ring->rx_stats + - (uintptr_t)ena_stats->stat_offset); + ptr = (u64 *)&ring->rx_stats + + ena_stats->stat_offset; ena_safe_update_stat(ptr, (*data)++, &ring->syncp); } @@ -170,8 +169,8 @@ static void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data) for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) { ena_stats = &ena_stats_ena_com_strings[i]; - ptr = (u64 *)((uintptr_t)&adapter->ena_dev->admin_queue.stats + - (uintptr_t)ena_stats->stat_offset); + ptr = (u64 *)&adapter->ena_dev->admin_queue.stats + + ena_stats->stat_offset; *(*data)++ = *ptr; } @@ -189,8 +188,7 @@ static void ena_get_ethtool_stats(struct net_device *netdev, for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) { ena_stats = &ena_stats_global_strings[i]; - ptr = (u64 *)((uintptr_t)&adapter->dev_stats + - (uintptr_t)ena_stats->stat_offset); + ptr = (u64 *)&adapter->dev_stats + ena_stats->stat_offset; ena_safe_update_stat(ptr, data++, &adapter->syncp); } From 713865da3c623034a46b382b5d544048edcce827 Mon Sep 17 00:00:00 2001 From: Sameeh Jubran Date: Thu, 10 Sep 2020 13:07:11 +0000 Subject: [PATCH 2/4] net: ena: ethtool: Add new device statistics 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 Signed-off-by: Sameeh Jubran Signed-off-by: David S. Miller --- .../net/ethernet/amazon/ena/ena_admin_defs.h | 37 +++++- drivers/net/ethernet/amazon/ena/ena_com.c | 19 +++- drivers/net/ethernet/amazon/ena/ena_com.h | 9 ++ drivers/net/ethernet/amazon/ena/ena_ethtool.c | 106 ++++++++++++++---- drivers/net/ethernet/amazon/ena/ena_netdev.c | 18 +++ drivers/net/ethernet/amazon/ena/ena_netdev.h | 4 + 6 files changed, 170 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h index b818a169c193..86869baa7b8e 100644 --- a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h +++ b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h @@ -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 { @@ -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 { diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 435bf05a853c..452e66b39a17 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -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) { @@ -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; } diff --git a/drivers/net/ethernet/amazon/ena/ena_com.h b/drivers/net/ethernet/amazon/ena/ena_com.h index 4287d47b2b0b..e4aafeda0cae 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.h +++ b/drivers/net/ethernet/amazon/ena/ena_com.h @@ -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 diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 291d169dde48..07e9f3df0d61 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -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) @@ -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), @@ -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), @@ -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) @@ -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; @@ -193,10 +210,42 @@ 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); @@ -204,8 +253,7 @@ int ena_get_sset_count(struct net_device *netdev, int sset) 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) @@ -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) { @@ -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, @@ -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; @@ -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) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index a3a8edf9a734..08474db755aa 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -3178,6 +3178,19 @@ err: 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) { @@ -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); diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 0c8504006247..4c95a4d93e5c 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -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; @@ -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); From 0201bda10679267f98b776b4af73e081d55cb73e Mon Sep 17 00:00:00 2001 From: Sameeh Jubran Date: Thu, 10 Sep 2020 13:07:12 +0000 Subject: [PATCH 3/4] net: ena: ethtool: add stats printing to XDP queues Added statistics for TX queues that are used for XDP TX. The statistics are the same as the ones printed for regular non-XDP TX queues. The XDP queue statistics can be queried using `ethtool -S ` Signed-off-by: Shay Agroskin Signed-off-by: Sameeh Jubran Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_ethtool.c | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 07e9f3df0d61..137a36a6bd5f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -152,7 +152,7 @@ static void ena_queue_stats(struct ena_adapter *adapter, u64 **data) u64 *ptr; int i, j; - for (i = 0; i < adapter->num_io_queues; i++) { + for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) { /* Tx stats */ ring = &adapter->tx_ring[i]; @@ -163,17 +163,19 @@ static void ena_queue_stats(struct ena_adapter *adapter, u64 **data) ena_safe_update_stat(ptr, (*data)++, &ring->syncp); } + /* XDP TX queues don't have a RX queue counterpart */ + if (!ENA_IS_XDP_INDEX(adapter, i)) { + /* Rx stats */ + ring = &adapter->rx_ring[i]; - /* Rx stats */ - ring = &adapter->rx_ring[i]; + for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { + ena_stats = &ena_stats_rx_strings[j]; - for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { - ena_stats = &ena_stats_rx_strings[j]; + ptr = (u64 *)&ring->rx_stats + + ena_stats->stat_offset; - ptr = (u64 *)&ring->rx_stats + - ena_stats->stat_offset; - - ena_safe_update_stat(ptr, (*data)++, &ring->syncp); + ena_safe_update_stat(ptr, (*data)++, &ring->syncp); + } } } } @@ -238,6 +240,7 @@ static void ena_get_ethtool_stats(struct net_device *netdev, static int ena_get_sw_stats_count(struct ena_adapter *adapter) { return adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX) + + adapter->xdp_num_queues * ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM; } @@ -259,24 +262,32 @@ int ena_get_sset_count(struct net_device *netdev, int sset) static void ena_queue_strings(struct ena_adapter *adapter, u8 **data) { const struct ena_stats *ena_stats; + bool is_xdp; int i, j; - for (i = 0; i < adapter->num_io_queues; i++) { + for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) { + is_xdp = ENA_IS_XDP_INDEX(adapter, i); /* Tx stats */ for (j = 0; j < ENA_STATS_ARRAY_TX; j++) { ena_stats = &ena_stats_tx_strings[j]; snprintf(*data, ETH_GSTRING_LEN, - "queue_%u_tx_%s", i, ena_stats->name); + "queue_%u_%s_%s", i, + is_xdp ? "xdp_tx" : "tx", ena_stats->name); (*data) += ETH_GSTRING_LEN; } - /* Rx stats */ - for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { - ena_stats = &ena_stats_rx_strings[j]; - snprintf(*data, ETH_GSTRING_LEN, - "queue_%u_rx_%s", i, ena_stats->name); - (*data) += ETH_GSTRING_LEN; + if (!is_xdp) { + /* RX stats, in XDP there isn't a RX queue + * counterpart + */ + for (j = 0; j < ENA_STATS_ARRAY_RX; j++) { + ena_stats = &ena_stats_rx_strings[j]; + + snprintf(*data, ETH_GSTRING_LEN, + "queue_%u_rx_%s", i, ena_stats->name); + (*data) += ETH_GSTRING_LEN; + } } } } From 4cd28b214d561e9882923919bfd4a73afb980ec9 Mon Sep 17 00:00:00 2001 From: Sameeh Jubran Date: Thu, 10 Sep 2020 13:07:13 +0000 Subject: [PATCH 4/4] net: ena: xdp: add queue counters for xdp actions When using XDP every ingress packet is passed to an eBPF (xdp) program which returns an action for this packet. This patch adds counters for the number of times each such action was received. It also counts all the invalid actions received from the eBPF program. Signed-off-by: Shay Agroskin Signed-off-by: Sameeh Jubran Signed-off-by: David S. Miller --- drivers/net/ethernet/amazon/ena/ena_ethtool.c | 5 +++++ drivers/net/ethernet/amazon/ena/ena_netdev.c | 21 ++++++++++++++++--- drivers/net/ethernet/amazon/ena/ena_netdev.h | 5 +++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index 137a36a6bd5f..1e6457dd662a 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -116,6 +116,11 @@ static const struct ena_stats ena_stats_rx_strings[] = { ENA_STAT_RX_ENTRY(bad_req_id), ENA_STAT_RX_ENTRY(empty_rx_ring), ENA_STAT_RX_ENTRY(csum_unchecked), + ENA_STAT_RX_ENTRY(xdp_aborted), + ENA_STAT_RX_ENTRY(xdp_drop), + ENA_STAT_RX_ENTRY(xdp_pass), + ENA_STAT_RX_ENTRY(xdp_tx), + ENA_STAT_RX_ENTRY(xdp_invalid), }; static const struct ena_stats ena_stats_ena_com_strings[] = { diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 08474db755aa..b52e8d0c7951 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -365,6 +365,7 @@ static int ena_xdp_execute(struct ena_ring *rx_ring, { struct bpf_prog *xdp_prog; u32 verdict = XDP_PASS; + u64 *xdp_stat; rcu_read_lock(); xdp_prog = READ_ONCE(rx_ring->xdp_bpf_prog); @@ -374,17 +375,31 @@ static int ena_xdp_execute(struct ena_ring *rx_ring, verdict = bpf_prog_run_xdp(xdp_prog, xdp); - if (verdict == XDP_TX) + if (verdict == XDP_TX) { ena_xdp_xmit_buff(rx_ring->netdev, xdp, rx_ring->qid + rx_ring->adapter->num_io_queues, rx_info); - else if (unlikely(verdict == XDP_ABORTED)) + + xdp_stat = &rx_ring->rx_stats.xdp_tx; + } else if (unlikely(verdict == XDP_ABORTED)) { trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict); - else if (unlikely(verdict > XDP_TX)) + xdp_stat = &rx_ring->rx_stats.xdp_aborted; + } else if (unlikely(verdict == XDP_DROP)) { + xdp_stat = &rx_ring->rx_stats.xdp_drop; + } else if (unlikely(verdict == XDP_PASS)) { + xdp_stat = &rx_ring->rx_stats.xdp_pass; + } else { bpf_warn_invalid_xdp_action(verdict); + xdp_stat = &rx_ring->rx_stats.xdp_invalid; + } + + u64_stats_update_begin(&rx_ring->syncp); + (*xdp_stat)++; + u64_stats_update_end(&rx_ring->syncp); out: rcu_read_unlock(); + return verdict; } diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 4c95a4d93e5c..52abb6a4f87e 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -261,6 +261,11 @@ struct ena_stats_rx { u64 bad_req_id; u64 empty_rx_ring; u64 csum_unchecked; + u64 xdp_aborted; + u64 xdp_drop; + u64 xdp_pass; + u64 xdp_tx; + u64 xdp_invalid; }; struct ena_ring {