DPDK patches and discussions
 help / color / mirror / Atom feed
From: Andrey Vesnovaty <andreyv@nvidia.com>
To: dev@dpdk.org
Cc: jer@marvell.com, jerinjacobk@gmail.com, thomas@monjalon.net,
	ferruh.yigit@intel.com, stephen@networkplumber.org,
	bruce.richardson@intel.com, orika@nvidia.com,
	viacheslavo@nvidia.com, andrey.vesnovaty@gmail.com,
	mdr@ashroe.eu, nhorman@tuxdriver.com, ajit.khaparde@broadcom.com,
	samik.gupta@broadcom.com, Wenzhuo Lu <wenzhuo.lu@intel.com>,
	Beilei Xing <beilei.xing@intel.com>,
	Bernard Iremonger <bernard.iremonger@intel.com>
Subject: [dpdk-dev] [PATCH v5 2/2] app/testpmd: support shared action
Date: Wed,  7 Oct 2020 15:56:12 +0300	[thread overview]
Message-ID: <20201007125612.20579-3-andreyv@nvidia.com> (raw)
In-Reply-To: <20201007125612.20579-1-andreyv@nvidia.com>

This patch adds shared action support to testpmd CLI.

All shared actions created via testpmd CLI assigned ID for further
reference in other CLI commands. Shared action ID supplied as CLI
argument or assigned by testpmd is similar to flow ID & limited to
scope of testpdm CLI.

Create shared action syntax:
flow shared_action (port) create {action_id (shared_action_id)} \
	(action) / end

Create shared action examples:
	flow shared_action 0 create action_id 100 \
		rss queues 1 2 end / end
	This creates shared rss action with id 100 on port 0.

	flow shared_action 0 create action_id \
		rss queues 0 1 end / end
	This creates shared rss action with id assigned by tetspmd
	on port 0.

Update shared action syntax:
flow shared_action (port) update (shared_action_id) (action) / end

Update shared action example:
	flow shared_action 0 update 100 rss queues 0 3 end / end
	This updates shared rss action having id 100 on port 0
	with rss to queues 0 3 (in create example rss queues were
	1 & 2).

Destroy shared action syntax:
flow shared_action (port) destroy action_id (shared_action_id) \
	{ action_id (shared_action_id) [...]}

Update shared action example:
	flow shared_action 0 destroy action_id 100 action_id 101
	This destroys shared actions having id 100 & 101

Query shared action syntax:
flow shared_action (port) query (shared_action_id)

Query shared action example:
	flow shared_action 0 query 100
	This queries shared actions having id 100

Use shared action as flow action syntax:
flow create (port) ... / end actions {action / [...]} \
	shared (action_id) / {action / [...]} end

Use shared action as flow action example:
	flow create 0 ingress pattern ... / end \
		actions shared 100 / end
	This creates flow rule where rss action is shared rss action
	having id 100.

All shared action CLIs report status of the command.
Shared action query CLI output depends on action type.

