Blame SOURCES/mlnx-dpdk-0009-net-mlx-control-netdevices-through-ioctl-only.patch

a6040a
From 8f419225febbd2f02748fb142aab2c1b96fd3902 Mon Sep 17 00:00:00 2001
a6040a
From: Adrien Mazarguil <adrien.mazarguil@6wind.com>
a6040a
Date: Wed, 7 Feb 2018 11:45:03 +0100
a6040a
Subject: [PATCH 9/9] net/mlx: control netdevices through ioctl only
a6040a
a6040a
Several control operations implemented by these PMDs affect netdevices
a6040a
through sysfs, itself subject to file system permission checks enforced by
a6040a
the kernel, which limits their use for most purposes to applications
a6040a
running with root privileges.
a6040a
a6040a
Since performing the same operations through ioctl() requires fewer
a6040a
capabilities (only CAP_NET_ADMIN) and given the remaining operations are
a6040a
already implemented this way, this patch standardizes on ioctl() and gets
a6040a
rid of redundant code.
a6040a
a6040a
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
a6040a
(cherry picked from commit 84c07af48024fc9d1027770e5143106e16ac49e7)
a6040a
---
a6040a
 drivers/net/mlx4/mlx4_ethdev.c | 192 ++-----------------------------
a6040a
 drivers/net/mlx5/mlx5.h        |   2 -
a6040a
 drivers/net/mlx5/mlx5_ethdev.c | 255 +++++------------------------------------
a6040a
 drivers/net/mlx5/mlx5_stats.c  |  28 ++++-
a6040a
 4 files changed, 63 insertions(+), 414 deletions(-)
a6040a
a6040a
diff --git a/drivers/net/mlx4/mlx4_ethdev.c b/drivers/net/mlx4/mlx4_ethdev.c
a6040a
index e2f9509..cf7afe3 100644
a6040a
--- a/drivers/net/mlx4/mlx4_ethdev.c
a6040a
+++ b/drivers/net/mlx4/mlx4_ethdev.c
a6040a
@@ -160,167 +160,6 @@
a6040a
 }
a6040a
 
