Skip to contentSkip to conversation

ethdev: add indirect list flow action

PATCH Superseded Gregory Etelson 4 participants 17 messages Apr 18, 2023 – May 31, 2023

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ethdev: add indirect list flow action

Indirect flow action provides a handler to hardware flow action object. The handler is used in flow rules for sharing hardware action object state.

Current INDIRECT flow handler can reference a single flow action type.

New INDIRECT_LIST extends existing functionality. INDIRECT_LIST flow handler can reference one or many flow actions.

testpmd example:

set raw_encap 0 \
eth src is 11:00:00:00:00:11 dst is aa:00:00:00:00:aa / \
ipv4 src is 1.1.1.1 dst is 2.2.2.2 ttl is 64 proto is 17 / \
udp src is 0x1234 dst is 4789 / vxlan vni is 0xabcd / end_set set raw_encap 1 \
eth src is 22:00:00:00:00:22 dst is bb:00:00:00:00:bb / \
ipv6 src is 2001::1111 dst is 2001::2222 proto is 17 / \
udp src is 0x1234 dst is 4789 / vxlan vni is 0xabcd / end_set

set sample_actions 0 \
raw_encap index 0 / represented_port ethdev_port_id 0 / end set sample_actions 1 \
raw_encap index 1 / represented_port ethdev_port_id 0 / end

flow indirect_action 0 create transfer list actions \
sample ratio 1 index 0 / \
sample ratio 1 index 1 / \
jump group 0xcaca / end

flow actions_template 0 create transfer actions_template_id 10 \
template indirect_list 0 / end mask indirect_list / end

---
 app/test-pmd/cmdline_flow.c            |  41 ++++++-
 app/test-pmd/config.c                  | 162 +++++++++++++++++++------
 app/test-pmd/testpmd.h                 |   7 +-
 doc/guides/nics/features/default.ini   |   1 +
 doc/guides/prog_guide/rte_flow.rst     |   6 +
 doc/guides/rel_notes/release_23_07.rst |   4 +
 lib/ethdev/rte_flow.c                  |  92 ++++++++++++++
 lib/ethdev/rte_flow.h                  | 149 +++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h           |  27 ++++-
 lib/ethdev/version.map                 |   4 +
 10 files changed, 452 insertions(+), 41 deletions(-)
