From: Andrey Vesnovaty <andrey.vesnovaty@gmail.com>
To: Thomas Monjalon <thomas@monjalon.net>,
Ferruh Yigit <ferruh.yigit@intel.com>,
Andrew Rybchenko <arybchenko@solarflare.com>,
Ori Kam <orika@mellanox.com>
Cc: dev@dpdk.org, Andrey Vesnovaty <andrey.vesnovaty@gmail.com>
Subject: [dpdk-dev] [RFC] add flow action context API
Date: Wed, 20 May 2020 12:18:01 +0300 [thread overview]
Message-ID: <20200520091801.30163-1-andrey.vesnovaty@gmail.com> (raw)
This commit introduces extension of DPDK flow action API enabling
modification of single rte_flow_action.
Motivation and example
===
Adding or removing one or more queues to RSS actions cloned in multiple
flow rules imposes per rule toll for current DPDK flow API; the scenario
requires for each flow sharing cloned RSS action:
- call `rte_flow_destroy()`
- call `rte_flow_create()` with modified RSS action
In order to prevent the overhead of multiple RSS flow rules reconfiguration
API for in-place flow action modification introduced in this commit.
Change description
===
Provide an API to create single rte_flow_action context to point/reference
rte_flow_action object contents from multiple rte_flow_rule objects.
Actually the introduced API makes action object shared and modification
of such an action effects all the rules referencing the action via context
(see struct rte_flow_action_ctx).
Action context lifetime
---
Once action context created (see rte_flow_action_ctx_create()) it can be
safely reused for:
- new flow rule creation
- action configuration/state modification
(see rte_flow_action_ctx_modify())
- action state query (see rte_flow_action_ctx_query())
Once rte_flow_action_ctx_destroy() called the destroyed action context
should not be used i.e. result of the usage undefined.
Action query
---
Provide separate API to query action shared by multiple flows via action
context detached from any specific flow. Taking a counter as an example:
query returns value virtually aggregated across all flow rules referencing
the counter object via action context.
PMD support
---
The support of introduced API is pure PMD specific design and
responsibility for each action type (see struct rte_flow_ops).
testpmd
===
In order to utilize introduced API testpmd cli may implement following
extension create/modify/destroy/query action context iaccordingly
flow action_ctx create {port_id} [index] {action}
flow action_ctx modify {port_id} {index} {action}
flow action_ctx destroy {port_id} {index}
flow action_ctx query {port_id} {index}
example
---
configure rss to queues 1 & 2
testpmd> flow action_ctx create 0 100 rss 1 2
create flow rule utilizing action context
testpmd> flow create 0 ingress \
pattern eth dst is 0c:42:a1:15:fd:ac / ipv6 / tcp / end \
actions ctx 100 end / end
add 2 more queues
testpmd> flow action_ctx modify 0 100 rss 1 2 3 4
Signed-off-by: Andrey Vesnovaty <andrey.vesnovaty@gmail.com>
---
lib/librte_ethdev/rte_ethdev_version.map | 6 +
lib/librte_ethdev/rte_flow.c | 85 ++++++++++++++
lib/librte_ethdev/rte_flow.h | 135 ++++++++++++++++++++++-
lib/librte_ethdev/rte_flow_driver.h | 22 ++++
4 files changed, 247 insertions(+), 1 deletion(-)
diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map
index 3f32fdecf..d005abc33 100644
--- a/lib/librte_ethdev/rte_ethdev_version.map
+++ b/lib/librte_ethdev/rte_ethdev_version.map
@@ -230,4 +230,10 @@ EXPERIMENTAL {
# added in 20.02
rte_flow_dev_dump;
+
+ # added in 20.08
+ rte_flow_action_ctx_create;
+ rte_flow_action_ctx_destoy;
+ rte_flow_action_ctx_modify;
+ rte_flow_action_ctx_query;
};
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 885a7ff9a..b03de1aef 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -1231,3 +1231,88 @@ rte_flow_dev_dump(uint16_t port_id, FILE *file, struct rte_flow_error *error)
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, rte_strerror(ENOSYS));
}
+
+void *
+rte_flow_action_ctx_create(uint16_t port_id,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ void *ctx;
+ const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
+
+ if (unlikely(!ops))
+ return NULL;
+ if (likely(!!ops->action_ctx_create)) {
+ ctx = ops->action_ctx_create(dev, action, error);
+ if (ctx == NULL)
+ flow_err(port_id, -rte_errno, error);
+ return ctx;
+ }
+ rte_flow_error_set(error, ENOSYS, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOSYS));
+ return NULL;
+}
+
+int
+rte_flow_action_ctx_destoy(uint16_t port_id,
+ void *ctx,
+ struct rte_flow_error *error)
+{
+ (void)(port_id);
+ (void)(ctx);
+ (void)(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_ctx_destroy))
+ return flow_err(port_id,
+ ops->action_ctx_destroy(dev, ctx, error),
+ error);
+ return rte_flow_error_set(error, ENOSYS,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOSYS));
+}
+
+int
+rte_flow_action_ctx_modify(uint16_t port_id,
+ void *ctx,
+ const void *action_conf,
+ 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_ctx_modify))
+ return flow_err(port_id, ops->action_ctx_modify(dev, ctx,
+ action_conf, error),
+ error);
+ return rte_flow_error_set(error, ENOSYS,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOSYS));
+}
+
+int
+rte_flow_action_ctx_query(uint16_t port_id,
+ const void *ctx,
+ void *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);
+
+ if (unlikely(!ops))
+ return -rte_errno;
+ if (likely(!!ops->action_ctx_query))
+ return flow_err(port_id, ops->action_ctx_query(dev, ctx,
+ data, error),
+ error);
+ return rte_flow_error_set(error, ENOSYS,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, rte_strerror(ENOSYS));
+}
diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index 5625dc491..e109a07c5 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -1643,7 +1643,8 @@ enum rte_flow_action_type {
/**
* Enables counters for this flow rule.
*
- * These counters can be retrieved and reset through rte_flow_query(),
+ * These counters can be retrieved and reset through rte_flow_query() or
+ * rte_flow_action_ctx_query() if the action referenced via context/id,
* see struct rte_flow_query_count.
*
* See struct rte_flow_action_count.
@@ -2051,6 +2052,16 @@ enum rte_flow_action_type {
* See struct rte_flow_action_set_dscp.
*/
RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP,
+
+ /**
+ * Describes action context.
+ *
+ * Enables multiple rules reference the same action by id/ctx.
+ *
+ * No action specific struct here (void*) since it can be any
+ * action type.
+ */
+ RTE_FLOW_ACTION_TYPE_CTX,
};
/**
@@ -3224,6 +3235,128 @@ rte_flow_conv(enum rte_flow_conv_op op,
const void *src,
struct rte_flow_error *error);
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create the action context pointing to the action via id/ctx.
+ *
+ * @param[in] port_id
+ * The port identifier of the Ethernet device.
+ * @param[in] action
+ * Action to be pointed via id/ctx.
+ * @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:
+ * - (ENOSYS) if underlying device does not support this functionality.
+ * - (EIO) if underlying device is removed.
+ * - (EINVAL) if *action* invalid.
+ * - (ENOTSUP) if *action* valid but unsupported.
+ */
+__rte_experimental
+void *
+rte_flow_action_ctx_create(uint16_t port_id,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroys the action pointed by action context.
+ *
+ * @param[in] port_id
+ * The port identifier of the Ethernet device.
+ * @param[in] ctx
+ * Describes id/ctx pinting to the action 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.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-ENOENT) if action pointed by *ctx* was not found.
+ * - (-ETOOMANYREFS) if action pointed by *ctx* still referenced by one or
+ * more rules
+ * rte_errno is also set.
+ */
+__rte_experimental
+int
+rte_flow_action_ctx_destoy(uint16_t port_id,
+ void *ctx,
+ struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Modifies inplace the action configuration pointed by action context
+ * created via rte_flow_action_ctx_create().
+ *
+ * @param[in] port_id
+ * The port identifier of the Ethernet device.
+ * @param[in] ctx
+ * Action ctx pointing to the action to be modified.
+ * @param[in] action_conf
+ * Action specification used to modify the action pointed by ctx.
+ * action_conf should be of same type with the action pointed by ctx,
+ * otherwise function behavior undefined.
+ * @param[out] error
+ * Perform verbose error reporting if not NULL. PMDs initialize this
+ * structure in case of error only.
+ * @return
+ * - (0) if success.
+ * - (-ENOSYS) if underlying device does not support this functionality.
+ * - (-EIO) if underlying device is removed.
+ * - (-EINVAL) if *action_conf* invalid.
+ * - (-ENOTSUP) if *action_conf* valid but unsupported.
+ * - (-ENOENT) if action pointed by *ctx* was not found.
+ * rte_errno is also set.
+ */
+__rte_experimental
+int
+rte_flow_action_ctx_modify(uint16_t port_id,
+ void *ctx,
+ const void *action_conf,
+ struct rte_flow_error *error);
+
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Query an existing action referenced via id/context.
+ *
+ * This function allows retrieving action-specific data such as counters.
+ * Data is gathered by special action which may be present/referenced in
+ * more than one flow rule definition.
+ *
+ * \see RTE_FLOW_ACTION_TYPE_COUNT
+ *
+ * @param port_id
+ * Port identifier of Ethernet device.
+ * @param[in] ctx
+ * Action ctx pointing to the action to query.
+ * @param[in, out] data
+ * Pointer to storage for the associated query data type.
+ * @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_ctx_query(uint16_t port_id,
+ const void *ctx,
+ void *data,
+ struct rte_flow_error *error);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/librte_ethdev/rte_flow_driver.h b/lib/librte_ethdev/rte_flow_driver.h
index 51a9a57a0..3e9a08857 100644
--- a/lib/librte_ethdev/rte_flow_driver.h
+++ b/lib/librte_ethdev/rte_flow_driver.h
@@ -101,6 +101,28 @@ struct rte_flow_ops {
(struct rte_eth_dev *dev,
FILE *file,
struct rte_flow_error *error);
+ /** See rte_flow_action_ctx_destoy() */
+ void *(*action_ctx_create)
+ (struct rte_eth_dev *dev,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error);
+ /** See rte_flow_action_ctx_create() */
+ int (*action_ctx_destroy)
+ (struct rte_eth_dev *dev,
+ void *ctx,
+ struct rte_flow_error *error);
+ /** See rte_flow_action_ctx_modify() */
+ int (*action_ctx_modify)
+ (struct rte_eth_dev *dev,
+ void *ctx,
+ const void *action_conf,
+ struct rte_flow_error *error);
+ /** See rte_flow_action_ctx_query() */
+ int (*action_ctx_query)
+ (struct rte_eth_dev *dev,
+ const void *ctx,
+ void *data,
+ struct rte_flow_error *error);
};
/**
--
2.26.2
next reply other threads:[~2020-05-20 9:18 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-20 9:18 Andrey Vesnovaty [this message]
2020-06-03 10:02 ` Thomas Monjalon
2020-06-04 11:12 ` Andrey Vesnovaty
2020-06-04 17:23 ` Thomas Monjalon
2020-06-05 8:30 ` Bruce Richardson
2020-06-05 8:33 ` Thomas Monjalon
2020-06-03 10:53 ` Jerin Jacob
2020-06-04 11:25 ` Andrey Vesnovaty
2020-06-04 12:36 ` Jerin Jacob
2020-06-04 15:57 ` Andrey Vesnovaty
2020-06-09 16:01 ` Jerin Jacob
2020-06-20 13:32 ` [dpdk-dev] [RFC v2 0/1] " Andrey Vesnovaty
2020-06-22 15:22 ` Thomas Monjalon
2020-06-22 17:09 ` Andrey Vesnovaty
2020-06-26 11:44 ` Jerin Jacob
2020-06-28 8:44 ` Andrey Vesnovaty
2020-06-28 13:42 ` Jerin Jacob
2020-06-29 10:22 ` Andrey Vesnovaty
2020-06-30 9:52 ` Jerin Jacob
2020-07-01 9:24 ` Andrey Vesnovaty
2020-07-01 10:34 ` Jerin Jacob
2020-06-20 13:32 ` [dpdk-dev] [RFC v2 1/1] add flow shared action API Andrey Vesnovaty
2020-07-02 0:24 ` Stephen Hemminger
2020-07-02 7:20 ` Ori Kam
2020-07-02 8:06 ` Andrey Vesnovaty
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200520091801.30163-1-andrey.vesnovaty@gmail.com \
--to=andrey.vesnovaty@gmail.com \
--cc=arybchenko@solarflare.com \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@intel.com \
--cc=orika@mellanox.com \
--cc=thomas@monjalon.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).