[v2,1/4] ethdev: add template table insertion type

Message ID 20230126232802.3960109-2-akozyrev@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series ethdev: add template table insertion and matching types |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Alexander Kozyrev Jan. 26, 2023, 11:27 p.m. UTC
  Allow user to specify insertion type used in template tables.
The insertion type is responsible for choosing the appropriate key
value used to map inserted flow rules into a template table.

Flow rules can be inserted by calculating the hash value for
the pattern or inserted by index via the new create_by_index() API.
The idea of the index-based insertion is to avoid additional matches
and simply execute predefined actions after jumping to the index.

The insertion into an already occupied index results in an error.
The old rule must be destroyed first. An index cannot be bigger than
the size of the table, otherwise, the rule is rejected as well.

Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>
---
 doc/guides/prog_guide/rte_flow.rst     | 20 ++++++++
 doc/guides/rel_notes/release_23_03.rst |  6 +++
 lib/ethdev/rte_flow.c                  | 24 ++++++++++
 lib/ethdev/rte_flow.h                  | 65 ++++++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h           | 11 +++++
 lib/ethdev/version.map                 |  3 ++
 6 files changed, 129 insertions(+)
  

Comments

Andrew Rybchenko Feb. 2, 2023, 10:57 a.m. UTC | #1
On 1/27/23 02:27, Alexander Kozyrev wrote:
> Allow user to specify insertion type used in template tables.
> The insertion type is responsible for choosing the appropriate key
> value used to map inserted flow rules into a template table.
> 
> Flow rules can be inserted by calculating the hash value for
> the pattern or inserted by index via the new create_by_index() API.
> The idea of the index-based insertion is to avoid additional matches
> and simply execute predefined actions after jumping to the index.
> 
> The insertion into an already occupied index results in an error.
> The old rule must be destroyed first. An index cannot be bigger than
> the size of the table, otherwise, the rule is rejected as well.

I'm sorry, but all my attempts to understand what happens here
are unsuccessful. Unfortunately the structure is unclear.
It sounds like your insert something by index into the template
table, but I don't understand the idea why it makes sense and
why it is needed.

> 
> Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>

[snip]

> diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
> index c15f6fbb9f..fa9391de2b 100644
> --- a/doc/guides/rel_notes/release_23_03.rst
> +++ b/doc/guides/rel_notes/release_23_03.rst
> @@ -69,6 +69,12 @@ New Features
>       ``rte_event_dev_config::nb_single_link_event_port_queues`` parameter
>       required for eth_rx, eth_tx, crypto and timer eventdev adapters.
>   
> +* **Added index-based rules insertion in flow API.**
> +
> +  Added ``rte_flow_table_insertion_type`` to allow the creation
> +  of index-based template tables in addition to pattern-based tables.
> +  Introduced new function ``rte_flow_async_create_by_index()``
> +  to insert rules by index into index-based template tables.

One more empty line here please, to have two before the next
section.