app/test-pmd/cmdline_flow.c +40 -1
index 58939ec321..956a39d167 100644
@@ -145,6 +145,7 @@ enum index {
 
 	/* Queue indirect action arguments */
 	QUEUE_INDIRECT_ACTION_CREATE,
+	QUEUE_INDIRECT_ACTION_LIST_CREATE,
 	QUEUE_INDIRECT_ACTION_UPDATE,
 	QUEUE_INDIRECT_ACTION_DESTROY,
 	QUEUE_INDIRECT_ACTION_QUERY,
@@ -157,6 +158,7 @@ enum index {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 
 	/* Queue indirect action update arguments */
 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
@@ -242,6 +244,7 @@ enum index {
 
 	/* Indirect action arguments */
 	INDIRECT_ACTION_CREATE,
+	INDIRECT_ACTION_LIST_CREATE,
 	INDIRECT_ACTION_UPDATE,
 	INDIRECT_ACTION_DESTROY,
 	INDIRECT_ACTION_QUERY,
@@ -253,6 +256,7 @@ enum index {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
 
 	/* Indirect action destroy arguments */
 	INDIRECT_ACTION_DESTROY_ID,
@@ -626,6 +630,7 @@ enum index {
 	ACTION_SAMPLE_INDEX,
 	ACTION_SAMPLE_INDEX_VALUE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
 	ACTION_SHARED_INDIRECT,
 	INDIRECT_ACTION_PORT,
 	INDIRECT_ACTION_ID2PTR,
@@ -1266,6 +1271,7 @@ static const enum index next_qia_create_attr[] = {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 	ZERO,
 };
 
@@ -1294,6 +1300,7 @@ static const enum index next_ia_create_attr[] = {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
 	ZERO,
 };
 
@@ -2013,6 +2020,7 @@ static const enum index next_action[] = {
 	ACTION_AGE_UPDATE,
 	ACTION_SAMPLE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
 	ACTION_SHARED_INDIRECT,
 	ACTION_MODIFY_FIELD,
 	ACTION_CONNTRACK,
@@ -2289,6 +2297,7 @@ static const enum index next_action_sample[] = {
 	ACTION_RAW_ENCAP,
 	ACTION_VXLAN_ENCAP,
 	ACTION_NVGRE_ENCAP,
+	ACTION_REPRESENTED_PORT,
 	ACTION_NEXT,
 	ZERO,
 };
@@ -3426,6 +3435,12 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[QUEUE_INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_qia,
+	},
 	/* Top-level command. */
 	[PUSH] = {
 		.name = "push",
@@ -6775,6 +6790,14 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
 		.call = parse_vc,
 	},
+	[ACTION_INDIRECT_LIST] = {
+		.name = "indirect_list",
+		.help = "apply indirect list action by id",
+		.priv = PRIV_ACTION(INDIRECT_LIST, 0),
+		.next = NEXT(next_ia),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
+		.call = parse_vc,
+	},
 	[ACTION_SHARED_INDIRECT] = {
 		.name = "shared_indirect",
 		.help = "apply indirect action by id and port",
@@ -6823,6 +6846,12 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_ia,
+	},
 	[ACTION_POL_G] = {
 		.name = "g_actions",
 		.help = "submit a list of associated actions for green",
@@ -7181,6 +7210,9 @@ parse_ia(struct context *ctx, const struct token *token,
 		return len;
 	case INDIRECT_ACTION_QU_MODE:
 		return len;
+	case INDIRECT_ACTION_LIST:
+		out->command = INDIRECT_ACTION_LIST_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7278,6 +7310,9 @@ parse_qia(struct context *ctx, const struct token *token,
 		return len;
 	case QUEUE_INDIRECT_ACTION_QU_MODE:
 		return len;
+	case QUEUE_INDIRECT_ACTION_LIST:
+		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7454,10 +7489,12 @@ parse_vc(struct context *ctx, const struct token *token,
 			return -1;
 		break;
 	case ACTIONS:
-		out->args.vc.actions =
+		out->args.vc.actions = out->args.vc.pattern ?
 			(void *)RTE_ALIGN_CEIL((uintptr_t)
 					       (out->args.vc.pattern +
 						out->args.vc.pattern_n),
+					       sizeof(double)) :
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
 					       sizeof(double));
 		ctx->object = out->args.vc.actions;
 		ctx->objmask = NULL;
@@ -11532,6 +11569,7 @@ cmd_flow_parsed(const struct buffer *in)
 				     in->args.aged.destroy);
 		break;
 	case QUEUE_INDIRECT_ACTION_CREATE:
+	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
 		port_queue_action_handle_create(
 				in->port, in->queue, in->postpone,
 				in->args.vc.attr.group,
@@ -11567,6 +11605,7 @@ cmd_flow_parsed(const struct buffer *in)
 						      in->args.vc.actions);
 		break;
 	case INDIRECT_ACTION_CREATE:
+	case INDIRECT_ACTION_LIST_CREATE:
 		port_action_handle_create(
 				in->port, in->args.vc.attr.group,
 				&((const struct rte_flow_indir_action_conf) {
app/test-pmd/config.c +124 -38

228 lines not on this page · raw message

app/test-pmd/testpmd.h +6 -1
index bdfbfd36d3..9786e62d28 100644
@@ -228,7 +228,12 @@ struct port_indirect_action {
 	struct port_indirect_action *next; /**< Next flow in list. */
 	uint32_t id; /**< Indirect action ID. */
 	enum rte_flow_action_type type; /**< Action type. */
-	struct rte_flow_action_handle *handle;	/**< Indirect action handle. */
+	union {
+		struct rte_flow_action_handle *handle;
+		/**< Indirect action handle. */
+		struct rte_flow_action_list_handle *list_handle;
+		/**< Indirect action list handle*/
+	};
 	enum age_action_context_type age_type; /**< Age action context type. */
 };
 
doc/guides/nics/features/default.ini +1 -0
index 1a5087abad..10a1c1af77 100644
@@ -158,6 +158,7 @@ drop                 =
 flag                 =
 inc_tcp_ack          =
 inc_tcp_seq          =
+indirect_list        =
 jump                 =
 mac_swap             =
 mark                 =
doc/guides/prog_guide/rte_flow.rst +6 -0
index 32fc45516a..ed67e86c58 100644
@@ -3300,6 +3300,12 @@ The ``quota`` value is reduced according to ``mode`` setting.
    | ``RTE_FLOW_QUOTA_MODE_L3``      | Count packet bytes starting from L3 |
    +------------------+----------------------------------------------------+
 
+Action: ``INDIRECT_LIST``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The new ``INDIRECT_LIST`` flow action references one or many flow actions.
+Extends the ``INDIRECT`` flow action.
+
 Negative types
 ~~~~~~~~~~~~~~
 
doc/guides/rel_notes/release_23_07.rst +4 -0
index a9b1293689..955493e445 100644
@@ -55,6 +55,10 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+   * **Added indirect list flow action.**
+
+     * ``RTE_FLOW_ACTION_TYPE_INDIRECT_LIST``
+
 
 Removed Items
 -------------
lib/ethdev/rte_flow.c +92 -0

101 lines not on this page · raw message

lib/ethdev/rte_flow.h +149 -0

161 lines not on this page · raw message

lib/ethdev/rte_flow_driver.h +26 -1
index a129a4605d..71d9b4b0a7 100644
@@ -121,6 +121,17 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_create() */
+	struct rte_flow_action_list_handle *(*action_list_handle_create)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action actions[],
+		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_destroy() */
+	int (*action_list_handle_destroy)
+		(struct rte_eth_dev *dev,
+		 struct rte_flow_action_list_handle *handle,
+		 struct rte_flow_error *error);
 	/** See rte_flow_tunnel_decap_set() */
 	int (*tunnel_decap_set)
 		(struct rte_eth_dev *dev,
@@ -294,7 +305,7 @@ struct rte_flow_ops {
 		 void *data,
 		 void *user_data,
 		 struct rte_flow_error *error);
-	/** See rte_flow_async_action_handle_query_update */
+	/** @see rte_flow_async_action_handle_query_update */
 	int (*async_action_handle_query_update)
 		(struct rte_eth_dev *dev, uint32_t queue_id,
 		 const struct rte_flow_op_attr *op_attr,
@@ -302,6 +313,20 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_create() */
+	struct rte_flow_action_list_handle *
+	(*async_action_list_handle_create)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action *actions,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_destroy() */
+	int (*async_action_list_handle_destroy)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *action_handle,
+		 void *user_data, struct rte_flow_error *error);
 };
 
 /**
lib/ethdev/version.map +4 -0
index 357d1a88c0..d6c0b927f1 100644
@@ -299,6 +299,10 @@ EXPERIMENTAL {
 	rte_flow_action_handle_query_update;
 	rte_flow_async_action_handle_query_update;
 	rte_flow_async_create_by_index;
+	rte_flow_action_list_handle_create;
+	rte_flow_action_list_handle_destroy;
+	rte_flow_async_action_list_handle_create;
+	rte_flow_async_action_list_handle_destroy;
 };
 
 INTERNAL {
Signature · 1 line
2.34.1
#1 lore raw

RFC PATCH v2 1/1 ethdev: add indirect list flow action

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

Indirect action lists action will deprecate and replace existing indirect action after transition period.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), PMD compiles base action
configuration during action template, table template and flow rule phases - depending on PMD action implementation. Otherwise, action is compiled from scratch during flow rule processing.

2 If Htmpl and Ctmpl were masked (Hmask !=0 and Cmask != 0), table
template processing overwrites base action configuration with Ctmpl parameters.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was masked, Hflow can reference a different action of the
same type as Htmpl.

4 If Cflow was specified, it overwrites action configuration.

---
 lib/ethdev/rte_flow.h        | 266 +++++++++++++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h |  41 ++++++
 2 files changed, 307 insertions(+)
lib/ethdev/rte_flow.h +266 -0
index 713ba8b65c..ac1f51e564 100644
@@ -2912,6 +2912,13 @@ enum rte_flow_action_type {
 	 * applied to the given ethdev Rx queue.
 	 */
 	RTE_FLOW_ACTION_TYPE_SKIP_CMAN,
+
+	/**
+	 * Action handle to reference flow actions list.
+	 *
+	 * @see struct rte_flow_action_indirect_list
+	 */
+	RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
 };
 
 /**
@@ -6118,6 +6125,265 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,
 					  void *user_data,
 					  struct rte_flow_error *error);
 
+struct rte_flow_action_list_handle;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Configure INDIRECT_LIST flow action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ */
+struct rte_flow_action_indirect_list {
+	struct rte_flow_action_list_handle; /**< Indirect action list handle */
+	/**
+	 * Flow mutable configuration array.
+	 * NULL if the handle has no flow mutable configuration update.
+	 * Otherwise, if the handle was created with list A1 / A2 .. An / END
+	 * size of conf is n.
+	 * conf[i] points to flow mutable update of Ai in the handle
+	 * actions list or NULL if Ai has no update.
+	 */
+	const void **conf;
+};
+
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create an indirect flow action object from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action lists.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+				   const
+				   struct rte_flow_indir_action_conf *conf,
+				   const struct rte_flow_action *actions,
+				   struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Async function call to create an indirect flow action object
+ * from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to update the rule.
+ * @param[in] attr
+ *   Indirect action update operation attributes.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action list.
+ * @param[in] user_data
+ *   The user data that will be returned on async completion event.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,
+					 const struct rte_flow_op_attr *attr,
+					 const struct
+					 rte_flow_indir_action_conf *conf,
+					 const struct rte_flow_action *actions,
+					 void *user_data,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy indirect actions list by handle.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] handle
+ *   Handle for the indirect actions list to be destroyed.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.
+ *   - (-EBUSY) if actions list pointed by *action* handle still used
+ *   rte_errno is also set.
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+				    struct rte_flow_action_list_handle *handle,
+				    struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action list destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ *   Port identifier of Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to destroy the rule.
+ * @param[in] op_attr
+ *   Indirect action destruction operation attributes.
+ * @param[in] handle
+ *   Handle for the indirect action object to be destroyed.
+ * @param[in] user_data
+ *   The user data that will be returned on the completion events.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_destroy
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *handle,
+		 void *user_data, struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query and/or update indirect flow actions list.
+ * If both query and update not NULL, the function atomically
+ * queries and updates indirect action. Query and update are carried in order
+ * specified in the mode parameter.
+ * If ether query or update is NULL, the function executes
+ * complementing operation.
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL pointer to storage for the associated query data type.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *query* and *update* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_query_update(uint16_t port_id,
+					 const struct
+					 rte_flow_action_list_handle *handle,
+					 const void **update, void **query,
+					 enum rte_flow_query_update_mode mode,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue async indirect flow actions list query and/or update
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param queue_id
+ *   Flow queue which is used to update the rule.
+ * @param attr
+ *   Indirect action update operation attributes.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL, pointer to storage for the associated query data type.
+ *   Query result returned on async completion event.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param user_data
+ *   The user data that will be returned on async completion event.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *update* and *query* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_id,
+					  const struct rte_flow_op_attr *attr,
+					  const struct
+					  rte_flow_action_list_handle *handle,
+					  const void *update, void *query,
+					  enum rte_flow_query_update_mode mode,
+					  void *user_data,
+					  struct rte_flow_error *error);
+
+
 #ifdef __cplusplus
 }
 #endif
lib/ethdev/rte_flow_driver.h +41 -0

53 lines not on this page · raw message

Signature · 1 line
2.34.1
#2 lore raw

Hi Gregory,

Overall, the idea of action list indirection sounds good. But why deprecate the existing indirect action API? Are there any strong reasons for that? This action should probably stay. Well, at least, I wouldn't expect this patch to immediately introduce some transition period. Let's cross that bridge
when we get there. What do you think?

Also, what are the target applications/projects to benefit from the new indirect action list API? Could you please provide some examples. Or, alternatively, you could shed light on which "shapes" of flow rules would
be the primary users of the action.

Thank you.

Quoted 448 lines · Gregory Etelson

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                  |       |
                  |       |
                  |       |         flow 2:
                  |       |         / indirect handle H conf C2 /
                  |       |                           |      |
                  |       |                           |      |
                  |       |                           |      |
           =========================================================
           ^      |       |                           |      |
           |      |       V                           |      V
           |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
           |     flow mutable                        flow mutable
           |     context 1                           context 2
           |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
 indirect  |      |                                   |
 action    |      |                                   |
 context   |      V                                   V
           |   -----------------------------------------------------
           |                 action mutable context
           |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

Indirect action lists action will deprecate and replace existing indirect action after transition period.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), PMD compiles base action
configuration during action template, table template and flow rule phases - depending on PMD action implementation. Otherwise, action is compiled from scratch during flow rule processing.

2 If Htmpl and Ctmpl were masked (Hmask !=0 and Cmask != 0), table
template processing overwrites base action configuration with Ctmpl parameters.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was masked, Hflow can reference a different action of the
same type as Htmpl.

4 If Cflow was specified, it overwrites action configuration.

---
lib/ethdev/rte_flow.h | 266 +++++++++++++++++++++++++++++++++++
lib/ethdev/rte_flow_driver.h | 41 ++++++

2 files changed, 307 insertions(+)
lib/ethdev/rte_flow.h +266 -0
index 713ba8b65c..ac1f51e564 100644
@@ -2912,6 +2912,13 @@ enum rte_flow_action_type {
 	 * applied to the given ethdev Rx queue.
 	 */
 	RTE_FLOW_ACTION_TYPE_SKIP_CMAN,
+
+	/**
+	 * Action handle to reference flow actions list.
+	 *
+	 * @see struct rte_flow_action_indirect_list
+	 */
+	RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
 };
 
 /**
@@ -6118,6 +6125,265 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,
 					  void *user_data,
 					  struct rte_flow_error *error);
 
+struct rte_flow_action_list_handle;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Configure INDIRECT_LIST flow action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ */
+struct rte_flow_action_indirect_list {
+	struct rte_flow_action_list_handle; /**< Indirect action list handle */
+	/**
+	 * Flow mutable configuration array.
+	 * NULL if the handle has no flow mutable configuration update.
+	 * Otherwise, if the handle was created with list A1 / A2 .. An / END
+	 * size of conf is n.
+	 * conf[i] points to flow mutable update of Ai in the handle
+	 * actions list or NULL if Ai has no update.
+	 */
+	const void **conf;
+};
+
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create an indirect flow action object from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action lists.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+				   const
+				   struct rte_flow_indir_action_conf *conf,
+				   const struct rte_flow_action *actions,
+				   struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Async function call to create an indirect flow action object
+ * from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to update the rule.
+ * @param[in] attr
+ *   Indirect action update operation attributes.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action list.
+ * @param[in] user_data
+ *   The user data that will be returned on async completion event.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,
+					 const struct rte_flow_op_attr *attr,
+					 const struct
+					 rte_flow_indir_action_conf *conf,
+					 const struct rte_flow_action *actions,
+					 void *user_data,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy indirect actions list by handle.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] handle
+ *   Handle for the indirect actions list to be destroyed.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.
+ *   - (-EBUSY) if actions list pointed by *action* handle still used
+ *   rte_errno is also set.
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+				    struct rte_flow_action_list_handle *handle,
+				    struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action list destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ *   Port identifier of Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to destroy the rule.
+ * @param[in] op_attr
+ *   Indirect action destruction operation attributes.
+ * @param[in] handle
+ *   Handle for the indirect action object to be destroyed.
+ * @param[in] user_data
+ *   The user data that will be returned on the completion events.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_destroy
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *handle,
+		 void *user_data, struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query and/or update indirect flow actions list.
+ * If both query and update not NULL, the function atomically
+ * queries and updates indirect action. Query and update are carried in order
+ * specified in the mode parameter.
+ * If ether query or update is NULL, the function executes
+ * complementing operation.
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL pointer to storage for the associated query data type.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *query* and *update* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_query_update(uint16_t port_id,
+					 const struct
+					 rte_flow_action_list_handle *handle,
+					 const void **update, void **query,
+					 enum rte_flow_query_update_mode mode,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue async indirect flow actions list query and/or update
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param queue_id
+ *   Flow queue which is used to update the rule.
+ * @param attr
+ *   Indirect action update operation attributes.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL, pointer to storage for the associated query data type.
+ *   Query result returned on async completion event.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param user_data
+ *   The user data that will be returned on async completion event.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *update* and *query* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_id,
+					  const struct rte_flow_op_attr *attr,
+					  const struct
+					  rte_flow_action_list_handle *handle,
+					  const void *update, void *query,
+					  enum rte_flow_query_update_mode mode,
+					  void *user_data,
+					  struct rte_flow_error *error);
+
+
 #ifdef __cplusplus
 }
 #endif
lib/ethdev/rte_flow_driver.h +41 -0
index a129a4605d..8dc803023c 100644
@@ -121,6 +121,17 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_create() */
+	struct rte_flow_action_list_handle *(*action_list_handle_create)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action actions[],
+		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_destroy() */
+	int (*action_list_handle_destroy)
+		(struct rte_eth_dev *dev,
+		 struct rte_flow_action_list_handle *handle,
+		 struct rte_flow_error *error);
 	/** See rte_flow_tunnel_decap_set() */
 	int (*tunnel_decap_set)
 		(struct rte_eth_dev *dev,
@@ -302,6 +313,36 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_create() */
+	struct rte_flow_action_list_handle *
+	(*async_action_list_handle_create)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action *actions,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_destroy() */
+	int (*async_action_list_handle_destroy)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *action_handle,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_query_update() */
+	int (*action_list_handle_query_update)
+		(uint16_t port_id,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_query_update() */
+	int (*async_action_list_handle_query_update)
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 void *user_data, struct rte_flow_error *error);
+
 };
 
 /**
Signature · 1 line
2.34.1
#3 lore raw

Hello Ivan,

Quoted 2 lines

Overall, the idea of action list indirection sounds good. But why deprecate the existing indirect action API?

Deprecation is not necessary.
If the decision is to keep existing indirect action API, it must be updated to differentiate between action mutable and flow mutable update parameters.

Quoted 6 lines

Are there any strong reasons for that? This action should probably stay. Well, at least, I wouldn't expect this patch to immediately introduce some transition period. Let's cross that bridge when we get there. What do you think?

Quoted 7 lines

Also, what are the target applications/projects to benefit from the new indirect action list API? Could you please provide some examples. Or, alternatively, you could shed light on which "shapes" of flow rules would
be the primary users of the action.

We have 2 usages for the new indirect list API
1. Create single HW action from input list of RTE actions.
For example, MLX5 template API will create single mirror HW action from SAMPLE / JUMP list.
2. METER_MARK init_color and CONNTRACK last_direction parameters are flow mutable, by the actions definitions. However, current indirect action cannot update flow parameters.

Regards,
Gregory

#4 lore raw

RFC PATCH v3 1/1 ethdev: add indirect list flow action

In reply to Gregory Etelson

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), PMD compiles base action
configuration during action template, table template and flow rule phases - depending on PMD action implementation. Otherwise, action is compiled from scratch during flow rule processing.

2 If Htmpl and Ctmpl were masked (Hmask !=0 and Cmask != 0), table
template processing overwrites base action configuration with Ctmpl parameters.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was masked, Hflow can reference a different action of the
same type as Htmpl.

4 If Cflow was specified, it overwrites action configuration.

---
v3: do not deprecate indirect flow action.

---
 lib/ethdev/rte_flow.h        | 266 +++++++++++++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h |  41 ++++++
 2 files changed, 307 insertions(+)
lib/ethdev/rte_flow.h +266 -0
index 713ba8b65c..ac1f51e564 100644
@@ -2912,6 +2912,13 @@ enum rte_flow_action_type {
 	 * applied to the given ethdev Rx queue.
 	 */
 	RTE_FLOW_ACTION_TYPE_SKIP_CMAN,
+
+	/**
+	 * Action handle to reference flow actions list.
+	 *
+	 * @see struct rte_flow_action_indirect_list
+	 */
+	RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
 };
 
 /**
@@ -6118,6 +6125,265 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,
 					  void *user_data,
 					  struct rte_flow_error *error);
 
+struct rte_flow_action_list_handle;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Configure INDIRECT_LIST flow action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ */
+struct rte_flow_action_indirect_list {
+	struct rte_flow_action_list_handle; /**< Indirect action list handle */
+	/**
+	 * Flow mutable configuration array.
+	 * NULL if the handle has no flow mutable configuration update.
+	 * Otherwise, if the handle was created with list A1 / A2 .. An / END
+	 * size of conf is n.
+	 * conf[i] points to flow mutable update of Ai in the handle
+	 * actions list or NULL if Ai has no update.
+	 */
+	const void **conf;
+};
+
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create an indirect flow action object from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action lists.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+				   const
+				   struct rte_flow_indir_action_conf *conf,
+				   const struct rte_flow_action *actions,
+				   struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Async function call to create an indirect flow action object
+ * from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to update the rule.
+ * @param[in] attr
+ *   Indirect action update operation attributes.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action list.
+ * @param[in] user_data
+ *   The user data that will be returned on async completion event.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,
+					 const struct rte_flow_op_attr *attr,
+					 const struct
+					 rte_flow_indir_action_conf *conf,
+					 const struct rte_flow_action *actions,
+					 void *user_data,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy indirect actions list by handle.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] handle
+ *   Handle for the indirect actions list to be destroyed.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.
+ *   - (-EBUSY) if actions list pointed by *action* handle still used
+ *   rte_errno is also set.
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+				    struct rte_flow_action_list_handle *handle,
+				    struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action list destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ *   Port identifier of Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to destroy the rule.
+ * @param[in] op_attr
+ *   Indirect action destruction operation attributes.
+ * @param[in] handle
+ *   Handle for the indirect action object to be destroyed.
+ * @param[in] user_data
+ *   The user data that will be returned on the completion events.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_destroy
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *handle,
+		 void *user_data, struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query and/or update indirect flow actions list.
+ * If both query and update not NULL, the function atomically
+ * queries and updates indirect action. Query and update are carried in order
+ * specified in the mode parameter.
+ * If ether query or update is NULL, the function executes
+ * complementing operation.
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL pointer to storage for the associated query data type.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *query* and *update* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_query_update(uint16_t port_id,
+					 const struct
+					 rte_flow_action_list_handle *handle,
+					 const void **update, void **query,
+					 enum rte_flow_query_update_mode mode,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue async indirect flow actions list query and/or update
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param queue_id
+ *   Flow queue which is used to update the rule.
+ * @param attr
+ *   Indirect action update operation attributes.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL, pointer to storage for the associated query data type.
+ *   Query result returned on async completion event.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param user_data
+ *   The user data that will be returned on async completion event.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *update* and *query* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_query_update(uint16_t port_id, uint32_t queue_id,
+					  const struct rte_flow_op_attr *attr,
+					  const struct
+					  rte_flow_action_list_handle *handle,
+					  const void *update, void *query,
+					  enum rte_flow_query_update_mode mode,
+					  void *user_data,
+					  struct rte_flow_error *error);
+
+
 #ifdef __cplusplus
 }
 #endif
lib/ethdev/rte_flow_driver.h +41 -0

53 lines not on this page · raw message

Signature · 1 line
2.34.1
#5 lore raw

Hi Gregory

First I'm assuming this is just RFC, since there is no code implementation.

Quoted 74 lines

-----Original Message-----
From: Gregory Etelson <[email protected]>
Sent: Sunday, May 7, 2023 12:51 PM

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

Template API:

Action template format:

Quoted 9 lines

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), PMD compiles base action
configuration during action template, table template and flow rule phases - depending on PMD action implementation. Otherwise, action is compiled from scratch during flow rule processing.

Why not just say if Hmask != NULL this action is fixed for this template, else action will be set per each flow?

Also since this is a list of action it is possible that one action will have null while other will have a fixed value.
This means that the Ctmpl should also be checked per each entery:
Conf[0] != null, conf[1] != null.
This will also mean that if application wants to use fixed confs he also must supply a valid example action_list, (can be different action_list object per flow but must be composed of the same actions.)

Quoted 4 lines

2 If Htmpl and Ctmpl were masked (Hmask !=0 and Cmask != 0), table
template processing overwrites base action configuration with Ctmpl parameters.

What do you mean based action?
If the Htmpl and Cmask is non zero it means that the configuration and action are based on the one set in the template create and not per flow.

Quoted 43 lines

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was masked, Hflow can reference a different action of the
same type as Htmpl.

4 If Cflow was specified, it overwrites action configuration.

---
v3: do not deprecate indirect flow action.

---
 lib/ethdev/rte_flow.h        | 266 +++++++++++++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h |  41 ++++++
 2 files changed, 307 insertions(+)
lib/ethdev/rte_flow.h +7 -0
index 713ba8b65c..ac1f51e564 100644
@@ -2912,6 +2912,13 @@ enum rte_flow_action_type {
 	 * applied to the given ethdev Rx queue.
 	 */
 	RTE_FLOW_ACTION_TYPE_SKIP_CMAN,
+
+	/**
+	 * Action handle to reference flow actions list.
+	 *
+	 * @see struct rte_flow_action_indirect_list
+	 */
+	RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
 };
 
 /**
@@ -6118,6 +6125,265 @@

rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,

lib/ethdev/rte_flow.h +2 -0
 					  void *user_data,
 					  struct rte_flow_error *error);
 
+struct rte_flow_action_list_handle;
+

lib/ethdev/rte_flow.h rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id, · line 6139

Quoted 10 lines
lib/ethdev/rte_flow.h +10 -0
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Configure INDIRECT_LIST flow action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ */
+struct rte_flow_action_indirect_list {
+	struct rte_flow_action_list_handle; /**< Indirect action list handle */

Since the comments above the member the comment should start with /** only

Quoted 29 lines
lib/ethdev/rte_flow.h +29 -0
+	/**
+	 * Flow mutable configuration array.
+	 * NULL if the handle has no flow mutable configuration update.
+	 * Otherwise, if the handle was created with list A1 / A2 .. An / END
+	 * size of conf is n.
+	 * conf[i] points to flow mutable update of Ai in the handle
+	 * actions list or NULL if Ai has no update.
+	 */
+	const void **conf;
+};
+
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create an indirect flow action object from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action lists.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this

lib/ethdev/rte_flow.h rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id, · line 6178

Quoted 10 lines
lib/ethdev/rte_flow.h +10 -0
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*

How can you get this error?

Quoted 33 lines

+ */

lib/ethdev/rte_flow.h +32 -0
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+				   const
+				   struct rte_flow_indir_action_conf *conf,
+				   const struct rte_flow_action *actions,
+				   struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Async function call to create an indirect flow action object
+ * from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to update the rule.
+ * @param[in] attr
+ *   Indirect action update operation attributes.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action list.
+ * @param[in] user_data
+ *   The user data that will be returned on async completion event.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this

lib/ethdev/rte_flow.h rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id, · line 6221

Quoted 10 lines
lib/ethdev/rte_flow.h +10 -0
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*

Same as above question

Quoted 24 lines

+ */

lib/ethdev/rte_flow.h +3 -0
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t

queue_id,

lib/ethdev/rte_flow.h +4 -0
+					 const struct rte_flow_op_attr *attr,
+					 const struct
+					 rte_flow_indir_action_conf *conf,
+					 const struct rte_flow_action

*actions,

lib/ethdev/rte_flow.h +14 -0
+					 void *user_data,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy indirect actions list by handle.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] handle
+ *   Handle for the indirect actions list to be destroyed.
+ * @param[out] error

lib/ethdev/rte_flow.h rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id, · line 6253

Quoted 10 lines
lib/ethdev/rte_flow.h +10 -0
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.
+ *   - (-EBUSY) if actions list pointed by *action* handle still used
+ *   rte_errno is also set.

Why not keep the same return description as above?

Quoted 22 lines

+ */

lib/ethdev/rte_flow.h +4 -0
+__rte_experimental
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+				    struct rte_flow_action_list_handle

*handle,

lib/ethdev/rte_flow.h +16 -0
+				    struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action list destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ *   Port identifier of Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to destroy the rule.
+ * @param[in] op_attr
+ *   Indirect action destruction operation attributes.

lib/ethdev/rte_flow.h rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id, · line 6284

Quoted 10 lines
lib/ethdev/rte_flow.h +10 -0
+ * @param[in] handle
+ *   Handle for the indirect action object to be destroyed.
+ * @param[in] user_data
+ *   The user data that will be returned on the completion events.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.

Same errors as above?

Quoted 26 lines

+ */

lib/ethdev/rte_flow.h +15 -0
+__rte_experimental
+int
+rte_flow_async_action_list_handle_destroy
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *handle,
+		 void *user_data, struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query and/or update indirect flow actions list.
+ * If both query and update not NULL, the function atomically
+ * queries and updates indirect action. Query and update are carried in

order
+ * specified in the mode parameter.
+ * If ether query or update is NULL, the function executes
+ * complementing operation.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param handle
+ * Handle for the indirect actions list object to be updated.
+ * @param update

Quoted 3 lines
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list

It should be clear that the update/query is in the order the action was created and if the action i doesn't have configuration it should be s set to NULL. And goes without saying that the list size must be equal to the number of actions, that this list is build from.

Quoted 141 lines

+ * @param query
+ * If not NULL pointer to storage for the associated query data type.
+ * @see struct rte_flow_action_indirect_list
+ * @param mode
+ * Operational mode.
+ * @param error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ * both *query* and *update* are NULL.
+ */

lib/ethdev/rte_flow.h +7 -0
+__rte_experimental
+int
+rte_flow_action_list_handle_query_update(uint16_t port_id,
+					 const struct
+					 rte_flow_action_list_handle *handle,
+					 const void **update, void **query,
+					 enum rte_flow_query_update_mode

mode,

lib/ethdev/rte_flow.h +42 -0
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue async indirect flow actions list query and/or update
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param queue_id
+ *   Flow queue which is used to update the rule.
+ * @param attr
+ *   Indirect action update operation attributes.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL, pointer to storage for the associated query data type.
+ *   Query result returned on async completion event.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param user_data
+ *   The user data that will be returned on async completion event.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *update* and *query* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_query_update(uint16_t port_id,

uint32_t queue_id,

lib/ethdev/rte_flow.h +3 -0
+					  const struct rte_flow_op_attr *attr,
+					  const struct
+					  rte_flow_action_list_handle

*handle,

lib/ethdev/rte_flow.h +2 -0
+					  const void *update, void *query,
+					  enum

rte_flow_query_update_mode mode,

lib/ethdev/rte_flow.h +4 -0
+					  void *user_data,
+					  struct rte_flow_error *error);
+
+
 #ifdef __cplusplus
 }
 #endif
lib/ethdev/rte_flow_driver.h +41 -1
index a129a4605d..8dc803023c 100644
@@ -121,6 +121,17 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_create() */
+	struct rte_flow_action_list_handle *(*action_list_handle_create)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action actions[],
+		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_destroy() */
+	int (*action_list_handle_destroy)
+		(struct rte_eth_dev *dev,
+		 struct rte_flow_action_list_handle *handle,
+		 struct rte_flow_error *error);
 	/** See rte_flow_tunnel_decap_set() */
 	int (*tunnel_decap_set)
 		(struct rte_eth_dev *dev,
@@ -302,6 +313,36 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_create() */
+	struct rte_flow_action_list_handle *
+	(*async_action_list_handle_create)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action *actions,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_destroy() */
+	int (*async_action_list_handle_destroy)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *action_handle,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_query_update() */
+	int (*action_list_handle_query_update)
+		(uint16_t port_id,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_query_update() */
+	int (*async_action_list_handle_query_update)
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 void *user_data, struct rte_flow_error *error);
+
 };
 
 /**
--
Quoted 1 line

2.34.1

Best,
Ori

#6 lore raw

Hello Ori,

Quoted 2 lines

First I'm assuming this is just RFC, since there is no code implementation.

I'll add code implementation in v4.

Quoted 86 lines
Quoted 74 lines

-----Original Message-----
From: Gregory Etelson <[email protected]>
Sent: Sunday, May 7, 2023 12:51 PM

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

Template API:

Action template format:

Quoted 9 lines

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), PMD compiles base action
configuration during action template, table template and flow rule phases - depending on PMD action implementation. Otherwise, action is compiled from scratch during flow rule processing.

Why not just say if Hmask != NULL this action is fixed for this template, else action will be set per each flow?

Quoted 8 lines

Also since this is a list of action it is possible that one action will have null while other will have a fixed value.
This means that the Ctmpl should also be checked per each entery:
Conf[0] != null, conf[1] != null.
This will also mean that if application wants to use fixed confs he also must supply a valid example action_list, (can be different action_list object per flow but must be composed of the same actions.)

Will update indirect_list action template description in v4

Quoted 49 lines
Quoted 4 lines

2 If Htmpl and Ctmpl were masked (Hmask !=0 and Cmask != 0), table
template processing overwrites base action configuration with Ctmpl parameters.

What do you mean based action?
If the Htmpl and Cmask is non zero it means that the configuration and action are based on the one set in the template create and not per flow.

Quoted 41 lines

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was masked, Hflow can reference a different action of the
same type as Htmpl.

4 If Cflow was specified, it overwrites action configuration.

---
v3: do not deprecate indirect flow action.

---
 lib/ethdev/rte_flow.h        | 266 +++++++++++++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h |  41 ++++++
 2 files changed, 307 insertions(+)
lib/ethdev/rte_flow.h +7 -0
index 713ba8b65c..ac1f51e564 100644
@@ -2912,6 +2912,13 @@ enum rte_flow_action_type {
 	 * applied to the given ethdev Rx queue.
 	 */
 	RTE_FLOW_ACTION_TYPE_SKIP_CMAN,
+
+	/**
+	 * Action handle to reference flow actions list.
+	 *
+	 * @see struct rte_flow_action_indirect_list
+	 */
+	RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
 };
 
 /**
@@ -6118,6 +6125,265 @@

rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,

lib/ethdev/rte_flow.h +0 -0
 					  void *user_data,
 					  struct rte_flow_error *error);
Quoted 14 lines

lib/ethdev/rte_flow.h rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id, · line 6139

Quoted 12 lines
lib/ethdev/rte_flow.h +12 -0
+struct rte_flow_action_list_handle;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Configure INDIRECT_LIST flow action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ */
+struct rte_flow_action_indirect_list {
+	struct rte_flow_action_list_handle; /**< Indirect action list handle */

Since the comments above the member the comment should start with /** only

Will update the comment in v4.

Quoted 32 lines
Quoted 32 lines
lib/ethdev/rte_flow.h +32 -0
+	/**
+	 * Flow mutable configuration array.
+	 * NULL if the handle has no flow mutable configuration update.
+	 * Otherwise, if the handle was created with list A1 / A2 .. An / END
+	 * size of conf is n.
+	 * conf[i] points to flow mutable update of Ai in the handle
+	 * actions list or NULL if Ai has no update.
+	 */
+	const void **conf;
+};
+
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create an indirect flow action object from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action lists.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
Quoted 9 lines
Quoted 7 lines
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*

