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

Reply via email to