[dpdk-dev,v4,2/2] app/testpmd: add command to configure VMDq
Checks
Commit Message
Add the following command to configure VMDq:
port config <port> vmdq
Add new command to testpmd user guide.
Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
---
app/test-pmd/cmdline.c | 60 +++++++++++++
app/test-pmd/testpmd.c | 126 +++++++++++++++++++++++++++-
app/test-pmd/testpmd.h | 1 +
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 7 ++
4 files changed, 193 insertions(+), 1 deletion(-)
Comments
> -----Original Message-----
> From: Iremonger, Bernard
> Sent: Wednesday, January 18, 2017 12:39 AM
> To: dev@dpdk.org; Lu, Wenzhuo <wenzhuo.lu@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>; Zhang, Helin <helin.zhang@intel.com>
> Cc: Iremonger, Bernard <bernard.iremonger@intel.com>
> Subject: [PATCH v4 2/2] app/testpmd: add command to configure VMDq
>
> Add the following command to configure VMDq:
> port config <port> vmdq
>
> Add new command to testpmd user guide.
>
> Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> ---
> app/test-pmd/cmdline.c | 60 +++++++++++++
> app/test-pmd/testpmd.c | 126 +++++++++++++++++++++++++++-
> app/test-pmd/testpmd.h | 1 +
> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 7 ++
> 4 files changed, 193 insertions(+), 1 deletion(-)
>
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> 21d10e4..30969b4 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -629,6 +629,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.\n\n"
> +
> "port config all burst (value)\n"
> " Set the number of packets per burst.\n\n"
>
> @@ -2322,6 +2325,62 @@ 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 initialize network ports.\n");
> + return;
> + }
> +
> + cmd_reconfig_device_queue(port_id, 0, 1); }
I think the device also need to be reconfigured, it should be
cmd_reconfig_device_queue(port_id, 1, 1);
> +
> +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;
> @@ -12438,6 +12497,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/testpmd.c b/app/test-pmd/testpmd.c index bfb2f8e..11d263d 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
> @@ -196,6 +196,34 @@ uint8_t dcb_test = 0; queueid_t nb_rxq = 1; /**<
> Number of RX queues per port. */ queueid_t nb_txq = 1; /**< Number of TX
> queues per port. */
>
> +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},},
> + },
> + },
> +};
> +
> /*
> * Configurable number of RX/TX ring descriptors.
> */
> @@ -1895,6 +1923,102 @@ const uint16_t vlan_tags[] = {
> 24, 25, 26, 27, 28, 29, 30, 31
> };
>
> +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;
> +/* number of pools (if user does not specify any, 8 by default */
> +static uint32_t num_queues = 8; static uint32_t num_pools = 8;
> +
> +/**
> + * 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 num_pools) {
> + struct rte_eth_vmdq_rx_conf conf;
> + uint8_t i;
> +
> + conf.nb_queue_pools = (enum rte_eth_nb_pools)num_pools;
> + conf.nb_pool_maps = num_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 % num_pools));
> + }
> +
> + (void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf)));
> + (void)(rte_memcpy(ð_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_conf port_conf;
> + uint16_t rx_queues, tx_queues;
> + int retval;
> + 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 num_pools in
> + * command line.
> + */
Only found "static uint32_t num_pools = 8;", haven't found any code related
with the num_pools as command arguments.
> + if (num_pools > max_nb_pools) {
> + printf("num_pools %d >max_nb_pools %d\n",
> + num_pools, max_nb_pools);
> + return -1;
> + }
> +
> + retval = get_eth_vmdq_conf(&port_conf, num_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 = num_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;
The variable is set only for printing?
> +
> + printf("num_pf_queues: %u num_pools: %u\n", num_pf_queues,
> num_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);
> + return retval;
> +}
> +
> 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..67bb641 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -582,6 +582,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 60f30bb..ddc4016 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -1438,6 +1438,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
Hi Jingjing,
<snip>
> > Subject: [PATCH v4 2/2] app/testpmd: add command to configure VMDq
> >
> > Add the following command to configure VMDq:
> > port config <port> vmdq
> >
> > Add new command to testpmd user guide.
> >
> > Signed-off-by: Bernard Iremonger <bernard.iremonger@intel.com>
> > ---
> > app/test-pmd/cmdline.c | 60 +++++++++++++
> > app/test-pmd/testpmd.c | 126
> +++++++++++++++++++++++++++-
> > app/test-pmd/testpmd.h | 1 +
> > doc/guides/testpmd_app_ug/testpmd_funcs.rst | 7 ++
> > 4 files changed, 193 insertions(+), 1 deletion(-)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > 21d10e4..30969b4 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -629,6 +629,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.\n\n"
> > +
> > "port config all burst (value)\n"
> > " Set the number of packets per burst.\n\n"
> >
> > @@ -2322,6 +2325,62 @@ 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 initialize network ports.\n");
> > + return;
> > + }
> > +
> > + cmd_reconfig_device_queue(port_id, 0, 1); }
> I think the device also need to be reconfigured, it should be
> cmd_reconfig_device_queue(port_id, 1, 1);
The device has just been configured by the VMDq command so I think it is ok, but I will check it.
> > +
> > +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;
> > @@ -12438,6 +12497,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/testpmd.c b/app/test-pmd/testpmd.c index bfb2f8e..11d263d 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
> > @@ -196,6 +196,34 @@ uint8_t dcb_test = 0; queueid_t nb_rxq = 1; /**<
> > Number of RX queues per port. */ queueid_t nb_txq = 1; /**< Number of
> > TX queues per port. */
> >
> > +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},},
> > + },
> > + },
> > +};
> > +
> > /*
> > * Configurable number of RX/TX ring descriptors.
> > */
> > @@ -1895,6 +1923,102 @@ const uint16_t vlan_tags[] = {
> > 24, 25, 26, 27, 28, 29, 30, 31
> > };
> >
> > +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;
> > +/* number of pools (if user does not specify any, 8 by default */
> > +static uint32_t num_queues = 8; static uint32_t num_pools = 8;
> > +
> > +/**
> > + * 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
> num_pools) {
> > + struct rte_eth_vmdq_rx_conf conf;
> > + uint8_t i;
> > +
> > + conf.nb_queue_pools = (enum rte_eth_nb_pools)num_pools;
> > + conf.nb_pool_maps = num_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 % num_pools));
> > + }
> > +
> > + (void)(rte_memcpy(eth_conf, &vmdq_conf_default,
> sizeof(*eth_conf)));
> > + (void)(rte_memcpy(ð_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_conf port_conf;
> > + uint16_t rx_queues, tx_queues;
> > + int retval;
> > + 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 num_pools in
> > + * command line.
> > + */
> Only found "static uint32_t num_pools = 8;", haven't found any code related
> with the num_pools as command arguments.
>
The default value is 8. I will check if num_pools can be changed with from the command line.
> > + if (num_pools > max_nb_pools) {
> > + printf("num_pools %d >max_nb_pools %d\n",
> > + num_pools, max_nb_pools);
> > + return -1;
> > + }
> > +
> > + retval = get_eth_vmdq_conf(&port_conf, num_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 = num_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;
>
> The variable is set only for printing?
Yes, this is just debug information, similar to sample VMDq code.
> > +
> > + printf("num_pf_queues: %u num_pools: %u\n", num_pf_queues,
> > num_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);
> > + return retval;
> > +}
> > +
> > 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..67bb641 100644
> > --- a/app/test-pmd/testpmd.h
> > +++ b/app/test-pmd/testpmd.h
> > @@ -582,6 +582,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 60f30bb..ddc4016 100644
> > --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > @@ -1438,6 +1438,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
Regards,
Bernard.
@@ -629,6 +629,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.\n\n"
+
"port config all burst (value)\n"
" Set the number of packets per burst.\n\n"
@@ -2322,6 +2325,62 @@ 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 initialize network ports.\n");
+ return;
+ }
+
+ cmd_reconfig_device_queue(port_id, 0, 1);
+}
+
+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;
@@ -12438,6 +12497,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,
@@ -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
@@ -196,6 +196,34 @@ uint8_t dcb_test = 0;
queueid_t nb_rxq = 1; /**< Number of RX queues per port. */
queueid_t nb_txq = 1; /**< Number of TX queues per port. */
+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},},
+ },
+ },
+};
+
/*
* Configurable number of RX/TX ring descriptors.
*/
@@ -1895,6 +1923,102 @@ const uint16_t vlan_tags[] = {
24, 25, 26, 27, 28, 29, 30, 31
};
+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;
+/* number of pools (if user does not specify any, 8 by default */
+static uint32_t num_queues = 8;
+static uint32_t num_pools = 8;
+
+/**
+ * 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 num_pools)
+{
+ struct rte_eth_vmdq_rx_conf conf;
+ uint8_t i;
+
+ conf.nb_queue_pools = (enum rte_eth_nb_pools)num_pools;
+ conf.nb_pool_maps = num_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 % num_pools));
+ }
+
+ (void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf)));
+ (void)(rte_memcpy(ð_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_conf port_conf;
+ uint16_t rx_queues, tx_queues;
+ int retval;
+ 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 num_pools in
+ * command line.
+ */
+ if (num_pools > max_nb_pools) {
+ printf("num_pools %d >max_nb_pools %d\n",
+ num_pools, max_nb_pools);
+ return -1;
+ }
+
+ retval = get_eth_vmdq_conf(&port_conf, num_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 = num_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 num_pools: %u\n", num_pf_queues, num_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);
+ return retval;
+}
+
static int
get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
enum dcb_mode_enable dcb_mode,
@@ -582,6 +582,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);
@@ -1438,6 +1438,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
~~~~~~~~~~~~~~~~~~~