How can you get this error?

Will remove E2BIG in v4.

Quoted 36 lines
Quoted 36 lines

+ */

lib/ethdev/rte_flow.h +35 -0
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+				   const
+				   struct rte_flow_indir_action_conf *conf,
+				   const struct rte_flow_action *actions,
+				   struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Async function call to create an indirect flow action object
+ * from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to update the rule.
+ * @param[in] attr
+ *   Indirect action update operation attributes.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action list.
+ * @param[in] user_data
+ *   The user data that will be returned on async completion event.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
Quoted 9 lines
Quoted 7 lines
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*

Same as above question

Will remove E2BIG in v4.

Quoted 27 lines
Quoted 27 lines

+ */

lib/ethdev/rte_flow.h +3 -0
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t

queue_id,

lib/ethdev/rte_flow.h +4 -0
+					 const struct rte_flow_op_attr *attr,
+					 const struct
+					 rte_flow_indir_action_conf *conf,
+					 const struct rte_flow_action

*actions,

lib/ethdev/rte_flow.h +17 -0
+					 void *user_data,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy indirect actions list by handle.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] handle
+ *   Handle for the indirect actions list to be destroyed.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
Quoted 9 lines
Quoted 7 lines
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.
+ *   - (-EBUSY) if actions list pointed by *action* handle still used
+ *   rte_errno is also set.

Why not keep the same return description as above?

Will update the format in v4.

Quoted 25 lines
Quoted 25 lines

+ */

lib/ethdev/rte_flow.h +4 -0
+__rte_experimental
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+				    struct rte_flow_action_list_handle

*handle,

lib/ethdev/rte_flow.h +19 -0
+				    struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action list destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ *   Port identifier of Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to destroy the rule.
+ * @param[in] op_attr
+ *   Indirect action destruction operation attributes.
+ * @param[in] handle
+ *   Handle for the indirect action object to be destroyed.
+ * @param[in] user_data
Quoted 9 lines
Quoted 7 lines

+ * The user data that will be returned on the completion events.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.

Same errors as above?

Will update the format in v4.

Quoted 25 lines
Quoted 25 lines

+ */

lib/ethdev/rte_flow.h +15 -0
+__rte_experimental
+int
+rte_flow_async_action_list_handle_destroy
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *handle,
+		 void *user_data, struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query and/or update indirect flow actions list.
+ * If both query and update not NULL, the function atomically
+ * queries and updates indirect action. Query and update are carried in

order
+ * specified in the mode parameter.
+ * If ether query or update is NULL, the function executes
+ * complementing operation.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param handle
+ * Handle for the indirect actions list object to be updated.

Quoted 9 lines
Quoted 4 lines

+ * @param update

+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list

It should be clear that the update/query is in the order the action was created and if the action i doesn't have configuration it should be s set to NULL. And goes without saying that the list size must be equal to the number of actions, that this list is build from.

Will update in v4.

Quoted 145 lines
Quoted 141 lines

+ * @param query
+ * If not NULL pointer to storage for the associated query data type.
+ * @see struct rte_flow_action_indirect_list
+ * @param mode
+ * Operational mode.
+ * @param error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ * both *query* and *update* are NULL.
+ */

lib/ethdev/rte_flow.h +7 -0
+__rte_experimental
+int
+rte_flow_action_list_handle_query_update(uint16_t port_id,
+					 const struct
+					 rte_flow_action_list_handle *handle,
+					 const void **update, void **query,
+					 enum rte_flow_query_update_mode

mode,

lib/ethdev/rte_flow.h +42 -0
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue async indirect flow actions list query and/or update
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param queue_id
+ *   Flow queue which is used to update the rule.
+ * @param attr
+ *   Indirect action update operation attributes.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL, pointer to storage for the associated query data type.
+ *   Query result returned on async completion event.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param user_data
+ *   The user data that will be returned on async completion event.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *update* and *query* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_query_update(uint16_t port_id,

uint32_t queue_id,

lib/ethdev/rte_flow.h +3 -0
+					  const struct rte_flow_op_attr *attr,
+					  const struct
+					  rte_flow_action_list_handle

*handle,

lib/ethdev/rte_flow.h +2 -0
+					  const void *update, void *query,
+					  enum

rte_flow_query_update_mode mode,

lib/ethdev/rte_flow.h +4 -0
+					  void *user_data,
+					  struct rte_flow_error *error);
+
+
 #ifdef __cplusplus
 }
 #endif
