Add the following command to configure VMDq:
port config <port> vmdq

Add the following command to set number of pools:
set nbpool <N>
Add new commands to testpmd user guide.

Signed-off-by: Bernard Iremonger <bernard.iremon...@intel.com>
---
 app/test-pmd/cmdline.c                      |  72 ++++++++-
 app/test-pmd/config.c                       |  14 +-
 app/test-pmd/parameters.c                   |  15 +-
 app/test-pmd/testpmd.c                      | 220 +++++++++++++++++++++++++++-
 app/test-pmd/testpmd.h                      |   7 +-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  18 ++-
 6 files changed, 334 insertions(+), 12 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 2fd862f..f017833 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   Copyright(c) 2014 6WIND S.A.
  *   All rights reserved.
  *
@@ -238,6 +238,9 @@ static void cmd_help_long_parsed(void *parsed_result,
                        "set nbcore (num)\n"
                        "    Set number of cores.\n\n"
 
+                       "set nbpool (num)\n"
+                       "    Set number of VMDq pools.\n\n"
+
                        "set coremask (mask)\n"
                        "    Set the forwarding cores hexadecimal mask.\n\n"
 
@@ -629,6 +632,9 @@ static void cmd_help_long_parsed(void *parsed_result,
                        " pfc (on|off)\n"
                        "    Set the DCB mode.\n\n"
 
+                       "port config (port_id) vmdq\n"
+                       "    Configure VMDq for a port.\n\n"
+
                        "port config all burst (value)\n"
                        "    Set the number of packets per burst.\n\n"
 
@@ -2322,6 +2328,61 @@ cmdline_parse_inst_t cmd_config_dcb = {
         },
 };
 
+/* *** Configure VMDq *** */
+struct cmd_config_vmdq {
+       cmdline_fixed_string_t port;
+       cmdline_fixed_string_t config;
+       uint8_t port_id;
+       cmdline_fixed_string_t vmdq;
+};
+
+static void
+cmd_config_vmdq_parsed(void *parsed_result,
+                      __attribute__((unused)) struct cmdline *cl,
+                      __attribute__((unused)) void *data)
+{
+       struct cmd_config_vmdq *res = parsed_result;
+       portid_t port_id = res->port_id;
+       struct rte_port *port;
+       int ret;
+
+       port = &ports[port_id];
+       /** Check if the port is not started **/
+       if (port->port_status != RTE_PORT_STOPPED) {
+               printf("Please stop port %d first\n", port_id);
+               return;
+       }
+
+       ret = init_port_vmdq_config(port_id);
+       if (ret != 0) {
+               printf("Cannot configure VMDQ for port %d.\n", port_id);
+               return;
+       }
+       cmd_reconfig_device_queue(port_id, 0, 0);
+}
+
+cmdline_parse_token_string_t cmd_config_vmdq_port =
+       TOKEN_STRING_INITIALIZER(struct cmd_config_vmdq, port, "port");
+cmdline_parse_token_string_t cmd_config_vmdq_config =
+       TOKEN_STRING_INITIALIZER(struct cmd_config_vmdq, config, "config");
+cmdline_parse_token_num_t cmd_config_vmdq_port_id =
+       TOKEN_NUM_INITIALIZER(struct cmd_config_vmdq, port_id, UINT8);
+cmdline_parse_token_string_t cmd_config_vmdq_vmdq =
+       TOKEN_STRING_INITIALIZER(struct cmd_config_vmdq, vmdq, "vmdq");
+
+cmdline_parse_inst_t cmd_config_vmdq = {
+       .f = cmd_config_vmdq_parsed,
+       .data = NULL,
+       .help_str = "port config <port-id> vmdq",
+       .tokens = {
+               (void *)&cmd_config_vmdq_port,
+               (void *)&cmd_config_vmdq_config,
+               (void *)&cmd_config_vmdq_port_id,
+               (void *)&cmd_config_vmdq_vmdq,
+               NULL,
+       },
+};
+
 /* *** configure number of packets per burst *** */
 struct cmd_config_burst {
        cmdline_fixed_string_t port;
@@ -2722,7 +2783,7 @@ cmdline_parse_inst_t cmd_set_fwd_mask = {
 };
 
 /*
- * SET NBPORT, NBCORE, PACKET BURST, and VERBOSE LEVEL CONFIGURATION
+ * SET NBPORT, NBCORE, NBPOOL, PACKET BURST, and VERBOSE LEVEL CONFIGURATION
  */
 struct cmd_set_result {
        cmdline_fixed_string_t set;
@@ -2741,6 +2802,8 @@ static void cmd_set_parsed(void *parsed_result,
        } else if (!strcmp(res->what, "nbcore")) {
                set_fwd_lcores_number(res->value);
                fwd_config_setup();
+       } else if (!strcmp(res->what, "nbpool")) {
+               set_vmdq_pool_number(res->value);
        } else if (!strcmp(res->what, "burst"))
                set_nb_pkt_per_burst(res->value);
        else if (!strcmp(res->what, "verbose"))
@@ -2751,14 +2814,14 @@ cmdline_parse_token_string_t cmd_set_set =
        TOKEN_STRING_INITIALIZER(struct cmd_set_result, set, "set");
 cmdline_parse_token_string_t cmd_set_what =
        TOKEN_STRING_INITIALIZER(struct cmd_set_result, what,
-                                "nbport#nbcore#burst#verbose");
+                                "nbport#nbcore#nbpool#burst#verbose");
 cmdline_parse_token_num_t cmd_set_value =
        TOKEN_NUM_INITIALIZER(struct cmd_set_result, value, UINT16);
 
 cmdline_parse_inst_t cmd_set_numbers = {
        .f = cmd_set_parsed,
        .data = NULL,
-       .help_str = "set nbport|nbcore|burst|verbose <value>",
+       .help_str = "set nbport|nbcore|nbpool|burst|verbose <value>",
        .tokens = {
                (void *)&cmd_set_set,
                (void *)&cmd_set_what,
@@ -12462,6 +12525,7 @@ cmdline_parse_ctx_t main_ctx[] = {
        (cmdline_parse_inst_t *)&cmd_link_flow_control_set_autoneg,
        (cmdline_parse_inst_t *)&cmd_priority_flow_control_set,
        (cmdline_parse_inst_t *)&cmd_config_dcb,
+       (cmdline_parse_inst_t *)&cmd_config_vmdq,
        (cmdline_parse_inst_t *)&cmd_read_reg,
        (cmdline_parse_inst_t *)&cmd_read_reg_bit_field,
        (cmdline_parse_inst_t *)&cmd_read_reg_bit,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 5834498..2df501f 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -2063,6 +2063,18 @@ set_fwd_lcores_number(uint16_t nb_lc)
 }
 
 void
+set_vmdq_pool_number(uint32_t nbpool)
+{
+       if (nbpool <= ETH_64_POOLS) {
+               nb_pools = nbpool;
+               printf("Number of VMDq pools set to %u\n", nb_pools);
+       } else {
+               printf("invalid nbpool %u ignored\n", nbpool);
+               return;
+       }
+}
+
+void
 set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt)
 {
        unsigned int i;
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index 28db8cd..5674f94 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -90,7 +90,7 @@ usage(char* progname)
               "[--help|-h] | [--auto-start|-a] | ["
               "--coremask=COREMASK --portmask=PORTMASK --numa "
               "--mbuf-size= | --total-num-mbufs= | "
-              "--nb-cores= | --nb-ports= | "
+              "--nb-cores= | --nb-ports= | --nb-pools |"
 #ifdef RTE_LIBRTE_CMDLINE
               "--eth-peers-configfile= | "
               "--eth-peer=X,M:M:M:M:M:M | "
@@ -196,6 +196,7 @@ usage(char* progname)
                " or total packet length.\n");
        printf("  --disable-link-check: disable check on link status when "
               "starting/stopping ports.\n");
+       printf("  --nb-pools=N: set the number of VMDq pools (N < 64).\n");
 }
 
 #ifdef RTE_LIBRTE_CMDLINE
@@ -561,6 +562,7 @@ launch_args_parse(int argc, char** argv)
                { "no-flush-rx",        0, 0, 0 },
                { "txpkts",                     1, 0, 0 },
                { "disable-link-check",         0, 0, 0 },
+               { "nb-pools",           1, 0, 0 },
                { 0, 0, 0, 0 },
        };
 
@@ -978,7 +980,14 @@ launch_args_parse(int argc, char** argv)
                                no_flush_rx = 1;
                        if (!strcmp(lgopts[opt_idx].name, "disable-link-check"))
                                no_link_check = 1;
-
+                       if (!strcmp(lgopts[opt_idx].name, "nb-pools")) {
+                               n = atoi(optarg);
+                               if (n <= ETH_64_POOLS)
+                                       nb_pools = (uint32_t)n;
+                               else
+                                       rte_exit(EXIT_FAILURE,
+                                                "Invalid number of pools 
%d\n", n);
+                       }
                        break;
                case 'h':
                        usage(argv[0]);
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index bfb2f8e..3d25436 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -1888,13 +1888,229 @@ uint8_t port_is_bonding_slave(portid_t slave_pid)
        return port->slave_flag;
 }
 
+static const struct rte_eth_conf vmdq_conf_default = {
+       .rxmode = {
+               .mq_mode        = ETH_MQ_RX_VMDQ_ONLY,
+               .split_hdr_size = 0,
+               .header_split   = 0, /**< Header Split disabled */
+               .hw_ip_checksum = 0, /**< IP checksum offload disabled */
+               .hw_vlan_filter = 0, /**< VLAN filtering disabled */
+               .jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
+       },
+
+       .txmode = {
+               .mq_mode = ETH_MQ_TX_NONE,
+       },
+       .rx_adv_conf = {
+               /*
+                * should be overridden separately in code with
+                * appropriate values
+                */
+               .vmdq_rx_conf = {
+                       .nb_queue_pools = ETH_8_POOLS,
+                       .enable_default_pool = 0,
+                       .default_pool = 0,
+                       .nb_pool_maps = 0,
+                       .pool_map = {{0, 0},},
+               },
+       },
+};
+
 const uint16_t vlan_tags[] = {
                0,  1,  2,  3,  4,  5,  6,  7,
                8,  9, 10, 11,  12, 13, 14, 15,
                16, 17, 18, 19, 20, 21, 22, 23,
-               24, 25, 26, 27, 28, 29, 30, 31
+               24, 25, 26, 27, 28, 29, 30, 31,
+               32, 33, 34, 35, 36, 37, 38, 39,
+               40, 41, 42, 43, 44, 45, 46, 47,
+               48, 49, 50, 51, 52, 53, 54, 55,
+               56, 57, 58, 59, 60, 61, 62, 63,
+};
+
+const uint16_t num_vlans = RTE_DIM(vlan_tags);
+static uint16_t num_pf_queues, num_vmdq_queues;
+static uint16_t vmdq_pool_base, vmdq_queue_base;
+static uint32_t num_queues;
+/* number of pools (if user does not specify any, 8 by default */
+uint32_t nb_pools = ETH_8_POOLS;
+/* ethernet addresses of ports */
+static struct ether_addr vmdq_ports_eth_addr[RTE_MAX_ETHPORTS];
+/* pool mac addr template, pool mac addr is like: 52 54 00 12 port# pool# */
+static struct ether_addr pool_addr_template = {
+       .addr_bytes = {0x52, 0x54, 0x00, 0x12, 0x00, 0x00}
 };
 
+/**
+ * Builds up the correct configuration for vmdq based on the vlan tags array
+ * given above, and determine the queue number and pool map number according to
+ * valid pool number
+ */
+static int
+get_eth_vmdq_conf(struct rte_eth_conf *eth_conf, uint32_t nb_pools)
+{
+       struct rte_eth_vmdq_rx_conf conf;
+       uint8_t i;
+
+       conf.nb_queue_pools = (enum rte_eth_nb_pools)nb_pools;
+       conf.nb_pool_maps = nb_pools;
+       conf.enable_default_pool = 0;
+       conf.default_pool = 0; /* set explicit value, even if not used */
+
+       for (i = 0; i < conf.nb_pool_maps; i++) {
+               conf.pool_map[i].vlan_id = vlan_tags[i];
+               conf.pool_map[i].pools = (1UL << (i % nb_pools));
+       }
+
+       (void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf)));
+       (void)(rte_memcpy(&eth_conf->rx_adv_conf.vmdq_rx_conf, &conf,
+              sizeof(eth_conf->rx_adv_conf.vmdq_rx_conf)));
+       return 0;
+}
+
+/**
+ * Configures VMDq for a given port using global settings.
+ */
+int
+init_port_vmdq_config(uint8_t port)
+{
+       struct rte_eth_dev_info dev_info;
+       struct rte_eth_rxconf *rxconf;
+       struct rte_eth_conf port_conf;
+       struct rte_mempool *mbp;
+       uint16_t rx_queues, tx_queues;
+       const uint16_t rx_queue_size = RTE_TEST_RX_DESC_DEFAULT;
+       const uint16_t tx_queue_size = RTE_TEST_TX_DESC_DEFAULT;
+       int retval;
+       uint16_t q;
+       uint16_t queues_per_pool;
+       uint32_t max_nb_pools;
+
+       if (port >= rte_eth_dev_count())
+               return -1;
+       /**
+        * The max pool number from dev_info will be used to validate the pool
+        * number.
+        */
+       rte_eth_dev_info_get(port, &dev_info);
+       max_nb_pools = (uint32_t)dev_info.max_vmdq_pools;
+       /**
+        * We allow to process part of VMDQ pools specified by nb_pools in
+        * command line.
+        */
+       if (nb_pools > max_nb_pools) {
+               printf("nb_pools %d > max_nb_pools %d\n",
+                       nb_pools, max_nb_pools);
+               return -1;
+       }
+
+       retval = get_eth_vmdq_conf(&port_conf, max_nb_pools);
+       if (retval < 0)
+               return retval;
+
+       /*
+        * NIC queues are divided into pf queues and vmdq queues.
+        */
+       /* There is assumption here all ports have the same configuration! */
+       num_pf_queues = dev_info.max_rx_queues - dev_info.vmdq_queue_num;
+       queues_per_pool = dev_info.vmdq_queue_num / dev_info.max_vmdq_pools;
+       num_vmdq_queues = nb_pools * queues_per_pool;
+       num_queues = num_pf_queues + num_vmdq_queues;
+       vmdq_queue_base = dev_info.vmdq_queue_base;
+       vmdq_pool_base  = dev_info.vmdq_pool_base;
+
+       printf("num_pf_queues: %u nb_pools: %u\n", num_pf_queues, nb_pools);
+       printf("each vmdq pool has %u queues\n", queues_per_pool);
+       printf("vmdq_queue_base: %d vmdq_pool_base: %d\n", vmdq_queue_base, 
vmdq_pool_base);
+
+       /*
+        * All queues including pf queues are setup.
+        * This is because VMDQ queues doesn't always start from zero, and the
+        * PMD layer doesn't support selectively initialising part of rx/tx
+        * queues.
+        */
+       rx_queues = (uint16_t)dev_info.max_rx_queues;
+       tx_queues = (uint16_t)dev_info.max_tx_queues;
+       retval = rte_eth_dev_configure(port, rx_queues, tx_queues, &port_conf);
+       if (retval < 0) {
+               printf("rte_eth_dev_configure %d failed\n", retval);
+               return retval;
+       }
+
+       mbp = mbuf_pool_find(0);
+       if (mbp == NULL) {
+               printf("mbuf_pool_find failed\n");
+               return -1;
+       }
+
+       rte_eth_dev_info_get(port, &dev_info);
+       rxconf = &dev_info.default_rxconf;
+       rxconf->rx_drop_en = 1;
+       for (q = 0; q < rx_queues; q++) {
+               retval = rte_eth_rx_queue_setup(port, q, rx_queue_size,
+                                       rte_eth_dev_socket_id(port),
+                                       rxconf,
+                                       mbp);
+               if (retval < 0) {
+                       printf("initialise rx queue %d failed\n", q);
+                       return retval;
+               }
+       }
+
+       for (q = 0; q < tx_queues; q++) {
+               retval = rte_eth_tx_queue_setup(port, q, tx_queue_size,
+                                       rte_eth_dev_socket_id(port),
+                                       NULL);
+               if (retval < 0) {
+                       printf("initialise tx queue %d failed\n", q);
+                       return retval;
+               }
+       }
+
+       retval  = rte_eth_dev_start(port);
+       if (retval < 0) {
+               printf("rte_eth_dev_start %d failed\n", retval);
+               return retval;
+       }
+       printf("port %d started\n", port);
+
+       rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]);
+
+       printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
+                       " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", port,
+                       vmdq_ports_eth_addr[port].addr_bytes[0],
+                       vmdq_ports_eth_addr[port].addr_bytes[1],
+                       vmdq_ports_eth_addr[port].addr_bytes[2],
+                       vmdq_ports_eth_addr[port].addr_bytes[3],
+                       vmdq_ports_eth_addr[port].addr_bytes[4],
+                       vmdq_ports_eth_addr[port].addr_bytes[5]);
+
+       /*
+        * Set mac for each pool.
+        * There is no default mac for the pools in i40.
+        * Removes this after i40e fixes this issue.
+        */
+       for (q = 0; q < nb_pools; q++) {
+               struct ether_addr mac;
+
+               mac = pool_addr_template;
+               mac.addr_bytes[4] = port;
+               mac.addr_bytes[5] = q;
+               printf("Port %u vmdq pool %u set mac 
%02x:%02x:%02x:%02x:%02x:%02x\n",
+                       port, q,
+                       mac.addr_bytes[0], mac.addr_bytes[1],
+                       mac.addr_bytes[2], mac.addr_bytes[3],
+                       mac.addr_bytes[4], mac.addr_bytes[5]);
+               retval = rte_eth_dev_mac_addr_add(port, &mac,
+                               q + vmdq_pool_base);
+               if (retval) {
+                       printf("mac addr add failed at pool %d\n", q);
+                       return retval;
+               }
+       }
+
+       return 0;
+}
+
 static  int
 get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
                 enum dcb_mode_enable dcb_mode,
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index ee59460..eadb1c2 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -368,6 +368,8 @@ extern queueid_t nb_txq;
 extern uint16_t nb_rxd;
 extern uint16_t nb_txd;
 