Signed-off-by: Andrey Vesnovaty <andreyv@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 app/test-pmd/cmdline_flow.c                 | 262 +++++++++++++++++++-
 app/test-pmd/config.c                       | 217 ++++++++++++++++
 app/test-pmd/testpmd.h                      |  19 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 111 +++++++++
 4 files changed, 608 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 6e04d538ea..402ce69aa3 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -49,6 +49,7 @@ enum index {
 	PORT_ID,
 	GROUP_ID,
 	PRIORITY_LEVEL,
+	SHARED_ACTION_ID,
 
 	/* Top-level command. */
 	SET,
@@ -60,6 +61,7 @@ enum index {
 	/* Top-level command. */
 	FLOW,
 	/* Sub-level commands. */
+	SHARED_ACTION,
 	VALIDATE,
 	CREATE,
 	DESTROY,
@@ -89,6 +91,18 @@ enum index {
 	EGRESS,
 	TRANSFER,
 
+	/* Shared action arguments */
+	SHARED_ACTION_CREATE,
+	SHARED_ACTION_UPDATE,
+	SHARED_ACTION_DESTROY,
+	SHARED_ACTION_QUERY,
+
+	/* Shared action create arguments */
+	SHARED_ACTION_CREATE_ID,
+
+	/* Shared action destroy arguments */
+	SHARED_ACTION_DESTROY_ID,
+
 	/* Validate/create pattern. */
 	PATTERN,
 	ITEM_PARAM_IS,
@@ -360,6 +374,8 @@ enum index {
 	ACTION_SET_IPV6_DSCP_VALUE,
 	ACTION_AGE,
 	ACTION_AGE_TIMEOUT,
+	ACTION_SHARED,
+	SHARED_ACTION_ID2PTR,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -653,6 +669,13 @@ struct buffer {
 	enum index command; /**< Flow command. */
 	portid_t port; /**< Affected port ID. */
 	union {
+		struct {
+			uint32_t *action_id;
+			uint32_t action_id_n;
+		} sa_destroy; /**< Shared action destroy arguments. */
+		struct {
+			uint32_t action_id;
+		} sa; /* Shared action query arguments */
 		struct {
 			struct rte_flow_attr attr;
 			struct rte_flow_item *pattern;
@@ -709,6 +732,19 @@ struct parse_action_priv {
 		.size = s, \
 	})
 
+static const enum index next_sa_create_attr[] = {
+	SHARED_ACTION_CREATE_ID,
+	ACTION_RSS,
+	ZERO,
+};
+
+static const enum index next_sa_subcmd[] = {
+	SHARED_ACTION_CREATE,
+	SHARED_ACTION_UPDATE,
+	SHARED_ACTION_DESTROY,
+	SHARED_ACTION_QUERY,
+};
+
 static const enum index next_vc_attr[] = {
 	GROUP,
 	PRIORITY,
@@ -743,6 +779,12 @@ static const enum index next_aged_attr[] = {
 	ZERO,
 };
 
+static const enum index next_sa_destroy_attr[] = {
+	SHARED_ACTION_DESTROY_ID,
+	END,
+	ZERO,
+};
+
 static const enum index item_param[] = {
 	ITEM_PARAM_IS,
 	ITEM_PARAM_SPEC,
@@ -1193,6 +1235,7 @@ static const enum index next_action[] = {
 	ACTION_SET_IPV4_DSCP,
 	ACTION_SET_IPV6_DSCP,
 	ACTION_AGE,
+	ACTION_SHARED,
 	ZERO,
 };
 
@@ -1550,6 +1593,15 @@ static int parse_ipv6_addr(struct context *, const struct token *,
 static int parse_port(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
+static int parse_sa(struct context *, const struct token *,
+		    const char *, unsigned int,
+		    void *, unsigned int);
+static int parse_sa_destroy(struct context *ctx, const struct token *token,
+			    const char *str, unsigned int len,
+			    void *buf, unsigned int size);
+static int parse_sa_id2ptr(struct context *ctx, const struct token *token,
+			   const char *str, unsigned int len, void *buf,
+			   unsigned int size);
 static int comp_none(struct context *, const struct token *,
 		     unsigned int, char *, unsigned int);
 static int comp_boolean(struct context *, const struct token *,
@@ -1688,13 +1740,21 @@ static const struct token token_list[] = {
 		.call = parse_int,
 		.comp = comp_none,
 	},
+	[SHARED_ACTION_ID] = {
+		.name = "{shared_action_id}",
+		.type = "SHARED_ACTION_ID",
+		.help = "shared action id",
+		.call = parse_int,
+		.comp = comp_none,
+	},
 	/* Top-level command. */
 	[FLOW] = {
 		.name = "flow",
 		.type = "{command} {port_id} [{arg} [...]]",
 		.help = "manage ingress/egress flow rules",
 		.next = NEXT(NEXT_ENTRY
-			     (VALIDATE,
+			     (SHARED_ACTION,
+			      VALIDATE,
 			      CREATE,
 			      DESTROY,
 			      FLUSH,
@@ -1705,7 +1765,45 @@ static const struct token token_list[] = {
 			      ISOLATE)),
 		.call = parse_init,
 	},
+	/* Top-level command. */
+	[SHARED_ACTION] = {
+		.name = "shared_action",
+		.type = "{command} {port_id} [{arg} [...]]",
+		.help = "manage shared actions",
+		.next = NEXT(next_sa_subcmd, NEXT_ENTRY(PORT_ID)),
+		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
+		.call = parse_sa,
+	},
 	/* Sub-level commands. */
+	[SHARED_ACTION_CREATE] = {
+		.name = "create",
+		.help = "create shared action",
+		.next = NEXT(next_sa_create_attr),
+		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+		.call = parse_sa,
+	},
+	[SHARED_ACTION_UPDATE] = {
+		.name = "update",
+		.help = "update shared action",
+		.next = NEXT(NEXT_ENTRY(ACTION_RSS),
+			     NEXT_ENTRY(SHARED_ACTION_ID)),
+		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+		.call = parse_sa,
+	},
+	[SHARED_ACTION_DESTROY] = {
+		.name = "destroy",
+		.help = "destroy shared action",
+		.next = NEXT(NEXT_ENTRY(SHARED_ACTION_DESTROY_ID)),
+		.args = ARGS(ARGS_ENTRY(struct buffer, port)),
+		.call = parse_sa_destroy,
+	},
+	[SHARED_ACTION_QUERY] = {
+		.name = "query",
+		.help = "query shared action",
+		.next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(SHARED_ACTION_ID)),
+		.args = ARGS(ARGS_ENTRY(struct buffer, args.sa.action_id)),
+		.call = parse_sa,
+	},
 	[VALIDATE] = {
 		.name = "validate",
 		.help = "check whether a flow rule can be created",
@@ -3859,6 +3957,40 @@ static const struct token token_list[] = {
 		.next = NEXT(action_age, NEXT_ENTRY(UNSIGNED)),
 		.call = parse_vc_conf,
 	},
+	/* Shared action destroy arguments. */
+	[SHARED_ACTION_DESTROY_ID] = {
+		.name = "action_id",
+		.help = "specify a shared action id to destroy",
+		.next = NEXT(next_sa_destroy_attr,
+			     NEXT_ENTRY(SHARED_ACTION_ID)),
+		.args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+					    args.sa_destroy.action_id)),
+		.call = parse_sa_destroy,
+	},
+	/* Shared action create arguments. */
+	[SHARED_ACTION_CREATE_ID] = {
+		.name = "action_id",
+		.help = "specify a shared action id to create",
+		.next = NEXT(NEXT_ENTRY(ACTION_RSS),
+			     NEXT_ENTRY(SHARED_ACTION_ID)),
+		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+	},
+	[ACTION_SHARED] = {
+		.name = "shared",
+		.help = "apply shared action by id",
+		.priv = PRIV_ACTION(SHARED, 0),
+		.next = NEXT(NEXT_ENTRY(SHARED_ACTION_ID2PTR)),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
+		.call = parse_vc,
+	},
+	[SHARED_ACTION_ID2PTR] = {
+		.name = "{action_id}",
+		.type = "SHARED_ACTION_ID",
+		.help = "shared action id",
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_sa_id2ptr,
+		.comp = comp_none,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
@@ -4043,6 +4175,91 @@ parse_init(struct context *ctx, const struct token *token,
 	return len;
 }
 
+/** Parse tokens for shared action commands. */
+static int
+parse_sa(struct context *ctx, const struct token *token,
+	 const char *str, unsigned int len,
+	 void *buf, unsigned int size)
+{
+	struct buffer *out = buf;
+
+	/* Token name must match. */
+	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+		return -1;
+	/* Nothing else to do if there is no buffer. */
+	if (!out)
+		return len;
+	if (!out->command) {
+		if (ctx->curr != SHARED_ACTION)
+			return -1;
+		if (sizeof(*out) > size)
+			return -1;
+		out->command = ctx->curr;
+		ctx->objdata = 0;
+		ctx->object = out;
+		ctx->objmask = NULL;
+		out->args.vc.data = (uint8_t *)out + size;
+		return len;
+	}
+	switch (ctx->curr) {
+	case SHARED_ACTION_CREATE:
+	case SHARED_ACTION_UPDATE:
+		out->args.vc.actions =
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+					       sizeof(double));
+		out->args.vc.attr.group = UINT32_MAX;
+		/* fallthrough */
+	case SHARED_ACTION_QUERY:
+		out->command = ctx->curr;
+		ctx->objdata = 0;
+		ctx->object = out;
+		ctx->objmask = NULL;
+		return len;
+	default:
+		return -1;
+	}
+}
+
+
+/** Parse tokens for shared action destroy command. */
+static int
+parse_sa_destroy(struct context *ctx, const struct token *token,
+		 const char *str, unsigned int len,
+		 void *buf, unsigned int size)
+{
+	struct buffer *out = buf;
+	uint32_t *action_id;
+
+	/* Token name must match. */
+	if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+		return -1;
+	/* Nothing else to do if there is no buffer. */
+	if (!out)
+		return len;
+	if (!out->command || out->command == SHARED_ACTION) {
+		if (ctx->curr != SHARED_ACTION_DESTROY)
+			return -1;
+		if (sizeof(*out) > size)
+			return -1;
+		out->command = ctx->curr;
+		ctx->objdata = 0;
+		ctx->object = out;
+		ctx->objmask = NULL;
+		out->args.sa_destroy.action_id =
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+					       sizeof(double));
+		return len;
+	}
+	action_id = out->args.sa_destroy.action_id
+		    + out->args.sa_destroy.action_id_n++;
+	if ((uint8_t *)action_id > (uint8_t *)out + size)
+		return -1;
+	ctx->objdata = 0;
+	ctx->object = action_id;
+	ctx->objmask = NULL;
+	return len;
+}
+
 /** Parse tokens for validate/create commands. */
 static int
 parse_vc(struct context *ctx, const struct token *token,
@@ -6110,6 +6327,32 @@ parse_port(struct context *ctx, const struct token *token,
 	return ret;
 }
 
+static int
+parse_sa_id2ptr(struct context *ctx, const struct token *token,
+		const char *str, unsigned int len,
+		void *buf, unsigned int size)
+{
+	struct rte_flow_action *action = ctx->object;
+	uint32_t id;
+	int ret;
+
+	(void)buf;
+	(void)size;
+	ctx->objdata = 0;
+	ctx->object = &id;
+	ctx->objmask = NULL;
+	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
+	ctx->object = action;
+	if (ret != (int)len)
+		return ret;
+	/* set shared action */
+	if (action) {
+		action->conf = port_shared_action_get_by_id(ctx->port, id);
+		ret = (action->conf) ? ret : -1;
+	}
+	return ret;
+}
+
 /** Parse set command, initialize output buffer for subsequent tokens. */
 static int
 parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
@@ -6559,6 +6802,23 @@ static void
 cmd_flow_parsed(const struct buffer *in)
 {
 	switch (in->command) {
+	case SHARED_ACTION_CREATE:
+		port_shared_action_create(in->port,
+					  in->args.vc.attr.group,
+					  in->args.vc.actions);
+		break;
+	case SHARED_ACTION_DESTROY:
+		port_shared_action_destroy(in->port,
+					   in->args.sa_destroy.action_id_n,
+					   in->args.sa_destroy.action_id);
+		break;
+	case SHARED_ACTION_UPDATE:
+		port_shared_action_update(in->port, in->args.vc.attr.group,
+					  in->args.vc.actions);
+		break;
+	case SHARED_ACTION_QUERY:
+		port_shared_action_query(in->port, in->args.sa.action_id);
+		break;
 	case VALIDATE:
 		port_flow_validate(in->port, &in->args.vc.attr,
 				   in->args.vc.pattern, in->args.vc.actions);
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 418ea6dda4..d5adf881c5 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1580,6 +1580,223 @@ rss_config_display(struct rte_flow_action_rss *rss_conf)
 	}
 }
 
+static struct port_shared_action *
+action_get_by_id(portid_t port_id, uint32_t id)
+{
+	struct rte_port *port;
+	struct port_shared_action **ppsa;
+	struct port_shared_action *psa = NULL;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+	    port_id == (portid_t)RTE_PORT_ALL)
+		return NULL;
+	port = &ports[port_id];
+	ppsa = &port->actions_list;
+	while (*ppsa) {
+		if ((*ppsa)->id == id) {
+			psa = *ppsa;
+			break;
+		}
+		ppsa = &(*ppsa)->next;
+	}
+	if (!psa)
+		printf("Failed to find shared action #%u on port %u\n",
+		       id, port_id);
+	return psa;
+}
+
+static int
+action_alloc(portid_t port_id, uint32_t id,
+	     struct port_shared_action **action)
+{
+	struct rte_port *port;
+	struct port_shared_action **ppsa;
+	struct port_shared_action *psa = NULL;
+
+	*action = NULL;
+	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+	    port_id == (portid_t)RTE_PORT_ALL)
+		return -EINVAL;
+	port = &ports[port_id];
+	if (id == UINT32_MAX) {
+		/* taking first available ID */
+		if (port->actions_list) {
+			if (port->actions_list->id == UINT32_MAX - 1) {
+				printf("Highest shared action ID is already"
+				" assigned, delete it first\n");
+				return -ENOMEM;
+			}
+			id = port->actions_list->id + 1;
+		} else {
+			id = 0;
+		}
+	}
+	psa = calloc(1, sizeof(*psa));
+	if (!psa) {
+		printf("Allocation of port %u shared action failed\n",
+		       port_id);
+		return -ENOMEM;
+	}
+	ppsa = &port->actions_list;
+	while (*ppsa && (*ppsa)->id > id)
+		ppsa = &(*ppsa)->next;
+	if (*ppsa && (*ppsa)->id == id) {
+		printf("Shared action #%u is already assigned,"
+			" delete it first\n", id);
+		free(psa);
+		return -EINVAL;
+	}
+	psa->next = *ppsa;
+	psa->id = id;
+	*ppsa = psa;
+	*action = psa;
+	return 0;
+}
+
+/** Create shared action */
+int
+port_shared_action_create(portid_t port_id, uint32_t id,
+			  const struct rte_flow_action *action)
+{
+	struct port_shared_action *psa;
+	int ret;
+	struct rte_flow_error error;
+
+	ret = action_alloc(port_id, id, &psa);
+	if (ret)
+		return ret;
+	/* Poisoning to make sure PMDs update it in case of error. */
+	memset(&error, 0x22, sizeof(error));
+	psa->action = rte_flow_shared_action_create(port_id, NULL, action,
+						    &error);
+	if (!psa->action) {
+		uint32_t destroy_id = psa->id;
+		port_shared_action_destroy(port_id, 1, &destroy_id);
+		return port_flow_complain(&error);
+	}
+	psa->type = action->type;
+	printf("Shared action #%u created\n", psa->id);
+	return 0;
+}
+
+/** Destroy shared action */
+int
+port_shared_action_destroy(portid_t port_id,
+			   uint32_t n,
+			   const uint32_t *actions)
+{
+	struct rte_port *port;
+	struct port_shared_action **tmp;
+	uint32_t c = 0;
+	int ret = 0;
+
+	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+	    port_id == (portid_t)RTE_PORT_ALL)
+		return -EINVAL;
+	port = &ports[port_id];
+	tmp = &port->actions_list;
+	while (*tmp) {
+		uint32_t i;
+
+		for (i = 0; i != n; ++i) {
+			struct rte_flow_error error;
+			struct port_shared_action *psa = *tmp;
+
+			if (actions[i] != psa->id)
+				continue;
+			/*
+			 * Poisoning to make sure PMDs update it in case
+			 * of error.
+			 */
+			memset(&error, 0x33, sizeof(error));
+
+			if (psa->action && rte_flow_shared_action_destroy(
+					port_id, psa->action, &error)) {
+				ret = port_flow_complain(&error);
+				continue;
+			}
+			*tmp = psa->next;
+			free(psa);
+			printf("Shared action #%u destroyed\n", psa->id);
+			break;
+		}
+		if (i == n)
+			tmp = &(*tmp)->next;
+		++c;
+	}
+	return ret;
+}
+
+
+/** Get shared action by port + id */
+struct rte_flow_shared_action *
+port_shared_action_get_by_id(portid_t port_id, uint32_t id)
+{
+
+	struct port_shared_action *psa = action_get_by_id(port_id, id);
+
+	return (psa) ? psa->action : NULL;
+}
+
+/** Update shared action */
+int
+port_shared_action_update(portid_t port_id, uint32_t id,
+			  const struct rte_flow_action *action)
+{
+	struct rte_flow_error error;
+	struct rte_flow_shared_action *shared_action;
+
+	shared_action = port_shared_action_get_by_id(port_id, id);
+	if (!shared_action)
+		return -EINVAL;
+	if (rte_flow_shared_action_update(port_id, shared_action, action,
+					  &error)) {
+		return port_flow_complain(&error);
+	}
+	printf("Shared action #%u updated\n", id);
+	return 0;
+}
+
+int
+port_shared_action_query(portid_t port_id, uint32_t id)
+{
+	struct rte_flow_error error;
+	struct port_shared_action *psa;
+	uint64_t default_data;
+	void *data = NULL;
+	int ret = 0;
+
+	psa = action_get_by_id(port_id, id);
+	if (!psa)
+		return -EINVAL;
+	switch (psa->type) {
+	case RTE_FLOW_ACTION_TYPE_RSS:
+		data = &default_data;
+		break;
+	default:
+		printf("Shared action %u (type: %d) on port %u doesn't support"
+		       " query\n", id, psa->type, port_id);
+		return -1;
+	}
+	if (rte_flow_shared_action_query(port_id, psa->action, data, &error))
+		ret = port_flow_complain(&error);
+	switch (psa->type) {
+	case RTE_FLOW_ACTION_TYPE_RSS:
+		if (!ret)
+			printf("Shared RSS action:\n\trefs:%u\n",
+			       *((uint32_t *)data));
+		data = NULL;
+		break;
+	default:
+		printf("Shared action %u (type: %d) on port %u doesn't support"
+		       " query\n", id, psa->type, port_id);
+		ret = -1;
+	}
+	if (data)
+		free(data);
+	return ret;
+}
+
 /** Validate flow rule. */
 int
 port_flow_validate(portid_t port_id,
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index c7e7e41a97..a78fc9f3f0 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -142,6 +142,14 @@ struct port_flow {
 	uint8_t data[]; /**< Storage for flow rule description */
 };
 
+/* Descriptor for shared action */
+struct port_shared_action {
+	struct port_shared_action *next; /**< Next flow in list. */
+	uint32_t id; /**< Shared action ID. */
+	enum rte_flow_action_type type; /**< Action type. */
+	struct rte_flow_shared_action *action;	/**< Shared action handle. */
+};
+
 /**
  * The data structure associated with each port.
  */
@@ -172,6 +180,8 @@ struct rte_port {
 	uint32_t                mc_addr_nb; /**< nb. of addr. in mc_addr_pool */
 	uint8_t                 slave_flag; /**< bonding slave port */
 	struct port_flow        *flow_list; /**< Associated flows. */
+	struct port_shared_action *actions_list;
+	/**< Associated shared actions. */
 	const struct rte_eth_rxtx_callback *rx_dump_cb[RTE_MAX_QUEUES_PER_PORT+1];
 	const struct rte_eth_rxtx_callback *tx_dump_cb[RTE_MAX_QUEUES_PER_PORT+1];
 	/**< metadata value to insert in Tx packets. */
@@ -748,6 +758,14 @@ void port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
 			    uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value);
 void port_reg_display(portid_t port_id, uint32_t reg_off);
 void port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t value);
+int port_shared_action_create(portid_t port_id, uint32_t id,
+			      const struct rte_flow_action *action);
+int port_shared_action_destroy(portid_t port_id,
+			       uint32_t n, const uint32_t *action);
+struct rte_flow_shared_action *port_shared_action_get_by_id(portid_t port_id,
+							    uint32_t id);
+int port_shared_action_update(portid_t port_id, uint32_t id,
+			      const struct rte_flow_action *action);
 int port_flow_validate(portid_t port_id,
 		       const struct rte_flow_attr *attr,
 		       const struct rte_flow_item *pattern,
@@ -756,6 +774,7 @@ int port_flow_create(portid_t port_id,
 		     const struct rte_flow_attr *attr,
 		     const struct rte_flow_item *pattern,
 		     const struct rte_flow_action *actions);
+int port_shared_action_query(portid_t port_id, uint32_t id);
 void update_age_action_context(const struct rte_flow_action *actions,
 		     struct port_flow *pf);
 int port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 72bdb1be43..f4b26ed307 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -4382,6 +4382,11 @@ This section lists supported actions and their attributes, if any.
 
   - ``dscp_value {unsigned}``: The new DSCP value to be set
 
+- ``shared``: Use shared action created via
+  ``flow shared_action {port_id} create``
+
+  - ``shared_action_id {unsigned}``: Shared action ID to use
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
@@ -4671,6 +4676,112 @@ If attach ``destroy`` parameter, the command will destroy all the list aged flow
    testpmd> flow aged 0
    Port 0 total aged flows: 0
 
+Creating shared actions
+~~~~~~~~~~~~~~~~~~~~~~~
+``flow shared_action {port_id} create`` creates shared action with optional
+shared action ID. It is bound to ``rte_flow_shared_action_create()``::
+
+   flow shared_action {port_id} create [action_id {shared_action_id}] \
+      {action} / end
+
+If successful, it will show::
+
+   Shared action #[...] created
+
+Otherwise, it will complain either that shared action already exists or that
+some error occurred::
+
+   Shared action #[...] is already assigned, delete it first
+
+::
+
+   Caught error type [...] ([...]): [...]
+
+Create shared rss action with id 100 to queues 1 and 2 on port 0::
+
+   testpmd> flow shared_action 0 create action_id 100 \
+      rss queues 1 2 end / end
+
+Create shared rss action with id assigned by testpmd to queues 1 and 2 on
+port 0::
+
+	testpmd> flow shared_action 0 create action_id \
+		rss queues 0 1 end / end
+
+Updating shared actions
+~~~~~~~~~~~~~~~~~~~~~~~
+``flow shared_action {port_id} update`` updates configuration of the shared
+action from its shared action ID (as returned by
+``flow shared_action {port_id} create``). It is bound to
+``rte_flow_shared_action_update()``::
+
+  flow shared_action {port_id} update {shared_action_id} {action} / end
+
+If successful, it will show::
+
+   Shared action #[...] updated
+
+Otherwise, it will complain either that shared action not found or that some
+error occurred::
+
+   Failed to find shared action #[...] on port [...]
+
+::
+
+   Caught error type [...] ([...]): [...]
+
+Update shared rss action having id 100 on port 0 with rss to queues 0 and 3
+(in create example above rss queues were 1 and 2)::
+
+   testpmd> flow shared_action 0 update 100 rss queues 0 3 end / end
+
+Destroying shared actions
+~~~~~~~~~~~~~~~~~~~~~~~~~
+``flow shared_action {port_id} update`` destroys one or more shared actions
+from their shared action IDs (as returned by
+``flow shared_action {port_id} create``). It is bound to
+``rte_flow_shared_action_destroy()``::
+
+   flow shared_action {port_id} destroy action_id {shared_action_id} [...]
+
+If successful, it will show::
+
+   Shared action #[...] destroyed
+
+It does not report anything for shared action IDs that do not exist.
+The usual error message is shown when a shared action cannot be destroyed::
+
+   Caught error type [...] ([...]): [...]
+
+Destroy shared actions having id 100 & 101::
+
+   testpmd> flow shared_action 0 destroy action_id 100 action_id 101
+
+Query shared actions
+~~~~~~~~~~~~~~~~~~~~
+``flow shared_action {port_id} query`` queries the shared action from its
+shared action ID (as returned by ``flow shared_action {port_id} create``).
+It is bound to ``rte_flow_shared_action_query()``::
+
+  flow shared_action {port_id} query {shared_action_id}
+
+Currently only rss shared action supported. If successful, it will show::
+
+   Shared RSS action:
+      refs:[...]
+
+Otherwise, it will complain either that shared action not found or that some
+error occurred::
+
+   Failed to find shared action #[...] on port [...]
+
+::
+
+   Caught error type [...] ([...]): [...]
+
+Query shared action having id 100::
+
+   testpmd> flow shared_action 0 query 100
 
 Sample QinQ flow rules
 ~~~~~~~~~~~~~~~~~~~~~~
-- 
2.26.2


  parent reply	other threads:[~2020-10-07 12:57 UTC|newest]

Thread overview: 106+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-02 12:05 [dpdk-dev] [PATCH] add flow shared action API Andrey Vesnovaty
2020-07-03 15:02 ` Jerin Jacob
2020-07-03 15:21   ` Thomas Monjalon
2020-07-04  9:54     ` Andrey Vesnovaty
2020-07-04 10:10   ` Andrey Vesnovaty
2020-07-04 12:33     ` Jerin Jacob
2020-07-05 10:26       ` Ori Kam
2020-07-06  9:00         ` Jerin Jacob
2020-07-06 12:28           ` Ori Kam
2020-07-06 13:32             ` Andrey Vesnovaty
2020-07-07  2:30               ` Jerin Jacob
2020-07-07  6:21                 ` Ori Kam
2020-07-07 15:21                   ` Ferruh Yigit
2020-07-07 17:24                     ` Ori Kam
2020-07-07 17:52                       ` Ferruh Yigit
2020-07-07 19:38                   ` Jerin Jacob
2020-07-07 21:03                     ` Ori Kam
2020-07-08  9:25                       ` Jerin Jacob
2020-07-08  9:47                         ` Ori Kam
2020-07-08 11:00                           ` Jerin Jacob
2020-07-08 11:50                             ` Thomas Monjalon
2020-07-08 12:18                             ` Ori Kam
     [not found]                               ` <20200708204015.24429-2-andreyv@mellanox.com>
2020-07-13  8:04                                 ` [dpdk-dev] [PATCH v2 1/6] ethdev: " Kinsella, Ray
2020-07-13 10:16                                   ` Andrew Rybchenko
2020-07-15  8:54                                   ` Andrew Rybchenko
2020-07-15  9:00                                     ` Andrew Rybchenko
2020-09-15 11:30                                     ` Andrey Vesnovaty
     [not found]                               ` <20200708204015.24429-3-andreyv@mellanox.com>
2020-07-13  8:06                                 ` [dpdk-dev] [PATCH v2 2/6] common/mlx5: modify advanced Rx object via DevX Kinsella, Ray
2020-07-08 21:39 ` [dpdk-dev] [PATCH v2 0/6] add flow shared action API + PMD Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 1/6] ethdev: add flow shared action API Andrey Vesnovaty
2020-09-12  2:18     ` Ajit Khaparde
2020-09-15 11:50       ` Andrey Vesnovaty
2020-09-15 15:49         ` Ajit Khaparde
2020-09-16 15:52           ` Andrey Vesnovaty
2020-09-16 19:20             ` Ajit Khaparde
2020-09-17 15:33               ` Andrew Rybchenko
2020-09-17 16:02                 ` Ori Kam
2020-09-24 19:25                   ` Ajit Khaparde
2020-09-26 11:09                     ` Andrey Vesnovaty
2020-10-03 22:06                       ` [dpdk-dev] [PATCH v3 00/10] RTE flow shared action Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 01/10] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-04 11:10                           ` Ori Kam
2020-10-06 10:22                             ` Andrey Vesnovaty
2020-10-04 17:00                           ` Stephen Hemminger
2020-10-04 17:01                             ` Stephen Hemminger
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 02/10] ethdev: add conf arg to shared action icreate API Andrey Vesnovaty
2020-10-04 11:11                           ` Ori Kam
2020-10-06 10:28                             ` Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 03/10] common/mlx5: modify advanced Rx object via DevX Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 04/10] net/mlx5: modify hash Rx queue objects Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 05/10] net/mlx5: shared action PMD Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 06/10] net/mlx5: shared action PMD create conf arg Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 07/10] net/mlx5: driver support for shared action Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 08/10] net/mlx5: shared action create conf drv support Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 09/10] examples/flow_filtering: utilize shared RSS action Andrey Vesnovaty
2020-10-04 11:21                           ` Ori Kam
2020-10-06 10:34                             ` Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 10/10] app/testpmd: support shared action Andrey Vesnovaty
2020-10-04 11:28                           ` Ori Kam
2020-10-04 12:04                             ` Ori Kam
2020-10-06 10:36                               ` Andrey Vesnovaty
2020-10-04 11:14                         ` [dpdk-dev] [PATCH v3 00/10] RTE flow " Ori Kam
2020-10-06 10:28                           ` Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 2/6] common/mlx5: modify advanced Rx object via DevX Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 3/6] net/mlx5: modify hash Rx queue objects Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 4/6] net/mlx5: shared action PMD Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 5/6] net/mlx5: driver support for shared action Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 6/6] examples/flow_filtering: utilize shared RSS action Andrey Vesnovaty
2020-07-09  4:44     ` Jerin Jacob
2020-07-09  6:08       ` Ori Kam
2020-07-09 12:25         ` Andrey Vesnovaty
2020-07-09 12:39           ` Thomas Monjalon
2020-07-09  4:39   ` [dpdk-dev] [PATCH v2 0/6] add flow shared action API + PMD Jerin Jacob
2020-10-06 20:08 ` [dpdk-dev] [PATCH v4 0/2] RTE flow shared action Andrey Vesnovaty
2020-10-06 20:08   ` [dpdk-dev] [PATCH v4 1/2] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-07  6:27     ` Ori Kam
2020-10-06 20:08   ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: support shared action Andrey Vesnovaty
2020-10-07  6:30     ` Ori Kam
2020-10-07 12:56 ` [dpdk-dev] [PATCH v5 0/2] RTE flow " Andrey Vesnovaty
2020-10-07 12:56   ` [dpdk-dev] [PATCH v5 1/2] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-07 13:01     ` Ori Kam
2020-10-07 21:23     ` Ajit Khaparde
2020-10-08  7:28       ` Andrey Vesnovaty
2020-10-07 12:56   ` Andrey Vesnovaty [this message]
2020-10-07 18:36 ` [dpdk-dev] [PATCH v6 0/2] RTE flow shared action Andrey Vesnovaty
2020-10-07 18:36   ` [dpdk-dev] [PATCH v6 1/2] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-07 18:36   ` [dpdk-dev] [PATCH v6 2/2] app/testpmd: support shared action Andrey Vesnovaty
2020-10-07 20:01     ` Ajit Khaparde
2020-10-08 10:58       ` Andrey Vesnovaty
2020-10-08 11:51 ` [dpdk-dev] [PATCH v7 0/2] RTE flow " Andrey Vesnovaty
2020-10-08 11:51   ` [dpdk-dev] [PATCH v7 1/2] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-08 22:30     ` Ajit Khaparde
2020-10-14 11:47       ` Andrey Vesnovaty
2020-10-12 14:19     ` Andrew Rybchenko
2020-10-13 20:06       ` Andrey Vesnovaty
2020-10-14  6:49         ` Andrew Rybchenko
2020-10-14  7:22           ` Thomas Monjalon
2020-10-14 11:43             ` Andrey Vesnovaty
2020-10-14 11:42           ` Andrey Vesnovaty
2020-10-08 11:51   ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: support shared action Andrey Vesnovaty
2020-10-08 23:54     ` Ajit Khaparde
2020-10-14 11:40 ` [dpdk-dev] [PATCH v8 0/2] RTE flow " Andrey Vesnovaty
2020-10-14 11:40   ` [dpdk-dev] [PATCH v8 1/2] ethdev: add shared actions to flow API Andrey Vesnovaty
2020-10-14 11:44     ` Andrew Rybchenko
2020-10-14 16:17       ` Ferruh Yigit
2020-10-14 11:40   ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: support shared action Andrey Vesnovaty

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201007125612.20579-3-andreyv@nvidia.com \
    --to=andreyv@nvidia.com \
    --cc=ajit.khaparde@broadcom.com \
    --cc=andrey.vesnovaty@gmail.com \
    --cc=beilei.xing@intel.com \
    --cc=bernard.iremonger@intel.com \
    --cc=bruce.richardson@intel.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=jer@marvell.com \
    --cc=jerinjacobk@gmail.com \
    --cc=mdr@ashroe.eu \
    --cc=nhorman@tuxdriver.com \
    --cc=orika@nvidia.com \
    --cc=samik.gupta@broadcom.com \
    --cc=stephen@networkplumber.org \
    --cc=thomas@monjalon.net \
    --cc=viacheslavo@nvidia.com \
    --cc=wenzhuo.lu@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).