diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/dpdk/device/dpdk.h | 1 | ||||
-rw-r--r-- | src/plugins/dpdk/device/dpdk_priv.h | 29 | ||||
-rw-r--r-- | src/plugins/dpdk/device/init.c | 72 |
3 files changed, 90 insertions, 12 deletions
diff --git a/src/plugins/dpdk/device/dpdk.h b/src/plugins/dpdk/device/dpdk.h index 88a4d9ff618..692bbbc09d9 100644 --- a/src/plugins/dpdk/device/dpdk.h +++ b/src/plugins/dpdk/device/dpdk.h @@ -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); diff --git a/src/plugins/dpdk/device/dpdk_priv.h b/src/plugins/dpdk/device/dpdk_priv.h index cb7b185c112..0af435767d2 100644 --- a/src/plugins/dpdk/device/dpdk_priv.h +++ b/src/plugins/dpdk/device/dpdk_priv.h @@ -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) \ @@ -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) diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c index e416efe2e4d..453d9cff7ef 100644 --- a/src/plugins/dpdk/device/init.c +++ b/src/plugins/dpdk/device/init.c @@ -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> @@ -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) { @@ -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++) |