@@ -3626,6 +3626,130 @@ Return values:
- 0 on success, a negative errno value otherwise and ``rte_errno`` is set.
+Flow templates
+~~~~~~~~~~~~~~
+
+Oftentimes in an application, many flow rules share a common structure
+(the same pattern and/or action list) so they can be grouped and classified
+together. This knowledge may be used as a source of optimization by a PMD/HW.
+The flow rule creation is done by selecting a table, an item template
+and an action template (which are bound to the table), and setting unique
+values for the items and actions. This API is not thread-safe.
+
+Item templates
+^^^^^^^^^^^^^^
+
+The item template defines a common pattern (the item mask) without values.
+The mask value is used to select a field to match on, spec/last are ignored.
+The item template may be used by multiple tables and must not be destroyed
+until all these tables are destroyed first.
+
+.. code-block:: c
+
+ struct rte_flow_item_template *
+ rte_flow_item_template_create(uint16_t port_id,
+ const struct rte_flow_item_template_attr *it_attr,
+ const struct rte_flow_item items[],
+ struct rte_flow_error *error);
+
+For example, to create an item template to match on the destination MAC:
+
+.. code-block:: c
+
+ struct rte_flow_item root_items[2] = {{0}};
+ struct rte_flow_item_eth eth_m = {0};
+ items[0].type = RTE_FLOW_ITEM_TYPE_ETH;
+ eth_m.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff";
+ items[0].mask = ð_m;
+ items[1].type = RTE_FLOW_ITEM_TYPE_END;
+
+ struct rte_flow_item_template *it =
+ rte_flow_item_template_create(port, &itr, &items, &error);
+
+The concrete value to match on will be provided at the rule creation.
+
+Action templates
+^^^^^^^^^^^^^^^^
+
+The action template holds a list of action types to be used in flow rules.
+The mask parameter allows specifying a shared constant value for every rule.
+The action template may be used by multiple tables and must not be destroyed
+until all these tables are destroyed first.
+
+.. code-block:: c
+
+ struct rte_flow_action_template *
+ rte_flow_action_template_create(uint16_t port_id,
+ const struct rte_flow_action_template_attr *at_attr,
+ const struct rte_flow_action actions[],
+ const struct rte_flow_action masks[],
+ struct rte_flow_error *error);
+
+For example, to create an action template with the same Mark ID
+but different Queue Index for every rule:
+
+.. code-block:: c
+
+ struct rte_flow_action actions[] = {
+ /* Mark ID is constant (4) for every rule, Queue Index is unique */
+ [0] = {.type = RTE_FLOW_ACTION_TYPE_MARK,
+ .conf = &(struct rte_flow_action_mark){.id = 4}},
+ [1] = {.type = RTE_FLOW_ACTION_TYPE_QUEUE},
+ [2] = {.type = RTE_FLOW_ACTION_TYPE_END,},
+ };
+ struct rte_flow_action masks[] = {
+ /* Assign to MARK mask any non-zero value to make it constant */
+ [0] = {.type = RTE_FLOW_ACTION_TYPE_MARK,
+ .conf = &(struct rte_flow_action_mark){.id = 1}},
+ [1] = {.type = RTE_FLOW_ACTION_TYPE_QUEUE},
+ [2] = {.type = RTE_FLOW_ACTION_TYPE_END,},
+ };
+
+ struct rte_flow_action_template *at =
+ rte_flow_action_template_create(port, &atr, &actions, &masks, &error);
+
+The concrete value for Queue Index will be provided at the rule creation.
+
+Flow table
+^^^^^^^^^^
+
+A table combines a number of item and action templates along with shared flow
+rule attributes (group ID, priority and traffic direction). This way a PMD/HW
+can prepare all the resources needed for efficient flow rules creation in
+the datapath. To avoid any hiccups due to memory reallocation, the maximum
+number of flow rules is defined at table creation time. Any flow rule
+creation beyond the maximum table size is rejected. Application may create
+another table to accommodate more rules in this case.
+
+.. code-block:: c
+
+ struct rte_flow_table *
+ rte_flow_table_create(uint16_t port_id,
+ const struct rte_flow_table_attr *table_attr,
+ struct rte_flow_item_template *item_templates[],
+ uint8_t nb_item_templates,
+ struct rte_flow_action_template *action_templates[],
+ uint8_t nb_action_templates,
+ struct rte_flow_error *error);
+
+A table can be created only after the Flow Rules management is configured
+and item and action templates are created.
+
+.. code-block:: c
+
+ rte_flow_configure(port, *port_attr, *error);
+
+ struct rte_flow_item_template *it[0] =
+ rte_flow_item_template_create(port, &itr, &items, &error);
+ struct rte_flow_action_template *at[0] =
+ rte_flow_action_template_create(port, &atr, &actions, &masks, &error);
+
+ struct rte_flow_table *table =
+ rte_flow_table_create(port, *table_attr,
+ *it, nb_item_templates,
+ *at, nb_action_templates,
+ *error);
+
.. _flow_isolated_mode:
Flow isolated mode
@@ -58,6 +58,14 @@ New Features
* ethdev: Added ``rte_flow_configure`` API to configure Flow Management
library, allowing to pre-allocate some resources for better performance.
+* ethdev: Added ``rte_flow_table_create`` API to group flow rules with
+ the same flow attributes and common matching patterns and actions
+ defined by ``rte_flow_item_template_create`` and
+ ``rte_flow_action_template_create`` respectively.
+ Corresponding functions to destroy these entities are:
+ ``rte_flow_table_destroy``, ``rte_flow_item_template_destroy``
+ and ``rte_flow_action_template_destroy`` respectively.
+
Removed Items
-------------
@@ -1411,3 +1411,144 @@ rte_flow_configure(uint16_t port_id,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, rte_strerror(ENOTSUP));
}
+
+struct rte_flow_item_template *
+rte_flow_item_template_create(uint16_t port_id,
+ const struct rte_flow_item_template_attr *it_attr,
+ const struct rte_flow_item items[],
+ 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_item_template *template;
+
+ if (unlikely(!ops))
+ return NULL;
+ if (likely(!!ops->item_template_create)) {
+ template = ops->item_template_create(dev, it_attr,
+ items, error);
+ if (template == NULL)
+ flow_err(port_id, -rte_errno, error);
+ return template;
+ }
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+ return NULL;
+}
+
+int
+rte_flow_item_template_destroy(uint16_t port_id,
+ struct rte_flow_item_template *it,
+ 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);
+
+ if (unlikely(!ops))
+ return -rte_errno;
+ if (likely(!!ops->item_template_destroy)) {
+ return flow_err(port_id,
+ ops->item_template_destroy(dev, it, error),
+ error);
+ }
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+}
+
+struct rte_flow_action_template *
+rte_flow_action_template_create(uint16_t port_id,
+ const struct rte_flow_action_template_attr *at_attr,
+ const struct rte_flow_action actions[],
+ const struct rte_flow_action masks[],
+ 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_action_template *template;
+
+ if (unlikely(!ops))
+ return NULL;
+ if (likely(!!ops->action_template_create)) {
+ template = ops->action_template_create(dev, at_attr,
+ actions, masks, error);
+ if (template == NULL)
+ flow_err(port_id, -rte_errno, error);
+ return template;
+ }
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+ return NULL;
+}
+
+int
+rte_flow_action_template_destroy(uint16_t port_id,
+ struct rte_flow_action_template *at,
+ 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);
+
+ if (unlikely(!ops))
+ return -rte_errno;
+ if (likely(!!ops->action_template_destroy)) {
+ return flow_err(port_id,
+ ops->action_template_destroy(dev, at, error),
+ error);
+ }
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+}
+
+struct rte_flow_table *
+rte_flow_table_create(uint16_t port_id,
+ const struct rte_flow_table_attr *table_attr,
+ struct rte_flow_item_template *item_templates[],
+ uint8_t nb_item_templates,
+ struct rte_flow_action_template *action_templates[],
+ uint8_t nb_action_templates,
+ 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_table *table;
+
+ if (unlikely(!ops))
+ return NULL;
+ if (likely(!!ops->table_create)) {
+ table = ops->table_create(dev, table_attr,
+ item_templates, nb_item_templates,
+ action_templates, nb_action_templates,
+ error);
+ if (table == NULL)
+ flow_err(port_id, -rte_errno, error);
+ return table;
+ }
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+ return NULL;
+}
+
+int
+rte_flow_table_destroy(uint16_t port_id,
+ struct rte_flow_table *table,
+ 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);
+
+ if (unlikely(!ops))
+ return -rte_errno;
+ if (likely(!!ops->table_destroy)) {
+ return flow_err(port_id,
+ ops->table_destroy(dev, table, error),
+ error);
+ }
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOTSUP));
+}
@@ -4916,6 +4916,275 @@ rte_flow_configure(uint16_t port_id,
const struct rte_flow_port_attr *port_attr,
struct rte_flow_error *error);
+/**
+ * Opaque type returned after successful creation of item template.
+ * This handle can be used to manage the created item template.
+ */
+struct rte_flow_item_template;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Flow item template attributes.
+ */
+__extension__
+struct rte_flow_item_template_attr {
+ /**
+ * Version of the struct layout, should be 0.
+ */
+ uint32_t version;
+ /**
+ * Relaxed matching policy, PMD may match only on items
+ * with mask member set and skip matching on protocol
+ * layers specified without any masks.
+ * If not set, PMD will match on protocol layers
+ * specified without any masks as well.
+ * Packet data must be stacked in the same order as the
+ * protocol layers to match inside packets,
+ * starting from the lowest.
+ */
+ uint32_t relaxed_matching:1;
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create item template.
+ * The item template defines common matching fields (item mask) without values.
+ * For example, matching on 5 tuple TCP flow, the template will be
+ * eth(null) + IPv4(source + dest) + TCP(s_port + d_port),
+ * while values for each rule will be set during the flow rule creation.
+ * The number and order of items in the template must be the same
+ * at the rule creation.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param[in] it_attr
+ * Item template attributes.
+ * @param[in] items
+ * Pattern specification (list terminated by the END pattern item).
+ * The spec member of an item is not used unless the end member is used.
+ * @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.
+ */
+__rte_experimental
+struct rte_flow_item_template *
+rte_flow_item_template_create(uint16_t port_id,
+ const struct rte_flow_item_template_attr *it_attr,
+ const struct rte_flow_item items[],
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy item template.
+ * This function may be called only when
+ * there are no more tables referencing this template.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param[in] it
+ * Handle of the template to be destroyed.
+ * @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_item_template_destroy(uint16_t port_id,
+ struct rte_flow_item_template *it,
+ struct rte_flow_error *error);
+
+/**
+ * Opaque type returned after successful creation of action template.
+ * This handle can be used to manage the created action template.
+ */
+struct rte_flow_action_template;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Flow action template attributes.
+ */
+struct rte_flow_action_template_attr {
+ /**
+ * Version of the struct layout, should be 0.
+ */
+ uint32_t version;
+ /* No attributes so far. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create action template.
+ * The action template holds a list of action types without values.
+ * For example, the template to change TCP ports is TCP(s_port + d_port),
+ * while values for each rule will be set during the flow rule creation.
+ * The number and order of actions in the template must be the same
+ * at the rule creation.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param[in] at_attr
+ * Template attributes.
+ * @param[in] actions
+ * Associated actions (list terminated by the END action).
+ * The spec member is only used if @p masks spec is non-zero.
+ * @param[in] masks
+ * List of actions that marks which of the action's member is constant.
+ * A mask has the same format as the corresponding action.
+ * If the action field in @p masks is not 0,
+ * the corresponding value in an action from @p actions will be the part
+ * of the template and used in all flow rules.
+ * The order of actions in @p masks is the same as in @p actions.
+ * In case of indirect actions present in @p actions,
+ * the actual action type should be present in @p mask.
+ * @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.
+ */
+__rte_experimental
+struct rte_flow_action_template *
+rte_flow_action_template_create(uint16_t port_id,
+ const struct rte_flow_action_template_attr *at_attr,
+ const struct rte_flow_action actions[],
+ const struct rte_flow_action masks[],
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy action template.
+ * This function may be called only when
+ * there are no more tables referencing this template.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param[in] at
+ * Handle to the template to be destroyed.
+ * @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_action_template_destroy(uint16_t port_id,
+ struct rte_flow_action_template *at,
+ struct rte_flow_error *error);
+
+
+/**
+ * Opaque type returned after successful creation of table.
+ * This handle can be used to manage the created table.
+ */
+struct rte_flow_table;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Table attributes.
+ */
+struct rte_flow_table_attr {
+ /**
+ * Version of the struct layout, should be 0.
+ */
+ uint32_t version;
+ /**
+ * Flow attributes that will be used in the table.
+ */
+ struct rte_flow_attr flow_attr;
+ /**
+ * Maximum number of flow rules that this table holds.
+ */
+ uint32_t nb_flows;
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create table.
+ * Table is a group of flow rules with the same flow attributes
+ * (group ID, priority and traffic direction) defined for it.
+ * The table holds multiple item and action templates to build a flow rule.
+ * Each rule is free to use any combination of item and action templates
+ * and specify particular values for items and actions it would like to change.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param[in] table_attr
+ * Table attributes.
+ * @param[in] item_templates
+ * Array of item templates to be used in this table.
+ * @param[in] nb_item_templates
+ * The number of item templates in the item_templates array.
+ * @param[in] action_templates
+ * Array of action templates to be used in this table.
+ * @param[in] nb_action_templates
+ * The number of action templates in the action_templates array.
+ * @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.
+ */
+__rte_experimental
+struct rte_flow_table *
+rte_flow_table_create(uint16_t port_id,
+ const struct rte_flow_table_attr *table_attr,
+ struct rte_flow_item_template *item_templates[],
+ uint8_t nb_item_templates,
+ struct rte_flow_action_template *action_templates[],
+ uint8_t nb_action_templates,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy table.
+ * This function may be called only when
+ * there are no more flow rules referencing this table.
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param[in] table
+ * Handle to the table to be destroyed.
+ * @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_table_destroy(uint16_t port_id,
+ struct rte_flow_table *table,
+ struct rte_flow_error *error);
+
#ifdef __cplusplus
}
#endif
@@ -157,6 +157,43 @@ struct rte_flow_ops {
(struct rte_eth_dev *dev,
const struct rte_flow_port_attr *port_attr,
struct rte_flow_error *err);
+ /** See rte_flow_item_template_create() */
+ struct rte_flow_item_template *(*item_template_create)
+ (struct rte_eth_dev *dev,
+ const struct rte_flow_item_template_attr *it_attr,
+ const struct rte_flow_item items[],
+ struct rte_flow_error *err);
+ /** See rte_flow_item_template_destroy() */
+ int (*item_template_destroy)
+ (struct rte_eth_dev *dev,
+ struct rte_flow_item_template *it,
+ struct rte_flow_error *err);
+ /** See rte_flow_action_template_create() */
+ struct rte_flow_action_template *(*action_template_create)
+ (struct rte_eth_dev *dev,
+ const struct rte_flow_action_template_attr *at_attr,
+ const struct rte_flow_action actions[],
+ const struct rte_flow_action masks[],
+ struct rte_flow_error *err);
+ /** See rte_flow_action_template_destroy() */
+ int (*action_template_destroy)
+ (struct rte_eth_dev *dev,
+ struct rte_flow_action_template *at,
+ struct rte_flow_error *err);
+ /** See rte_flow_table_create() */
+ struct rte_flow_table *(*table_create)
+ (struct rte_eth_dev *dev,
+ const struct rte_flow_table_attr *table_attr,
+ struct rte_flow_item_template *item_templates[],
+ uint8_t nb_item_templates,
+ struct rte_flow_action_template *action_templates[],
+ uint8_t nb_action_templates,
+ struct rte_flow_error *err);
+ /** See rte_flow_table_destroy() */
+ int (*table_destroy)
+ (struct rte_eth_dev *dev,
+ struct rte_flow_table *table,
+ struct rte_flow_error *err);
};
/**
@@ -259,6 +259,12 @@ EXPERIMENTAL {
# added in 22.03
rte_flow_configure;
+ rte_flow_item_template_create;
+ rte_flow_item_template_destroy;
+ rte_flow_action_template_create;
+ rte_flow_action_template_destroy;
+ rte_flow_table_create;
+ rte_flow_table_destroy;
};
INTERNAL {