lib/ethdev/rte_flow_driver.h +41 -1
index a129a4605d..8dc803023c 100644
@@ -121,6 +121,17 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_create() */
+	struct rte_flow_action_list_handle *(*action_list_handle_create)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action actions[],
+		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_destroy() */
+	int (*action_list_handle_destroy)
+		(struct rte_eth_dev *dev,
+		 struct rte_flow_action_list_handle *handle,
+		 struct rte_flow_error *error);
 	/** See rte_flow_tunnel_decap_set() */
 	int (*tunnel_decap_set)
 		(struct rte_eth_dev *dev,
@@ -302,6 +313,36 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_create() */
+	struct rte_flow_action_list_handle *
+	(*async_action_list_handle_create)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action *actions,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_destroy() */
+	int (*async_action_list_handle_destroy)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *action_handle,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_query_update() */
+	int (*action_list_handle_query_update)
+		(uint16_t port_id,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_query_update() */
+	int (*async_action_list_handle_query_update)
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 void *user_data, struct rte_flow_error *error);
+
 };
 
 /**
--
Quoted 1 line

2.34.1

Best,
Ori

#7 lore raw

PATCH v4 1/1 ethdev: add indirect list flow action

In reply to Gregory Etelson

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

If indirect list handle was created from a list of actions A1 / A2 ... An / END
indirect list flow action can update Ai flow mutable context in the action configuration parameter.
Indirect list action configuration is and array [C1, C2, .., Cn] where Ci corresponds to Ai in the action handle source. Ci configuration element points Ai flow mutable update, or it's NULL if Ai has no flow mutable update.
Indirect list action configuration can be NULL if the action has no flow mutable updates.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), it will be fixed in that template.
Otherwise, indirect action value is set in a flow rule.

2 If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),
Htmpl's Ai action flow mutable context fill be updated to Ctmpl[i] values and will be fixed in that template.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was not masked in actions template, Hflow references an
action of the same type as Htmpl.

4 Cflow[i] updates handle's Ai flow mutable configuration if
the Ci was not masked in action template.

---
 app/test-pmd/cmdline_flow.c            | 207 ++++++++++++++++++-
 app/test-pmd/config.c                  | 163 +++++++++++----
 app/test-pmd/testpmd.h                 |   9 +-
 doc/guides/nics/features/default.ini   |   1 +
 doc/guides/prog_guide/rte_flow.rst     | 119 +++++++++++
 doc/guides/rel_notes/release_23_07.rst |   2 +
 lib/ethdev/ethdev_trace.h              |  88 ++++++++
 lib/ethdev/ethdev_trace_points.c       |  18 ++
 lib/ethdev/rte_flow.c                  | 171 ++++++++++++++++
 lib/ethdev/rte_flow.h                  | 269 +++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h           |  41 ++++
 lib/ethdev/version.map                 |   8 +
 12 files changed, 1054 insertions(+), 42 deletions(-)
app/test-pmd/cmdline_flow.c +206 -1
index 58939ec321..4663b6217f 100644
@@ -145,6 +145,7 @@ enum index {
 
 	/* Queue indirect action arguments */
 	QUEUE_INDIRECT_ACTION_CREATE,
+	QUEUE_INDIRECT_ACTION_LIST_CREATE,
 	QUEUE_INDIRECT_ACTION_UPDATE,
 	QUEUE_INDIRECT_ACTION_DESTROY,
 	QUEUE_INDIRECT_ACTION_QUERY,
@@ -157,6 +158,7 @@ enum index {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 
 	/* Queue indirect action update arguments */
 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
@@ -242,6 +244,8 @@ enum index {
 
 	/* Indirect action arguments */
 	INDIRECT_ACTION_CREATE,
+	INDIRECT_ACTION_LIST_CREATE,
+	INDIRECT_ACTION_FLOW_CONF_CREATE,
 	INDIRECT_ACTION_UPDATE,
 	INDIRECT_ACTION_DESTROY,
 	INDIRECT_ACTION_QUERY,
@@ -253,6 +257,8 @@ enum index {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
+	INDIRECT_ACTION_FLOW_CONF,
 
 	/* Indirect action destroy arguments */
 	INDIRECT_ACTION_DESTROY_ID,
@@ -626,6 +632,11 @@ enum index {
 	ACTION_SAMPLE_INDEX,
 	ACTION_SAMPLE_INDEX_VALUE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
+	ACTION_INDIRECT_LIST_HANDLE,
+	ACTION_INDIRECT_LIST_CONF,
+	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
+	INDIRECT_LIST_ACTION_ID2PTR_CONF,
 	ACTION_SHARED_INDIRECT,
 	INDIRECT_ACTION_PORT,
 	INDIRECT_ACTION_ID2PTR,
@@ -1266,6 +1277,7 @@ static const enum index next_qia_create_attr[] = {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 	ZERO,
 };
 
@@ -1294,6 +1306,8 @@ static const enum index next_ia_create_attr[] = {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
+	INDIRECT_ACTION_FLOW_CONF,
 	ZERO,
 };
 
@@ -1303,6 +1317,13 @@ static const enum index next_ia[] = {
 	ZERO
 };
 
+static const enum index next_ial[] = {
+	ACTION_INDIRECT_LIST_HANDLE,
+	ACTION_INDIRECT_LIST_CONF,
+	ACTION_NEXT,
+	ZERO
+};
+
 static const enum index next_qia_qu_attr[] = {
 	QUEUE_INDIRECT_ACTION_QU_MODE,
 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
@@ -2013,6 +2034,7 @@ static const enum index next_action[] = {
 	ACTION_AGE_UPDATE,
 	ACTION_SAMPLE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
 	ACTION_SHARED_INDIRECT,
 	ACTION_MODIFY_FIELD,
 	ACTION_CONNTRACK,
@@ -2289,6 +2311,7 @@ static const enum index next_action_sample[] = {
 	ACTION_RAW_ENCAP,
 	ACTION_VXLAN_ENCAP,
 	ACTION_NVGRE_ENCAP,
+	ACTION_REPRESENTED_PORT,
 	ACTION_NEXT,
 	ZERO,
 };
@@ -2539,6 +2562,10 @@ static int parse_ia_destroy(struct context *ctx, const struct token *token,
 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
 			   const char *str, unsigned int len, void *buf,
 			   unsigned int size);
+
+static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
+			       const char *str, unsigned int len, void *buf,
+			       unsigned int size);
 static int parse_ia_port(struct context *ctx, const struct token *token,
 			 const char *str, unsigned int len, void *buf,
 			 unsigned int size);
@@ -2627,6 +2654,16 @@ static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
 
+struct indlst_conf {
+	uint32_t id;
+	uint32_t conf_num;
+	struct rte_flow_action *actions;
+	const void **conf;
+	SLIST_ENTRY(indlst_conf) next;
+};
+
+static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
+
 /** Token definitions. */
 static const struct token token_list[] = {
 	/* Special tokens. */
@@ -3426,6 +3463,12 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[QUEUE_INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_qia,
+	},
 	/* Top-level command. */
 	[PUSH] = {
 		.name = "push",
@@ -6775,6 +6818,37 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
 		.call = parse_vc,
 	},
+	[ACTION_INDIRECT_LIST] = {
+		.name = "indirect_list",
+		.help = "apply indirect list action by id",
+		.priv = PRIV_ACTION(INDIRECT_LIST,
+				    sizeof(struct
+				           rte_flow_action_indirect_list)),
+		.next = NEXT(next_ial),
+		.call = parse_vc,
+	},
+	[ACTION_INDIRECT_LIST_HANDLE] = {
+		.name = "handle",
+		.help = "indirect list handle",
+		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
+	},
+	[ACTION_INDIRECT_LIST_CONF] = {
+		.name = "conf",
+		.help = "indirect list configuration",
+		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
+	},
+	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
+		.type = "UNSIGNED",
+		.help = "unsigned integer value",
+		.call = parse_indlst_id2ptr,
+	},
+	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
+		.type = "UNSIGNED",
+		.help = "unsigned integer value",
+		.call = parse_indlst_id2ptr,
+	},
 	[ACTION_SHARED_INDIRECT] = {
 		.name = "shared_indirect",
 		.help = "apply indirect action by id and port",
@@ -6823,6 +6897,18 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_ia,
+	},
+	[INDIRECT_ACTION_FLOW_CONF] = {
+		.name = "flow_conf",
+		.help = "specify actions configuration for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_ia,
+	},
 	[ACTION_POL_G] = {
 		.name = "g_actions",
 		.help = "submit a list of associated actions for green",
@@ -7181,6 +7267,12 @@ parse_ia(struct context *ctx, const struct token *token,
 		return len;
 	case INDIRECT_ACTION_QU_MODE:
 		return len;
+	case INDIRECT_ACTION_LIST:
+		out->command = INDIRECT_ACTION_LIST_CREATE;
+		return len;
+        case INDIRECT_ACTION_FLOW_CONF:
+		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7278,6 +7370,9 @@ parse_qia(struct context *ctx, const struct token *token,
 		return len;
 	case QUEUE_INDIRECT_ACTION_QU_MODE:
 		return len;
+	case QUEUE_INDIRECT_ACTION_LIST:
+		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7454,10 +7549,12 @@ parse_vc(struct context *ctx, const struct token *token,
 			return -1;
 		break;
 	case ACTIONS:
-		out->args.vc.actions =
+		out->args.vc.actions = out->args.vc.pattern ?
 			(void *)RTE_ALIGN_CEIL((uintptr_t)
 					       (out->args.vc.pattern +
 						out->args.vc.pattern_n),
+					       sizeof(double)) :
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
 					       sizeof(double));
 		ctx->object = out->args.vc.actions;
 		ctx->objmask = NULL;
@@ -10412,6 +10509,49 @@ parse_ia_id2ptr(struct context *ctx, const struct token *token,
 	return ret;
 }
 
+static int
+parse_indlst_id2ptr(struct context *ctx, const struct token *token,
+		    const char *str, unsigned int len,
+		    void __rte_unused *buf, unsigned int __rte_unused size)
+{
+	struct rte_flow_action *action = ctx->object;
+	struct rte_flow_action_indirect_list *action_conf;
+	const struct indlst_conf *indlst_conf;
+	uint32_t id;
+	int ret;
+
+	if (!action)
+		return -1;
+	ctx->objdata = 0;
+	ctx->object = &id;
+	ctx->objmask = NULL;
+	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
+	if (ret != (int)len)
+		return ret;
+	ctx->object = action;
+	action_conf = (void *)(uintptr_t)action->conf;
+	action_conf->conf = NULL;
+	switch (ctx->curr) {
+	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
+        action_conf->handle = (typeof(action_conf->handle))
+				port_action_handle_get_by_id(ctx->port, id);
+		if (!action_conf->handle) {
+			printf("no indirect list handle for id %u\n", id);
+			return -1;
+		}
+		break;
+	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
+		indlst_conf = indirect_action_list_conf_get(id);
+		if (!indlst_conf)
+			return -1;
+		action_conf->conf = (const void **)indlst_conf->conf;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
 static int
 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
 		const char *str, unsigned int len,
@@ -11453,6 +11593,64 @@ cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
 	*hdr = &cmd_flow_token_hdr;
 }
 
+static SLIST_HEAD(, indlst_conf) indlst_conf_head =
+	SLIST_HEAD_INITIALIZER();
+
+static void
+indirect_action_flow_conf_create(const struct buffer *in)
+{
+	int len, ret;
+	uint32_t i;
+	struct indlst_conf *indlst_conf = NULL;
+	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
+	struct rte_flow_action *src = in->args.vc.actions;
+
+	if (!in->args.vc.actions_n)
+		goto end;
+	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
+	if (len <= 0)
+		goto end;
+	len = RTE_ALIGN(len, 16);
+
+	indlst_conf = calloc(1, base + len +
+			     in->args.vc.actions_n * sizeof(uintptr_t));
+	if (!indlst_conf)
+		goto end;
+	indlst_conf->id = in->args.vc.attr.group;
+	indlst_conf->conf_num = in->args.vc.actions_n - 1;
+	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
+	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
+			    len, src, NULL);
+	if (ret <= 0) {
+		free(indlst_conf);
+		indlst_conf = NULL;
+		goto end;
+	}
+	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
+	for (i = 0; i < indlst_conf->conf_num; i++)
+		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
+	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
+end:
+	if (indlst_conf)
+        printf("created indirect action list configuration %u\n",
+               in->args.vc.attr.group);
+	else
+        printf("cannot create indirect action list configuration %u\n",
+               in->args.vc.attr.group);
+}
+
+static const struct indlst_conf *
+indirect_action_list_conf_get(uint32_t conf_id)
+{
+	const struct indlst_conf *conf;
+
+	SLIST_FOREACH(conf, &indlst_conf_head, next) {
+		if (conf->id == conf_id)
+			return conf;
+	}
+	return NULL;
+}
+
 /** Dispatch parsed buffer to function calls. */
 static void
 cmd_flow_parsed(const struct buffer *in)
@@ -11532,6 +11730,7 @@ cmd_flow_parsed(const struct buffer *in)
 				     in->args.aged.destroy);
 		break;
 	case QUEUE_INDIRECT_ACTION_CREATE:
+	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
 		port_queue_action_handle_create(
 				in->port, in->queue, in->postpone,
 				in->args.vc.attr.group,
@@ -11567,8 +11766,10 @@ cmd_flow_parsed(const struct buffer *in)
 						      in->args.vc.actions);
 		break;
 	case INDIRECT_ACTION_CREATE:
+	case INDIRECT_ACTION_LIST_CREATE:
 		port_action_handle_create(
 				in->port, in->args.vc.attr.group,
+				in->command == INDIRECT_ACTION_LIST_CREATE,
 				&((const struct rte_flow_indir_action_conf) {
 					.ingress = in->args.vc.attr.ingress,
 					.egress = in->args.vc.attr.egress,
@@ -11576,6 +11777,9 @@ cmd_flow_parsed(const struct buffer *in)
 				}),
 				in->args.vc.actions);
 		break;
+	case INDIRECT_ACTION_FLOW_CONF_CREATE:
+		indirect_action_flow_conf_create(in);
+		break;
 	case INDIRECT_ACTION_DESTROY:
 		port_action_handle_destroy(in->port,
 					   in->args.ia_destroy.action_id_n,
@@ -11653,6 +11857,7 @@ cmd_flow_parsed(const struct buffer *in)
 	default:
 		break;
 	}
+	fflush(stdout);
 }
 
 /** Token generator and output processing callback (cmdline API). */
app/test-pmd/config.c +124 -39

229 lines not on this page · raw message

app/test-pmd/testpmd.h +7 -2
index bdfbfd36d3..5c43b4db0b 100644
@@ -228,7 +228,12 @@ struct port_indirect_action {
 	struct port_indirect_action *next; /**< Next flow in list. */
 	uint32_t id; /**< Indirect action ID. */
 	enum rte_flow_action_type type; /**< Action type. */
-	struct rte_flow_action_handle *handle;	/**< Indirect action handle. */
+	union {
+		struct rte_flow_action_handle *handle;
+		/**< Indirect action handle. */
+		struct rte_flow_action_list_handle *list_handle;
+		/**< Indirect action list handle*/
+	};
 	enum age_action_context_type age_type; /**< Age action context type. */
 };
 
@@ -921,7 +926,7 @@ void update_fwd_ports(portid_t new_pid);
 void set_fwd_eth_peer(portid_t port_id, char *peer_addr);
 
 void port_mtu_set(portid_t port_id, uint16_t mtu);
-int port_action_handle_create(portid_t port_id, uint32_t id,
+int port_action_handle_create(portid_t port_id, uint32_t id, bool indirect_list,
 			      const struct rte_flow_indir_action_conf *conf,
 			      const struct rte_flow_action *action);
 int port_action_handle_destroy(portid_t port_id,
doc/guides/nics/features/default.ini +1 -0
index 1a5087abad..10a1c1af77 100644
@@ -158,6 +158,7 @@ drop                 =
 flag                 =
 inc_tcp_ack          =
 inc_tcp_seq          =
+indirect_list        =
 jump                 =
 mac_swap             =
 mark                 =
doc/guides/prog_guide/rte_flow.rst +119 -0

125 lines not on this page · raw message

doc/guides/rel_notes/release_23_07.rst +2 -0
index a9b1293689..d9643a35ef 100644
@@ -55,6 +55,8 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+   * **Added INDIRECT_LIST flow action.**
+
 
 Removed Items
 -------------
lib/ethdev/ethdev_trace.h +88 -0

94 lines not on this page · raw message

lib/ethdev/ethdev_trace_points.c +18 -0
index 61010cae56..5e1462a6fb 100644
@@ -750,3 +750,21 @@ RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_add,
 
 RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_delete,
 	lib.ethdev.tm.wred_profile_delete)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_create,
+			 lib.ethdev.flow.action_list_handle_create)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_destroy,
+			 lib.ethdev.flow.action_list_handle_destroy)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_query_update,
+			 lib.ethdev.flow.action_list_handle_query_update)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_create,
+	lib.ethdev.flow.async_action_list_handle_create)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_destroy,
+	lib.ethdev.flow.async_action_list_handle_destroy)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_query_update,
+			 lib.ethdev.flow.async_action_list_handle_query_update)
lib/ethdev/rte_flow.c +171 -0

