[dpdk-dev] [PATCH 3/3] net/vdev_netvsc: prefer netvsc devices in scan

Matan Azrad matan at mellanox.com
Tue Apr 10 15:32:08 CEST 2018


There is an option to run a non-netvsc device as a netvsc device only
when the "force" parameter is set to 1 in the EAL command line.
Consequently, more than one device may be found to be matching the
"mac" parameter specifying the device.

Prefer netvsc devices to be scanned before any non-netvsc device, even
when the "force" parameter is set.

Cc: stable at dpdk.org

Signed-off-by: Matan Azrad <matan at mellanox.com>
---
 drivers/net/vdev_netvsc/vdev_netvsc.c | 122 ++++++++++++++++++----------------
 1 file changed, 65 insertions(+), 57 deletions(-)

diff --git a/drivers/net/vdev_netvsc/vdev_netvsc.c b/drivers/net/vdev_netvsc/vdev_netvsc.c
index 018ffae..75aec89 100644
--- a/drivers/net/vdev_netvsc/vdev_netvsc.c
+++ b/drivers/net/vdev_netvsc/vdev_netvsc.c
@@ -98,6 +98,43 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 }
 
 /**
+ * Determine if a network interface is NetVSC.
+ *
+ * @param[in] iface
+ *   Pointer to netdevice description structure (name and index).
+ *
+ * @return
+ *   A nonzero value when interface is detected as NetVSC. In case of error,
+ *   rte_errno is updated and 0 returned.
+ */
+static int
+vdev_netvsc_iface_is_netvsc(const struct if_nameindex *iface)
+{
+	static const char temp[] = "/sys/class/net/%s/device/class_id";
+	char path[sizeof(temp) + IF_NAMESIZE];
+	FILE *f;
+	int ret;
+	int len = 0;
+
+	ret = snprintf(path, sizeof(path), temp, iface->if_name);
+	if (ret == -1 || (size_t)ret >= sizeof(path)) {
+		rte_errno = ENOBUFS;
+		return 0;
+	}
+	f = fopen(path, "r");
+	if (!f) {
+		rte_errno = errno;
+		return 0;
+	}
+	ret = fscanf(f, NETVSC_CLASS_ID "%n", &len);
+	if (ret == EOF)
+		rte_errno = errno;
+	ret = len == (int)strlen(NETVSC_CLASS_ID);
+	fclose(f);
+	return ret;
+}
+
+/**
  * Iterate over system network interfaces.
  *
  * This function runs a given callback function for each netdevice found on
@@ -106,6 +143,8 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
  * @param func
  *   Callback function pointer. List traversal is aborted when this function
  *   returns a nonzero value.
+ * @param is_netvsc
+ *   Indicates the device type to iterate - netvsc or non-netvsc.
  * @param ...
  *   Variable parameter list passed as @p va_list to @p func.
  *
@@ -117,7 +156,7 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 static int
 vdev_netvsc_foreach_iface(int (*func)(const struct if_nameindex *iface,
 				      const struct ether_addr *eth_addr,
-				      va_list ap), ...)
+				      va_list ap), int is_netvsc, ...)
 {
 	struct if_nameindex *iface = if_nameindex();
 	int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
@@ -135,10 +174,14 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 		goto error;
 	}
 	for (i = 0; iface[i].if_name; ++i) {
+		int is_netvsc_ret;
 		struct ifreq req;
 		struct ether_addr eth_addr;
 		va_list ap;
 
+		is_netvsc_ret = vdev_netvsc_iface_is_netvsc(&iface[i]) ? 1 : 0;
+		if (is_netvsc ^ is_netvsc_ret)
+			continue;
 		strncpy(req.ifr_name, iface[i].if_name, sizeof(req.ifr_name));
 		if (ioctl(s, SIOCGIFHWADDR, &req) == -1) {
 			DRV_LOG(WARNING, "cannot retrieve information about"
@@ -153,7 +196,7 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 		}
 		memcpy(eth_addr.addr_bytes, req.ifr_hwaddr.sa_data,
 		       RTE_DIM(eth_addr.addr_bytes));
-		va_start(ap, func);
+		va_start(ap, is_netvsc);
 		ret = func(&iface[i], &eth_addr, ap);
 		va_end(ap);
 		if (ret)
@@ -168,43 +211,6 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 }
 
 /**
- * Determine if a network interface is NetVSC.
- *
- * @param[in] iface
- *   Pointer to netdevice description structure (name and index).
- *
- * @return
- *   A nonzero value when interface is detected as NetVSC. In case of error,
- *   rte_errno is updated and 0 returned.
- */
-static int
-vdev_netvsc_iface_is_netvsc(const struct if_nameindex *iface)
-{
-	static const char temp[] = "/sys/class/net/%s/device/class_id";
-	char path[sizeof(temp) + IF_NAMESIZE];
-	FILE *f;
-	int ret;
-	int len = 0;
-
-	ret = snprintf(path, sizeof(path), temp, iface->if_name);
-	if (ret == -1 || (size_t)ret >= sizeof(path)) {
-		rte_errno = ENOBUFS;
-		return 0;
-	}
-	f = fopen(path, "r");
-	if (!f) {
-		rte_errno = errno;
-		return 0;
-	}
-	ret = fscanf(f, NETVSC_CLASS_ID "%n", &len);
-	if (ret == EOF)
-		rte_errno = errno;
-	ret = len == (int)strlen(NETVSC_CLASS_ID);
-	fclose(f);
-	return ret;
-}
-
-/**
  * Determine if a network interface has a route.
  *
  * @param[in] name
@@ -379,8 +385,6 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 		strncpy(ctx->if_name, iface->if_name, sizeof(ctx->if_name));
 		return 0;
 	}
-	if (vdev_netvsc_iface_is_netvsc(iface))
-		return 0;
 	if (!is_same_ether_addr(eth_addr, &ctx->if_addr))
 		return 0;
 	/* Look for associated PCI device. */
