[v2,1/3] app/testpmd: support congestion management CLIs

Message ID 20220929095455.2173071-1-skori@marvell.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series [v2,1/3] app/testpmd: support congestion management CLIs |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/iol-testing warning apply patch failure

Commit Message

Sunil Kumar Kori Sept. 29, 2022, 9:54 a.m. UTC
  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

Sunil Kumar Kori Oct. 12, 2022, 9:01 a.m. UTC | #1
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
  
Andrew Rybchenko Nov. 6, 2022, 10:08 a.m. UTC | #2
@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
>
  
Singh, Aman Deep Nov. 7, 2022, 7:12 a.m. UTC | #3
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
>>
>
  
Sunil Kumar Kori Nov. 29, 2022, 7:54 a.m. UTC | #4
> -----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
> >>
> >
  

Patch

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
 ------------------------