180 lines not on this page · raw message

lib/ethdev/rte_flow.h +269 -0

281 lines not on this page · raw message

lib/ethdev/rte_flow_driver.h +41 -0

53 lines not on this page · raw message

lib/ethdev/version.map +8 -0
index 357d1a88c0..02372b3a7e 100644
@@ -299,6 +299,14 @@ EXPERIMENTAL {
 	rte_flow_action_handle_query_update;
 	rte_flow_async_action_handle_query_update;
 	rte_flow_async_create_by_index;
+
+	# added in 23.07
+    rte_flow_action_list_handle_create;
+    rte_flow_action_list_handle_destroy;
+    rte_flow_action_list_handle_query_update;
+    rte_flow_async_action_list_handle_create;
+    rte_flow_async_action_list_handle_destroy;
+    rte_flow_async_action_list_handle_query_update;
 };
 
 INTERNAL {
Signature · 1 line
2.34.1
#8 lore raw

Hi Gregory

Quoted 107 lines

-----Original Message-----
From: Gregory Etelson <[email protected]>
Sent: Friday, May 19, 2023 3:00 PM

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

If indirect list handle was created from a list of actions A1 / A2 ... An / END
indirect list flow action can update Ai flow mutable context in the action configuration parameter.
Indirect list action configuration is and array [C1, C2, .., Cn] where Ci corresponds to Ai in the action handle source. Ci configuration element points Ai flow mutable update, or it's NULL if Ai has no flow mutable update.
Indirect list action configuration can be NULL if the action has no flow mutable updates.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), it will be fixed in that template.
Otherwise, indirect action value is set in a flow rule.

2 If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),
Htmpl's Ai action flow mutable context fill be updated to Ctmpl[i] values and will be fixed in that template.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was not masked in actions template, Hflow references an
action of the same type as Htmpl.

4 Cflow[i] updates handle's Ai flow mutable configuration if
the Ci was not masked in action template.

---

[Snip]

Quoted 206 lines
lib/ethdev/rte_flow.h +7 -0
index 713ba8b65c..b65096b3b7 100644
@@ -2912,6 +2912,13 @@ enum rte_flow_action_type {
 	 * applied to the given ethdev Rx queue.
 	 */
 	RTE_FLOW_ACTION_TYPE_SKIP_CMAN,
+
+	/**
+	 * Action handle to reference flow actions list.
+	 *
+	 * @see struct rte_flow_action_indirect_list
+	 */
+	RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
 };
 
 /**
@@ -6118,6 +6125,268 @@

rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,

lib/ethdev/rte_flow.h +97 -0
 					  void *user_data,
 					  struct rte_flow_error *error);
 
+struct rte_flow_action_list_handle;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Configure INDIRECT_LIST flow action.
+ *
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ */
+struct rte_flow_action_indirect_list {
+	/** Indirect action list handle */
+	struct rte_flow_action_list_handle *handle;
+	/**
+	 * Flow mutable configuration array.
+	 * NULL if the handle has no flow mutable configuration update.
+	 * Otherwise, if the handle was created with list A1 / A2 .. An / END
+	 * size of conf is n.
+	 * conf[i] points to flow mutable update of Ai in the handle
+	 * actions list or NULL if Ai has no update.
+	 */
+	const void **conf;
+};
+
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create an indirect flow action object from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action lists.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+				   const
+				   struct rte_flow_indir_action_conf *conf,
+				   const struct rte_flow_action *actions,
+				   struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Async function call to create an indirect flow action object
+ * from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to update the rule.
+ * @param[in] attr
+ *   Indirect action update operation attributes.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action list.
+ * @param[in] user_data
+ *   The user data that will be returned on async completion event.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t

queue_id,

lib/ethdev/rte_flow.h +4 -0
+					 const struct rte_flow_op_attr *attr,
+					 const struct
+					 rte_flow_indir_action_conf *conf,
+					 const struct rte_flow_action

*actions,

lib/ethdev/rte_flow.h +28 -0
+					 void *user_data,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy indirect actions list by handle.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] handle
+ *   Handle for the indirect actions list to be destroyed.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.
+ *   - (-EBUSY) if actions list pointed by *action* handle still used
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+				    struct rte_flow_action_list_handle

*handle,

lib/ethdev/rte_flow.h +47 -0
+				    struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action list destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ *   Port identifier of Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to destroy the rule.
+ * @param[in] op_attr
+ *   Indirect action destruction operation attributes.
+ * @param[in] handle
+ *   Handle for the indirect action object to be destroyed.
+ * @param[in] user_data
+ *   The user data that will be returned on the completion events.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.
+ *   - (-EBUSY) if actions list pointed by *action* handle still used
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_destroy
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *handle,
+		 void *user_data, struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query and/or update indirect flow actions list.
+ * If both query and update not NULL, the function atomically
+ * queries and updates indirect action. Query and update are carried in

order
+ * specified in the mode parameter.
+ * If ether query or update is NULL, the function executes

Quoted 8 lines

+ * complementing operation.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param handle
+ * Handle for the indirect actions list object to be updated.
+ * @param update
+ * If not NULL, update profile specification used to modify the action

It should be explained that the upate/query points always to array with the size of number of actions, the the query/update query/upate all the actions at the same time

This comment is for all such parameters in async and synced functions.

Quoted 164 lines

+ * pointed by handle.
+ * @see struct rte_flow_action_indirect_list
+ * @param query
+ * If not NULL pointer to storage for the associated query data type.
+ * @see struct rte_flow_action_indirect_list
+ * @param mode
+ * Operational mode.
+ * @param error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * - (0) if success.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ * both *query* and *update* are NULL.
+ */

lib/ethdev/rte_flow.h +5 -0
+__rte_experimental
+int
+rte_flow_action_list_handle_query_update(uint16_t port_id,
+					 const struct
+					 rte_flow_action_list_handle

*handle,

lib/ethdev/rte_flow.h +2 -0
+					 const void **update, void **query,
+					 enum

rte_flow_query_update_mode mode,

lib/ethdev/rte_flow.h +42 -0
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue async indirect flow actions list query and/or update
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param queue_id
+ *   Flow queue which is used to update the rule.
+ * @param attr
+ *   Indirect action update operation attributes.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL, pointer to storage for the associated query data type.
+ *   Query result returned on async completion event.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param user_data
+ *   The user data that will be returned on async completion event.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   - (0) if success.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *update* and *query* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_query_update(uint16_t port_id,

uint32_t queue_id,

lib/ethdev/rte_flow.h +3 -0
+					  const struct rte_flow_op_attr *attr,
+					  const struct
+					  rte_flow_action_list_handle

*handle,

lib/ethdev/rte_flow.h +2 -0
+					  const void **update, void **query,
+					  enum

rte_flow_query_update_mode mode,

lib/ethdev/rte_flow.h +4 -0
+					  void *user_data,
+					  struct rte_flow_error *error);
+
+
 #ifdef __cplusplus
 }
 #endif
lib/ethdev/rte_flow_driver.h +41 -0
index a129a4605d..af63ef9b5c 100644
@@ -121,6 +121,17 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_create() */
+	struct rte_flow_action_list_handle *(*action_list_handle_create)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action actions[],
+		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_destroy() */
+	int (*action_list_handle_destroy)
+		(struct rte_eth_dev *dev,
+		 struct rte_flow_action_list_handle *handle,
+		 struct rte_flow_error *error);
 	/** See rte_flow_tunnel_decap_set() */
 	int (*tunnel_decap_set)
 		(struct rte_eth_dev *dev,
@@ -302,6 +313,36 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_create() */
+	struct rte_flow_action_list_handle *
+	(*async_action_list_handle_create)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action *actions,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_destroy() */
+	int (*async_action_list_handle_destroy)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *action_handle,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_query_update() */
+	int (*action_list_handle_query_update)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_query_update() */
+	int (*async_action_list_handle_query_update)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 void *user_data, struct rte_flow_error *error);
+
 };
 
 /**
lib/ethdev/version.map +8 -1
index 357d1a88c0..02372b3a7e 100644
@@ -299,6 +299,14 @@ EXPERIMENTAL {
 	rte_flow_action_handle_query_update;
 	rte_flow_async_action_handle_query_update;
 	rte_flow_async_create_by_index;
+
+	# added in 23.07
+    rte_flow_action_list_handle_create;
+    rte_flow_action_list_handle_destroy;
+    rte_flow_action_list_handle_query_update;
+    rte_flow_async_action_list_handle_create;
+    rte_flow_async_action_list_handle_destroy;
+    rte_flow_async_action_list_handle_query_update;
 };
 
 INTERNAL {
--

2.34.1

#9 lore raw

Hello Ori,

[snip]

Quoted 19 lines
Quoted 10 lines

+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query and/or update indirect flow actions list.
+ * If both query and update not NULL, the function atomically
+ * queries and updates indirect action. Query and update are carried in order
+ * specified in the mode parameter.
+ * If ether query or update is NULL, the function executes

Quoted 8 lines

+ * complementing operation.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param handle
+ * Handle for the indirect actions list object to be updated.
+ * @param update
+ * If not NULL, update profile specification used to modify the action

Quoted 4 lines

It should be explained that the upate/query points always to array with the size of number of actions, the the query/update query/upate all the actions at the same time

I added update and query parameters description in v5

Quoted 166 lines

This comment is for all such parameters in async and synced functions.

Quoted 164 lines

+ * pointed by handle.
+ * @see struct rte_flow_action_indirect_list
+ * @param query
+ * If not NULL pointer to storage for the associated query data type.
+ * @see struct rte_flow_action_indirect_list
+ * @param mode
+ * Operational mode.
+ * @param error
+ * Perform verbose error reporting if not NULL.
+ * PMDs initialize this structure in case of error only.
+ *
+ * @return
+ * - (0) if success.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ * both *query* and *update* are NULL.
+ */

lib/ethdev/rte_flow.h +5 -0
+__rte_experimental
+int
+rte_flow_action_list_handle_query_update(uint16_t port_id,
+					 const struct
+					 rte_flow_action_list_handle

*handle,

(quoted diff) +2 -0
+					 const void **update, void **query,
+					 enum

rte_flow_query_update_mode mode,

lib/ethdev/rte_flow.h +42 -0
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue async indirect flow actions list query and/or update
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param queue_id
+ *   Flow queue which is used to update the rule.
+ * @param attr
+ *   Indirect action update operation attributes.
+ * @param handle
+ *   Handle for the indirect actions list object to be updated.
+ * @param update
+ *   If not NULL, update profile specification used to modify the action
+ *   pointed by handle.
+ *   @see struct rte_flow_action_indirect_list
+ * @param query
+ *   If not NULL, pointer to storage for the associated query data type.
+ *   Query result returned on async completion event.
+ *   @see struct rte_flow_action_indirect_list
+ * @param mode
+ *   Operational mode.
+ * @param user_data
+ *   The user data that will be returned on async completion event.
+ * @param error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   - (0) if success.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-ENOTSUP) if underlying device does not support this functionality.
+ * - (-EINVAL) if *handle* or *mode* invalid or
+ *             both *update* and *query* are NULL.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_query_update(uint16_t port_id,

uint32_t queue_id,

lib/ethdev/rte_flow.c +3 -0
+					  const struct rte_flow_op_attr *attr,
+					  const struct
+					  rte_flow_action_list_handle

*handle,

(quoted diff) +2 -0
+					  const void **update, void **query,
+					  enum

rte_flow_query_update_mode mode,

lib/ethdev/rte_flow.h +4 -0
+					  void *user_data,
+					  struct rte_flow_error *error);
+
+
 #ifdef __cplusplus
 }
 #endif
lib/ethdev/rte_flow_driver.h +41 -0
index a129a4605d..af63ef9b5c 100644
@@ -121,6 +121,17 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_create() */
+	struct rte_flow_action_list_handle *(*action_list_handle_create)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action actions[],
+		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_destroy() */
+	int (*action_list_handle_destroy)
+		(struct rte_eth_dev *dev,
+		 struct rte_flow_action_list_handle *handle,
+		 struct rte_flow_error *error);
 	/** See rte_flow_tunnel_decap_set() */
 	int (*tunnel_decap_set)
 		(struct rte_eth_dev *dev,
@@ -302,6 +313,36 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_create() */
+	struct rte_flow_action_list_handle *
+	(*async_action_list_handle_create)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action *actions,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_destroy() */
+	int (*async_action_list_handle_destroy)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *action_handle,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_query_update() */
+	int (*action_list_handle_query_update)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_query_update() */
+	int (*async_action_list_handle_query_update)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_action_list_handle *handle,
+		 const void **update, void **query,
+		 enum rte_flow_query_update_mode mode,
+		 void *user_data, struct rte_flow_error *error);
+
 };
 
 /**
lib/ethdev/version.map +8 -1
index 357d1a88c0..02372b3a7e 100644
@@ -299,6 +299,14 @@ EXPERIMENTAL {
 	rte_flow_action_handle_query_update;
 	rte_flow_async_action_handle_query_update;
 	rte_flow_async_create_by_index;
+
+	# added in 23.07
+    rte_flow_action_list_handle_create;
+    rte_flow_action_list_handle_destroy;
+    rte_flow_action_list_handle_query_update;
+    rte_flow_async_action_list_handle_create;
+    rte_flow_async_action_list_handle_destroy;
+    rte_flow_async_action_list_handle_query_update;
 };
 
 INTERNAL {
--

2.34.1

#10 lore raw

PATCH v5 1/2 ethdev: add indirect list flow action

In reply to Gregory Etelson

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

If indirect list handle was created from a list of actions A1 / A2 ... An / END
indirect list flow action can update Ai flow mutable context in the action configuration parameter.
Indirect list action configuration is and array [C1, C2, .., Cn] where Ci corresponds to Ai in the action handle source. Ci configuration element points Ai flow mutable update, or it's NULL if Ai has no flow mutable update.
Indirect list action configuration can be NULL if the action has no flow mutable updates.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), it will be fixed in that template.
Otherwise, indirect action value is set in a flow rule.

2 If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),
Htmpl's Ai action flow mutable context fill be updated to Ctmpl[i] values and will be fixed in that template.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was not masked in actions template, Hflow references an
action of the same type as Htmpl.

4 Cflow[i] updates handle's Ai flow mutable configuration if
the Ci was not masked in action template.

---
 app/test-pmd/cmdline_flow.c            | 207 ++++++++++++++++++-
 app/test-pmd/config.c                  | 163 +++++++++++----
 app/test-pmd/testpmd.h                 |   9 +-
 doc/guides/nics/features/default.ini   |   1 +
 doc/guides/prog_guide/rte_flow.rst     | 119 +++++++++++
 doc/guides/rel_notes/release_23_07.rst |   2 +
 lib/ethdev/ethdev_trace.h              |  88 ++++++++
 lib/ethdev/ethdev_trace_points.c       |  18 ++
 lib/ethdev/rte_flow.c                  | 171 ++++++++++++++++
 lib/ethdev/rte_flow.h                  | 270 +++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h           |  41 ++++
 lib/ethdev/version.map                 |   8 +
 12 files changed, 1055 insertions(+), 42 deletions(-)
app/test-pmd/cmdline_flow.c +206 -1
index 58939ec321..af4c471306 100644
@@ -145,6 +145,7 @@ enum index {
 
 	/* Queue indirect action arguments */
 	QUEUE_INDIRECT_ACTION_CREATE,