+extern uint32_t nb_pools;
+
 extern int16_t rx_free_thresh;
 extern int8_t rx_drop_en;
 extern int16_t tx_free_thresh;
@@ -546,6 +548,8 @@ void set_fwd_ports_mask(uint64_t portmask);
 void set_fwd_ports_number(uint16_t nb_pt);
 int port_is_forwarding(portid_t port_id);
 
+void set_vmdq_pool_number(uint32_t nbpool);
+
 void rx_vlan_strip_set(portid_t port_id, int on);
 void rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on);
 
@@ -582,6 +586,7 @@ uint8_t port_is_bonding_slave(portid_t slave_pid);
 int init_port_dcb_config(portid_t pid, enum dcb_mode_enable dcb_mode,
                     enum rte_eth_nb_tcs num_tcs,
                     uint8_t pfc_en);
+int init_port_vmdq_config(uint8_t port);
 int start_port(portid_t pid);
 void stop_port(portid_t pid);
 void close_port(portid_t pid);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst 
b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 16ac097..37bf7b1 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -1,5 +1,5 @@
 ..  BSD LICENSE
-    Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+    Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
     All rights reserved.
 
     Redistribution and use in source and binary forms, with or without
@@ -360,6 +360,15 @@ set nbport (num)
 
 This is equivalent to the ``--nb-ports`` command-line option.
 
+set nbpool
+~~~~~~~~~~
+
+Set the number of pools used by the application::
+
+   testpmd> set nbpool (num)
+
+This is equivalent to the ``--nb-pools`` command-line option.
+
 set nbcore
 ~~~~~~~~~~
 
@@ -1438,6 +1447,13 @@ Set the DCB mode for an individual port::
 
 The traffic class should be 4 or 8.
 
+port config - VMDq
+~~~~~~~~~~~~~~~~~~
+
+Configure VMDq for an individual port::
+
+   testpmd> port config (port_id) vmdq
+
 port config - Burst
 ~~~~~~~~~~~~~~~~~~~
 
-- 
2.10.1

Reply via email to