From patchwork Thu Jan 28 15:55:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fan Zhang X-Patchwork-Id: 10196 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id E0C9FC4C8; Thu, 28 Jan 2016 16:56:30 +0100 (CET) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id E6C46C4C2 for ; Thu, 28 Jan 2016 16:56:28 +0100 (CET) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP; 28 Jan 2016 07:55:41 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.22,358,1449561600"; d="scan'208";a="891158591" Received: from sie-lab-212-033.ir.intel.com (HELO silpixa00383881.ir.intel.com) ([10.237.212.33]) by fmsmga001.fm.intel.com with ESMTP; 28 Jan 2016 07:55:41 -0800 From: Fan Zhang To: dev@dpdk.org Date: Thu, 28 Jan 2016 15:55:39 +0000 Message-Id: <1453996539-11148-1-git-send-email-roy.fan.zhang@intel.com> X-Mailer: git-send-email 2.5.0 Subject: [dpdk-dev] [PATCH] examples/ip_pipeline: add link identification feature X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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 --- 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 #include #include +#include #include #include #include +#include +#include +#include #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))