+	QUEUE_INDIRECT_ACTION_LIST_CREATE,
 	QUEUE_INDIRECT_ACTION_UPDATE,
 	QUEUE_INDIRECT_ACTION_DESTROY,
 	QUEUE_INDIRECT_ACTION_QUERY,
@@ -157,6 +158,7 @@ enum index {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 
 	/* Queue indirect action update arguments */
 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
@@ -242,6 +244,8 @@ enum index {
 
 	/* Indirect action arguments */
 	INDIRECT_ACTION_CREATE,
+	INDIRECT_ACTION_LIST_CREATE,
+	INDIRECT_ACTION_FLOW_CONF_CREATE,
 	INDIRECT_ACTION_UPDATE,
 	INDIRECT_ACTION_DESTROY,
 	INDIRECT_ACTION_QUERY,
@@ -253,6 +257,8 @@ enum index {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
+	INDIRECT_ACTION_FLOW_CONF,
 
 	/* Indirect action destroy arguments */
 	INDIRECT_ACTION_DESTROY_ID,
@@ -626,6 +632,11 @@ enum index {
 	ACTION_SAMPLE_INDEX,
 	ACTION_SAMPLE_INDEX_VALUE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
+	ACTION_INDIRECT_LIST_HANDLE,
+	ACTION_INDIRECT_LIST_CONF,
+	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
+	INDIRECT_LIST_ACTION_ID2PTR_CONF,
 	ACTION_SHARED_INDIRECT,
 	INDIRECT_ACTION_PORT,
 	INDIRECT_ACTION_ID2PTR,
@@ -1266,6 +1277,7 @@ static const enum index next_qia_create_attr[] = {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 	ZERO,
 };
 
@@ -1294,6 +1306,8 @@ static const enum index next_ia_create_attr[] = {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
+	INDIRECT_ACTION_FLOW_CONF,
 	ZERO,
 };
 
@@ -1303,6 +1317,13 @@ static const enum index next_ia[] = {
 	ZERO
 };
 
+static const enum index next_ial[] = {
+	ACTION_INDIRECT_LIST_HANDLE,
+	ACTION_INDIRECT_LIST_CONF,
+	ACTION_NEXT,
+	ZERO
+};
+
 static const enum index next_qia_qu_attr[] = {
 	QUEUE_INDIRECT_ACTION_QU_MODE,
 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
@@ -2013,6 +2034,7 @@ static const enum index next_action[] = {
 	ACTION_AGE_UPDATE,
 	ACTION_SAMPLE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
 	ACTION_SHARED_INDIRECT,
 	ACTION_MODIFY_FIELD,
 	ACTION_CONNTRACK,
@@ -2289,6 +2311,7 @@ static const enum index next_action_sample[] = {
 	ACTION_RAW_ENCAP,
 	ACTION_VXLAN_ENCAP,
 	ACTION_NVGRE_ENCAP,
+	ACTION_REPRESENTED_PORT,
 	ACTION_NEXT,
 	ZERO,
 };
@@ -2539,6 +2562,10 @@ static int parse_ia_destroy(struct context *ctx, const struct token *token,
 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
 			   const char *str, unsigned int len, void *buf,
 			   unsigned int size);
+
+static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
+			       const char *str, unsigned int len, void *buf,
+			       unsigned int size);
 static int parse_ia_port(struct context *ctx, const struct token *token,
 			 const char *str, unsigned int len, void *buf,
 			 unsigned int size);
@@ -2627,6 +2654,16 @@ static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
 
+struct indlst_conf {
+	uint32_t id;
+	uint32_t conf_num;
+	struct rte_flow_action *actions;
+	const void **conf;
+	SLIST_ENTRY(indlst_conf) next;
+};
+
+static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
+
 /** Token definitions. */
 static const struct token token_list[] = {
 	/* Special tokens. */
@@ -3426,6 +3463,12 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[QUEUE_INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_qia,
+	},
 	/* Top-level command. */
 	[PUSH] = {
 		.name = "push",
@@ -6775,6 +6818,37 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
 		.call = parse_vc,
 	},
+	[ACTION_INDIRECT_LIST] = {
+		.name = "indirect_list",
+		.help = "apply indirect list action by id",
+		.priv = PRIV_ACTION(INDIRECT_LIST,
+				    sizeof(struct
+					   rte_flow_action_indirect_list)),
+		.next = NEXT(next_ial),
+		.call = parse_vc,
+	},
+	[ACTION_INDIRECT_LIST_HANDLE] = {
+		.name = "handle",
+		.help = "indirect list handle",
+		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
+	},
+	[ACTION_INDIRECT_LIST_CONF] = {
+		.name = "conf",
+		.help = "indirect list configuration",
+		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
+	},
+	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
+		.type = "UNSIGNED",
+		.help = "unsigned integer value",
+		.call = parse_indlst_id2ptr,
+	},
+	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
+		.type = "UNSIGNED",
+		.help = "unsigned integer value",
+		.call = parse_indlst_id2ptr,
+	},
 	[ACTION_SHARED_INDIRECT] = {
 		.name = "shared_indirect",
 		.help = "apply indirect action by id and port",
@@ -6823,6 +6897,18 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_ia,
+	},
+	[INDIRECT_ACTION_FLOW_CONF] = {
+		.name = "flow_conf",
+		.help = "specify actions configuration for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_ia,
+	},
 	[ACTION_POL_G] = {
 		.name = "g_actions",
 		.help = "submit a list of associated actions for green",
@@ -7181,6 +7267,12 @@ parse_ia(struct context *ctx, const struct token *token,
 		return len;
 	case INDIRECT_ACTION_QU_MODE:
 		return len;
+	case INDIRECT_ACTION_LIST:
+		out->command = INDIRECT_ACTION_LIST_CREATE;
+		return len;
+	case INDIRECT_ACTION_FLOW_CONF:
+		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7278,6 +7370,9 @@ parse_qia(struct context *ctx, const struct token *token,
 		return len;
 	case QUEUE_INDIRECT_ACTION_QU_MODE:
 		return len;
+	case QUEUE_INDIRECT_ACTION_LIST:
+		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7454,10 +7549,12 @@ parse_vc(struct context *ctx, const struct token *token,
 			return -1;
 		break;
 	case ACTIONS:
-		out->args.vc.actions =
+		out->args.vc.actions = out->args.vc.pattern ?
 			(void *)RTE_ALIGN_CEIL((uintptr_t)
 					       (out->args.vc.pattern +
 						out->args.vc.pattern_n),
+					       sizeof(double)) :
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
 					       sizeof(double));
 		ctx->object = out->args.vc.actions;
 		ctx->objmask = NULL;
@@ -10412,6 +10509,49 @@ parse_ia_id2ptr(struct context *ctx, const struct token *token,
 	return ret;
 }
 
+static int
+parse_indlst_id2ptr(struct context *ctx, const struct token *token,
+		    const char *str, unsigned int len,
+		    void __rte_unused *buf, unsigned int __rte_unused size)
+{
+	struct rte_flow_action *action = ctx->object;
+	struct rte_flow_action_indirect_list *action_conf;
+	const struct indlst_conf *indlst_conf;
+	uint32_t id;
+	int ret;
+
+	if (!action)
+		return -1;
+	ctx->objdata = 0;
+	ctx->object = &id;
+	ctx->objmask = NULL;
+	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
+	if (ret != (int)len)
+		return ret;
+	ctx->object = action;
+	action_conf = (void *)(uintptr_t)action->conf;
+	action_conf->conf = NULL;
+	switch (ctx->curr) {
+	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
+	action_conf->handle = (typeof(action_conf->handle))
+				port_action_handle_get_by_id(ctx->port, id);
+		if (!action_conf->handle) {
+			printf("no indirect list handle for id %u\n", id);
+			return -1;
+		}
+		break;
+	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
+		indlst_conf = indirect_action_list_conf_get(id);
+		if (!indlst_conf)
+			return -1;
+		action_conf->conf = (const void **)indlst_conf->conf;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
 static int
 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
 		const char *str, unsigned int len,
@@ -11453,6 +11593,64 @@ cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
 	*hdr = &cmd_flow_token_hdr;
 }
 
+static SLIST_HEAD(, indlst_conf) indlst_conf_head =
+	SLIST_HEAD_INITIALIZER();
+
+static void
+indirect_action_flow_conf_create(const struct buffer *in)
+{
+	int len, ret;
+	uint32_t i;
+	struct indlst_conf *indlst_conf = NULL;
+	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
+	struct rte_flow_action *src = in->args.vc.actions;
+
+	if (!in->args.vc.actions_n)
+		goto end;
+	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
+	if (len <= 0)
+		goto end;
+	len = RTE_ALIGN(len, 16);
+
+	indlst_conf = calloc(1, base + len +
+			     in->args.vc.actions_n * sizeof(uintptr_t));
+	if (!indlst_conf)
+		goto end;
+	indlst_conf->id = in->args.vc.attr.group;
+	indlst_conf->conf_num = in->args.vc.actions_n - 1;
+	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
+	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
+			    len, src, NULL);
+	if (ret <= 0) {
+		free(indlst_conf);
+		indlst_conf = NULL;
+		goto end;
+	}
+	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
+	for (i = 0; i < indlst_conf->conf_num; i++)
+		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
+	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
+end:
+	if (indlst_conf)
+		printf("created indirect action list configuration %u\n",
+		       in->args.vc.attr.group);
+	else
+		printf("cannot create indirect action list configuration %u\n",
+		       in->args.vc.attr.group);
+}
+
+static const struct indlst_conf *
+indirect_action_list_conf_get(uint32_t conf_id)
+{
+	const struct indlst_conf *conf;
+
+	SLIST_FOREACH(conf, &indlst_conf_head, next) {
+		if (conf->id == conf_id)
+			return conf;
+	}
+	return NULL;
+}
+
 /** Dispatch parsed buffer to function calls. */
 static void
 cmd_flow_parsed(const struct buffer *in)
@@ -11532,6 +11730,7 @@ cmd_flow_parsed(const struct buffer *in)
 				     in->args.aged.destroy);
 		break;
 	case QUEUE_INDIRECT_ACTION_CREATE:
+	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
 		port_queue_action_handle_create(
 				in->port, in->queue, in->postpone,
 				in->args.vc.attr.group,
@@ -11567,8 +11766,10 @@ cmd_flow_parsed(const struct buffer *in)
 						      in->args.vc.actions);
 		break;
 	case INDIRECT_ACTION_CREATE:
+	case INDIRECT_ACTION_LIST_CREATE:
 		port_action_handle_create(
 				in->port, in->args.vc.attr.group,
+				in->command == INDIRECT_ACTION_LIST_CREATE,
 				&((const struct rte_flow_indir_action_conf) {
 					.ingress = in->args.vc.attr.ingress,
 					.egress = in->args.vc.attr.egress,
@@ -11576,6 +11777,9 @@ cmd_flow_parsed(const struct buffer *in)
 				}),
 				in->args.vc.actions);
 		break;
+	case INDIRECT_ACTION_FLOW_CONF_CREATE:
+		indirect_action_flow_conf_create(in);
+		break;
 	case INDIRECT_ACTION_DESTROY:
 		port_action_handle_destroy(in->port,
 					   in->args.ia_destroy.action_id_n,
@@ -11653,6 +11857,7 @@ cmd_flow_parsed(const struct buffer *in)
 	default:
 		break;
 	}
+	fflush(stdout);
 }
 
 /** Token generator and output processing callback (cmdline API). */
app/test-pmd/config.c +124 -39

229 lines not on this page · raw message

app/test-pmd/testpmd.h +7 -2
index bdfbfd36d3..5c43b4db0b 100644
@@ -228,7 +228,12 @@ struct port_indirect_action {
 	struct port_indirect_action *next; /**< Next flow in list. */
 	uint32_t id; /**< Indirect action ID. */
 	enum rte_flow_action_type type; /**< Action type. */
-	struct rte_flow_action_handle *handle;	/**< Indirect action handle. */
+	union {
+		struct rte_flow_action_handle *handle;
+		/**< Indirect action handle. */
+		struct rte_flow_action_list_handle *list_handle;
+		/**< Indirect action list handle*/
+	};
 	enum age_action_context_type age_type; /**< Age action context type. */
 };
 
@@ -921,7 +926,7 @@ void update_fwd_ports(portid_t new_pid);
 void set_fwd_eth_peer(portid_t port_id, char *peer_addr);
 
 void port_mtu_set(portid_t port_id, uint16_t mtu);
-int port_action_handle_create(portid_t port_id, uint32_t id,
+int port_action_handle_create(portid_t port_id, uint32_t id, bool indirect_list,
 			      const struct rte_flow_indir_action_conf *conf,
 			      const struct rte_flow_action *action);
 int port_action_handle_destroy(portid_t port_id,
doc/guides/nics/features/default.ini +1 -0
index 1a5087abad..10a1c1af77 100644
@@ -158,6 +158,7 @@ drop                 =
 flag                 =
 inc_tcp_ack          =
 inc_tcp_seq          =
+indirect_list        =
 jump                 =
 mac_swap             =
 mark                 =
doc/guides/prog_guide/rte_flow.rst +119 -0

125 lines not on this page · raw message

doc/guides/rel_notes/release_23_07.rst +2 -0
index a9b1293689..d9643a35ef 100644
@@ -55,6 +55,8 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+   * **Added INDIRECT_LIST flow action.**
+
 
 Removed Items
 -------------
lib/ethdev/ethdev_trace.h +88 -0

94 lines not on this page · raw message

lib/ethdev/ethdev_trace_points.c +18 -0
index 61010cae56..5e1462a6fb 100644
@@ -750,3 +750,21 @@ RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_add,
 
 RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_delete,
 	lib.ethdev.tm.wred_profile_delete)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_create,
+			 lib.ethdev.flow.action_list_handle_create)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_destroy,
+			 lib.ethdev.flow.action_list_handle_destroy)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_query_update,
+			 lib.ethdev.flow.action_list_handle_query_update)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_create,
+	lib.ethdev.flow.async_action_list_handle_create)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_destroy,
+	lib.ethdev.flow.async_action_list_handle_destroy)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_query_update,
+			 lib.ethdev.flow.async_action_list_handle_query_update)
lib/ethdev/rte_flow.c +171 -0

