aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/dpdk/device/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/dpdk/device/init.c')
-rw-r--r--src/plugins/dpdk/device/init.c82
1 files changed, 80 insertions, 2 deletions
diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c
index 421f662efa2..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++)
@@ -1045,12 +1115,14 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
dpdk_main_t *dm = &dpdk_main;
clib_error_t *error = 0;
dpdk_config_main_t *conf = &dpdk_config_main;
- vlib_thread_main_t *tm = vlib_get_thread_main ();
dpdk_device_config_t *devconf;
vlib_pci_addr_t pci_addr = { 0 };
vlib_vmbus_addr_t vmbus_addr = { 0 };
unformat_input_t sub_input;
+#ifdef __linux
+ vlib_thread_main_t *tm = vlib_get_thread_main ();
uword default_hugepage_sz, x;
+#endif /* __linux__ */
u8 *s, *tmp = 0;
int ret, i;
int num_whitelisted = 0;
@@ -1258,6 +1330,11 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
{
vec_add1 (conf->eal_init_args, (u8 *) "--in-memory");
+#ifdef __linux__
+ /*
+ * FreeBSD performs huge page prealloc through a dedicated kernel mode
+ * this process is only required on Linux.
+ */
default_hugepage_sz = clib_mem_get_default_hugepage_size ();
clib_bitmap_foreach (x, tm->cpu_socket_bitmap)
@@ -1272,6 +1349,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
if ((e = clib_sysfs_prealloc_hugepages(x, 0, n_pages)))
clib_error_report (e);
}
+#endif /* __linux__ */
}
/* on/off dpdk's telemetry thread */