[dpdk-dev] [PATCH] examples/ip_pipeline: add link identification feature

Fan Zhang roy.fan.zhang at intel.com
Thu Jan 28 16:55:39 CET 2016


This patch adds link identification feature to packet framework. To
identify a link, user can use both existing port-mask option, or specify
PCI device in each LINK section in the configuration file.

Signed-off-by: Fan Zhang <roy.fan.zhang at intel.com>
---
 examples/ip_pipeline/app.h          |   1 +
 examples/ip_pipeline/config_parse.c | 138 +++++++++++++++++++++++++++++++++---
 2 files changed, 131 insertions(+), 8 deletions(-)

diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h
index 6510d6d..43bee8a 100644
--- a/examples/ip_pipeline/app.h
+++ b/examples/ip_pipeline/app.h
@@ -73,6 +73,7 @@ struct app_link_params {
 	uint32_t ip; /* 0 = Invalid */
 	uint32_t depth; /* Valid only when IP is valid */
 	uint64_t mac_addr; /* Read from HW */
+	struct rte_pci_addr *pci_bdf; /* Hardware PCI address */
 
 	struct rte_eth_conf conf;
 	uint8_t promisc;
diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c
index 1bedbe4..961e753 100644
--- a/examples/ip_pipeline/config_parse.c
+++ b/examples/ip_pipeline/config_parse.c
@@ -41,10 +41,14 @@
 #include <libgen.h>
 #include <unistd.h>
 #include <sys/wait.h>
+#include <dirent.h>
 
 #include <rte_errno.h>
 #include <rte_cfgfile.h>
 #include <rte_string_fns.h>
+#include <rte_ethdev.h>
+#include <rte_devargs.h>
+#include <rte_string_fns.h>
 
 #include "app.h"
 
@@ -2532,12 +2536,113 @@ filenamedup(const char *filename, const char *suffix)
 	return s;
 }
 
+#define IGB_UIO_DEVICES		"/sys/bus/pci/drivers/igb_uio/"
+/*
+ * split up a pci address into its constituent parts.
+ */
+static int
+parse_pci_addr_format(const char *buf, int bufsize, uint16_t *domain,
+		uint8_t *bus, uint8_t *devid, uint8_t *function)
+{
+	/* first split on ':' */
+	union splitaddr {
+		struct {
+			char *domain;
+			char *bus;
+			char *devid;
+			char *function;
+		};
+		char *str[PCI_FMT_NVAL];
+	} splitaddr;
+	char *buf_copy = strndup(buf, bufsize);
+
+	if (buf_copy == NULL)
+		return -1;
+
+	if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':')
+			!= PCI_FMT_NVAL - 1)
+		goto error;
+	/* final split is on '.' between devid and function */
+	splitaddr.function = strchr(splitaddr.devid, '.');
+	if (splitaddr.function == NULL)
+		goto error;
+	*splitaddr.function++ = '\0';
+
+	/* now convert to int values */
+	errno = 0;
+	*domain = (uint16_t)strtoul(splitaddr.domain, NULL, 16);
+	*bus = (uint8_t)strtoul(splitaddr.bus, NULL, 16);
+	*devid = (uint8_t)strtoul(splitaddr.devid, NULL, 16);
+	*function = (uint8_t)strtoul(splitaddr.function, NULL, 10);
+	if (errno != 0)
+		goto error;
+
+	free(buf_copy); /* free the copy made with strdup */
+	return 0;
+error:
+	free(buf_copy);
+	return -1;
+}
+
+static int
+parse_pci_dev_str(struct app_params *app, const char *devArgStr)
+{
+	struct dirent *e;
+	DIR *dir;
+	char dev_name[PATH_MAX];
+	uint16_t domain;
+	uint8_t bus, devid, function;
+	uint8_t port_id = 0;
+	struct rte_pci_addr *pci_addr;
+	uint8_t found_match = 0;
+
+	dir = opendir(IGB_UIO_DEVICES);
+	if (dir == NULL)
+		return -1;
+
+	while ((e = readdir(dir)) != NULL) {
+		if (e->d_name[0] == '.')
+			continue;
+
+		if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &domain,
+				&bus, &devid, &function) != 0)
+			continue;
+
+		snprintf(dev_name, sizeof(dev_name), PCI_PRI_FMT,
+			domain, bus, devid, function);
+
+		if (strncmp(devArgStr, dev_name, sizeof(dev_name)) == 0) {
+			found_match = 1;
+			pci_addr = malloc(sizeof(struct rte_pci_addr));
+			PARSE_ERROR_MALLOC(pci_addr != NULL);
+			pci_addr->domain = domain;
+			pci_addr->bus = bus;
+			pci_addr->devid = devid;
+			pci_addr->function = function;
+
+			app->link_params[port_id].pci_bdf = pci_addr;
+			app->port_mask |= 1 << port_id;
+
+			break;
+		}
+		/* Assuming all devices will be taken account in EAL */
+		port_id++;
+	}
+
+	closedir(dir);
+
+	if (found_match == 0)
+		return -1;
+
+	return 0;
+}
+
 int
 app_config_args(struct app_params *app, int argc, char **argv)
 {
 	const char *optname;
 	int opt, option_index;
-	int f_present, s_present, p_present, l_present;
+	int f_present, s_present, p_present, l_present, w_present;
 	int preproc_present, preproc_params_present;
 	int scaned = 0;
 
@@ -2554,10 +2659,11 @@ app_config_args(struct app_params *app, int argc, char **argv)
 	s_present = 0;
 	p_present = 0;
 	l_present = 0;
+	w_present = 0;
 	preproc_present = 0;
 	preproc_params_present = 0;
 
-	while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts,
+	while ((opt = getopt_long(argc, argv, "f:s:p:l:w:", lgopts,
 			&option_index)) != EOF)
 		switch (opt) {
 		case 'f':
@@ -2591,10 +2697,11 @@ app_config_args(struct app_params *app, int argc, char **argv)
 			break;
 
 		case 'p':
-			if (p_present)
-				rte_panic("Error: PORT_MASK is provided "
-					"more than once\n");
-			p_present = 1;
+			if (w_present == 1)
+				rte_panic("Error: PORT_MASK is not allowed "
+					"when WHITE_LIST already existed\n");
+			if (p_present == 0)
+				p_present = 1;
 
 			if ((sscanf(optarg, "%" SCNx64 "%n", &app->port_mask,
 				&scaned) != 1) ||
@@ -2607,6 +2714,20 @@ app_config_args(struct app_params *app, int argc, char **argv)
 
 			break;
 
+		case 'w':
+			if (p_present == 1)
+				rte_panic("Error: WHITE_LIST is not allowed "
+					"when PORT_MASK already existed\n");
+
+			if (w_present == 0)
+				w_present = 1;
+
+			if (parse_pci_dev_str(app, optarg))
+				rte_panic("Error: Invalid WHITE_LIST "
+						"argument %s\n", optarg);
+
+			break;
+
 		case 'l':
 			if (l_present)
 				rte_panic("Error: LOG_LEVEL is provided "
@@ -2654,8 +2775,9 @@ app_config_args(struct app_params *app, int argc, char **argv)
 	optind = 0; /* reset getopt lib */
 
 	/* Check that mandatory args have been provided */
-	if (!p_present)
-		rte_panic("Error: PORT_MASK is not provided\n");
+	if ((!p_present) && (!w_present))
+		rte_panic("Error: Neither PORT_MASK nor "
+				"WHITE_LIST is provided\n");
 
 	/* Check dependencies between args */
 	if (preproc_params_present && (preproc_present == 0))
-- 
2.5.0



More information about the dev mailing list