180 lines not on this page · raw message

lib/ethdev/rte_flow.h +270 -0

282 lines not on this page · raw message

lib/ethdev/rte_flow_driver.h +41 -0

53 lines not on this page · raw message

lib/ethdev/version.map +8 -0
index 357d1a88c0..02372b3a7e 100644
@@ -299,6 +299,14 @@ EXPERIMENTAL {
 	rte_flow_action_handle_query_update;
 	rte_flow_async_action_handle_query_update;
 	rte_flow_async_create_by_index;
+
+	# added in 23.07
+    rte_flow_action_list_handle_create;
+    rte_flow_action_list_handle_destroy;
+    rte_flow_action_list_handle_query_update;
+    rte_flow_async_action_list_handle_create;
+    rte_flow_async_action_list_handle_destroy;
+    rte_flow_async_action_list_handle_query_update;
 };
 
 INTERNAL {
Signature · 1 line
2.34.1
#11 lore raw

PATCH v5 2/2 ethdev: add indirect list METER_MARK update structures

In the indirect list API, update action and update flow contexts are mutually exclusive.
The patch splits legacy METER_MASK update structure to support indirect list API:

struct rte_flow_indirect_update_action_meter_mark defines METER_MARK action context that is shared between all flows that reference a given indirect list handle.

struct rte_flow_indirect_update_flow_meter_mark defines METER_MARK context private to specific flow.

---
 lib/ethdev/rte_flow.h | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
lib/ethdev/rte_flow.h +32 -0
index a0d01a97e7..ce1aa336f2 100644
@@ -3891,6 +3891,38 @@ struct rte_flow_update_meter_mark {
 	uint32_t reserved:27;
 };
 
+/**
+ * @see RTE_FLOW_ACTION_TYPE_METER_MARK
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ *
+ * Update action mutable context.
+ */
+struct rte_flow_indirect_update_action_meter_mark {
+	/** New meter_mark parameters to be updated. */
+	struct rte_flow_action_meter_mark meter_mark;
+	/** The profile will be updated. */
+	uint32_t profile_valid:1;
+	/** The policy will be updated. */
+	uint32_t policy_valid:1;
+	/** The color mode will be updated. */
+	uint32_t color_mode_valid:1;
+	/** The meter state will be updated. */
+	uint32_t state_valid:1;
+	/** Reserved bits for the future usage. */
+	uint32_t reserved:28;
+};
+
+/**
+ * @see RTE_FLOW_ACTION_TYPE_METER_MARK
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ *
+ * Update flow mutable context.
+ */
+struct rte_flow_indirect_update_flow_meter_mark {
+	/** Updated init color applied to packet */
+	enum rte_color init_color;
+};
+
 /* Mbuf dynamic field offset for metadata. */
 extern int32_t rte_flow_dynf_metadata_offs;
 
Signature · 1 line
2.34.1
#12 lore raw

RE: [PATCH v5 2/2] ethdev: add indirect list METER_MARK update structures

Hi Gregory,

Quoted 41 lines

-----Original Message-----
From: Gregory Etelson <[email protected]>
Sent: Thursday, May 25, 2023 11:12 AM

In the indirect list API, update action and update flow contexts are mutually exclusive.
The patch splits legacy METER_MASK update structure to support indirect list API:

struct rte_flow_indirect_update_action_meter_mark defines METER_MARK
action context that is shared between all flows that reference a given indirect list handle.

struct rte_flow_indirect_update_flow_meter_mark defines METER_MARK context private to specific flow.

---
 lib/ethdev/rte_flow.h | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
lib/ethdev/rte_flow.h +11 -0
index a0d01a97e7..ce1aa336f2 100644
@@ -3891,6 +3891,38 @@ struct rte_flow_update_meter_mark {
 	uint32_t reserved:27;
 };
 
+/**
+ * @see RTE_FLOW_ACTION_TYPE_METER_MARK
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ *
+ * Update action mutable context.
+ */
+struct rte_flow_indirect_update_action_meter_mark {
+	/** New meter_mark parameters to be updated. */
+	struct rte_flow_action_meter_mark meter_mark;
+	/** The profile will be updated. */
+	uint32_t profile_valid:1;

lib/ethdev/rte_flow.h struct rte_flow_update_meter_mark { · line 3914

Quoted 10 lines
lib/ethdev/rte_flow.h +10 -0
+	/** The policy will be updated. */
+	uint32_t policy_valid:1;
+	/** The color mode will be updated. */
+	uint32_t color_mode_valid:1;
+	/** The meter state will be updated. */
+	uint32_t state_valid:1;
+	/** Reserved bits for the future usage. */
+	uint32_t reserved:28;
+};
+

Why did you create new meter_mark structure?

Quoted 15 lines
lib/ethdev/rte_flow.h +11 -1
+/**
+ * @see RTE_FLOW_ACTION_TYPE_METER_MARK
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ *
+ * Update flow mutable context.
+ */
+struct rte_flow_indirect_update_flow_meter_mark {
+	/** Updated init color applied to packet */
+	enum rte_color init_color;
+};
+
 /* Mbuf dynamic field offset for metadata. */
 extern int32_t rte_flow_dynf_metadata_offs;
 
--
Quoted 1 line

2.34.1

Best,
Ori

#13 lore raw

RE: [PATCH v5 2/2] ethdev: add indirect list METER_MARK update structures

Hello Ori,

[snip]

Quoted 15 lines
Quoted 15 lines
lib/ethdev/rte_flow.h +15 -0
+/**
+ * @see RTE_FLOW_ACTION_TYPE_METER_MARK
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ *
+ * Update action mutable context.
+ */
+struct rte_flow_indirect_update_action_meter_mark {
+	/** New meter_mark parameters to be updated. */
+	struct rte_flow_action_meter_mark meter_mark;
+	/** The profile will be updated. */
+	uint32_t profile_valid:1;
+	/** The policy will be updated. */
+	uint32_t policy_valid:1;
+	/** The color mode will be updated. */
+	uint32_t color_mode_valid:1;
Quoted 9 lines

lib/ethdev/rte_flow.h struct rte_flow_update_meter_mark { · line 3914

Quoted 6 lines
lib/ethdev/rte_flow.h +6 -0
+	/** The meter state will be updated. */
+	uint32_t state_valid:1;
+	/** Reserved bits for the future usage. */
+	uint32_t reserved:28;
+};
+

Why did you create new meter_mark structure?

Fixed.

Quoted 19 lines
Quoted 15 lines
lib/ethdev/rte_flow.h +11 -1
+/**
+ * @see RTE_FLOW_ACTION_TYPE_METER_MARK
+ * @see RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+ *
+ * Update flow mutable context.
+ */
+struct rte_flow_indirect_update_flow_meter_mark {
+	/** Updated init color applied to packet */
+	enum rte_color init_color;
+};
+
 /* Mbuf dynamic field offset for metadata. */
 extern int32_t rte_flow_dynf_metadata_offs;
 
--
Quoted 1 line

2.34.1

Best,
Ori

#14 lore raw

PATCH v6 1/1 ethdev: add indirect list flow action

In reply to Gregory Etelson

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

If indirect list handle was created from a list of actions A1 / A2 ... An / END
indirect list flow action can update Ai flow mutable context in the action configuration parameter.
Indirect list action configuration is and array [C1, C2, .., Cn] where Ci corresponds to Ai in the action handle source. Ci configuration element points Ai flow mutable update, or it's NULL if Ai has no flow mutable update.
Indirect list action configuration can be NULL if the action has no flow mutable updates.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), it will be fixed in that template.
Otherwise, indirect action value is set in a flow rule.

2 If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),
Htmpl's Ai action flow mutable context fill be updated to Ctmpl[i] values and will be fixed in that template.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was not masked in actions template, Hflow references an
action of the same type as Htmpl.

4 Cflow[i] updates handle's Ai flow mutable configuration if
the Ci was not masked in action template.

---
 app/test-pmd/cmdline_flow.c            | 207 ++++++++++++++++++-
 app/test-pmd/config.c                  | 163 +++++++++++----
 app/test-pmd/testpmd.h                 |   9 +-
 doc/guides/nics/features/default.ini   |   1 +
 doc/guides/prog_guide/rte_flow.rst     | 119 +++++++++++
 doc/guides/rel_notes/release_23_07.rst |   2 +
 lib/ethdev/ethdev_trace.h              |  88 ++++++++
 lib/ethdev/ethdev_trace_points.c       |  18 ++
 lib/ethdev/rte_flow.c                  | 171 +++++++++++++++
 lib/ethdev/rte_flow.h                  | 276 +++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h           |  41 ++++
 lib/ethdev/version.map                 |   8 +
 12 files changed, 1061 insertions(+), 42 deletions(-)
app/test-pmd/cmdline_flow.c +206 -1
index 58939ec321..af4c471306 100644
@@ -145,6 +145,7 @@ enum index {
 
 	/* Queue indirect action arguments */
 	QUEUE_INDIRECT_ACTION_CREATE,
+	QUEUE_INDIRECT_ACTION_LIST_CREATE,
 	QUEUE_INDIRECT_ACTION_UPDATE,
 	QUEUE_INDIRECT_ACTION_DESTROY,
 	QUEUE_INDIRECT_ACTION_QUERY,
@@ -157,6 +158,7 @@ enum index {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 
 	/* Queue indirect action update arguments */
 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
@@ -242,6 +244,8 @@ enum index {
 
 	/* Indirect action arguments */
 	INDIRECT_ACTION_CREATE,
+	INDIRECT_ACTION_LIST_CREATE,
+	INDIRECT_ACTION_FLOW_CONF_CREATE,
 	INDIRECT_ACTION_UPDATE,
 	INDIRECT_ACTION_DESTROY,
 	INDIRECT_ACTION_QUERY,
@@ -253,6 +257,8 @@ enum index {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
+	INDIRECT_ACTION_FLOW_CONF,
 
 	/* Indirect action destroy arguments */
 	INDIRECT_ACTION_DESTROY_ID,
@@ -626,6 +632,11 @@ enum index {
 	ACTION_SAMPLE_INDEX,
 	ACTION_SAMPLE_INDEX_VALUE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
+	ACTION_INDIRECT_LIST_HANDLE,
+	ACTION_INDIRECT_LIST_CONF,
+	INDIRECT_LIST_ACTION_ID2PTR_HANDLE,
+	INDIRECT_LIST_ACTION_ID2PTR_CONF,
 	ACTION_SHARED_INDIRECT,
 	INDIRECT_ACTION_PORT,
 	INDIRECT_ACTION_ID2PTR,
@@ -1266,6 +1277,7 @@ static const enum index next_qia_create_attr[] = {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 	ZERO,
 };
 
@@ -1294,6 +1306,8 @@ static const enum index next_ia_create_attr[] = {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
+	INDIRECT_ACTION_FLOW_CONF,
 	ZERO,
 };
 
@@ -1303,6 +1317,13 @@ static const enum index next_ia[] = {
 	ZERO
 };
 
+static const enum index next_ial[] = {
+	ACTION_INDIRECT_LIST_HANDLE,
+	ACTION_INDIRECT_LIST_CONF,
+	ACTION_NEXT,
+	ZERO
+};
+
 static const enum index next_qia_qu_attr[] = {
 	QUEUE_INDIRECT_ACTION_QU_MODE,
 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
@@ -2013,6 +2034,7 @@ static const enum index next_action[] = {
 	ACTION_AGE_UPDATE,
 	ACTION_SAMPLE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
 	ACTION_SHARED_INDIRECT,
 	ACTION_MODIFY_FIELD,
 	ACTION_CONNTRACK,
@@ -2289,6 +2311,7 @@ static const enum index next_action_sample[] = {
 	ACTION_RAW_ENCAP,
 	ACTION_VXLAN_ENCAP,
 	ACTION_NVGRE_ENCAP,
+	ACTION_REPRESENTED_PORT,
 	ACTION_NEXT,
 	ZERO,
 };
@@ -2539,6 +2562,10 @@ static int parse_ia_destroy(struct context *ctx, const struct token *token,
 static int parse_ia_id2ptr(struct context *ctx, const struct token *token,
 			   const char *str, unsigned int len, void *buf,
 			   unsigned int size);
+
+static int parse_indlst_id2ptr(struct context *ctx, const struct token *token,
+			       const char *str, unsigned int len, void *buf,
+			       unsigned int size);
 static int parse_ia_port(struct context *ctx, const struct token *token,
 			 const char *str, unsigned int len, void *buf,
 			 unsigned int size);
@@ -2627,6 +2654,16 @@ static int
 comp_qu_mode_name(struct context *ctx, const struct token *token,
 		  unsigned int ent, char *buf, unsigned int size);
 
+struct indlst_conf {
+	uint32_t id;
+	uint32_t conf_num;
+	struct rte_flow_action *actions;
+	const void **conf;
+	SLIST_ENTRY(indlst_conf) next;
+};
+
+static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id);
+
 /** Token definitions. */
 static const struct token token_list[] = {
 	/* Special tokens. */
@@ -3426,6 +3463,12 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[QUEUE_INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_qia,
+	},
 	/* Top-level command. */
 	[PUSH] = {
 		.name = "push",
@@ -6775,6 +6818,37 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
 		.call = parse_vc,
 	},
+	[ACTION_INDIRECT_LIST] = {
+		.name = "indirect_list",
+		.help = "apply indirect list action by id",
+		.priv = PRIV_ACTION(INDIRECT_LIST,
+				    sizeof(struct
+					   rte_flow_action_indirect_list)),
+		.next = NEXT(next_ial),
+		.call = parse_vc,
+	},
+	[ACTION_INDIRECT_LIST_HANDLE] = {
+		.name = "handle",
+		.help = "indirect list handle",
+		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
+	},
+	[ACTION_INDIRECT_LIST_CONF] = {
+		.name = "conf",
+		.help = "indirect list configuration",
+		.next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uintptr_t))),
+	},
+	[INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = {
+		.type = "UNSIGNED",
+		.help = "unsigned integer value",
+		.call = parse_indlst_id2ptr,
+	},
+	[INDIRECT_LIST_ACTION_ID2PTR_CONF] = {
+		.type = "UNSIGNED",
+		.help = "unsigned integer value",
+		.call = parse_indlst_id2ptr,
+	},
 	[ACTION_SHARED_INDIRECT] = {
 		.name = "shared_indirect",
 		.help = "apply indirect action by id and port",
@@ -6823,6 +6897,18 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_ia,
+	},
+	[INDIRECT_ACTION_FLOW_CONF] = {
+		.name = "flow_conf",
+		.help = "specify actions configuration for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_ia,
+	},
 	[ACTION_POL_G] = {
 		.name = "g_actions",
 		.help = "submit a list of associated actions for green",
@@ -7181,6 +7267,12 @@ parse_ia(struct context *ctx, const struct token *token,
 		return len;
 	case INDIRECT_ACTION_QU_MODE:
 		return len;
+	case INDIRECT_ACTION_LIST:
+		out->command = INDIRECT_ACTION_LIST_CREATE;
+		return len;
+	case INDIRECT_ACTION_FLOW_CONF:
+		out->command = INDIRECT_ACTION_FLOW_CONF_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7278,6 +7370,9 @@ parse_qia(struct context *ctx, const struct token *token,
 		return len;
 	case QUEUE_INDIRECT_ACTION_QU_MODE:
 		return len;
+	case QUEUE_INDIRECT_ACTION_LIST:
+		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7454,10 +7549,12 @@ parse_vc(struct context *ctx, const struct token *token,
 			return -1;
 		break;
 	case ACTIONS:
-		out->args.vc.actions =
+		out->args.vc.actions = out->args.vc.pattern ?
 			(void *)RTE_ALIGN_CEIL((uintptr_t)
 					       (out->args.vc.pattern +
 						out->args.vc.pattern_n),
+					       sizeof(double)) :
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
 					       sizeof(double));
 		ctx->object = out->args.vc.actions;
 		ctx->objmask = NULL;
@@ -10412,6 +10509,49 @@ parse_ia_id2ptr(struct context *ctx, const struct token *token,
 	return ret;
 }
 
+static int
+parse_indlst_id2ptr(struct context *ctx, const struct token *token,
+		    const char *str, unsigned int len,
+		    void __rte_unused *buf, unsigned int __rte_unused size)
+{
+	struct rte_flow_action *action = ctx->object;
+	struct rte_flow_action_indirect_list *action_conf;
+	const struct indlst_conf *indlst_conf;
+	uint32_t id;
+	int ret;
+
+	if (!action)
+		return -1;
+	ctx->objdata = 0;
+	ctx->object = &id;
+	ctx->objmask = NULL;
+	ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
+	if (ret != (int)len)
+		return ret;
+	ctx->object = action;
+	action_conf = (void *)(uintptr_t)action->conf;
+	action_conf->conf = NULL;
+	switch (ctx->curr) {
+	case INDIRECT_LIST_ACTION_ID2PTR_HANDLE:
+	action_conf->handle = (typeof(action_conf->handle))
+				port_action_handle_get_by_id(ctx->port, id);
+		if (!action_conf->handle) {
+			printf("no indirect list handle for id %u\n", id);
+			return -1;
+		}
+		break;
+	case INDIRECT_LIST_ACTION_ID2PTR_CONF:
+		indlst_conf = indirect_action_list_conf_get(id);
+		if (!indlst_conf)
+			return -1;
+		action_conf->conf = (const void **)indlst_conf->conf;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
 static int
 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token,
 		const char *str, unsigned int len,
@@ -11453,6 +11593,64 @@ cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
 	*hdr = &cmd_flow_token_hdr;
 }
 
+static SLIST_HEAD(, indlst_conf) indlst_conf_head =
+	SLIST_HEAD_INITIALIZER();
+
+static void
+indirect_action_flow_conf_create(const struct buffer *in)
+{
+	int len, ret;
+	uint32_t i;
+	struct indlst_conf *indlst_conf = NULL;
+	size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8);
+	struct rte_flow_action *src = in->args.vc.actions;
+
+	if (!in->args.vc.actions_n)
+		goto end;
+	len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL);
+	if (len <= 0)
+		goto end;
+	len = RTE_ALIGN(len, 16);
+
+	indlst_conf = calloc(1, base + len +
+			     in->args.vc.actions_n * sizeof(uintptr_t));
+	if (!indlst_conf)
+		goto end;
+	indlst_conf->id = in->args.vc.attr.group;
+	indlst_conf->conf_num = in->args.vc.actions_n - 1;
+	indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base);
+	ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions,
+			    len, src, NULL);
+	if (ret <= 0) {
+		free(indlst_conf);
+		indlst_conf = NULL;
+		goto end;
+	}
+	indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len);
+	for (i = 0; i < indlst_conf->conf_num; i++)
+		indlst_conf->conf[i] = indlst_conf->actions[i].conf;
+	SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next);
+end:
+	if (indlst_conf)
+		printf("created indirect action list configuration %u\n",
+		       in->args.vc.attr.group);
+	else
+		printf("cannot create indirect action list configuration %u\n",
+		       in->args.vc.attr.group);
+}
+
+static const struct indlst_conf *
+indirect_action_list_conf_get(uint32_t conf_id)
+{
+	const struct indlst_conf *conf;
+
+	SLIST_FOREACH(conf, &indlst_conf_head, next) {
+		if (conf->id == conf_id)
+			return conf;
+	}
+	return NULL;
+}
+
 /** Dispatch parsed buffer to function calls. */
 static void
 cmd_flow_parsed(const struct buffer *in)
@@ -11532,6 +11730,7 @@ cmd_flow_parsed(const struct buffer *in)
 				     in->args.aged.destroy);
 		break;
 	case QUEUE_INDIRECT_ACTION_CREATE:
+	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
 		port_queue_action_handle_create(
 				in->port, in->queue, in->postpone,
 				in->args.vc.attr.group,
@@ -11567,8 +11766,10 @@ cmd_flow_parsed(const struct buffer *in)
 						      in->args.vc.actions);
 		break;
 	case INDIRECT_ACTION_CREATE:
+	case INDIRECT_ACTION_LIST_CREATE:
 		port_action_handle_create(
 				in->port, in->args.vc.attr.group,
+				in->command == INDIRECT_ACTION_LIST_CREATE,
 				&((const struct rte_flow_indir_action_conf) {
 					.ingress = in->args.vc.attr.ingress,
 					.egress = in->args.vc.attr.egress,
@@ -11576,6 +11777,9 @@ cmd_flow_parsed(const struct buffer *in)
 				}),
 				in->args.vc.actions);
 		break;
+	case INDIRECT_ACTION_FLOW_CONF_CREATE:
+		indirect_action_flow_conf_create(in);
+		break;
 	case INDIRECT_ACTION_DESTROY:
 		port_action_handle_destroy(in->port,
 					   in->args.ia_destroy.action_id_n,
@@ -11653,6 +11857,7 @@ cmd_flow_parsed(const struct buffer *in)
 	default:
 		break;
 	}
+	fflush(stdout);
 }
 
 /** Token generator and output processing callback (cmdline API). */
app/test-pmd/config.c +124 -39

229 lines not on this page · raw message

app/test-pmd/testpmd.h +7 -2
index bdfbfd36d3..5c43b4db0b 100644
@@ -228,7 +228,12 @@ struct port_indirect_action {
 	struct port_indirect_action *next; /**< Next flow in list. */
 	uint32_t id; /**< Indirect action ID. */
 	enum rte_flow_action_type type; /**< Action type. */
-	struct rte_flow_action_handle *handle;	/**< Indirect action handle. */
+	union {
+		struct rte_flow_action_handle *handle;
+		/**< Indirect action handle. */
+		struct rte_flow_action_list_handle *list_handle;
+		/**< Indirect action list handle*/
+	};
 	enum age_action_context_type age_type; /**< Age action context type. */
 };
 
@@ -921,7 +926,7 @@ void update_fwd_ports(portid_t new_pid);
 void set_fwd_eth_peer(portid_t port_id, char *peer_addr);
 
 void port_mtu_set(portid_t port_id, uint16_t mtu);
-int port_action_handle_create(portid_t port_id, uint32_t id,
+int port_action_handle_create(portid_t port_id, uint32_t id, bool indirect_list,
 			      const struct rte_flow_indir_action_conf *conf,
 			      const struct rte_flow_action *action);
 int port_action_handle_destroy(portid_t port_id,
doc/guides/nics/features/default.ini +1 -0
index 1a5087abad..10a1c1af77 100644
@@ -158,6 +158,7 @@ drop                 =
 flag                 =
 inc_tcp_ack          =
 inc_tcp_seq          =
+indirect_list        =
 jump                 =
 mac_swap             =
 mark                 =
doc/guides/prog_guide/rte_flow.rst +119 -0

125 lines not on this page · raw message

doc/guides/rel_notes/release_23_07.rst +2 -0
index a9b1293689..d9643a35ef 100644
@@ -55,6 +55,8 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+   * **Added INDIRECT_LIST flow action.**
+
 
 Removed Items
 -------------
lib/ethdev/ethdev_trace.h +88 -0

94 lines not on this page · raw message

lib/ethdev/ethdev_trace_points.c +18 -0
index 61010cae56..5e1462a6fb 100644
@@ -750,3 +750,21 @@ RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_add,
 
 RTE_TRACE_POINT_REGISTER(rte_tm_trace_wred_profile_delete,
 	lib.ethdev.tm.wred_profile_delete)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_create,
+			 lib.ethdev.flow.action_list_handle_create)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_destroy,
+			 lib.ethdev.flow.action_list_handle_destroy)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_action_list_handle_query_update,
+			 lib.ethdev.flow.action_list_handle_query_update)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_create,
+	lib.ethdev.flow.async_action_list_handle_create)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_destroy,
+	lib.ethdev.flow.async_action_list_handle_destroy)
+
+RTE_TRACE_POINT_REGISTER(rte_flow_trace_async_action_list_handle_query_update,
+			 lib.ethdev.flow.async_action_list_handle_query_update)
lib/ethdev/rte_flow.c +171 -0