a6040a
 /**
a6040a
- * Read from sysfs entry.
a6040a
- *
a6040a
- * @param[in] priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param[in] entry
a6040a
- *   Entry name relative to sysfs path.
a6040a
- * @param[out] buf
a6040a
- *   Data output buffer.
a6040a
- * @param size
a6040a
- *   Buffer size.
a6040a
- *
a6040a
- * @return
a6040a
- *   Number of bytes read on success, negative errno value otherwise and
a6040a
- *   rte_errno is set.
a6040a
- */
a6040a
-static int
a6040a
-mlx4_sysfs_read(const struct priv *priv, const char *entry,
a6040a
-		char *buf, size_t size)
a6040a
-{
a6040a
-	char ifname[IF_NAMESIZE];
a6040a
-	FILE *file;
a6040a
-	int ret;
a6040a
-
a6040a
-	ret = mlx4_get_ifname(priv, &ifname);
a6040a
-	if (ret)
a6040a
-		return ret;
a6040a
-
a6040a
-	MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path,
a6040a
-	      ifname, entry);
a6040a
-
a6040a
-	file = fopen(path, "rb");
a6040a
-	if (file == NULL) {
a6040a
-		rte_errno = errno;
a6040a
-		return -rte_errno;
a6040a
-	}
a6040a
-	ret = fread(buf, 1, size, file);
a6040a
-	if ((size_t)ret < size && ferror(file)) {
a6040a
-		rte_errno = EIO;
a6040a
-		ret = -rte_errno;
a6040a
-	} else {
a6040a
-		ret = size;
a6040a
-	}
a6040a
-	fclose(file);
a6040a
-	return ret;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
- * Write to sysfs entry.
a6040a
- *
a6040a
- * @param[in] priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param[in] entry
a6040a
- *   Entry name relative to sysfs path.
a6040a
- * @param[in] buf
a6040a
- *   Data buffer.
a6040a
- * @param size
a6040a
- *   Buffer size.
a6040a
- *
a6040a
- * @return
a6040a
- *   Number of bytes written on success, negative errno value otherwise and
a6040a
- *   rte_errno is set.
a6040a
- */
a6040a
-static int
a6040a
-mlx4_sysfs_write(const struct priv *priv, const char *entry,
a6040a
-		 char *buf, size_t size)
a6040a
-{
a6040a
-	char ifname[IF_NAMESIZE];
a6040a
-	FILE *file;
a6040a
-	int ret;
a6040a
-
a6040a
-	ret = mlx4_get_ifname(priv, &ifname);
a6040a
-	if (ret)
a6040a
-		return ret;
a6040a
-
a6040a
-	MKSTR(path, "%s/device/net/%s/%s", priv->ctx->device->ibdev_path,
a6040a
-	      ifname, entry);
a6040a
-
a6040a
-	file = fopen(path, "wb");
a6040a
-	if (file == NULL) {
a6040a
-		rte_errno = errno;
a6040a
-		return -rte_errno;
a6040a
-	}
a6040a
-	ret = fwrite(buf, 1, size, file);
a6040a
-	if ((size_t)ret < size || ferror(file)) {
a6040a
-		rte_errno = EIO;
a6040a
-		ret = -rte_errno;
a6040a
-	} else {
a6040a
-		ret = size;
a6040a
-	}
a6040a
-	fclose(file);
a6040a
-	return ret;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
- * Get unsigned long sysfs property.
a6040a
- *
a6040a
- * @param priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param[in] name
a6040a
- *   Entry name relative to sysfs path.
a6040a
- * @param[out] value
a6040a
- *   Value output buffer.
a6040a
- *
a6040a
- * @return
a6040a
- *   0 on success, negative errno value otherwise and rte_errno is set.
a6040a
- */
a6040a
-static int
a6040a
-mlx4_get_sysfs_ulong(struct priv *priv, const char *name, unsigned long *value)
a6040a
-{
a6040a
-	int ret;
a6040a
-	unsigned long value_ret;
a6040a
-	char value_str[32];
a6040a
-
a6040a
-	ret = mlx4_sysfs_read(priv, name, value_str, (sizeof(value_str) - 1));
a6040a
-	if (ret < 0) {
a6040a
-		DEBUG("cannot read %s value from sysfs: %s",
a6040a
-		      name, strerror(rte_errno));
a6040a
-		return ret;
a6040a
-	}
a6040a
-	value_str[ret] = '\0';
a6040a
-	errno = 0;
a6040a
-	value_ret = strtoul(value_str, NULL, 0);
a6040a
-	if (errno) {
a6040a
-		rte_errno = errno;
a6040a
-		DEBUG("invalid %s value `%s': %s", name, value_str,
a6040a
-		      strerror(rte_errno));
a6040a
-		return -rte_errno;
a6040a
-	}
a6040a
-	*value = value_ret;
a6040a
-	return 0;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
- * Set unsigned long sysfs property.
a6040a
- *
a6040a
- * @param priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param[in] name
a6040a
- *   Entry name relative to sysfs path.
a6040a
- * @param value
a6040a
- *   Value to set.
a6040a
- *
a6040a
- * @return
a6040a
- *   0 on success, negative errno value otherwise and rte_errno is set.
a6040a
- */
a6040a
-static int
a6040a
-mlx4_set_sysfs_ulong(struct priv *priv, const char *name, unsigned long value)
a6040a
-{
a6040a
-	int ret;
a6040a
-	MKSTR(value_str, "%lu", value);
a6040a
-
a6040a
-	ret = mlx4_sysfs_write(priv, name, value_str, (sizeof(value_str) - 1));
a6040a
-	if (ret < 0) {
a6040a
-		DEBUG("cannot write %s `%s' (%lu) to sysfs: %s",
a6040a
-		      name, value_str, value, strerror(rte_errno));
a6040a
-		return ret;
a6040a
-	}
a6040a
-	return 0;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
  * Perform ifreq ioctl() on associated Ethernet device.
a6040a
  *
a6040a
  * @param[in] priv
a6040a
@@ -389,12 +228,12 @@
a6040a
 int
a6040a
 mlx4_mtu_get(struct priv *priv, uint16_t *mtu)
a6040a
 {
a6040a
-	unsigned long ulong_mtu = 0;
a6040a
-	int ret = mlx4_get_sysfs_ulong(priv, "mtu", &ulong_mtu);
a6040a
+	struct ifreq request;
a6040a
+	int ret = mlx4_ifreq(priv, SIOCGIFMTU, &request);
a6040a
 
a6040a
 	if (ret)
a6040a
 		return ret;
a6040a
-	*mtu = ulong_mtu;
a6040a
+	*mtu = request.ifr_mtu;
a6040a
 	return 0;
a6040a
 }
a6040a
 
a6040a
@@ -413,20 +252,13 @@
a6040a
 mlx4_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
a6040a
 {
a6040a
 	struct priv *priv = dev->data->dev_private;
a6040a
-	uint16_t new_mtu;
a6040a
-	int ret = mlx4_set_sysfs_ulong(priv, "mtu", mtu);
a6040a
+	struct ifreq request = { .ifr_mtu = mtu, };
a6040a
+	int ret = mlx4_ifreq(priv, SIOCSIFMTU, &request);
a6040a
 
a6040a
 	if (ret)
a6040a
 		return ret;
a6040a
-	ret = mlx4_mtu_get(priv, &new_mtu);
a6040a
-	if (ret)
a6040a
-		return ret;
a6040a
-	if (new_mtu == mtu) {
a6040a
-		priv->mtu = mtu;
a6040a
-		return 0;
a6040a
-	}
a6040a
-	rte_errno = EINVAL;
a6040a
-	return -rte_errno;
a6040a
+	priv->mtu = mtu;
a6040a
+	return 0;
a6040a
 }
a6040a
 
a6040a
 /**
a6040a
@@ -445,14 +277,14 @@
a6040a
 static int
a6040a
 mlx4_set_flags(struct priv *priv, unsigned int keep, unsigned int flags)
a6040a
 {
a6040a
-	unsigned long tmp = 0;
a6040a
-	int ret = mlx4_get_sysfs_ulong(priv, "flags", &tmp);
a6040a
+	struct ifreq request;
a6040a
+	int ret = mlx4_ifreq(priv, SIOCGIFFLAGS, &request);
a6040a
 
a6040a
 	if (ret)
a6040a
 		return ret;
a6040a
-	tmp &= keep;
a6040a
-	tmp |= (flags & (~keep));
a6040a
-	return mlx4_set_sysfs_ulong(priv, "flags", tmp);
a6040a
+	request.ifr_flags &= keep;
a6040a
+	request.ifr_flags |= flags & ~keep;
a6040a
+	return mlx4_ifreq(priv, SIOCSIFFLAGS, &request);
a6040a
 }
a6040a
 
a6040a
 /**
a6040a
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
a6040a
index e6a69b8..a34121c 100644
a6040a
--- a/drivers/net/mlx5/mlx5.h
a6040a
+++ b/drivers/net/mlx5/mlx5.h
a6040a
@@ -186,8 +186,6 @@ struct priv {
a6040a
 int mlx5_is_secondary(void);
a6040a
 int priv_get_ifname(const struct priv *, char (*)[IF_NAMESIZE]);
a6040a
 int priv_ifreq(const struct priv *, int req, struct ifreq *);
a6040a
-int priv_is_ib_cntr(const char *);
a6040a
-int priv_get_cntr_sysfs(struct priv *, const char *, uint64_t *);
a6040a
 int priv_get_num_vfs(struct priv *, uint16_t *);
a6040a
 int priv_get_mtu(struct priv *, uint16_t *);
a6040a
 int priv_set_flags(struct priv *, unsigned int, unsigned int);
a6040a
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
a6040a
index 5620cce..4dffa4f 100644
a6040a
--- a/drivers/net/mlx5/mlx5_ethdev.c
a6040a
+++ b/drivers/net/mlx5/mlx5_ethdev.c
a6040a
@@ -35,6 +35,7 @@
a6040a
 
a6040a
 #include <stddef.h>
a6040a
 #include <assert.h>
a6040a
+#include <inttypes.h>
a6040a
 #include <unistd.h>
a6040a
 #include <stdint.h>
a6040a
 #include <stdio.h>
a6040a
@@ -228,181 +229,6 @@ struct priv *
a6040a
 }
a6040a
 
a6040a
 /**
a6040a
- * Check if the counter is located on ib counters file.
a6040a
- *
a6040a
- * @param[in] cntr
a6040a
- *   Counter name.
a6040a
- *
a6040a
- * @return
a6040a
- *   1 if counter is located on ib counters file , 0 otherwise.
a6040a
- */
a6040a
-int
a6040a
-priv_is_ib_cntr(const char *cntr)
a6040a
-{
a6040a
-	if (!strcmp(cntr, "out_of_buffer"))
a6040a
-		return 1;
a6040a
-	return 0;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
- * Read from sysfs entry.
a6040a
- *
a6040a
- * @param[in] priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param[in] entry
a6040a
- *   Entry name relative to sysfs path.
a6040a
- * @param[out] buf
a6040a
- *   Data output buffer.
a6040a
- * @param size
a6040a
- *   Buffer size.
a6040a
- *
a6040a
- * @return
a6040a
- *   0 on success, -1 on failure and errno is set.
a6040a
- */
a6040a
-static int
a6040a
-priv_sysfs_read(const struct priv *priv, const char *entry,
a6040a
-		char *buf, size_t size)
a6040a
-{
a6040a
-	char ifname[IF_NAMESIZE];
a6040a
-	FILE *file;
a6040a
-	int ret;
a6040a
-	int err;
a6040a
-
a6040a
-	if (priv_get_ifname(priv, &ifname))
a6040a
-		return -1;
a6040a
-
a6040a
-	if (priv_is_ib_cntr(entry)) {
a6040a
-		MKSTR(path, "%s/ports/1/hw_counters/%s",
a6040a
-		      priv->ibdev_path, entry);
a6040a
-		file = fopen(path, "rb");
a6040a
-	} else {
a6040a
-		MKSTR(path, "%s/device/net/%s/%s",
a6040a
-		      priv->ibdev_path, ifname, entry);
a6040a
-		file = fopen(path, "rb");
a6040a
-	}
a6040a
-	if (file == NULL)
a6040a
-		return -1;
a6040a
-	ret = fread(buf, 1, size, file);
a6040a
-	err = errno;
a6040a
-	if (((size_t)ret < size) && (ferror(file)))
a6040a
-		ret = -1;
a6040a
-	else
a6040a
-		ret = size;
a6040a
-	fclose(file);
a6040a
-	errno = err;
a6040a
-	return ret;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
- * Write to sysfs entry.
a6040a
- *
a6040a
- * @param[in] priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param[in] entry
a6040a
- *   Entry name relative to sysfs path.
a6040a
- * @param[in] buf
a6040a
- *   Data buffer.
a6040a
- * @param size
a6040a
- *   Buffer size.
a6040a
- *
a6040a
- * @return
a6040a
- *   0 on success, -1 on failure and errno is set.
a6040a
- */
a6040a
-static int
a6040a
-priv_sysfs_write(const struct priv *priv, const char *entry,
a6040a
-		 char *buf, size_t size)
a6040a
-{
a6040a
-	char ifname[IF_NAMESIZE];
a6040a
-	FILE *file;
a6040a
-	int ret;
a6040a
-	int err;
a6040a
-
a6040a
-	if (priv_get_ifname(priv, &ifname))
a6040a
-		return -1;
a6040a
-
a6040a
-	MKSTR(path, "%s/device/net/%s/%s", priv->ibdev_path, ifname, entry);
a6040a
-
a6040a
-	file = fopen(path, "wb");
a6040a
-	if (file == NULL)
a6040a
-		return -1;
a6040a
-	ret = fwrite(buf, 1, size, file);
a6040a
-	err = errno;
a6040a
-	if (((size_t)ret < size) || (ferror(file)))
a6040a
-		ret = -1;
a6040a
-	else
a6040a
-		ret = size;
a6040a
-	fclose(file);
a6040a
-	errno = err;
a6040a
-	return ret;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
- * Get unsigned long sysfs property.
a6040a
- *
a6040a
- * @param priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param[in] name
a6040a
- *   Entry name relative to sysfs path.
a6040a
- * @param[out] value
a6040a
- *   Value output buffer.
a6040a
- *
a6040a
- * @return
a6040a
- *   0 on success, -1 on failure and errno is set.
a6040a
- */
a6040a
-static int
a6040a
-priv_get_sysfs_ulong(struct priv *priv, const char *name, unsigned long *value)
a6040a
-{
a6040a
-	int ret;
a6040a
-	unsigned long value_ret;
a6040a
-	char value_str[32];
a6040a
-
a6040a
-	ret = priv_sysfs_read(priv, name, value_str, (sizeof(value_str) - 1));
a6040a
-	if (ret == -1) {
a6040a
-		DEBUG("cannot read %s value from sysfs: %s",
a6040a
-		      name, strerror(errno));
a6040a
-		return -1;
a6040a
-	}
a6040a
-	value_str[ret] = '\0';
a6040a
-	errno = 0;
a6040a
-	value_ret = strtoul(value_str, NULL, 0);
a6040a
-	if (errno) {
a6040a
-		DEBUG("invalid %s value `%s': %s", name, value_str,
a6040a
-		      strerror(errno));
a6040a
-		return -1;
a6040a
-	}
a6040a
-	*value = value_ret;
a6040a
-	return 0;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
- * Set unsigned long sysfs property.
a6040a
- *
a6040a
- * @param priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param[in] name
a6040a
- *   Entry name relative to sysfs path.
a6040a
- * @param value
a6040a
- *   Value to set.
a6040a
- *
a6040a
- * @return
a6040a
- *   0 on success, -1 on failure and errno is set.
a6040a
- */
a6040a
-static int
a6040a
-priv_set_sysfs_ulong(struct priv *priv, const char *name, unsigned long value)
a6040a
-{
a6040a
-	int ret;
a6040a
-	MKSTR(value_str, "%lu", value);
a6040a
-
a6040a
-	ret = priv_sysfs_write(priv, name, value_str, (sizeof(value_str) - 1));
a6040a
-	if (ret == -1) {
a6040a
-		DEBUG("cannot write %s `%s' (%lu) to sysfs: %s",
a6040a
-		      name, value_str, value, strerror(errno));
a6040a
-		return -1;
a6040a
-	}
a6040a
-	return 0;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
  * Perform ifreq ioctl() on associated Ethernet device.
a6040a
  *
a6040a
  * @param[in] priv
a6040a
@@ -445,20 +271,25 @@ struct priv *
a6040a
 {
a6040a
 	/* The sysfs entry name depends on the operating system. */
a6040a
 	const char **name = (const char *[]){
a6040a
-		"device/sriov_numvfs",
a6040a
-		"device/mlx5_num_vfs",
a6040a
+		"sriov_numvfs",
a6040a
+		"mlx5_num_vfs",
a6040a
 		NULL,
a6040a
 	};
a6040a
-	int ret;
a6040a
 
a6040a
 	do {
a6040a
-		unsigned long ulong_num_vfs;
a6040a
+		int n;
a6040a
+		FILE *file;
a6040a
+		MKSTR(path, "%s/device/%s", priv->ibdev_path, *name);
a6040a
 
a6040a
-		ret = priv_get_sysfs_ulong(priv, *name, &ulong_num_vfs);
a6040a
-		if (!ret)
a6040a
-			*num_vfs = ulong_num_vfs;
a6040a
-	} while (*(++name) && ret);
a6040a
-	return ret;
a6040a
+		file = fopen(path, "rb");
a6040a
+		if (!file)
a6040a
+			continue;
a6040a
+		n = fscanf(file, "%" SCNu16, num_vfs);
a6040a
+		fclose(file);
a6040a
+		if (n == 1)
a6040a
+			return 0;
a6040a
+	} while (*(++name));
a6040a
+	return -1;
a6040a
 }
a6040a
 
a6040a
 /**
a6040a
@@ -475,35 +306,12 @@ struct priv *
a6040a
 int
a6040a
 priv_get_mtu(struct priv *priv, uint16_t *mtu)
a6040a
 {
a6040a
-	unsigned long ulong_mtu;
a6040a
+	struct ifreq request;
a6040a
+	int ret = priv_ifreq(priv, SIOCGIFMTU, &request);
a6040a
 
a6040a
-	if (priv_get_sysfs_ulong(priv, "mtu", &ulong_mtu) == -1)
a6040a
-		return -1;
a6040a
-	*mtu = ulong_mtu;
a6040a
-	return 0;
a6040a
-}
a6040a
-
a6040a
-/**
a6040a
- * Read device counter from sysfs.
a6040a
- *
a6040a
- * @param priv
a6040a
- *   Pointer to private structure.
a6040a
- * @param name
a6040a
- *   Counter name.
a6040a
- * @param[out] cntr
a6040a
- *   Counter output buffer.
a6040a
- *
a6040a
- * @return
a6040a
- *   0 on success, -1 on failure and errno is set.
a6040a
- */
a6040a
-int
a6040a
-priv_get_cntr_sysfs(struct priv *priv, const char *name, uint64_t *cntr)
a6040a
-{
a6040a
-	unsigned long ulong_ctr;
a6040a
-
a6040a
-	if (priv_get_sysfs_ulong(priv, name, &ulong_ctr) == -1)
a6040a
-		return -1;
a6040a
-	*cntr = ulong_ctr;
a6040a
+	if (ret)
a6040a
+		return ret;
a6040a
+	*mtu = request.ifr_mtu;
a6040a
 	return 0;
a6040a
 }
a6040a
 
a6040a
@@ -521,15 +329,9 @@ struct priv *
a6040a
 static int
a6040a
 priv_set_mtu(struct priv *priv, uint16_t mtu)
a6040a
 {
a6040a
-	uint16_t new_mtu;
a6040a
+	struct ifreq request = { .ifr_mtu = mtu, };
a6040a
 
a6040a
-	if (priv_set_sysfs_ulong(priv, "mtu", mtu) ||
a6040a
-	    priv_get_mtu(priv, &new_mtu))
a6040a
-		return -1;
a6040a
-	if (new_mtu == mtu)
a6040a
-		return 0;
a6040a
-	errno = EINVAL;
a6040a
-	return -1;
a6040a
+	return priv_ifreq(priv, SIOCSIFMTU, &request);
a6040a
 }
a6040a
 
a6040a
 /**
a6040a
@@ -548,13 +350,14 @@ struct priv *
a6040a
 int
a6040a
 priv_set_flags(struct priv *priv, unsigned int keep, unsigned int flags)
a6040a
 {
a6040a
-	unsigned long tmp;
a6040a
+	struct ifreq request;
a6040a
+	int ret = priv_ifreq(priv, SIOCGIFFLAGS, &request);
a6040a
 
a6040a
-	if (priv_get_sysfs_ulong(priv, "flags", &tmp) == -1)
a6040a
-		return -1;
a6040a
-	tmp &= keep;
a6040a
-	tmp |= (flags & (~keep));
a6040a
-	return priv_set_sysfs_ulong(priv, "flags", tmp);
a6040a
+	if (ret)
a6040a
+		return ret;
a6040a
+	request.ifr_flags &= keep;
a6040a
+	request.ifr_flags |= flags & ~keep;
a6040a
+	return priv_ifreq(priv, SIOCSIFFLAGS, &request);
a6040a
 }
a6040a
 
a6040a
 /**
a6040a
diff --git a/drivers/net/mlx5/mlx5_stats.c b/drivers/net/mlx5/mlx5_stats.c
a6040a
index 5e225d3..48422cc 100644
a6040a
--- a/drivers/net/mlx5/mlx5_stats.c
a6040a
+++ b/drivers/net/mlx5/mlx5_stats.c
a6040a
@@ -31,8 +31,11 @@
a6040a
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
a6040a
  */
a6040a
 
a6040a
+#include <inttypes.h>
a6040a
 #include <linux/sockios.h>
a6040a
 #include <linux/ethtool.h>
a6040a
+#include <stdint.h>
a6040a
+#include <stdio.h>
a6040a
 
a6040a
 #include <rte_ethdev.h>
a6040a
 #include <rte_common.h>
a6040a
@@ -47,6 +50,7 @@ struct mlx5_counter_ctrl {
a6040a
 	char dpdk_name[RTE_ETH_XSTATS_NAME_SIZE];
a6040a
 	/* Name of the counter on the device table. */
a6040a
 	char ctr_name[RTE_ETH_XSTATS_NAME_SIZE];
a6040a
+	uint32_t ib:1; /**< Nonzero for IB counters. */
a6040a
 };
a6040a
 
a6040a
 static const struct mlx5_counter_ctrl mlx5_counters_init[] = {
a6040a
@@ -121,6 +125,7 @@ struct mlx5_counter_ctrl {
a6040a
 	{
a6040a
 		.dpdk_name = "rx_out_of_buffer",
a6040a
 		.ctr_name = "out_of_buffer",
a6040a
+		.ib = 1,
a6040a
 	},
a6040a
 };
a6040a
 
a6040a
@@ -157,13 +162,24 @@ struct mlx5_counter_ctrl {
a6040a
 		return -1;
a6040a
 	}
a6040a
 	for (i = 0; i != xstats_n; ++i) {
a6040a
-		if (priv_is_ib_cntr(mlx5_counters_init[i].ctr_name))
a6040a
-			priv_get_cntr_sysfs(priv,
a6040a
-					    mlx5_counters_init[i].ctr_name,
a6040a
-					    &stats[i]);
a6040a
-		else
a6040a
+		if (mlx5_counters_init[i].ib) {
a6040a
+			FILE *file;
a6040a
+			MKSTR(path, "%s/ports/1/hw_counters/%s",
a6040a
+			      priv->ibdev_path,
a6040a
+			      mlx5_counters_init[i].ctr_name);
a6040a
+
a6040a
+			file = fopen(path, "rb");
a6040a
+			if (file) {
a6040a
+				int n = fscanf(file, "%" SCNu64, &stats[i]);
a6040a
+
a6040a
+				fclose(file);
a6040a
+				if (n != 1)
a6040a
+					stats[i] = 0;
a6040a
+			}
a6040a
+		} else {
a6040a
 			stats[i] = (uint64_t)
a6040a
 				et_stats->data[xstats_ctrl->dev_table_idx[i]];
a6040a
+		}
a6040a
 	}
a6040a
 	return 0;
a6040a
 }
a6040a
@@ -246,7 +262,7 @@ struct mlx5_counter_ctrl {
a6040a
 		}
a6040a
 	}
a6040a
 	for (j = 0; j != xstats_n; ++j) {
a6040a
-		if (priv_is_ib_cntr(mlx5_counters_init[j].ctr_name))
a6040a
+		if (mlx5_counters_init[j].ib)
a6040a
 			continue;
a6040a
 		if (xstats_ctrl->dev_table_idx[j] >= dev_stats_n) {
a6040a
 			WARN("counter \"%s\" is not recognized",
a6040a
-- 
a6040a
1.8.3.1
a6040a