[v2,1/3] app/testpmd: support congestion management CLIs
Checks
Commit Message
From: Sunil Kumar Kori <skori@marvell.com>
Support congestion management CLIs.
Depends-on: patch-24902 ("ethdev: support congestion management")
Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
---
v1..v2:
- Rebase on top of the dpdk-next-net-mrvl/for-next-net
app/test-pmd/cmdline.c | 15 +
app/test-pmd/cmdline_cman.c | 390 ++++++++++++++++++++
app/test-pmd/cmdline_cman.h | 12 +
app/test-pmd/meson.build | 1 +
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 26 ++
5 files changed, 444 insertions(+)
create mode 100644 app/test-pmd/cmdline_cman.c
create mode 100644 app/test-pmd/cmdline_cman.h
Comments
Please review the following changes and provide feedback.
Regards
Sunil Kumar Kori
> -----Original Message-----
> From: skori@marvell.com <skori@marvell.com>
> Sent: Thursday, September 29, 2022 3:25 PM
> To: Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> <yuying.zhang@intel.com>
> Cc: dev@dpdk.org; Sunil Kumar Kori <skori@marvell.com>
> Subject: [PATCH v2 1/3] app/testpmd: support congestion management CLIs
>
> From: Sunil Kumar Kori <skori@marvell.com>
>
> Support congestion management CLIs.
>
> Depends-on: patch-24902 ("ethdev: support congestion management")
>
> Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
> ---
> v1..v2:
> - Rebase on top of the dpdk-next-net-mrvl/for-next-net
>
> app/test-pmd/cmdline.c | 15 +
> app/test-pmd/cmdline_cman.c | 390 ++++++++++++++++++++
> app/test-pmd/cmdline_cman.h | 12 +
> app/test-pmd/meson.build | 1 +
> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 26 ++
> 5 files changed, 444 insertions(+)
> create mode 100644 app/test-pmd/cmdline_cman.c create mode 100644
> app/test-pmd/cmdline_cman.h
>
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> 51321de9ed..ce278eadb0 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -60,6 +60,7 @@
> #include <rte_pmd_bnxt.h>
> #endif
> #include "testpmd.h"
> +#include "cmdline_cman.h"
> #include "cmdline_mtr.h"
> #include "cmdline_tm.h"
> #include "bpf_cmd.h"
> @@ -599,6 +600,17 @@ static void cmd_help_long_parsed(void
> *parsed_result,
> "set port (port_id) fec_mode auto|off|rs|baser\n"
> " set fec mode for a specific port\n\n"
>
> + "show port cman capa (port_id)\n"
> + " Show congestion management capabilities\n\n"
> +
> + "show port cman config (port_id)\n"
> + " Show congestion management configuration\n\n"
> +
> + "set port cman config (port_id) (queue_id) default | "
> + "[obj (queue|queue_mempool) mode red
> (min_thresh) "
> + "(max_thresh) (prob_inv)]\n"
> + " Set congestion management configuration\n\n"
> +
> , list_pkt_forwarding_modes()
> );
> }
> @@ -12990,6 +13002,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
> (cmdline_parse_inst_t *)&cmd_show_capability,
> (cmdline_parse_inst_t *)&cmd_set_flex_is_pattern,
> (cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern,
> + (cmdline_parse_inst_t *)&cmd_show_port_cman_capa,
> + (cmdline_parse_inst_t *)&cmd_show_port_cman_config,
> + (cmdline_parse_inst_t *)&cmd_set_port_cman_config,
> NULL,
> };
>
> diff --git a/app/test-pmd/cmdline_cman.c b/app/test-pmd/cmdline_cman.c
> new file mode 100644 index 0000000000..344759189d
> --- /dev/null
> +++ b/app/test-pmd/cmdline_cman.c
> @@ -0,0 +1,390 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell International Ltd.
> + */
> +
> +#include <cmdline_parse.h>
> +#include <cmdline_parse_num.h>
> +#include <cmdline_parse_string.h>
> +
> +#include <rte_ethdev.h>
> +
> +#include "testpmd.h"
> +
> +#define PARSE_DELIMITER " \f\n\r\t\v"
> +
> +static int
> +parse_uint(uint64_t *value, const char *str) {
> + char *next = NULL;
> + uint64_t n;
> +
> + errno = 0;
> + /* Parse number string */
> + n = strtol(str, &next, 10);
> + if (errno != 0 || str == next || *next != '\0')
> + return -1;
> +
> + *value = n;
> +
> + return 0;
> +}
> +
> +static int
> +parse_cman_obj_str(char *str, uint64_t *obj) {
> + char *token;
> +
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (token == NULL)
> + return 0;
> +
> + if (strcasecmp(token, "queue") == 0)
> + *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE;
> + else if (strcasecmp(token, "queue_mempool") == 0)
> + *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE_MEMPOOL;
> + else
> + return -1;
> +
> + return 0;
> +}
> +
> +static int
> +parse_cman_mode_str(char *str, uint64_t *mode) {
> + char *token;
> +
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (token == NULL)
> + return 0;
> +
> + if (strcasecmp(token, "red") == 0)
> + *mode = RTE_CMAN_RED;
> + else
> + return -1;
> +
> + return 0;
> +}
> +
> +static int
> +parse_cman_params_str(uint16_t port_id, char *str,
> + struct rte_eth_cman_config *cfg) {
> + uint64_t obj = 0, mode = 0, min_th = 0, max_th = 0, maxp_inv = 0;
> + struct rte_eth_cman_info info;
> + char *token;
> + int ret;
> +
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (!strcasecmp(token, "default")) {
> + ret = rte_eth_cman_config_init(port_id, cfg);
> + if (ret) {
> + fprintf(stderr, "error in default initialization\n");
> + return ret;
> + }
> + return 0;
> + }
> +
> + /* First token: obj name */
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (token == NULL) {
> + fprintf(stderr, "Object param parse error\n");
> + goto error;
> + }
> +
> + ret = parse_cman_obj_str(token, &obj);
> + if (ret) {
> + fprintf(stderr, "Object value is invalid\n");
> + goto error;
> + }
> +
> + /* Second token: mode name */
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (token == NULL) {
> + fprintf(stderr, " Mode param is invalid\n");
> + goto error;
> + }
> +
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (token == NULL) {
> + fprintf(stderr, " Mode value is invalid\n");
> + goto error;
> + }
> +
> + ret = parse_cman_mode_str(token, &mode);
> + if (ret) {
> + fprintf(stderr, "mode string parse error\n");
> + goto error;
> + }
> +
> + /* Third token: minimum threshold */
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (token == NULL) {
> + fprintf(stderr, "Minimum threshold parse error\n");
> + goto error;
> + }
> +
> + ret = parse_uint(&min_th, token);
> + if (ret != 0 || min_th > UINT8_MAX) {
> + fprintf(stderr, "Minimum threshold is invalid\n");
> + goto error;
> + }
> +
> + /* Fourth token: maximum threshold */
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (token == NULL) {
> + fprintf(stderr, "Maximum threshold parse error\n");
> + goto error;
> + }
> +
> + ret = parse_uint(&max_th, token);
> + if (ret != 0 || max_th > UINT8_MAX) {
> + fprintf(stderr, "Maximum threshold is invalid\n");
> + goto error;
> + }
> +
> + /* Fifth token: probability inversion */
> + token = strtok_r(str, PARSE_DELIMITER, &str);
> + if (token == NULL) {
> + fprintf(stderr, "Maximum probability inversion parse
> error\n");
> + goto error;
> + }
> +
> + ret = parse_uint(&maxp_inv, token);
> + if (ret != 0 || maxp_inv == 0 || maxp_inv > UINT16_MAX) {
> + fprintf(stderr, "Maximum probability inversion is invalid\n");
> + goto error;
> + }
> +
> + memset(&info, 0, sizeof(struct rte_eth_cman_info));
> + ret = rte_eth_cman_info_get(port_id, &info);
> + if (ret) {
> + fprintf(stderr, "Congestion management capa get error\n");
> + goto error;
> + }
> +
> + if (!(info.objs_supported & obj)) {
> + fprintf(stderr, "Object type is not supported by driver\n");
> + goto error;
> + }
> +
> + if (!(info.modes_supported & mode)) {
> + fprintf(stderr, "Mode is not supported by driver\n");
> + goto error;
> + }
> +
> + cfg->obj = obj;
> + cfg->mode = mode;
> + cfg->mode_param.red.min_th = min_th;
> + cfg->mode_param.red.max_th = max_th;
> + cfg->mode_param.red.maxp_inv = maxp_inv;
> +
> + return 0;
> +
> +error:
> + return -EINVAL;
> +}
> +
> +/* *** Show Port Congestion Management Capabilities *** */ struct
> +cmd_show_port_cman_capa_result {
> + cmdline_fixed_string_t show;
> + cmdline_fixed_string_t port;
> + cmdline_fixed_string_t cman;
> + cmdline_fixed_string_t capa;
> + uint16_t port_id;
> +};
> +
> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_show =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_show_port_cman_capa_result, show, "show");
> +
> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_port =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_show_port_cman_capa_result, port, "port");
> +
> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_cman =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_show_port_cman_capa_result, cman, "cman");
> +
> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_capa =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_show_port_cman_capa_result, capa, "capa");
> +
> +static cmdline_parse_token_num_t cmd_show_port_cman_capa_port_id =
> + TOKEN_NUM_INITIALIZER(
> + struct cmd_show_port_cman_capa_result, port_id,
> RTE_UINT16);
> +
> +static void cmd_show_port_cman_capa_parsed(void *parsed_result,
> + __rte_unused struct cmdline *cl,
> + __rte_unused void *data)
> +{
> + struct cmd_show_port_cman_capa_result *res = parsed_result;
> + uint16_t port_id = res->port_id;
> + struct rte_eth_cman_info info;
> + int ret;
> +
> + memset(&info, 0, sizeof(struct rte_eth_cman_info));
> + ret = rte_eth_cman_info_get(port_id, &info);
> + if (ret)
> + return;
> +
> + printf("\n**** Port Congestion Management Capabilities
> ****\n\n");
> + printf("modes_supported 0x%" PRIx64 "\n", info.modes_supported);
> + printf("objs_supported 0x%" PRIx64 "\n", info.objs_supported); }
> +
> +cmdline_parse_inst_t cmd_show_port_cman_capa = {
> + .f = cmd_show_port_cman_capa_parsed,
> + .data = NULL,
> + .help_str = "show port cman capa <port_id>",
> + .tokens = {
> + (void *)&cmd_show_port_cman_capa_show,
> + (void *)&cmd_show_port_cman_capa_port,
> + (void *)&cmd_show_port_cman_capa_cman,
> + (void *)&cmd_show_port_cman_capa_capa,
> + (void *)&cmd_show_port_cman_capa_port_id,
> + NULL,
> + },
> +};
> +
> +/* *** Show Port Congestion Management configuration *** */ struct
> +cmd_show_port_cman_cfg_result {
> + cmdline_fixed_string_t show;
> + cmdline_fixed_string_t port;
> + cmdline_fixed_string_t cman;
> + cmdline_fixed_string_t cfg;
> + uint16_t port_id;
> +};
> +
> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_show =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_show_port_cman_cfg_result, show, "show");
> +
> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_port =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_show_port_cman_cfg_result, port, "port");
> +
> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cman =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_show_port_cman_cfg_result, cman, "cman");
> +
> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cfg =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_show_port_cman_cfg_result, cfg, "config");
> +
> +static cmdline_parse_token_num_t cmd_show_port_cman_cfg_port_id =
> + TOKEN_NUM_INITIALIZER(
> + struct cmd_show_port_cman_cfg_result, port_id,
> RTE_UINT16);
> +
> +static void cmd_show_port_cman_cfg_parsed(void *parsed_result,
> + __rte_unused struct cmdline *cl,
> + __rte_unused void *data)
> +{
> + struct cmd_show_port_cman_cfg_result *res = parsed_result;
> + uint16_t port_id = res->port_id;
> + struct rte_eth_cman_config cfg;
> + int ret;
> +
> + memset(&cfg, 0, sizeof(struct rte_eth_cman_config));
> + ret = rte_eth_cman_config_get(port_id, &cfg);
> + if (ret)
> + return;
> +
> + printf("\n**** Port Congestion Management Configuration
> ****\n\n");
> + printf("cman object 0x%" PRIx32 "\n", cfg.obj);
> + printf("cman Rx queue %" PRIx16 "\n", cfg.obj_param.rx_queue);
> + printf("cman mode 0x%" PRIx32 "\n", cfg.mode);
> + printf("cman RED min thresh %" PRIx8 "\n",
> cfg.mode_param.red.min_th);
> + printf("cman RED max thresh %" PRIx8 "\n",
> cfg.mode_param.red.max_th);
> + printf("cman RED Prob inversion %" PRIx16 "\n",
> + cfg.mode_param.red.maxp_inv);
> +}
> +
> +cmdline_parse_inst_t cmd_show_port_cman_config = {
> + .f = cmd_show_port_cman_cfg_parsed,
> + .data = NULL,
> + .help_str = "show port cman config <port_id>",
> + .tokens = {
> + (void *)&cmd_show_port_cman_cfg_show,
> + (void *)&cmd_show_port_cman_cfg_port,
> + (void *)&cmd_show_port_cman_cfg_cman,
> + (void *)&cmd_show_port_cman_cfg_cfg,
> + (void *)&cmd_show_port_cman_cfg_port_id,
> + NULL,
> + },
> +};
> +
> +/* *** Set Port Congestion Management configuration *** */ struct
> +cmd_set_port_cman_cfg_result {
> + cmdline_fixed_string_t set;
> + cmdline_fixed_string_t port;
> + cmdline_fixed_string_t cman;
> + cmdline_fixed_string_t cfg;
> + uint16_t port_id;
> + uint16_t qid;
> + cmdline_multi_string_t params;
> +};
> +
> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_set =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_set_port_cman_cfg_result, set, "set");
> +
> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_port =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_set_port_cman_cfg_result, port, "port");
> +
> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cman =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_set_port_cman_cfg_result, cman, "cman");
> +
> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cfg =
> + TOKEN_STRING_INITIALIZER(
> + struct cmd_set_port_cman_cfg_result, cfg, "config");
> +
> +static cmdline_parse_token_num_t cmd_set_port_cman_cfg_port_id =
> + TOKEN_NUM_INITIALIZER(
> + struct cmd_set_port_cman_cfg_result, port_id, RTE_UINT16);
> +
> +static cmdline_parse_token_num_t cmd_set_port_cman_cfg_qid =
> + TOKEN_NUM_INITIALIZER(
> + struct cmd_set_port_cman_cfg_result, qid, RTE_UINT16);
> +
> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_params =
> + TOKEN_STRING_INITIALIZER(struct cmd_set_port_cman_cfg_result,
> + params, TOKEN_STRING_MULTI);
> +
> +static void cmd_set_port_cman_cfg_parsed(void *parsed_result,
> + __rte_unused struct cmdline *cl,
> + __rte_unused void *data)
> +{
> + struct cmd_set_port_cman_cfg_result *res = parsed_result;
> + uint16_t port_id = res->port_id;
> + struct rte_eth_cman_config cfg;
> + int ret;
> +
> + ret = parse_cman_params_str(port_id, res->params, &cfg);
> + if (ret) {
> + fprintf(stderr, "params string parse error\n");
> + return;
> + }
> +
> + cfg.obj_param.rx_queue = res->qid;
> + rte_eth_cman_config_set(port_id, &cfg); }
> +
> +cmdline_parse_inst_t cmd_set_port_cman_config = {
> + .f = cmd_set_port_cman_cfg_parsed,
> + .data = NULL,
> + .help_str = "set port cman config <port_id> <queue_id> "
> + "default | [obj <queue|queue_mempool> mode red "
> + "<min_thresh> <max_thresh> <prob_inv>]",
> + .tokens = {
> + (void *)&cmd_set_port_cman_cfg_set,
> + (void *)&cmd_set_port_cman_cfg_port,
> + (void *)&cmd_set_port_cman_cfg_cman,
> + (void *)&cmd_set_port_cman_cfg_cfg,
> + (void *)&cmd_set_port_cman_cfg_port_id,
> + (void *)&cmd_set_port_cman_cfg_qid,
> + (void *)&cmd_set_port_cman_cfg_params,
> + NULL,
> + },
> +};
> diff --git a/app/test-pmd/cmdline_cman.h b/app/test-pmd/cmdline_cman.h
> new file mode 100644 index 0000000000..bd6c99ce35
> --- /dev/null
> +++ b/app/test-pmd/cmdline_cman.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell International Ltd.
> + */
> +
> +#ifndef _CMDLINE_CMAN_H_
> +#define _CMDLINE_CMAN_H_
> +
> +extern cmdline_parse_inst_t cmd_show_port_cman_capa; extern
> +cmdline_parse_inst_t cmd_show_port_cman_config; extern
> +cmdline_parse_inst_t cmd_set_port_cman_config;
> +
> +#endif /* _CMDLINE_CMAN_H_ */
> diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index
> 74399178dd..c03d9dfebb 100644
> --- a/app/test-pmd/meson.build
> +++ b/app/test-pmd/meson.build
> @@ -7,6 +7,7 @@ cflags += '-Wno-deprecated-declarations'
> sources = files(
> '5tswap.c',
> 'cmdline.c',
> + 'cmdline_cman.c',
> 'cmdline_flow.c',
> 'cmdline_mtr.c',
> 'cmdline_tm.c',
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index d3075bf87d..b9c7b468af 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -5317,6 +5317,32 @@ Flex pattern can be shared between ports.
> testpmd> flow create 0 ingress pattern eth / ipv4 / udp / flex item is 3
> pattern is 2 / end actions mark id 1 / queue index 0 / end
> Flow rule #0 created
>
> +Congestion Management
> +---------------------
> +
> +Get capabilities
> +~~~~~~~~~~~~~~~~
> +
> +Retrieve congestion management capabilities supported by driver for given
> port.
> +Below example command retrieves capabilities for port 0::
> +
> + testpmd> show port cman capa 0
> +
> +Get configuration
> +~~~~~~~~~~~~~~~~~
> +Retrieve congestion management configuration for given port. Below
> +example command retrieves configuration for port 0::
> +
> + testpmd> show port cman config 0
> +
> +Set configuration
> +~~~~~~~~~~~~~~~~~
> +Configures congestion management settings on given queue or mempool
> +associated with queue. Below example command configures RED as
> +congestion management algo for port 0 and queue 0::
> +
> + testpmd> set port cman config 0 0 obj queue mode red 10 100 1
> +
> Driver specific commands
> ------------------------
>
> --
> 2.25.1
@Aman, @Yuying, please, help to review the patch.
On 10/12/22 12:01, Sunil Kumar Kori wrote:
> Please review the following changes and provide feedback.
>
> Regards
> Sunil Kumar Kori
>
>> -----Original Message-----
>> From: skori@marvell.com <skori@marvell.com>
>> Sent: Thursday, September 29, 2022 3:25 PM
>> To: Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
>> <yuying.zhang@intel.com>
>> Cc: dev@dpdk.org; Sunil Kumar Kori <skori@marvell.com>
>> Subject: [PATCH v2 1/3] app/testpmd: support congestion management CLIs
>>
>> From: Sunil Kumar Kori <skori@marvell.com>
>>
>> Support congestion management CLIs.
>>
>> Depends-on: patch-24902 ("ethdev: support congestion management")
>>
>> Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
>> ---
>> v1..v2:
>> - Rebase on top of the dpdk-next-net-mrvl/for-next-net
>>
>> app/test-pmd/cmdline.c | 15 +
>> app/test-pmd/cmdline_cman.c | 390 ++++++++++++++++++++
>> app/test-pmd/cmdline_cman.h | 12 +
>> app/test-pmd/meson.build | 1 +
>> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 26 ++
>> 5 files changed, 444 insertions(+)
>> create mode 100644 app/test-pmd/cmdline_cman.c create mode 100644
>> app/test-pmd/cmdline_cman.h
>>
>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
>> 51321de9ed..ce278eadb0 100644
>> --- a/app/test-pmd/cmdline.c
>> +++ b/app/test-pmd/cmdline.c
>> @@ -60,6 +60,7 @@
>> #include <rte_pmd_bnxt.h>
>> #endif
>> #include "testpmd.h"
>> +#include "cmdline_cman.h"
>> #include "cmdline_mtr.h"
>> #include "cmdline_tm.h"
>> #include "bpf_cmd.h"
>> @@ -599,6 +600,17 @@ static void cmd_help_long_parsed(void
>> *parsed_result,
>> "set port (port_id) fec_mode auto|off|rs|baser\n"
>> " set fec mode for a specific port\n\n"
>>
>> + "show port cman capa (port_id)\n"
>> + " Show congestion management capabilities\n\n"
>> +
>> + "show port cman config (port_id)\n"
>> + " Show congestion management configuration\n\n"
>> +
>> + "set port cman config (port_id) (queue_id) default | "
>> + "[obj (queue|queue_mempool) mode red
>> (min_thresh) "
>> + "(max_thresh) (prob_inv)]\n"
>> + " Set congestion management configuration\n\n"
>> +
>> , list_pkt_forwarding_modes()
>> );
>> }
>> @@ -12990,6 +13002,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>> (cmdline_parse_inst_t *)&cmd_show_capability,
>> (cmdline_parse_inst_t *)&cmd_set_flex_is_pattern,
>> (cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern,
>> + (cmdline_parse_inst_t *)&cmd_show_port_cman_capa,
>> + (cmdline_parse_inst_t *)&cmd_show_port_cman_config,
>> + (cmdline_parse_inst_t *)&cmd_set_port_cman_config,
>> NULL,
>> };
>>
>> diff --git a/app/test-pmd/cmdline_cman.c b/app/test-pmd/cmdline_cman.c
>> new file mode 100644 index 0000000000..344759189d
>> --- /dev/null
>> +++ b/app/test-pmd/cmdline_cman.c
>> @@ -0,0 +1,390 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause
>> + * Copyright(C) 2022 Marvell International Ltd.
>> + */
>> +
>> +#include <cmdline_parse.h>
>> +#include <cmdline_parse_num.h>
>> +#include <cmdline_parse_string.h>
>> +
>> +#include <rte_ethdev.h>
>> +
>> +#include "testpmd.h"
>> +
>> +#define PARSE_DELIMITER " \f\n\r\t\v"
>> +
>> +static int
>> +parse_uint(uint64_t *value, const char *str) {
>> + char *next = NULL;
>> + uint64_t n;
>> +
>> + errno = 0;
>> + /* Parse number string */
>> + n = strtol(str, &next, 10);
>> + if (errno != 0 || str == next || *next != '\0')
>> + return -1;
>> +
>> + *value = n;
>> +
>> + return 0;
>> +}
>> +
>> +static int
>> +parse_cman_obj_str(char *str, uint64_t *obj) {
>> + char *token;
>> +
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (token == NULL)
>> + return 0;
>> +
>> + if (strcasecmp(token, "queue") == 0)
>> + *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE;
>> + else if (strcasecmp(token, "queue_mempool") == 0)
>> + *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE_MEMPOOL;
>> + else
>> + return -1;
>> +
>> + return 0;
>> +}
>> +
>> +static int
>> +parse_cman_mode_str(char *str, uint64_t *mode) {
>> + char *token;
>> +
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (token == NULL)
>> + return 0;
>> +
>> + if (strcasecmp(token, "red") == 0)
>> + *mode = RTE_CMAN_RED;
>> + else
>> + return -1;
>> +
>> + return 0;
>> +}
>> +
>> +static int
>> +parse_cman_params_str(uint16_t port_id, char *str,
>> + struct rte_eth_cman_config *cfg) {
>> + uint64_t obj = 0, mode = 0, min_th = 0, max_th = 0, maxp_inv = 0;
>> + struct rte_eth_cman_info info;
>> + char *token;
>> + int ret;
>> +
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (!strcasecmp(token, "default")) {
>> + ret = rte_eth_cman_config_init(port_id, cfg);
>> + if (ret) {
>> + fprintf(stderr, "error in default initialization\n");
>> + return ret;
>> + }
>> + return 0;
>> + }
>> +
>> + /* First token: obj name */
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (token == NULL) {
>> + fprintf(stderr, "Object param parse error\n");
>> + goto error;
>> + }
>> +
>> + ret = parse_cman_obj_str(token, &obj);
>> + if (ret) {
>> + fprintf(stderr, "Object value is invalid\n");
>> + goto error;
>> + }
>> +
>> + /* Second token: mode name */
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (token == NULL) {
>> + fprintf(stderr, " Mode param is invalid\n");
>> + goto error;
>> + }
>> +
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (token == NULL) {
>> + fprintf(stderr, " Mode value is invalid\n");
>> + goto error;
>> + }
>> +
>> + ret = parse_cman_mode_str(token, &mode);
>> + if (ret) {
>> + fprintf(stderr, "mode string parse error\n");
>> + goto error;
>> + }
>> +
>> + /* Third token: minimum threshold */
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (token == NULL) {
>> + fprintf(stderr, "Minimum threshold parse error\n");
>> + goto error;
>> + }
>> +
>> + ret = parse_uint(&min_th, token);
>> + if (ret != 0 || min_th > UINT8_MAX) {
>> + fprintf(stderr, "Minimum threshold is invalid\n");
>> + goto error;
>> + }
>> +
>> + /* Fourth token: maximum threshold */
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (token == NULL) {
>> + fprintf(stderr, "Maximum threshold parse error\n");
>> + goto error;
>> + }
>> +
>> + ret = parse_uint(&max_th, token);
>> + if (ret != 0 || max_th > UINT8_MAX) {
>> + fprintf(stderr, "Maximum threshold is invalid\n");
>> + goto error;
>> + }
>> +
>> + /* Fifth token: probability inversion */
>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>> + if (token == NULL) {
>> + fprintf(stderr, "Maximum probability inversion parse
>> error\n");
>> + goto error;
>> + }
>> +
>> + ret = parse_uint(&maxp_inv, token);
>> + if (ret != 0 || maxp_inv == 0 || maxp_inv > UINT16_MAX) {
>> + fprintf(stderr, "Maximum probability inversion is invalid\n");
>> + goto error;
>> + }
>> +
>> + memset(&info, 0, sizeof(struct rte_eth_cman_info));
>> + ret = rte_eth_cman_info_get(port_id, &info);
>> + if (ret) {
>> + fprintf(stderr, "Congestion management capa get error\n");
>> + goto error;
>> + }
>> +
>> + if (!(info.objs_supported & obj)) {
>> + fprintf(stderr, "Object type is not supported by driver\n");
>> + goto error;
>> + }
>> +
>> + if (!(info.modes_supported & mode)) {
>> + fprintf(stderr, "Mode is not supported by driver\n");
>> + goto error;
>> + }
>> +
>> + cfg->obj = obj;
>> + cfg->mode = mode;
>> + cfg->mode_param.red.min_th = min_th;
>> + cfg->mode_param.red.max_th = max_th;
>> + cfg->mode_param.red.maxp_inv = maxp_inv;
>> +
>> + return 0;
>> +
>> +error:
>> + return -EINVAL;
>> +}
>> +
>> +/* *** Show Port Congestion Management Capabilities *** */ struct
>> +cmd_show_port_cman_capa_result {
>> + cmdline_fixed_string_t show;
>> + cmdline_fixed_string_t port;
>> + cmdline_fixed_string_t cman;
>> + cmdline_fixed_string_t capa;
>> + uint16_t port_id;
>> +};
>> +
>> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_show =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_show_port_cman_capa_result, show, "show");
>> +
>> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_port =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_show_port_cman_capa_result, port, "port");
>> +
>> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_cman =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_show_port_cman_capa_result, cman, "cman");
>> +
>> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_capa =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_show_port_cman_capa_result, capa, "capa");
>> +
>> +static cmdline_parse_token_num_t cmd_show_port_cman_capa_port_id =
>> + TOKEN_NUM_INITIALIZER(
>> + struct cmd_show_port_cman_capa_result, port_id,
>> RTE_UINT16);
>> +
>> +static void cmd_show_port_cman_capa_parsed(void *parsed_result,
>> + __rte_unused struct cmdline *cl,
>> + __rte_unused void *data)
>> +{
>> + struct cmd_show_port_cman_capa_result *res = parsed_result;
>> + uint16_t port_id = res->port_id;
>> + struct rte_eth_cman_info info;
>> + int ret;
>> +
>> + memset(&info, 0, sizeof(struct rte_eth_cman_info));
>> + ret = rte_eth_cman_info_get(port_id, &info);
>> + if (ret)
>> + return;
>> +
>> + printf("\n**** Port Congestion Management Capabilities
>> ****\n\n");
>> + printf("modes_supported 0x%" PRIx64 "\n", info.modes_supported);
>> + printf("objs_supported 0x%" PRIx64 "\n", info.objs_supported); }
>> +
>> +cmdline_parse_inst_t cmd_show_port_cman_capa = {
>> + .f = cmd_show_port_cman_capa_parsed,
>> + .data = NULL,
>> + .help_str = "show port cman capa <port_id>",
>> + .tokens = {
>> + (void *)&cmd_show_port_cman_capa_show,
>> + (void *)&cmd_show_port_cman_capa_port,
>> + (void *)&cmd_show_port_cman_capa_cman,
>> + (void *)&cmd_show_port_cman_capa_capa,
>> + (void *)&cmd_show_port_cman_capa_port_id,
>> + NULL,
>> + },
>> +};
>> +
>> +/* *** Show Port Congestion Management configuration *** */ struct
>> +cmd_show_port_cman_cfg_result {
>> + cmdline_fixed_string_t show;
>> + cmdline_fixed_string_t port;
>> + cmdline_fixed_string_t cman;
>> + cmdline_fixed_string_t cfg;
>> + uint16_t port_id;
>> +};
>> +
>> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_show =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_show_port_cman_cfg_result, show, "show");
>> +
>> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_port =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_show_port_cman_cfg_result, port, "port");
>> +
>> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cman =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_show_port_cman_cfg_result, cman, "cman");
>> +
>> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cfg =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_show_port_cman_cfg_result, cfg, "config");
>> +
>> +static cmdline_parse_token_num_t cmd_show_port_cman_cfg_port_id =
>> + TOKEN_NUM_INITIALIZER(
>> + struct cmd_show_port_cman_cfg_result, port_id,
>> RTE_UINT16);
>> +
>> +static void cmd_show_port_cman_cfg_parsed(void *parsed_result,
>> + __rte_unused struct cmdline *cl,
>> + __rte_unused void *data)
>> +{
>> + struct cmd_show_port_cman_cfg_result *res = parsed_result;
>> + uint16_t port_id = res->port_id;
>> + struct rte_eth_cman_config cfg;
>> + int ret;
>> +
>> + memset(&cfg, 0, sizeof(struct rte_eth_cman_config));
>> + ret = rte_eth_cman_config_get(port_id, &cfg);
>> + if (ret)
>> + return;
>> +
>> + printf("\n**** Port Congestion Management Configuration
>> ****\n\n");
>> + printf("cman object 0x%" PRIx32 "\n", cfg.obj);
>> + printf("cman Rx queue %" PRIx16 "\n", cfg.obj_param.rx_queue);
>> + printf("cman mode 0x%" PRIx32 "\n", cfg.mode);
>> + printf("cman RED min thresh %" PRIx8 "\n",
>> cfg.mode_param.red.min_th);
>> + printf("cman RED max thresh %" PRIx8 "\n",
>> cfg.mode_param.red.max_th);
>> + printf("cman RED Prob inversion %" PRIx16 "\n",
>> + cfg.mode_param.red.maxp_inv);
>> +}
>> +
>> +cmdline_parse_inst_t cmd_show_port_cman_config = {
>> + .f = cmd_show_port_cman_cfg_parsed,
>> + .data = NULL,
>> + .help_str = "show port cman config <port_id>",
>> + .tokens = {
>> + (void *)&cmd_show_port_cman_cfg_show,
>> + (void *)&cmd_show_port_cman_cfg_port,
>> + (void *)&cmd_show_port_cman_cfg_cman,
>> + (void *)&cmd_show_port_cman_cfg_cfg,
>> + (void *)&cmd_show_port_cman_cfg_port_id,
>> + NULL,
>> + },
>> +};
>> +
>> +/* *** Set Port Congestion Management configuration *** */ struct
>> +cmd_set_port_cman_cfg_result {
>> + cmdline_fixed_string_t set;
>> + cmdline_fixed_string_t port;
>> + cmdline_fixed_string_t cman;
>> + cmdline_fixed_string_t cfg;
>> + uint16_t port_id;
>> + uint16_t qid;
>> + cmdline_multi_string_t params;
>> +};
>> +
>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_set =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_set_port_cman_cfg_result, set, "set");
>> +
>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_port =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_set_port_cman_cfg_result, port, "port");
>> +
>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cman =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_set_port_cman_cfg_result, cman, "cman");
>> +
>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cfg =
>> + TOKEN_STRING_INITIALIZER(
>> + struct cmd_set_port_cman_cfg_result, cfg, "config");
>> +
>> +static cmdline_parse_token_num_t cmd_set_port_cman_cfg_port_id =
>> + TOKEN_NUM_INITIALIZER(
>> + struct cmd_set_port_cman_cfg_result, port_id, RTE_UINT16);
>> +
>> +static cmdline_parse_token_num_t cmd_set_port_cman_cfg_qid =
>> + TOKEN_NUM_INITIALIZER(
>> + struct cmd_set_port_cman_cfg_result, qid, RTE_UINT16);
>> +
>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_params =
>> + TOKEN_STRING_INITIALIZER(struct cmd_set_port_cman_cfg_result,
>> + params, TOKEN_STRING_MULTI);
>> +
>> +static void cmd_set_port_cman_cfg_parsed(void *parsed_result,
>> + __rte_unused struct cmdline *cl,
>> + __rte_unused void *data)
>> +{
>> + struct cmd_set_port_cman_cfg_result *res = parsed_result;
>> + uint16_t port_id = res->port_id;
>> + struct rte_eth_cman_config cfg;
>> + int ret;
>> +
>> + ret = parse_cman_params_str(port_id, res->params, &cfg);
>> + if (ret) {
>> + fprintf(stderr, "params string parse error\n");
>> + return;
>> + }
>> +
>> + cfg.obj_param.rx_queue = res->qid;
>> + rte_eth_cman_config_set(port_id, &cfg); }
>> +
>> +cmdline_parse_inst_t cmd_set_port_cman_config = {
>> + .f = cmd_set_port_cman_cfg_parsed,
>> + .data = NULL,
>> + .help_str = "set port cman config <port_id> <queue_id> "
>> + "default | [obj <queue|queue_mempool> mode red "
>> + "<min_thresh> <max_thresh> <prob_inv>]",
>> + .tokens = {
>> + (void *)&cmd_set_port_cman_cfg_set,
>> + (void *)&cmd_set_port_cman_cfg_port,
>> + (void *)&cmd_set_port_cman_cfg_cman,
>> + (void *)&cmd_set_port_cman_cfg_cfg,
>> + (void *)&cmd_set_port_cman_cfg_port_id,
>> + (void *)&cmd_set_port_cman_cfg_qid,
>> + (void *)&cmd_set_port_cman_cfg_params,
>> + NULL,
>> + },
>> +};
>> diff --git a/app/test-pmd/cmdline_cman.h b/app/test-pmd/cmdline_cman.h
>> new file mode 100644 index 0000000000..bd6c99ce35
>> --- /dev/null
>> +++ b/app/test-pmd/cmdline_cman.h
>> @@ -0,0 +1,12 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause
>> + * Copyright(C) 2022 Marvell International Ltd.
>> + */
>> +
>> +#ifndef _CMDLINE_CMAN_H_
>> +#define _CMDLINE_CMAN_H_
>> +
>> +extern cmdline_parse_inst_t cmd_show_port_cman_capa; extern
>> +cmdline_parse_inst_t cmd_show_port_cman_config; extern
>> +cmdline_parse_inst_t cmd_set_port_cman_config;
>> +
>> +#endif /* _CMDLINE_CMAN_H_ */
>> diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index
>> 74399178dd..c03d9dfebb 100644
>> --- a/app/test-pmd/meson.build
>> +++ b/app/test-pmd/meson.build
>> @@ -7,6 +7,7 @@ cflags += '-Wno-deprecated-declarations'
>> sources = files(
>> '5tswap.c',
>> 'cmdline.c',
>> + 'cmdline_cman.c',
>> 'cmdline_flow.c',
>> 'cmdline_mtr.c',
>> 'cmdline_tm.c',
>> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>> index d3075bf87d..b9c7b468af 100644
>> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>> @@ -5317,6 +5317,32 @@ Flex pattern can be shared between ports.
>> testpmd> flow create 0 ingress pattern eth / ipv4 / udp / flex item is 3
>> pattern is 2 / end actions mark id 1 / queue index 0 / end
>> Flow rule #0 created
>>
>> +Congestion Management
>> +---------------------
>> +
>> +Get capabilities
>> +~~~~~~~~~~~~~~~~
>> +
>> +Retrieve congestion management capabilities supported by driver for given
>> port.
>> +Below example command retrieves capabilities for port 0::
>> +
>> + testpmd> show port cman capa 0
>> +
>> +Get configuration
>> +~~~~~~~~~~~~~~~~~
>> +Retrieve congestion management configuration for given port. Below
>> +example command retrieves configuration for port 0::
>> +
>> + testpmd> show port cman config 0
>> +
>> +Set configuration
>> +~~~~~~~~~~~~~~~~~
>> +Configures congestion management settings on given queue or mempool
>> +associated with queue. Below example command configures RED as
>> +congestion management algo for port 0 and queue 0::
>> +
>> + testpmd> set port cman config 0 0 obj queue mode red 10 100 1
>> +
>> Driver specific commands
>> ------------------------
>>
>> --
>> 2.25.1
>
These newly added files for Congestion Management look in-line to
Traffic Metering part,
would like @Cristian to also have a look.
Regards
Aman
On 11/6/2022 3:38 PM, Andrew Rybchenko wrote:
> @Aman, @Yuying, please, help to review the patch.
>
> On 10/12/22 12:01, Sunil Kumar Kori wrote:
>> Please review the following changes and provide feedback.
>>
>> Regards
>> Sunil Kumar Kori
>>
>>> -----Original Message-----
>>> From: skori@marvell.com <skori@marvell.com>
>>> Sent: Thursday, September 29, 2022 3:25 PM
>>> To: Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
>>> <yuying.zhang@intel.com>
>>> Cc: dev@dpdk.org; Sunil Kumar Kori <skori@marvell.com>
>>> Subject: [PATCH v2 1/3] app/testpmd: support congestion management CLIs
>>>
>>> From: Sunil Kumar Kori <skori@marvell.com>
>>>
>>> Support congestion management CLIs.
>>>
>>> Depends-on: patch-24902 ("ethdev: support congestion management")
>>>
>>> Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
Acked-by: Aman Singh <aman.deep.singh@intel.com>
>>> ---
>>> v1..v2:
>>> - Rebase on top of the dpdk-next-net-mrvl/for-next-net
>>>
>>> app/test-pmd/cmdline.c | 15 +
>>> app/test-pmd/cmdline_cman.c | 390
>>> ++++++++++++++++++++
>>> app/test-pmd/cmdline_cman.h | 12 +
>>> app/test-pmd/meson.build | 1 +
>>> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 26 ++
>>> 5 files changed, 444 insertions(+)
>>> create mode 100644 app/test-pmd/cmdline_cman.c create mode 100644
>>> app/test-pmd/cmdline_cman.h
>>>
>>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
>>> 51321de9ed..ce278eadb0 100644
>>> --- a/app/test-pmd/cmdline.c
>>> +++ b/app/test-pmd/cmdline.c
>>> @@ -60,6 +60,7 @@
>>> #include <rte_pmd_bnxt.h>
>>> #endif
>>> #include "testpmd.h"
>>> +#include "cmdline_cman.h"
>>> #include "cmdline_mtr.h"
>>> #include "cmdline_tm.h"
>>> #include "bpf_cmd.h"
>>> @@ -599,6 +600,17 @@ static void cmd_help_long_parsed(void
>>> *parsed_result,
>>> "set port (port_id) fec_mode auto|off|rs|baser\n"
>>> " set fec mode for a specific port\n\n"
>>>
>>> + "show port cman capa (port_id)\n"
>>> + " Show congestion management capabilities\n\n"
>>> +
>>> + "show port cman config (port_id)\n"
>>> + " Show congestion management configuration\n\n"
>>> +
>>> + "set port cman config (port_id) (queue_id) default | "
>>> + "[obj (queue|queue_mempool) mode red
>>> (min_thresh) "
>>> + "(max_thresh) (prob_inv)]\n"
>>> + " Set congestion management configuration\n\n"
>>> +
>>> , list_pkt_forwarding_modes()
>>> );
>>> }
>>> @@ -12990,6 +13002,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
>>> (cmdline_parse_inst_t *)&cmd_show_capability,
>>> (cmdline_parse_inst_t *)&cmd_set_flex_is_pattern,
>>> (cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern,
>>> + (cmdline_parse_inst_t *)&cmd_show_port_cman_capa,
>>> + (cmdline_parse_inst_t *)&cmd_show_port_cman_config,
>>> + (cmdline_parse_inst_t *)&cmd_set_port_cman_config,
>>> NULL,
>>> };
>>>
>>> diff --git a/app/test-pmd/cmdline_cman.c b/app/test-pmd/cmdline_cman.c
>>> new file mode 100644 index 0000000000..344759189d
>>> --- /dev/null
>>> +++ b/app/test-pmd/cmdline_cman.c
>>> @@ -0,0 +1,390 @@
>>> +/* SPDX-License-Identifier: BSD-3-Clause
>>> + * Copyright(C) 2022 Marvell International Ltd.
>>> + */
>>> +
>>> +#include <cmdline_parse.h>
>>> +#include <cmdline_parse_num.h>
>>> +#include <cmdline_parse_string.h>
>>> +
>>> +#include <rte_ethdev.h>
>>> +
>>> +#include "testpmd.h"
>>> +
>>> +#define PARSE_DELIMITER " \f\n\r\t\v"
>>> +
>>> +static int
>>> +parse_uint(uint64_t *value, const char *str) {
>>> + char *next = NULL;
>>> + uint64_t n;
>>> +
>>> + errno = 0;
>>> + /* Parse number string */
>>> + n = strtol(str, &next, 10);
>>> + if (errno != 0 || str == next || *next != '\0')
>>> + return -1;
>>> +
>>> + *value = n;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int
>>> +parse_cman_obj_str(char *str, uint64_t *obj) {
>>> + char *token;
>>> +
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (token == NULL)
>>> + return 0;
>>> +
>>> + if (strcasecmp(token, "queue") == 0)
>>> + *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE;
>>> + else if (strcasecmp(token, "queue_mempool") == 0)
>>> + *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE_MEMPOOL;
>>> + else
>>> + return -1;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int
>>> +parse_cman_mode_str(char *str, uint64_t *mode) {
>>> + char *token;
>>> +
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (token == NULL)
>>> + return 0;
>>> +
>>> + if (strcasecmp(token, "red") == 0)
>>> + *mode = RTE_CMAN_RED;
>>> + else
>>> + return -1;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int
>>> +parse_cman_params_str(uint16_t port_id, char *str,
>>> + struct rte_eth_cman_config *cfg) {
>>> + uint64_t obj = 0, mode = 0, min_th = 0, max_th = 0, maxp_inv = 0;
>>> + struct rte_eth_cman_info info;
>>> + char *token;
>>> + int ret;
>>> +
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (!strcasecmp(token, "default")) {
>>> + ret = rte_eth_cman_config_init(port_id, cfg);
>>> + if (ret) {
>>> + fprintf(stderr, "error in default initialization\n");
>>> + return ret;
>>> + }
>>> + return 0;
>>> + }
>>> +
>>> + /* First token: obj name */
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (token == NULL) {
>>> + fprintf(stderr, "Object param parse error\n");
>>> + goto error;
>>> + }
>>> +
>>> + ret = parse_cman_obj_str(token, &obj);
>>> + if (ret) {
>>> + fprintf(stderr, "Object value is invalid\n");
>>> + goto error;
>>> + }
>>> +
>>> + /* Second token: mode name */
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (token == NULL) {
>>> + fprintf(stderr, " Mode param is invalid\n");
>>> + goto error;
>>> + }
>>> +
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (token == NULL) {
>>> + fprintf(stderr, " Mode value is invalid\n");
>>> + goto error;
>>> + }
>>> +
>>> + ret = parse_cman_mode_str(token, &mode);
>>> + if (ret) {
>>> + fprintf(stderr, "mode string parse error\n");
>>> + goto error;
>>> + }
>>> +
>>> + /* Third token: minimum threshold */
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (token == NULL) {
>>> + fprintf(stderr, "Minimum threshold parse error\n");
>>> + goto error;
>>> + }
>>> +
>>> + ret = parse_uint(&min_th, token);
>>> + if (ret != 0 || min_th > UINT8_MAX) {
>>> + fprintf(stderr, "Minimum threshold is invalid\n");
>>> + goto error;
>>> + }
>>> +
>>> + /* Fourth token: maximum threshold */
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (token == NULL) {
>>> + fprintf(stderr, "Maximum threshold parse error\n");
>>> + goto error;
>>> + }
>>> +
>>> + ret = parse_uint(&max_th, token);
>>> + if (ret != 0 || max_th > UINT8_MAX) {
>>> + fprintf(stderr, "Maximum threshold is invalid\n");
>>> + goto error;
>>> + }
>>> +
>>> + /* Fifth token: probability inversion */
>>> + token = strtok_r(str, PARSE_DELIMITER, &str);
>>> + if (token == NULL) {
>>> + fprintf(stderr, "Maximum probability inversion parse
>>> error\n");
>>> + goto error;
>>> + }
>>> +
>>> + ret = parse_uint(&maxp_inv, token);
>>> + if (ret != 0 || maxp_inv == 0 || maxp_inv > UINT16_MAX) {
>>> + fprintf(stderr, "Maximum probability inversion is invalid\n");
>>> + goto error;
>>> + }
>>> +
>>> + memset(&info, 0, sizeof(struct rte_eth_cman_info));
>>> + ret = rte_eth_cman_info_get(port_id, &info);
>>> + if (ret) {
>>> + fprintf(stderr, "Congestion management capa get error\n");
>>> + goto error;
>>> + }
>>> +
>>> + if (!(info.objs_supported & obj)) {
>>> + fprintf(stderr, "Object type is not supported by driver\n");
>>> + goto error;
>>> + }
>>> +
>>> + if (!(info.modes_supported & mode)) {
>>> + fprintf(stderr, "Mode is not supported by driver\n");
>>> + goto error;
>>> + }
>>> +
>>> + cfg->obj = obj;
>>> + cfg->mode = mode;
>>> + cfg->mode_param.red.min_th = min_th;
>>> + cfg->mode_param.red.max_th = max_th;
>>> + cfg->mode_param.red.maxp_inv = maxp_inv;
>>> +
>>> + return 0;
>>> +
>>> +error:
>>> + return -EINVAL;
>>> +}
>>> +
>>> +/* *** Show Port Congestion Management Capabilities *** */ struct
>>> +cmd_show_port_cman_capa_result {
>>> + cmdline_fixed_string_t show;
>>> + cmdline_fixed_string_t port;
>>> + cmdline_fixed_string_t cman;
>>> + cmdline_fixed_string_t capa;
>>> + uint16_t port_id;
>>> +};
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_show =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_show_port_cman_capa_result, show, "show");
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_port =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_show_port_cman_capa_result, port, "port");
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_cman =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_show_port_cman_capa_result, cman, "cman");
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_port_cman_capa_capa =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_show_port_cman_capa_result, capa, "capa");
>>> +
>>> +static cmdline_parse_token_num_t cmd_show_port_cman_capa_port_id =
>>> + TOKEN_NUM_INITIALIZER(
>>> + struct cmd_show_port_cman_capa_result, port_id,
>>> RTE_UINT16);
>>> +
>>> +static void cmd_show_port_cman_capa_parsed(void *parsed_result,
>>> + __rte_unused struct cmdline *cl,
>>> + __rte_unused void *data)
>>> +{
>>> + struct cmd_show_port_cman_capa_result *res = parsed_result;
>>> + uint16_t port_id = res->port_id;
>>> + struct rte_eth_cman_info info;
>>> + int ret;
>>> +
>>> + memset(&info, 0, sizeof(struct rte_eth_cman_info));
>>> + ret = rte_eth_cman_info_get(port_id, &info);
>>> + if (ret)
>>> + return;
>>> +
>>> + printf("\n**** Port Congestion Management Capabilities
>>> ****\n\n");
>>> + printf("modes_supported 0x%" PRIx64 "\n", info.modes_supported);
>>> + printf("objs_supported 0x%" PRIx64 "\n", info.objs_supported); }
>>> +
>>> +cmdline_parse_inst_t cmd_show_port_cman_capa = {
>>> + .f = cmd_show_port_cman_capa_parsed,
>>> + .data = NULL,
>>> + .help_str = "show port cman capa <port_id>",
>>> + .tokens = {
>>> + (void *)&cmd_show_port_cman_capa_show,
>>> + (void *)&cmd_show_port_cman_capa_port,
>>> + (void *)&cmd_show_port_cman_capa_cman,
>>> + (void *)&cmd_show_port_cman_capa_capa,
>>> + (void *)&cmd_show_port_cman_capa_port_id,
>>> + NULL,
>>> + },
>>> +};
>>> +
>>> +/* *** Show Port Congestion Management configuration *** */ struct
>>> +cmd_show_port_cman_cfg_result {
>>> + cmdline_fixed_string_t show;
>>> + cmdline_fixed_string_t port;
>>> + cmdline_fixed_string_t cman;
>>> + cmdline_fixed_string_t cfg;
>>> + uint16_t port_id;
>>> +};
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_show =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_show_port_cman_cfg_result, show, "show");
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_port =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_show_port_cman_cfg_result, port, "port");
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cman =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_show_port_cman_cfg_result, cman, "cman");
>>> +
>>> +static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cfg =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_show_port_cman_cfg_result, cfg, "config");
>>> +
>>> +static cmdline_parse_token_num_t cmd_show_port_cman_cfg_port_id =
>>> + TOKEN_NUM_INITIALIZER(
>>> + struct cmd_show_port_cman_cfg_result, port_id,
>>> RTE_UINT16);
>>> +
>>> +static void cmd_show_port_cman_cfg_parsed(void *parsed_result,
>>> + __rte_unused struct cmdline *cl,
>>> + __rte_unused void *data)
>>> +{
>>> + struct cmd_show_port_cman_cfg_result *res = parsed_result;
>>> + uint16_t port_id = res->port_id;
>>> + struct rte_eth_cman_config cfg;
>>> + int ret;
>>> +
>>> + memset(&cfg, 0, sizeof(struct rte_eth_cman_config));
>>> + ret = rte_eth_cman_config_get(port_id, &cfg);
>>> + if (ret)
>>> + return;
>>> +
>>> + printf("\n**** Port Congestion Management Configuration
>>> ****\n\n");
>>> + printf("cman object 0x%" PRIx32 "\n", cfg.obj);
>>> + printf("cman Rx queue %" PRIx16 "\n", cfg.obj_param.rx_queue);
>>> + printf("cman mode 0x%" PRIx32 "\n", cfg.mode);
>>> + printf("cman RED min thresh %" PRIx8 "\n",
>>> cfg.mode_param.red.min_th);
>>> + printf("cman RED max thresh %" PRIx8 "\n",
>>> cfg.mode_param.red.max_th);
>>> + printf("cman RED Prob inversion %" PRIx16 "\n",
>>> + cfg.mode_param.red.maxp_inv);
>>> +}
>>> +
>>> +cmdline_parse_inst_t cmd_show_port_cman_config = {
>>> + .f = cmd_show_port_cman_cfg_parsed,
>>> + .data = NULL,
>>> + .help_str = "show port cman config <port_id>",
>>> + .tokens = {
>>> + (void *)&cmd_show_port_cman_cfg_show,
>>> + (void *)&cmd_show_port_cman_cfg_port,
>>> + (void *)&cmd_show_port_cman_cfg_cman,
>>> + (void *)&cmd_show_port_cman_cfg_cfg,
>>> + (void *)&cmd_show_port_cman_cfg_port_id,
>>> + NULL,
>>> + },
>>> +};
>>> +
>>> +/* *** Set Port Congestion Management configuration *** */ struct
>>> +cmd_set_port_cman_cfg_result {
>>> + cmdline_fixed_string_t set;
>>> + cmdline_fixed_string_t port;
>>> + cmdline_fixed_string_t cman;
>>> + cmdline_fixed_string_t cfg;
>>> + uint16_t port_id;
>>> + uint16_t qid;
>>> + cmdline_multi_string_t params;
>>> +};
>>> +
>>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_set =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_set_port_cman_cfg_result, set, "set");
>>> +
>>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_port =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_set_port_cman_cfg_result, port, "port");
>>> +
>>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cman =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_set_port_cman_cfg_result, cman, "cman");
>>> +
>>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cfg =
>>> + TOKEN_STRING_INITIALIZER(
>>> + struct cmd_set_port_cman_cfg_result, cfg, "config");
>>> +
>>> +static cmdline_parse_token_num_t cmd_set_port_cman_cfg_port_id =
>>> + TOKEN_NUM_INITIALIZER(
>>> + struct cmd_set_port_cman_cfg_result, port_id, RTE_UINT16);
>>> +
>>> +static cmdline_parse_token_num_t cmd_set_port_cman_cfg_qid =
>>> + TOKEN_NUM_INITIALIZER(
>>> + struct cmd_set_port_cman_cfg_result, qid, RTE_UINT16);
>>> +
>>> +static cmdline_parse_token_string_t cmd_set_port_cman_cfg_params =
>>> + TOKEN_STRING_INITIALIZER(struct cmd_set_port_cman_cfg_result,
>>> + params, TOKEN_STRING_MULTI);
>>> +
>>> +static void cmd_set_port_cman_cfg_parsed(void *parsed_result,
>>> + __rte_unused struct cmdline *cl,
>>> + __rte_unused void *data)
>>> +{
>>> + struct cmd_set_port_cman_cfg_result *res = parsed_result;
>>> + uint16_t port_id = res->port_id;
>>> + struct rte_eth_cman_config cfg;
>>> + int ret;
>>> +
>>> + ret = parse_cman_params_str(port_id, res->params, &cfg);
>>> + if (ret) {
>>> + fprintf(stderr, "params string parse error\n");
>>> + return;
>>> + }
>>> +
>>> + cfg.obj_param.rx_queue = res->qid;
>>> + rte_eth_cman_config_set(port_id, &cfg); }
>>> +
>>> +cmdline_parse_inst_t cmd_set_port_cman_config = {
>>> + .f = cmd_set_port_cman_cfg_parsed,
>>> + .data = NULL,
>>> + .help_str = "set port cman config <port_id> <queue_id> "
>>> + "default | [obj <queue|queue_mempool> mode red "
>>> + "<min_thresh> <max_thresh> <prob_inv>]",
>>> + .tokens = {
>>> + (void *)&cmd_set_port_cman_cfg_set,
>>> + (void *)&cmd_set_port_cman_cfg_port,
>>> + (void *)&cmd_set_port_cman_cfg_cman,
>>> + (void *)&cmd_set_port_cman_cfg_cfg,
>>> + (void *)&cmd_set_port_cman_cfg_port_id,
>>> + (void *)&cmd_set_port_cman_cfg_qid,
>>> + (void *)&cmd_set_port_cman_cfg_params,
>>> + NULL,
>>> + },
>>> +};
>>> diff --git a/app/test-pmd/cmdline_cman.h b/app/test-pmd/cmdline_cman.h
>>> new file mode 100644 index 0000000000..bd6c99ce35
>>> --- /dev/null
>>> +++ b/app/test-pmd/cmdline_cman.h
>>> @@ -0,0 +1,12 @@
>>> +/* SPDX-License-Identifier: BSD-3-Clause
>>> + * Copyright(C) 2022 Marvell International Ltd.
>>> + */
>>> +
>>> +#ifndef _CMDLINE_CMAN_H_
>>> +#define _CMDLINE_CMAN_H_
>>> +
>>> +extern cmdline_parse_inst_t cmd_show_port_cman_capa; extern
>>> +cmdline_parse_inst_t cmd_show_port_cman_config; extern
>>> +cmdline_parse_inst_t cmd_set_port_cman_config;
>>> +
>>> +#endif /* _CMDLINE_CMAN_H_ */
>>> diff --git a/app/test-pmd/meson.build b/app/test-pmd/meson.build index
>>> 74399178dd..c03d9dfebb 100644
>>> --- a/app/test-pmd/meson.build
>>> +++ b/app/test-pmd/meson.build
>>> @@ -7,6 +7,7 @@ cflags += '-Wno-deprecated-declarations'
>>> sources = files(
>>> '5tswap.c',
>>> 'cmdline.c',
>>> + 'cmdline_cman.c',
>>> 'cmdline_flow.c',
>>> 'cmdline_mtr.c',
>>> 'cmdline_tm.c',
>>> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>>> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>>> index d3075bf87d..b9c7b468af 100644
>>> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>>> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
>>> @@ -5317,6 +5317,32 @@ Flex pattern can be shared between ports.
>>> testpmd> flow create 0 ingress pattern eth / ipv4 / udp / flex
>>> item is 3
>>> pattern is 2 / end actions mark id 1 / queue index 0 / end
>>> Flow rule #0 created
>>>
>>> +Congestion Management
>>> +---------------------
>>> +
>>> +Get capabilities
>>> +~~~~~~~~~~~~~~~~
>>> +
>>> +Retrieve congestion management capabilities supported by driver for
>>> given
>>> port.
>>> +Below example command retrieves capabilities for port 0::
>>> +
>>> + testpmd> show port cman capa 0
>>> +
>>> +Get configuration
>>> +~~~~~~~~~~~~~~~~~
>>> +Retrieve congestion management configuration for given port. Below
>>> +example command retrieves configuration for port 0::
>>> +
>>> + testpmd> show port cman config 0
>>> +
>>> +Set configuration
>>> +~~~~~~~~~~~~~~~~~
>>> +Configures congestion management settings on given queue or mempool
>>> +associated with queue. Below example command configures RED as
>>> +congestion management algo for port 0 and queue 0::
>>> +
>>> + testpmd> set port cman config 0 0 obj queue mode red 10 100 1
>>> +
Rather than adding this section at the end can we put it near TM section 4.9
>>> Driver specific commands
>>> ------------------------
>>>
>>> --
>>> 2.25.1
>>
>
> -----Original Message-----
> From: Singh, Aman Deep <aman.deep.singh@intel.com>
> Sent: Monday, November 7, 2022 12:42 PM
> To: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>; Yuying Zhang
> <yuying.zhang@intel.com>; Cristian Dumitrescu
> <cristian.dumitrescu@intel.com>
> Cc: dev@dpdk.org; Sunil Kumar Kori <skori@marvell.com>
> Subject: [EXT] Re: [PATCH v2 1/3] app/testpmd: support congestion
> management CLIs
>
> External Email
>
> ----------------------------------------------------------------------
> These newly added files for Congestion Management look in-line to Traffic
> Metering part, would like @Cristian to also have a look.
>
> Regards
> Aman
>
> On 11/6/2022 3:38 PM, Andrew Rybchenko wrote:
> > @Aman, @Yuying, please, help to review the patch.
> >
> > On 10/12/22 12:01, Sunil Kumar Kori wrote:
> >> Please review the following changes and provide feedback.
> >>
> >> Regards
> >> Sunil Kumar Kori
> >>
> >>> -----Original Message-----
> >>> From: skori@marvell.com <skori@marvell.com>
> >>> Sent: Thursday, September 29, 2022 3:25 PM
> >>> To: Aman Singh <aman.deep.singh@intel.com>; Yuying Zhang
> >>> <yuying.zhang@intel.com>
> >>> Cc: dev@dpdk.org; Sunil Kumar Kori <skori@marvell.com>
> >>> Subject: [PATCH v2 1/3] app/testpmd: support congestion management
> >>> CLIs
> >>>
> >>> From: Sunil Kumar Kori <skori@marvell.com>
> >>>
> >>> Support congestion management CLIs.
> >>>
> >>> Depends-on: patch-24902 ("ethdev: support congestion management")
> >>>
> >>> Signed-off-by: Sunil Kumar Kori <skori@marvell.com>
> Acked-by: Aman Singh <aman.deep.singh@intel.com>
> >>> ---
> >>> v1..v2:
> >>> - Rebase on top of the dpdk-next-net-mrvl/for-next-net
> >>>
> >>> app/test-pmd/cmdline.c | 15 +
> >>> app/test-pmd/cmdline_cman.c | 390
> >>> ++++++++++++++++++++
> >>> app/test-pmd/cmdline_cman.h | 12 +
> >>> app/test-pmd/meson.build | 1 +
> >>> doc/guides/testpmd_app_ug/testpmd_funcs.rst | 26 ++
> >>> 5 files changed, 444 insertions(+)
> >>> create mode 100644 app/test-pmd/cmdline_cman.c create mode
> 100644
[snipped]
> >>>
> >>> +Congestion Management
> >>> +---------------------
> >>> +
> >>> +Get capabilities
> >>> +~~~~~~~~~~~~~~~~
> >>> +
> >>> +Retrieve congestion management capabilities supported by driver for
> >>> given
> >>> port.
> >>> +Below example command retrieves capabilities for port 0::
> >>> +
> >>> + testpmd> show port cman capa 0
> >>> +
> >>> +Get configuration
> >>> +~~~~~~~~~~~~~~~~~
> >>> +Retrieve congestion management configuration for given port. Below
> >>> +example command retrieves configuration for port 0::
> >>> +
> >>> + testpmd> show port cman config 0
> >>> +
> >>> +Set configuration
> >>> +~~~~~~~~~~~~~~~~~
> >>> +Configures congestion management settings on given queue or
> mempool
> >>> +associated with queue. Below example command configures RED as
> >>> +congestion management algo for port 0 and queue 0::
> >>> +
> >>> + testpmd> set port cman config 0 0 obj queue mode red 10 100 1
> >>> +
> Rather than adding this section at the end can we put it near TM section 4.9
Ack. But I believe keeping it after section 4.10 is okay.
> >>> Driver specific commands
> >>> ------------------------
> >>>
> >>> --
> >>> 2.25.1
> >>
> >
@@ -60,6 +60,7 @@
#include <rte_pmd_bnxt.h>
#endif
#include "testpmd.h"
+#include "cmdline_cman.h"
#include "cmdline_mtr.h"
#include "cmdline_tm.h"
#include "bpf_cmd.h"
@@ -599,6 +600,17 @@ static void cmd_help_long_parsed(void *parsed_result,
"set port (port_id) fec_mode auto|off|rs|baser\n"
" set fec mode for a specific port\n\n"
+ "show port cman capa (port_id)\n"
+ " Show congestion management capabilities\n\n"
+
+ "show port cman config (port_id)\n"
+ " Show congestion management configuration\n\n"
+
+ "set port cman config (port_id) (queue_id) default | "
+ "[obj (queue|queue_mempool) mode red (min_thresh) "
+ "(max_thresh) (prob_inv)]\n"
+ " Set congestion management configuration\n\n"
+
, list_pkt_forwarding_modes()
);
}
@@ -12990,6 +13002,9 @@ static cmdline_parse_ctx_t builtin_ctx[] = {
(cmdline_parse_inst_t *)&cmd_show_capability,
(cmdline_parse_inst_t *)&cmd_set_flex_is_pattern,
(cmdline_parse_inst_t *)&cmd_set_flex_spec_pattern,
+ (cmdline_parse_inst_t *)&cmd_show_port_cman_capa,
+ (cmdline_parse_inst_t *)&cmd_show_port_cman_config,
+ (cmdline_parse_inst_t *)&cmd_set_port_cman_config,
NULL,
};
new file mode 100644
@@ -0,0 +1,390 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+
+#include <rte_ethdev.h>
+
+#include "testpmd.h"
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+
+static int
+parse_uint(uint64_t *value, const char *str)
+{
+ char *next = NULL;
+ uint64_t n;
+
+ errno = 0;
+ /* Parse number string */
+ n = strtol(str, &next, 10);
+ if (errno != 0 || str == next || *next != '\0')
+ return -1;
+
+ *value = n;
+
+ return 0;
+}
+
+static int
+parse_cman_obj_str(char *str, uint64_t *obj)
+{
+ char *token;
+
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL)
+ return 0;
+
+ if (strcasecmp(token, "queue") == 0)
+ *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE;
+ else if (strcasecmp(token, "queue_mempool") == 0)
+ *obj = RTE_ETH_CMAN_OBJ_RX_QUEUE_MEMPOOL;
+ else
+ return -1;
+
+ return 0;
+}
+
+static int
+parse_cman_mode_str(char *str, uint64_t *mode)
+{
+ char *token;
+
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL)
+ return 0;
+
+ if (strcasecmp(token, "red") == 0)
+ *mode = RTE_CMAN_RED;
+ else
+ return -1;
+
+ return 0;
+}
+
+static int
+parse_cman_params_str(uint16_t port_id, char *str,
+ struct rte_eth_cman_config *cfg)
+{
+ uint64_t obj = 0, mode = 0, min_th = 0, max_th = 0, maxp_inv = 0;
+ struct rte_eth_cman_info info;
+ char *token;
+ int ret;
+
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (!strcasecmp(token, "default")) {
+ ret = rte_eth_cman_config_init(port_id, cfg);
+ if (ret) {
+ fprintf(stderr, "error in default initialization\n");
+ return ret;
+ }
+ return 0;
+ }
+
+ /* First token: obj name */
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL) {
+ fprintf(stderr, "Object param parse error\n");
+ goto error;
+ }
+
+ ret = parse_cman_obj_str(token, &obj);
+ if (ret) {
+ fprintf(stderr, "Object value is invalid\n");
+ goto error;
+ }
+
+ /* Second token: mode name */
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL) {
+ fprintf(stderr, " Mode param is invalid\n");
+ goto error;
+ }
+
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL) {
+ fprintf(stderr, " Mode value is invalid\n");
+ goto error;
+ }
+
+ ret = parse_cman_mode_str(token, &mode);
+ if (ret) {
+ fprintf(stderr, "mode string parse error\n");
+ goto error;
+ }
+
+ /* Third token: minimum threshold */
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL) {
+ fprintf(stderr, "Minimum threshold parse error\n");
+ goto error;
+ }
+
+ ret = parse_uint(&min_th, token);
+ if (ret != 0 || min_th > UINT8_MAX) {
+ fprintf(stderr, "Minimum threshold is invalid\n");
+ goto error;
+ }
+
+ /* Fourth token: maximum threshold */
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL) {
+ fprintf(stderr, "Maximum threshold parse error\n");
+ goto error;
+ }
+
+ ret = parse_uint(&max_th, token);
+ if (ret != 0 || max_th > UINT8_MAX) {
+ fprintf(stderr, "Maximum threshold is invalid\n");
+ goto error;
+ }
+
+ /* Fifth token: probability inversion */
+ token = strtok_r(str, PARSE_DELIMITER, &str);
+ if (token == NULL) {
+ fprintf(stderr, "Maximum probability inversion parse error\n");
+ goto error;
+ }
+
+ ret = parse_uint(&maxp_inv, token);
+ if (ret != 0 || maxp_inv == 0 || maxp_inv > UINT16_MAX) {
+ fprintf(stderr, "Maximum probability inversion is invalid\n");
+ goto error;
+ }
+
+ memset(&info, 0, sizeof(struct rte_eth_cman_info));
+ ret = rte_eth_cman_info_get(port_id, &info);
+ if (ret) {
+ fprintf(stderr, "Congestion management capa get error\n");
+ goto error;
+ }
+
+ if (!(info.objs_supported & obj)) {
+ fprintf(stderr, "Object type is not supported by driver\n");
+ goto error;
+ }
+
+ if (!(info.modes_supported & mode)) {
+ fprintf(stderr, "Mode is not supported by driver\n");
+ goto error;
+ }
+
+ cfg->obj = obj;
+ cfg->mode = mode;
+ cfg->mode_param.red.min_th = min_th;
+ cfg->mode_param.red.max_th = max_th;
+ cfg->mode_param.red.maxp_inv = maxp_inv;
+
+ return 0;
+
+error:
+ return -EINVAL;
+}
+
+/* *** Show Port Congestion Management Capabilities *** */
+struct cmd_show_port_cman_capa_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t cman;
+ cmdline_fixed_string_t capa;
+ uint16_t port_id;
+};
+
+static cmdline_parse_token_string_t cmd_show_port_cman_capa_show =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_cman_capa_result, show, "show");
+
+static cmdline_parse_token_string_t cmd_show_port_cman_capa_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_cman_capa_result, port, "port");
+
+static cmdline_parse_token_string_t cmd_show_port_cman_capa_cman =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_cman_capa_result, cman, "cman");
+
+static cmdline_parse_token_string_t cmd_show_port_cman_capa_capa =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_cman_capa_result, capa, "capa");
+
+static cmdline_parse_token_num_t cmd_show_port_cman_capa_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_cman_capa_result, port_id, RTE_UINT16);
+
+static void cmd_show_port_cman_capa_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_cman_capa_result *res = parsed_result;
+ uint16_t port_id = res->port_id;
+ struct rte_eth_cman_info info;
+ int ret;
+
+ memset(&info, 0, sizeof(struct rte_eth_cman_info));
+ ret = rte_eth_cman_info_get(port_id, &info);
+ if (ret)
+ return;
+
+ printf("\n**** Port Congestion Management Capabilities ****\n\n");
+ printf("modes_supported 0x%" PRIx64 "\n", info.modes_supported);
+ printf("objs_supported 0x%" PRIx64 "\n", info.objs_supported);
+}
+
+cmdline_parse_inst_t cmd_show_port_cman_capa = {
+ .f = cmd_show_port_cman_capa_parsed,
+ .data = NULL,
+ .help_str = "show port cman capa <port_id>",
+ .tokens = {
+ (void *)&cmd_show_port_cman_capa_show,
+ (void *)&cmd_show_port_cman_capa_port,
+ (void *)&cmd_show_port_cman_capa_cman,
+ (void *)&cmd_show_port_cman_capa_capa,
+ (void *)&cmd_show_port_cman_capa_port_id,
+ NULL,
+ },
+};
+
+/* *** Show Port Congestion Management configuration *** */
+struct cmd_show_port_cman_cfg_result {
+ cmdline_fixed_string_t show;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t cman;
+ cmdline_fixed_string_t cfg;
+ uint16_t port_id;
+};
+
+static cmdline_parse_token_string_t cmd_show_port_cman_cfg_show =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_cman_cfg_result, show, "show");
+
+static cmdline_parse_token_string_t cmd_show_port_cman_cfg_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_cman_cfg_result, port, "port");
+
+static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cman =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_cman_cfg_result, cman, "cman");
+
+static cmdline_parse_token_string_t cmd_show_port_cman_cfg_cfg =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_show_port_cman_cfg_result, cfg, "config");
+
+static cmdline_parse_token_num_t cmd_show_port_cman_cfg_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_show_port_cman_cfg_result, port_id, RTE_UINT16);
+
+static void cmd_show_port_cman_cfg_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_show_port_cman_cfg_result *res = parsed_result;
+ uint16_t port_id = res->port_id;
+ struct rte_eth_cman_config cfg;
+ int ret;
+
+ memset(&cfg, 0, sizeof(struct rte_eth_cman_config));
+ ret = rte_eth_cman_config_get(port_id, &cfg);
+ if (ret)
+ return;
+
+ printf("\n**** Port Congestion Management Configuration ****\n\n");
+ printf("cman object 0x%" PRIx32 "\n", cfg.obj);
+ printf("cman Rx queue %" PRIx16 "\n", cfg.obj_param.rx_queue);
+ printf("cman mode 0x%" PRIx32 "\n", cfg.mode);
+ printf("cman RED min thresh %" PRIx8 "\n", cfg.mode_param.red.min_th);
+ printf("cman RED max thresh %" PRIx8 "\n", cfg.mode_param.red.max_th);
+ printf("cman RED Prob inversion %" PRIx16 "\n",
+ cfg.mode_param.red.maxp_inv);
+}
+
+cmdline_parse_inst_t cmd_show_port_cman_config = {
+ .f = cmd_show_port_cman_cfg_parsed,
+ .data = NULL,
+ .help_str = "show port cman config <port_id>",
+ .tokens = {
+ (void *)&cmd_show_port_cman_cfg_show,
+ (void *)&cmd_show_port_cman_cfg_port,
+ (void *)&cmd_show_port_cman_cfg_cman,
+ (void *)&cmd_show_port_cman_cfg_cfg,
+ (void *)&cmd_show_port_cman_cfg_port_id,
+ NULL,
+ },
+};
+
+/* *** Set Port Congestion Management configuration *** */
+struct cmd_set_port_cman_cfg_result {
+ cmdline_fixed_string_t set;
+ cmdline_fixed_string_t port;
+ cmdline_fixed_string_t cman;
+ cmdline_fixed_string_t cfg;
+ uint16_t port_id;
+ uint16_t qid;
+ cmdline_multi_string_t params;
+};
+
+static cmdline_parse_token_string_t cmd_set_port_cman_cfg_set =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_cman_cfg_result, set, "set");
+
+static cmdline_parse_token_string_t cmd_set_port_cman_cfg_port =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_cman_cfg_result, port, "port");
+
+static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cman =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_cman_cfg_result, cman, "cman");
+
+static cmdline_parse_token_string_t cmd_set_port_cman_cfg_cfg =
+ TOKEN_STRING_INITIALIZER(
+ struct cmd_set_port_cman_cfg_result, cfg, "config");
+
+static cmdline_parse_token_num_t cmd_set_port_cman_cfg_port_id =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_cman_cfg_result, port_id, RTE_UINT16);
+
+static cmdline_parse_token_num_t cmd_set_port_cman_cfg_qid =
+ TOKEN_NUM_INITIALIZER(
+ struct cmd_set_port_cman_cfg_result, qid, RTE_UINT16);
+
+static cmdline_parse_token_string_t cmd_set_port_cman_cfg_params =
+ TOKEN_STRING_INITIALIZER(struct cmd_set_port_cman_cfg_result,
+ params, TOKEN_STRING_MULTI);
+
+static void cmd_set_port_cman_cfg_parsed(void *parsed_result,
+ __rte_unused struct cmdline *cl,
+ __rte_unused void *data)
+{
+ struct cmd_set_port_cman_cfg_result *res = parsed_result;
+ uint16_t port_id = res->port_id;
+ struct rte_eth_cman_config cfg;
+ int ret;
+
+ ret = parse_cman_params_str(port_id, res->params, &cfg);
+ if (ret) {
+ fprintf(stderr, "params string parse error\n");
+ return;
+ }
+
+ cfg.obj_param.rx_queue = res->qid;
+ rte_eth_cman_config_set(port_id, &cfg);
+}
+
+cmdline_parse_inst_t cmd_set_port_cman_config = {
+ .f = cmd_set_port_cman_cfg_parsed,
+ .data = NULL,
+ .help_str = "set port cman config <port_id> <queue_id> "
+ "default | [obj <queue|queue_mempool> mode red "
+ "<min_thresh> <max_thresh> <prob_inv>]",
+ .tokens = {
+ (void *)&cmd_set_port_cman_cfg_set,
+ (void *)&cmd_set_port_cman_cfg_port,
+ (void *)&cmd_set_port_cman_cfg_cman,
+ (void *)&cmd_set_port_cman_cfg_cfg,
+ (void *)&cmd_set_port_cman_cfg_port_id,
+ (void *)&cmd_set_port_cman_cfg_qid,
+ (void *)&cmd_set_port_cman_cfg_params,
+ NULL,
+ },
+};
new file mode 100644
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell International Ltd.
+ */
+
+#ifndef _CMDLINE_CMAN_H_
+#define _CMDLINE_CMAN_H_
+
+extern cmdline_parse_inst_t cmd_show_port_cman_capa;
+extern cmdline_parse_inst_t cmd_show_port_cman_config;
+extern cmdline_parse_inst_t cmd_set_port_cman_config;
+
+#endif /* _CMDLINE_CMAN_H_ */
@@ -7,6 +7,7 @@ cflags += '-Wno-deprecated-declarations'
sources = files(
'5tswap.c',
'cmdline.c',
+ 'cmdline_cman.c',
'cmdline_flow.c',
'cmdline_mtr.c',
'cmdline_tm.c',
@@ -5317,6 +5317,32 @@ Flex pattern can be shared between ports.
testpmd> flow create 0 ingress pattern eth / ipv4 / udp / flex item is 3 pattern is 2 / end actions mark id 1 / queue index 0 / end
Flow rule #0 created
+Congestion Management
+---------------------
+
+Get capabilities
+~~~~~~~~~~~~~~~~
+
+Retrieve congestion management capabilities supported by driver for given port.
+Below example command retrieves capabilities for port 0::
+
+ testpmd> show port cman capa 0
+
+Get configuration
+~~~~~~~~~~~~~~~~~
+Retrieve congestion management configuration for given port. Below example
+command retrieves configuration for port 0::
+
+ testpmd> show port cman config 0
+
+Set configuration
+~~~~~~~~~~~~~~~~~
+Configures congestion management settings on given queue or mempool associated
+with queue. Below example command configures RED as congestion management algo
+for port 0 and queue 0::
+
+ testpmd> set port cman config 0 0 obj queue mode red 10 100 1
+
Driver specific commands
------------------------