Skip to content

Commit

Permalink
dpdk: expose xstats in stats segment
Browse files Browse the repository at this point in the history
Expose DPDK xstats in the stat segment.
Represented as a 2D array. Thread by sw_if_index.
Each counter has the same name as the corresponding xstats counter,
under /if/<driver-name>/<xstats-name>

Type: improvement
Change-Id: Icd34b46e2b4d708f1c9a7063d6afd4ced3dfa4f5
Signed-off-by: Ole Troan <otroan@employees.org>
  • Loading branch information
otroan authored and florincoras committed Jun 18, 2024
1 parent 32dc913 commit dd6fb60
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/plugins/dpdk/device/dpdk.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ typedef struct
u32 interface_number_from_port_id : 1;
u32 use_intel_phdr_cksum : 1;
u32 int_unmaskable : 1;
vlib_simple_counter_main_t *xstats_counters;
} dpdk_driver_t;

dpdk_driver_t *dpdk_driver_find (const char *name, const char **desc);
Expand Down
29 changes: 18 additions & 11 deletions src/plugins/dpdk/device/dpdk_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,35 @@ dpdk_device_flag_set (dpdk_device_t *xd, __typeof__ (xd->flags) flag, int val)
xd->flags = val ? xd->flags | flag : xd->flags & ~flag;
}

void dpdk_counters_xstats_init (dpdk_device_t *xd);

static inline void
dpdk_get_xstats (dpdk_device_t * xd)
dpdk_get_xstats (dpdk_device_t *xd, u32 thread_index)
{
int len, ret;

int ret;
int i;
int len = vec_len (xd->xstats);
if (!(xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP))
return;

len = rte_eth_xstats_get (xd->port_id, NULL, 0);
if (len < 0)
if (xd->driver == 0)
return;

vec_validate (xd->xstats, len - 1);

ret = rte_eth_xstats_get (xd->port_id, xd->xstats, len);
if (ret < 0 || ret > len)
if (ret < 0 || ret > len || len != vec_len (xd->driver->xstats_counters))
{
/* Failed, expand vector and try again on next time around the track. */
vec_validate (xd->xstats, ret - 1);
vec_set_len (xd->xstats, 0);
dpdk_log_warn ("rte_eth_xstats_get(%d) failed: %d", xd->port_id, ret);
return;
}
vec_foreach_index (i, xd->xstats)
{
vlib_set_simple_counter (&xd->driver->xstats_counters[i], thread_index,
xd->sw_if_index, xd->xstats[i].value);
}

vec_set_len (xd->xstats, len);
vec_set_len (xd->xstats, ret);
}

#define DPDK_UPDATE_COUNTER(vnm, tidx, xd, stat, cnt) \
Expand Down Expand Up @@ -107,7 +114,7 @@ dpdk_update_counters (dpdk_device_t * xd, f64 now)
DPDK_UPDATE_COUNTER (vnm, thread_index, xd, ierrors,
VNET_INTERFACE_COUNTER_RX_ERROR);

dpdk_get_xstats (xd);
dpdk_get_xstats (xd, thread_index);
}

#if RTE_VERSION < RTE_VERSION_NUM(21, 11, 0, 0)
Expand Down
72 changes: 71 additions & 1 deletion src/plugins/dpdk/device/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
#include <dpdk/cryptodev/cryptodev.h>
#include <vlib/pci/pci.h>
#include <vlib/vmbus/vmbus.h>

#include <vlib/stats/stats.h>
#include <rte_ring.h>
#include <rte_vect.h>

Expand Down Expand Up @@ -226,6 +226,75 @@ dpdk_find_startup_config (struct rte_eth_dev_info *di)
return &dm->conf->default_devconf;
}

/*
* Initialise or refresh the xstats counters for a device
*/
void
dpdk_counters_xstats_init (dpdk_device_t *xd)
{
int len, ret, i;
struct rte_eth_xstat_name *xstats_names = 0;
char *name;
dpdk_driver_t *dr = xd->driver;

/* Only support xstats for supported drivers */
if (!dr)
return;

len = rte_eth_xstats_get_names (xd->port_id, 0, 0);
if (len < 0)
{
dpdk_log_err ("[%u] rte_eth_xstats_get_names failed: %d", xd->port_id,
len);
return;
}
/* Counters for this driver is already initialised */
if (vec_len (dr->xstats_counters) == len)
{
vec_foreach_index (i, dr->xstats_counters)
{
vlib_validate_simple_counter (&dr->xstats_counters[i],
xd->sw_if_index);
vlib_zero_simple_counter (&dr->xstats_counters[i], xd->sw_if_index);
}
return;
}

/* Same driver, different interface, different length of counter array. */
ASSERT (vec_len (dr->xstats_counters) == 0);

vec_validate (xstats_names, len - 1);

ret = rte_eth_xstats_get_names (xd->port_id, xstats_names, len);
if (ret >= 0 && ret <= len)
{
vec_validate (dr->xstats_counters, len - 1);
vec_foreach_index (i, xstats_names)
{
name = (char *) format (0, "/if/%s/%s%c", dr->drivers->name,
xstats_names[i].name, 0);

/* There is a bug in the ENA driver where the xstats names are not
* unique. */
if (vlib_stats_find_entry_index (name) != STAT_SEGMENT_INDEX_INVALID)
{
vec_free (name);
name = (char *) format (0, "/if/%s/%s_%d%c", dr->drivers->name,
xstats_names[i].name, i, 0);
}

dr->xstats_counters[i].name = name;
dr->xstats_counters[i].stat_segment_name = name;
dr->xstats_counters[i].counters = 0;
vlib_validate_simple_counter (&dr->xstats_counters[i],
xd->sw_if_index);
vlib_zero_simple_counter (&dr->xstats_counters[i], xd->sw_if_index);
vec_free (name);
}
}
vec_free (xstats_names);
}

static clib_error_t *
dpdk_lib_init (dpdk_main_t * dm)
{
Expand Down Expand Up @@ -532,6 +601,7 @@ dpdk_lib_init (dpdk_main_t * dm)
if (vec_len (xd->errors))
dpdk_log_err ("[%u] setup failed Errors:\n %U", port_id,
format_dpdk_device_errors, xd);
dpdk_counters_xstats_init (xd);
}

for (int i = 0; i < vec_len (dm->devices); i++)
Expand Down

0 comments on commit dd6fb60

Please sign in to comment.