ena: Support customer metric with sysctl

This commit adds sysctl support for customer metrics.
Different customer metrics can be found in the following sysctl node:
sysctl dev.ena.<device index>.customer_metrics

Approved by: cperciva (mentor)
MFC after: 2 weeks
Sponsored by: Amazon, Inc.
This commit is contained in:
Osama Abboud 2023-09-12 10:17:03 +00:00 committed by Arthur Kiyanovski
parent 5b925280d9
commit f97993ad7b
4 changed files with 135 additions and 3 deletions

View file

@ -166,6 +166,7 @@ static int ena_enable_msix_and_set_admin_interrupts(struct ena_adapter *);
static void ena_update_on_link_change(void *, struct ena_admin_aenq_entry *);
static void unimplemented_aenq_handler(void *, struct ena_admin_aenq_entry *);
static int ena_copy_eni_metrics(struct ena_adapter *);
static int ena_copy_customer_metrics(struct ena_adapter *);
static void ena_timer_service(void *);
static char ena_version[] = ENA_DEVICE_NAME ENA_DRV_MODULE_NAME
@ -3305,6 +3306,25 @@ ena_copy_eni_metrics(struct ena_adapter *adapter)
return (rc);
}
static int
ena_copy_customer_metrics(struct ena_adapter *adapter)
{
struct ena_com_dev *dev;
u32 supported_metrics_count;
int rc, len;
dev = adapter->ena_dev;
supported_metrics_count = ena_com_get_customer_metric_count(dev);
len = supported_metrics_count * sizeof(u64);
/* Fill the data buffer */
rc = ena_com_get_customer_metrics(adapter->ena_dev,
(char *)(adapter->customer_metrics_array), len);
return (rc);
}
static void
ena_timer_service(void *data)
{
@ -3542,7 +3562,12 @@ ena_metrics_task(void *arg, int pending)
struct ena_adapter *adapter = (struct ena_adapter *)arg;
ENA_LOCK_LOCK();
(void)ena_copy_eni_metrics(adapter);
if (ena_com_get_cap(adapter->ena_dev, ENA_ADMIN_CUSTOMER_METRICS))
(void)ena_copy_customer_metrics(adapter);
else if (ena_com_get_cap(adapter->ena_dev, ENA_ADMIN_ENI_STATS))
(void)ena_copy_eni_metrics(adapter);
ENA_LOCK_UNLOCK();
}
@ -3756,6 +3781,18 @@ ena_attach(device_t pdev)
/* initialize rings basic information */
ena_init_io_rings(adapter);
rc = ena_com_allocate_customer_metrics_buffer(ena_dev);
if (rc) {
ena_log(pdev, ERR, "Failed to allocate customer metrics buffer.\n");
goto err_msix_free;
}
rc = ena_sysctl_allocate_customer_metrics_buffer(adapter);
if (unlikely(rc)){
ena_log(pdev, ERR, "Failed to allocate sysctl customer metrics buffer.\n");
goto err_metrics_buffer_destroy;
}
/* Initialize statistics */
ena_alloc_counters((counter_u64_t *)&adapter->dev_stats,
sizeof(struct ena_stats_dev));
@ -3767,7 +3804,7 @@ ena_attach(device_t pdev)
rc = ena_setup_ifnet(pdev, adapter, &get_feat_ctx);
if (unlikely(rc != 0)) {
ena_log(pdev, ERR, "Error with network interface setup\n");
goto err_msix_free;
goto err_customer_metrics_alloc;
}
/* Initialize reset task queue */
@ -3805,6 +3842,10 @@ ena_attach(device_t pdev)
err_detach:
ether_ifdetach(adapter->ifp);
#endif /* DEV_NETMAP */
err_customer_metrics_alloc:
free(adapter->customer_metrics_array, M_DEVBUF);
err_metrics_buffer_destroy:
ena_com_delete_customer_metrics_buffer(ena_dev);
err_msix_free:
ena_free_stats(adapter);
ena_com_dev_reset(adapter->ena_dev, ENA_REGS_RESET_INIT_ERR);
@ -3903,6 +3944,10 @@ ena_detach(device_t pdev)
ena_com_delete_host_info(ena_dev);
free(adapter->customer_metrics_array, M_DEVBUF);
ena_com_delete_customer_metrics_buffer(ena_dev);
if_free(adapter->ifp);
free(ena_dev->bus, M_DEVBUF);

View file

@ -487,6 +487,7 @@ struct ena_adapter {
struct ena_stats_dev dev_stats;
struct ena_hw_stats hw_stats;
struct ena_admin_eni_stats eni_metrics;
uint64_t *customer_metrics_array;
enum ena_regs_reset_reason_types reset_reason;
};

View file