180 lines not on this page · raw message

lib/ethdev/rte_flow.h +276 -0

288 lines not on this page · raw message

lib/ethdev/rte_flow_driver.h +41 -0

53 lines not on this page · raw message

lib/ethdev/version.map +8 -0
index 357d1a88c0..02372b3a7e 100644
@@ -299,6 +299,14 @@ EXPERIMENTAL {
 	rte_flow_action_handle_query_update;
 	rte_flow_async_action_handle_query_update;
 	rte_flow_async_create_by_index;
+
+	# added in 23.07
+    rte_flow_action_list_handle_create;
+    rte_flow_action_list_handle_destroy;
+    rte_flow_action_list_handle_query_update;
+    rte_flow_async_action_list_handle_create;
+    rte_flow_async_action_list_handle_destroy;
+    rte_flow_async_action_list_handle_query_update;
 };
 
 INTERNAL {
Signature · 1 line
2.34.1
Acked-by on v6 1/1
#15 lore raw

Hi gregory,

Quoted 99 lines

-----Original Message-----
From: Gregory Etelson <[email protected]>
Sent: Sunday, May 28, 2023 6:44 PM

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

If indirect list handle was created from a list of actions A1 / A2 ... An / END
indirect list flow action can update Ai flow mutable context in the action configuration parameter.
Indirect list action configuration is and array [C1, C2, .., Cn] where Ci corresponds to Ai in the action handle source. Ci configuration element points Ai flow mutable update, or it's NULL if Ai has no flow mutable update.
Indirect list action configuration can be NULL if the action has no flow mutable updates.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), it will be fixed in that template.
Otherwise, indirect action value is set in a flow rule.

2 If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),
Htmpl's Ai action flow mutable context fill be updated to Ctmpl[i] values and will be fixed in that template.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

Quoted 8 lines

3 If Htmpl was not masked in actions template, Hflow references an
action of the same type as Htmpl.

4 Cflow[i] updates handle's Ai flow mutable configuration if
the Ci was not masked in action template.

---

Best,
Ori

Applied
#16 lore raw
Quoted 104 lines · Ori Kam

Hi gregory,

Quoted 102 lines

-----Original Message-----
From: Gregory Etelson <[email protected]>
Sent: Sunday, May 28, 2023 6:44 PM

Indirect API creates a shared flow action with unique action handle. Flow rules can access the shared flow action and resources related to that action through the indirect action handle.
In addition, the API allows to update existing shared flow action configuration. After the update completes, new action configuration is available to all flows that reference that shared action.

Indirect actions list expands the indirect action API:
• Indirect action list creates a handle for one or several flow actions, while legacy indirect action handle references single action only.
Input flow actions arranged in END terminated list.
• Flow rule can provide rule specific configuration parameters to existing shared handle.
Updates of flow rule specific configuration will not change the base action configuration.
Base action configuration was set during the action creation.

Indirect action list handle defines 2 types of resources:
• Mutable handle resource can be changed during handle lifespan.
• Immutable handle resource value is set during handle creation and cannot be changed.

There are 2 types of mutable indirect handle contexts:
• Action mutable context is always shared between all flows that referenced indirect actions list handle. Action mutable context can be changed by explicit invocation of indirect handle update function.
• Flow mutable context is private to a flow.
Flow mutable context can be updated by indirect list handle flow rule configuration.

flow 1:
/ indirect handle H conf C1 /

                   |       |
                   |       |
                   |       |         flow 2:
                   |       |         / indirect handle H conf C2 /
                   |       |                           |      |
                   |       |                           |      |
                   |       |                           |      |
            =========================================================
            ^      |       |                           |      |
            |      |       V                           |      V
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
            |     flow mutable                        flow mutable
            |     context 1                           context 2
            |    ~~~~~~~~~~~~~~                      ~~~~~~~~~~~~~~~
  indirect  |      |                                   |
  action    |      |                                   |
  context   |      V                                   V
            |   -----------------------------------------------------
            |                 action mutable context
            |   -----------------------------------------------------

v action immutable context
=========================================================

Indirect action types - immutable, action / flow mutable, are mutually exclusive and depend on the action definition.
For example:
• Indirect METER_MARK policy is immutable action member and profile is action mutable action member.
• Indirect METER_MARK flow action defines init_color as flow mutable member.
• Indirect QUOTA flow action does not define flow mutable members.

If indirect list handle was created from a list of actions A1 / A2 ... An / END
indirect list flow action can update Ai flow mutable context in the action configuration parameter.
Indirect list action configuration is and array [C1, C2, .., Cn] where Ci corresponds to Ai in the action handle source. Ci configuration element points Ai flow mutable update, or it's NULL if Ai has no flow mutable update.
Indirect list action configuration can be NULL if the action has no flow mutable updates.

Template API:

Action template format:

template .. indirect_list handle Htmpl conf Ctmpl ..
mask .. indirect_list handle Hmask conf Cmask ..

1 If Htmpl was masked (Hmask != 0), it will be fixed in that template.
Otherwise, indirect action value is set in a flow rule.

2 If Htmpl and Ctmpl[i] were masked (Hmask !=0 and Cmask[i] != 0),
Htmpl's Ai action flow mutable context fill be updated to Ctmpl[i] values and will be fixed in that template.

Flow rule format:

actions .. indirect_list handle Hflow conf Cflow ..

3 If Htmpl was not masked in actions template, Hflow references an
action of the same type as Htmpl.

Quoted 8 lines
Quoted 5 lines

4 Cflow[i] updates handle's Ai flow mutable configuration if
the Ci was not masked in action template.

---

Applied to dpdk-next-net/main, thanks.

(checkpatch warnings fixed while merging.)