>   
>   Removed Items
>   -------------
> diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
> index 7d0c24366c..013eb355ca 100644
> --- a/lib/ethdev/rte_flow.c
> +++ b/lib/ethdev/rte_flow.c
> @@ -1765,6 +1765,30 @@ rte_flow_async_create(uint16_t port_id,
>   	return flow;
>   }
>   
> +struct rte_flow *
> +rte_flow_async_create_by_index(uint16_t port_id,
> +			       uint32_t queue_id,
> +			       const struct rte_flow_op_attr *op_attr,
> +			       struct rte_flow_template_table *template_table,
> +			       uint32_t rule_index,
> +			       const struct rte_flow_action actions[],
> +			       uint8_t actions_template_index,
> +			       void *user_data,
> +			       struct rte_flow_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
> +	struct rte_flow *flow;

All generic checks of arguments must be done here.
I guess template_table cannot be NULL.  Anything else?
Can we check queue_id?

ops must be checked vs NULL, callback must be checked vs NULL.

> +
> +	flow = ops->async_create_by_index(dev, queue_id,
> +					  op_attr, template_table, rule_index,
> +					  actions, actions_template_index,
> +					  user_data, error);
> +	if (flow == NULL)
> +		flow_err(port_id, -rte_errno, error);
> +	return flow;
> +}
> +
>   int
>   rte_flow_async_destroy(uint16_t port_id,
>   		       uint32_t queue_id,
> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
> index b60987db4b..2ba616eeb1 100644
> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> @@ -5187,6 +5187,23 @@ rte_flow_actions_template_destroy(uint16_t port_id,
>    */
>   struct rte_flow_template_table;
>   
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Template table flow rules insertion type.
> + */
> +enum rte_flow_table_insertion_type {
> +	/**
> +	 * Pattern-based insertion.
> +	 */
> +	RTE_FLOW_TABLE_INSERTION_TYPE_PATTERN,
> +	/**
> +	 * Index-based insertion.
> +	 */
> +	RTE_FLOW_TABLE_INSERTION_TYPE_INDEX,
> +};
> +
>   /**
>    * @warning
>    * @b EXPERIMENTAL: this API may change without prior notice.
> @@ -5202,6 +5219,10 @@ struct rte_flow_template_table_attr {
>   	 * Maximum number of flow rules that this table holds.
>   	 */
>   	uint32_t nb_flows;
> +	/**
> +	 * Insertion type for flow rules.
> +	 */
> +	enum rte_flow_table_insertion_type insertion_type;
>   };
>   
>   /**
> @@ -5336,6 +5357,50 @@ rte_flow_async_create(uint16_t port_id,
>   		      void *user_data,
>   		      struct rte_flow_error *error);
>   
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Enqueue rule creation operation.
> + *
> + * @param port_id
> + *   Port identifier of Ethernet device.
> + * @param queue_id
> + *   Flow queue used to insert the rule.
> + * @param[in] op_attr
> + *   Rule creation operation attributes.

May be NULL?

> + * @param[in] template_table
> + *   Template table to select templates from.
> + * @param[in] rule_index
> + *   Rule index in the table.
> + * @param[in] actions
> + *   List of actions to be used.
> + *   The list order should match the order in the actions template.

Should we mention that it should be terminated with END?

> + * @param[in] actions_template_index
> + *   Actions template index in the table.
> + * @param[in] user_data
> + *   The user data that will be returned on the completion events.

May be NULL?

> + * @param[out] error
> + *   Perform verbose error reporting if not NULL.
> + *   PMDs initialize this structure in case of error only.
> + *
> + * @return
> + *   Handle on success, NULL otherwise and rte_errno is set.
> + *   The rule handle doesn't mean that the rule has been populated.
> + *   Only completion result indicates that if there was success or failure.
> + */
> +__rte_experimental
> +struct rte_flow *
> +rte_flow_async_create_by_index(uint16_t port_id,
> +			       uint32_t queue_id,
> +			       const struct rte_flow_op_attr *op_attr,
> +			       struct rte_flow_template_table *template_table,
> +			       uint32_t rule_index,
> +			       const struct rte_flow_action actions[],
> +			       uint8_t actions_template_index,
> +			       void *user_data,
> +			       struct rte_flow_error *error);
> +
>   /**
>    * @warning
>    * @b EXPERIMENTAL: this API may change without prior notice.

[snip]
  
Alexander Kozyrev Feb. 7, 2023, 3:06 p.m. UTC | #2
> > Allow user to specify insertion type used in template tables.
> > The insertion type is responsible for choosing the appropriate key
> > value used to map inserted flow rules into a template table.
> >
> > Flow rules can be inserted by calculating the hash value for
> > the pattern or inserted by index via the new create_by_index() API.
> > The idea of the index-based insertion is to avoid additional matches
> > and simply execute predefined actions after jumping to the index.
> >
> > The insertion into an already occupied index results in an error.
> > The old rule must be destroyed first. An index cannot be bigger than
> > the size of the table, otherwise, the rule is rejected as well.
> 
> I'm sorry, but all my attempts to understand what happens here
> are unsuccessful. Unfortunately the structure is unclear.
> It sounds like your insert something by index into the template
> table, but I don't understand the idea why it makes sense and
> why it is needed.

Sorry, Andrew, for the confusion. Looks like I need to include this explanation from the RFC:
This is how the regular pattern-based table works:
you calculate hash on 5-tuple, go to the table entry with the corresponding hash,
check if there is a collision and search for the proper entry if so, execute actions.
Index-based table:
 take an index value from a specified field, go to this index, and execute actions.
The whole idea is to skip any lookups for the packet if an user know exactly what should be executed.

> [snip]
> 
> > diff --git a/doc/guides/rel_notes/release_23_03.rst
> b/doc/guides/rel_notes/release_23_03.rst
> > index c15f6fbb9f..fa9391de2b 100644
> > --- a/doc/guides/rel_notes/release_23_03.rst
> > +++ b/doc/guides/rel_notes/release_23_03.rst
> > @@ -69,6 +69,12 @@ New Features
> >       ``rte_event_dev_config::nb_single_link_event_port_queues``
> parameter
> >       required for eth_rx, eth_tx, crypto and timer eventdev adapters.
> >
> > +* **Added index-based rules insertion in flow API.**
> > +
> > +  Added ``rte_flow_table_insertion_type`` to allow the creation
> > +  of index-based template tables in addition to pattern-based tables.
> > +  Introduced new function ``rte_flow_async_create_by_index()``
> > +  to insert rules by index into index-based template tables.
> 
> One more empty line here please, to have two before the next
> section.

No problem.

> >   Removed Items
> >   -------------
> > diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
> > index 7d0c24366c..013eb355ca 100644
> > --- a/lib/ethdev/rte_flow.c
> > +++ b/lib/ethdev/rte_flow.c
> > @@ -1765,6 +1765,30 @@ rte_flow_async_create(uint16_t port_id,
> >   	return flow;
> >   }
> >
> > +struct rte_flow *
> > +rte_flow_async_create_by_index(uint16_t port_id,
> > +			       uint32_t queue_id,
> > +			       const struct rte_flow_op_attr *op_attr,
> > +			       struct rte_flow_template_table *template_table,
> > +			       uint32_t rule_index,
> > +			       const struct rte_flow_action actions[],
> > +			       uint8_t actions_template_index,
> > +			       void *user_data,
> > +			       struct rte_flow_error *error)
> > +{
> > +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> > +	const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
> > +	struct rte_flow *flow;
> 
> All generic checks of arguments must be done here.
> I guess template_table cannot be NULL.  Anything else?
> Can we check queue_id?
> 
> ops must be checked vs NULL, callback must be checked vs NULL.

We are following the convention about asynchronous API.
No NULL checks are performed in any async Flow API for the sake of performance.
You can see this behaviour in any other async functions there.

> > +
> > +	flow = ops->async_create_by_index(dev, queue_id,
> > +					  op_attr, template_table,
> rule_index,
> > +					  actions, actions_template_index,
> > +					  user_data, error);
> > +	if (flow == NULL)
> > +		flow_err(port_id, -rte_errno, error);
> > +	return flow;
> > +}
> > +
> >   int
> >   rte_flow_async_destroy(uint16_t port_id,
> >   		       uint32_t queue_id,
> > diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
> > index b60987db4b..2ba616eeb1 100644
> > --- a/lib/ethdev/rte_flow.h
> > +++ b/lib/ethdev/rte_flow.h
> > @@ -5187,6 +5187,23 @@ rte_flow_actions_template_destroy(uint16_t
> port_id,
> >    */
> >   struct rte_flow_template_table;
> >
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change without prior notice.
> > + *
> > + * Template table flow rules insertion type.
> > + */
> > +enum rte_flow_table_insertion_type {
> > +	/**
> > +	 * Pattern-based insertion.
> > +	 */
> > +	RTE_FLOW_TABLE_INSERTION_TYPE_PATTERN,
> > +	/**
> > +	 * Index-based insertion.
> > +	 */
> > +	RTE_FLOW_TABLE_INSERTION_TYPE_INDEX,
> > +};
> > +
> >   /**
> >    * @warning
> >    * @b EXPERIMENTAL: this API may change without prior notice.
> > @@ -5202,6 +5219,10 @@ struct rte_flow_template_table_attr {
> >   	 * Maximum number of flow rules that this table holds.
> >   	 */
> >   	uint32_t nb_flows;
> > +	/**
> > +	 * Insertion type for flow rules.
> > +	 */
> > +	enum rte_flow_table_insertion_type insertion_type;
> >   };
> >
> >   /**
> > @@ -5336,6 +5357,50 @@ rte_flow_async_create(uint16_t port_id,
> >   		      void *user_data,
> >   		      struct rte_flow_error *error);
> >
> > +/**
> > + * @warning
> > + * @b EXPERIMENTAL: this API may change without prior notice.
> > + *
> > + * Enqueue rule creation operation.
> > + *
> > + * @param port_id
> > + *   Port identifier of Ethernet device.
> > + * @param queue_id
> > + *   Flow queue used to insert the rule.
> > + * @param[in] op_attr
> > + *   Rule creation operation attributes.
> 
> May be NULL?
No.

> > + * @param[in] template_table
> > + *   Template table to select templates from.
> > + * @param[in] rule_index
> > + *   Rule index in the table.
> > + * @param[in] actions
> > + *   List of actions to be used.
> > + *   The list order should match the order in the actions template.
> 
> Should we mention that it should be terminated with END?
Isn't redundant? Flow API assumes that pattern and actions always end with END.

> > + * @param[in] actions_template_index
> > + *   Actions template index in the table.
> > + * @param[in] user_data
> > + *   The user data that will be returned on the completion events.
> 
> May be NULL?
Yes, it may be NULL if the user doesn’t want any data associated with the flow.
  

Patch

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 3e6242803d..fbed7da9d8 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -3669,6 +3669,26 @@  Enqueueing a flow rule creation operation is similar to simple creation.
 A valid handle in case of success is returned. It must be destroyed later
 by calling ``rte_flow_async_destroy()`` even if the rule is rejected by HW.
 
+Enqueue creation by index operation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Enqueueing a flow rule creation operation to insert a rule at a table index.
+
+.. code-block:: c
+
+   struct rte_flow *
+   rte_flow_async_create_by_index(uint16_t port_id,
+                                  uint32_t queue_id,
+                                  const struct rte_flow_op_attr *op_attr,
+                                  struct rte_flow_template_table *template_table,
+                                  uint32_t rule_index,
+                                  const struct rte_flow_action actions[],
+                                  uint8_t actions_template_index,
+                                  void *user_data,
+                                  struct rte_flow_error *error);
+
+A valid handle in case of success is returned. It must be destroyed later
+by calling ``rte_flow_async_destroy()`` even if the rule is rejected by HW.
+
 Enqueue destruction operation
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index c15f6fbb9f..fa9391de2b 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -69,6 +69,12 @@  New Features
     ``rte_event_dev_config::nb_single_link_event_port_queues`` parameter
     required for eth_rx, eth_tx, crypto and timer eventdev adapters.
 
+* **Added index-based rules insertion in flow API.**
+
+  Added ``rte_flow_table_insertion_type`` to allow the creation
+  of index-based template tables in addition to pattern-based tables.
+  Introduced new function ``rte_flow_async_create_by_index()``
+  to insert rules by index into index-based template tables.
 
 Removed Items
 -------------
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 7d0c24366c..013eb355ca 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -1765,6 +1765,30 @@  rte_flow_async_create(uint16_t port_id,
 	return flow;
 }
 
+struct rte_flow *
+rte_flow_async_create_by_index(uint16_t port_id,
+			       uint32_t queue_id,
+			       const struct rte_flow_op_attr *op_attr,
+			       struct rte_flow_template_table *template_table,
+			       uint32_t rule_index,
+			       const struct rte_flow_action actions[],
+			       uint8_t actions_template_index,
+			       void *user_data,
+			       struct rte_flow_error *error)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
+	struct rte_flow *flow;
+
+	flow = ops->async_create_by_index(dev, queue_id,
+					  op_attr, template_table, rule_index,
+					  actions, actions_template_index,
+					  user_data, error);
+	if (flow == NULL)
+		flow_err(port_id, -rte_errno, error);
+	return flow;
+}
+
 int
 rte_flow_async_destroy(uint16_t port_id,
 		       uint32_t queue_id,
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index b60987db4b..2ba616eeb1 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -5187,6 +5187,23 @@  rte_flow_actions_template_destroy(uint16_t port_id,
  */
 struct rte_flow_template_table;
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Template table flow rules insertion type.
+ */
+enum rte_flow_table_insertion_type {
+	/**
+	 * Pattern-based insertion.
+	 */
+	RTE_FLOW_TABLE_INSERTION_TYPE_PATTERN,
+	/**
+	 * Index-based insertion.
+	 */
+	RTE_FLOW_TABLE_INSERTION_TYPE_INDEX,
+};
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change without prior notice.
@@ -5202,6 +5219,10 @@  struct rte_flow_template_table_attr {
 	 * Maximum number of flow rules that this table holds.
 	 */
 	uint32_t nb_flows;
+	/**
+	 * Insertion type for flow rules.
+	 */
+	enum rte_flow_table_insertion_type insertion_type;
 };
 
 /**
@@ -5336,6 +5357,50 @@  rte_flow_async_create(uint16_t port_id,
 		      void *user_data,
 		      struct rte_flow_error *error);
 
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue rule creation operation.
+ *
+ * @param port_id
+ *   Port identifier of Ethernet device.
+ * @param queue_id
+ *   Flow queue used to insert the rule.
+ * @param[in] op_attr
+ *   Rule creation operation attributes.
+ * @param[in] template_table
+ *   Template table to select templates from.
+ * @param[in] rule_index
+ *   Rule index in the table.
+ * @param[in] actions
+ *   List of actions to be used.
+ *   The list order should match the order in the actions template.
+ * @param[in] actions_template_index
+ *   Actions template index in the table.
+ * @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
+ *   Handle on success, NULL otherwise and rte_errno is set.
+ *   The rule handle doesn't mean that the rule has been populated.
+ *   Only completion result indicates that if there was success or failure.
+ */
+__rte_experimental
+struct rte_flow *
+rte_flow_async_create_by_index(uint16_t port_id,
+			       uint32_t queue_id,
+			       const struct rte_flow_op_attr *op_attr,
+			       struct rte_flow_template_table *template_table,
+			       uint32_t rule_index,
+			       const struct rte_flow_action actions[],
+			       uint8_t actions_template_index,
+			       void *user_data,
+			       struct rte_flow_error *error);
+
 /**
  * @warning
  * @b EXPERIMENTAL: this API may change without prior notice.
diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h
index c7d0699c91..b5b597dd28 100644
--- a/lib/ethdev/rte_flow_driver.h
+++ b/lib/ethdev/rte_flow_driver.h
@@ -221,6 +221,17 @@  struct rte_flow_ops {
 		 uint8_t actions_template_index,
 		 void *user_data,
 		 struct rte_flow_error *err);
+	/** See rte_flow_async_create_by_index() */
+	struct rte_flow *(*async_create_by_index)
+		(struct rte_eth_dev *dev,
+		 uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_template_table *template_table,
+		 uint32_t rule_index,
+		 const struct rte_flow_action actions[],
+		 uint8_t actions_template_index,
+		 void *user_data,
+		 struct rte_flow_error *err);
 	/** See rte_flow_async_destroy() */
 	int (*async_destroy)
 		(struct rte_eth_dev *dev,
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 17201fbe0f..dbc2bffe64 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -298,6 +298,9 @@  EXPERIMENTAL {
 	rte_flow_get_q_aged_flows;
 	rte_mtr_meter_policy_get;
 	rte_mtr_meter_profile_get;
+
+	# added in 23.03
+	rte_flow_async_create_by_index;
 };
 
 INTERNAL {