[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