@ -37,6 +37,7 @@
static void ena_sysctl_add_wd(struct ena_adapter *);
static void ena_sysctl_add_stats(struct ena_adapter *);
static void ena_sysctl_add_eni_metrics(struct ena_adapter *);
static void ena_sysctl_add_customer_metrics(struct ena_adapter *);
static void ena_sysctl_add_tuneables(struct ena_adapter *);
static void ena_sysctl_add_irq_affinity(struct ena_adapter *);
/* Kernel option RSS prevents manipulation of key hash and indirection table. */
@ -58,6 +59,39 @@ static int ena_sysctl_rss_indir_table(SYSCTL_HANDLER_ARGS);
#define ENA_METRICS_MAX_SAMPLE_INTERVAL 3600
#define ENA_HASH_KEY_MSG_SIZE (ENA_HASH_KEY_SIZE * 2 + 1)
#define SYSCTL_GSTRING_LEN 64
#define ENA_METRIC_ENI_ENTRY(stat, desc) { \
.name = #stat, \
.description = #desc, \
}
struct ena_hw_metrics {
char name[SYSCTL_GSTRING_LEN];
char description[SYSCTL_GSTRING_LEN];
};
static const struct ena_hw_metrics ena_hw_stats_strings[] = {
ENA_METRIC_ENI_ENTRY(
bw_in_allowance_exceeded, Inbound BW allowance exceeded),
ENA_METRIC_ENI_ENTRY(
bw_out_allowance_exceeded, Outbound BW allowance exceeded),
ENA_METRIC_ENI_ENTRY(
pps_allowance_exceeded, PPS allowance exceeded),
ENA_METRIC_ENI_ENTRY(
conntrack_allowance_exceeded, Connection tracking allowance exceeded),
ENA_METRIC_ENI_ENTRY(
linklocal_allowance_exceeded, Linklocal packet rate allowance),
ENA_METRIC_ENI_ENTRY(
conntrack_allowance_available, Number of available conntracks),
};
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#endif
#define ENA_CUSTOMER_METRICS_ARRAY_SIZE ARRAY_SIZE(ena_hw_stats_strings)
static SYSCTL_NODE(_hw, OID_AUTO, ena, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"ENA driver parameters");
@ -98,12 +132,29 @@ SYSCTL_BOOL(_hw_ena, OID_AUTO, force_large_llq_header, CTLFLAG_RDTUN,
int ena_rss_table_size = ENA_RX_RSS_TABLE_SIZE;
int ena_sysctl_allocate_customer_metrics_buffer(struct ena_adapter *adapter)
{
int rc = 0;
adapter->customer_metrics_array = malloc((sizeof(u64) * ENA_CUSTOMER_METRICS_ARRAY_SIZE),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (unlikely(adapter->customer_metrics_array == NULL))
rc = ENOMEM;
return rc;
}
void
ena_sysctl_add_nodes(struct ena_adapter *adapter)
{
struct ena_com_dev *dev = adapter->ena_dev;
if (ena_com_get_cap(dev, ENA_ADMIN_CUSTOMER_METRICS))
ena_sysctl_add_customer_metrics(adapter);
else if (ena_com_get_cap(dev, ENA_ADMIN_ENI_STATS))
ena_sysctl_add_eni_metrics(adapter);
ena_sysctl_add_wd(adapter);
ena_sysctl_add_stats(adapter);
ena_sysctl_add_eni_metrics(adapter);
ena_sysctl_add_tuneables(adapter);
ena_sysctl_add_irq_affinity(adapter);
#ifndef RSS
@ -328,6 +379,40 @@ ena_sysctl_add_stats(struct ena_adapter *adapter)
&admin_stats->no_completion, 0, "Commands not completed");
}
static void
ena_sysctl_add_customer_metrics(struct ena_adapter *adapter)
{
device_t dev;
struct ena_com_dev *ena_dev;
struct sysctl_ctx_list *ctx;
struct sysctl_oid *tree;
struct sysctl_oid_list *child;
struct sysctl_oid *customer_metric;
struct sysctl_oid_list *customer_list;
int i;
dev = adapter->pdev;
ena_dev = adapter->ena_dev;
ctx = device_get_sysctl_ctx(dev);
tree = device_get_sysctl_tree(dev);
child = SYSCTL_CHILDREN(tree);
customer_metric = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "customer_metrics",
CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "ENA's customer metrics");
customer_list = SYSCTL_CHILDREN(customer_metric);
for (i = 0; i < ENA_CUSTOMER_METRICS_ARRAY_SIZE; i++) {
if (ena_com_get_customer_metric_support(ena_dev, i)) {
SYSCTL_ADD_U64(ctx, customer_list, OID_AUTO, ena_hw_stats_strings[i].name,
CTLFLAG_RD, &adapter->customer_metrics_array[i], 0,
ena_hw_stats_strings[i].description);
}
}
}
static void
ena_sysctl_add_eni_metrics(struct ena_adapter *adapter)
{

View file

@ -40,6 +40,7 @@
void ena_sysctl_add_nodes(struct ena_adapter *adapter);
void ena_sysctl_update_queue_node_nb(struct ena_adapter *adapter, int old,
int new);
int ena_sysctl_allocate_customer_metrics_buffer(struct ena_adapter *adapter);
extern int ena_enable_9k_mbufs;
#define ena_mbuf_sz (ena_enable_9k_mbufs ? MJUM9BYTES : MJUMPAGESIZE)