From patchwork Wed May 20 09:18:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Vesnovaty X-Patchwork-Id: 70465 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 408E6A0093; Wed, 20 May 2020 11:18:10 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 3117D1C439; Wed, 20 May 2020 11:18:09 +0200 (CEST) Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by dpdk.org (Postfix) with ESMTP id 91E951C437 for ; Wed, 20 May 2020 11:18:07 +0200 (CEST) Received: by mail-wm1-f68.google.com with SMTP id m12so1868956wmc.0 for ; Wed, 20 May 2020 02:18:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=3VHzLeIKtAs76E14eccIai320Gnw2LDVFmug2LsRLQQ=; b=DUrEnMSXIcwhH4jw+QlklMVH6mWfZin6yY5Ih6MYLd/6dITOVZl5faIsqYVVD8bgS8 T3pGlvKGfrV1LvWRkLneGrvc7Xs1q9VPieHyE9LPEn4J8uSwvhMJyJMxQBtTa2xOCO1z QACyp6b++oAgKO8PC3iDaF/EXvEwTa5UMOEIyhil7zH8URZ6YHfF97LK/K4ZwGzoYevd SOKq6927v6e8bLeaKhnTsrQtaMmihPfLyfQw5vgEiZGfDgAXTaklfMkqTvScjk1vWcXP MgmDiSUYyI21MxaoKTZNjaBVPE+IlsCGOe9vBiP2hvslmrms7JpZwxDfsTLUs1vAUnnS c4dA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=3VHzLeIKtAs76E14eccIai320Gnw2LDVFmug2LsRLQQ=; b=uba/59PMCysu6bkKpg1NP5xn4Y/jaZTl3Zle3OYqcqYSeuxXH3d2MkD6HE0I87esol BNM9XECjR4nBm5I0zIemfN8sL0O9x6N/nFOfOFZkJN+mX0Nqvg2jJ9X/IPoXMZx4cOi1 y1mdJhHHvmHpnwlSZO1FG3dNm4uLsyR3sfvJf8nFHyhLjfkvnTYWNjKndyhaLrqY8Q9J 32u48/TJsMQH91PRLcRKJZp0iQomdEDebu2Xicly7BEfN/eMwavsyH6A5hwUQpJcLMKB paldSTYiFrQdikqJLyDWfAAvZ6i5yjBe49W8S3VmUtThUvqEYmH9DHx09S6oUxof+z0n hQNw== X-Gm-Message-State: AOAM533QSzDX4rzD27Tw1MU7fD+XEmkFEsEEoDTz/20QD/VIfau3rtXg 8PL8fHN900SVcUsp3EGccs0= X-Google-Smtp-Source: ABdhPJwsNzZebUXh+/kbX2DyXshLLkCcRDNXXpc/BR0MXojgFbqAF8uEe3VTZ6DYyQdPLys/O7inkg== X-Received: by 2002:a7b:cd04:: with SMTP id f4mr3661591wmj.3.1589966287014; Wed, 20 May 2020 02:18:07 -0700 (PDT) Received: from r-arch-host11.mtr.labs.mlnx. ([37.142.13.130]) by smtp.gmail.com with ESMTPSA id g187sm2405230wmf.30.2020.05.20.02.18.04 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 20 May 2020 02:18:05 -0700 (PDT) From: Andrey Vesnovaty To: Thomas Monjalon , Ferruh Yigit , Andrew Rybchenko , Ori Kam Cc: dev@dpdk.org, Andrey Vesnovaty Date: Wed, 20 May 2020 12:18:01 +0300 Message-Id: <20200520091801.30163-1-andrey.vesnovaty@gmail.com> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 Subject: [dpdk-dev] [RFC] add flow action context API X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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 --- 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); }; /**