@@ -449,7 +453,8 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 	int ret;
 
 	LIST_FOREACH(ctx, &vdev_netvsc_ctx_list, entry) {
-		ret = vdev_netvsc_foreach_iface(vdev_netvsc_device_probe, ctx);
+		ret = vdev_netvsc_foreach_iface(vdev_netvsc_device_probe, 0,
+		      ctx);
 		if (ret < 0)
 			break;
 	}
@@ -505,7 +510,6 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 {
 	const char *name = va_arg(ap, const char *);
 	struct rte_kvargs *kvargs = va_arg(ap, struct rte_kvargs *);
-	int force = va_arg(ap, int);
 	unsigned int specified = va_arg(ap, unsigned int);
 	unsigned int *matched = va_arg(ap, unsigned int *);
 	unsigned int i;
@@ -559,13 +563,6 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 			iface->if_name, iface->if_index);
 		return 0;
 	}
-	if (!vdev_netvsc_iface_is_netvsc(iface)) {
-		if (!specified || !force)
-			return 0;
-		DRV_LOG(WARNING,
-			"using non-NetVSC interface \"%s\" (index %u)",
-			iface->if_name, iface->if_index);
-	}
 	/* Routed NetVSC should not be probed. */
 	if (vdev_netvsc_has_route(iface, AF_INET) ||
 	    vdev_netvsc_has_route(iface, AF_INET6)) {
@@ -632,7 +629,7 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 	/* Request virtual device generation. */
 	DRV_LOG(DEBUG, "generating virtual device \"%s\" with arguments \"%s\"",
 		ctx->devname, ctx->devargs);
-	vdev_netvsc_foreach_iface(vdev_netvsc_device_probe, ctx);
+	vdev_netvsc_foreach_iface(vdev_netvsc_device_probe, 0, ctx);
 	ret = rte_eal_hotplug_add("vdev", ctx->devname, ctx->devargs);
 	if (ret)
 		goto error;
@@ -709,14 +706,25 @@ static LIST_HEAD(, vdev_netvsc_ctx) vdev_netvsc_ctx_list =
 	}
 	rte_eal_alarm_cancel(vdev_netvsc_alarm, NULL);
 	/* Gather interfaces. */
-	ret = vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, name, kvargs,
-					force, specified, &matched);
+	ret = vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, 1, name,
+					kvargs, specified, &matched);
 	if (ret < 0)
 		goto error;
-	if (matched < specified)
-		DRV_LOG(WARNING,
-			"some of the specified parameters did not match"
-			" recognized network interfaces");
+	if (specified && matched < specified) {
+		if (!force) {
+			DRV_LOG(ERR, "Cannot find the specified netvsc device");
+			goto error;
+		}
+		/* Try to force probing on non-netvsc specified device. */
+		if (vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, 0, name,
+					      kvargs, specified, &matched) < 0)
+			goto error;
+		if (matched < specified) {
+			DRV_LOG(ERR, "Cannot find the specified device");
+			goto error;
+		}
+		DRV_LOG(WARNING, "non-netvsc device was probed as netvsc");
+	}
 	ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
 				vdev_netvsc_alarm, NULL);
 	if (ret < 0) {
-- 
1.9.5



More information about the dev mailing list