From patchwork Wed Jun 7 13:02:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Malov X-Patchwork-Id: 128319 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8946842C4D; Wed, 7 Jun 2023 15:07:22 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 13CDA4300A; Wed, 7 Jun 2023 15:03:27 +0200 (CEST) Received: from agw.arknetworks.am (agw.arknetworks.am [79.141.165.80]) by mails.dpdk.org (Postfix) with ESMTP id DF04742C76 for ; Wed, 7 Jun 2023 15:03:03 +0200 (CEST) Received: from localhost.localdomain (unknown [78.109.69.83]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by agw.arknetworks.am (Postfix) with ESMTPSA id 679A0E1B5B; Wed, 7 Jun 2023 17:03:03 +0400 (+04) From: Ivan Malov To: dev@dpdk.org Cc: Andrew Rybchenko , Ferruh Yigit , Andy Moreton Subject: [PATCH v4 30/34] net/sfc: support indirect count action in transfer flows Date: Wed, 7 Jun 2023 17:02:41 +0400 Message-Id: <20230607130245.8048-31-ivan.malov@arknetworks.am> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230607130245.8048-1-ivan.malov@arknetworks.am> References: <20230601195538.8265-1-ivan.malov@arknetworks.am> <20230607130245.8048-1-ivan.malov@arknetworks.am> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Indirect count action is useful to applications that need to gather aggregated statistics for many flows. Signed-off-by: Ivan Malov Reviewed-by: Andy Moreton --- doc/guides/nics/sfc_efx.rst | 2 + doc/guides/rel_notes/release_23_07.rst | 3 + drivers/net/sfc/sfc.h | 1 + drivers/net/sfc/sfc_flow.c | 126 +++++++++++++++++++ drivers/net/sfc/sfc_flow.h | 14 +++ drivers/net/sfc/sfc_mae.c | 167 ++++++++++++++++++++++++- drivers/net/sfc/sfc_mae.h | 15 +++ 7 files changed, 327 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index 6e974c3720..ba82b02093 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -306,6 +306,8 @@ Supported actions (***transfer*** rules): - COUNT +- INDIRECT + - DROP Validating flow rules depends on the firmware variant. diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst index 6fae4eb0a7..5a77b71d0a 100644 --- a/doc/guides/rel_notes/release_23_07.rst +++ b/doc/guides/rel_notes/release_23_07.rst @@ -70,6 +70,9 @@ New Features The caller is responsible to request this offload only when the target header is an IPv4-based one. + * Added support for transfer flow action INDIRECT + with subtype COUNT, for aggregated statistics. + Removed Items ------------- diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h index 6b301aad60..f84a21009e 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -248,6 +248,7 @@ struct sfc_adapter { struct sfc_tbls hw_tables; struct sfc_repr_proxy repr_proxy; + struct sfc_flow_indir_actions flow_indir_actions; struct sfc_flow_list flow_list; unsigned int rxq_max; diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 0abeabfbf2..a35f20770d 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -2776,6 +2776,128 @@ sfc_flow_pick_transfer_proxy(struct rte_eth_dev *dev, return 0; } +static struct rte_flow_action_handle * +sfc_flow_action_handle_create(struct rte_eth_dev *dev, + const struct rte_flow_indir_action_conf *conf, + const struct rte_flow_action *action, + struct rte_flow_error *error) +{ + struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); + struct rte_flow_action_handle *handle; + int ret; + + if (!conf->transfer) { + rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "non-transfer domain does not support indirect actions"); + return NULL; + } + + if (conf->ingress || conf->egress) { + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "cannot combine ingress/egress with transfer"); + return NULL; + } + + handle = rte_zmalloc("sfc_rte_flow_action_handle", sizeof(*handle), 0); + if (handle == NULL) { + rte_flow_error_set(error, ENOMEM, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "failed to allocate memory"); + return NULL; + } + + sfc_adapter_lock(sa); + + ret = sfc_mae_indir_action_create(sa, action, handle, error); + if (ret != 0) { + sfc_adapter_unlock(sa); + rte_free(handle); + return NULL; + } + + TAILQ_INSERT_TAIL(&sa->flow_indir_actions, handle, entries); + + handle->transfer = (bool)conf->transfer; + + sfc_adapter_unlock(sa); + + return handle; +} + +static int +sfc_flow_action_handle_destroy(struct rte_eth_dev *dev, + struct rte_flow_action_handle *handle, + struct rte_flow_error *error) +{ + struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); + struct rte_flow_action_handle *entry; + int rc = EINVAL; + + sfc_adapter_lock(sa); + + TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) { + if (entry != handle) + continue; + + if (entry->transfer) { + rc = sfc_mae_indir_action_destroy(sa, handle, + error); + if (rc != 0) + goto exit; + } else { + SFC_ASSERT(B_FALSE); + } + + TAILQ_REMOVE(&sa->flow_indir_actions, entry, entries); + rte_free(entry); + goto exit; + } + + rc = rte_flow_error_set(error, ENOENT, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "indirect action handle not found"); + +exit: + sfc_adapter_unlock(sa); + return rc; +} + +static int +sfc_flow_action_handle_query(struct rte_eth_dev *dev, + const struct rte_flow_action_handle *handle, + void *data, struct rte_flow_error *error) +{ + struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev); + struct rte_flow_action_handle *entry; + int rc = EINVAL; + + sfc_adapter_lock(sa); + + TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) { + if (entry != handle) + continue; + + if (entry->transfer) { + rc = sfc_mae_indir_action_query(sa, handle, + data, error); + } else { + SFC_ASSERT(B_FALSE); + } + + goto exit; + } + + rc = rte_flow_error_set(error, ENOENT, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "indirect action handle not found"); + +exit: + sfc_adapter_unlock(sa); + return rc; +} + const struct rte_flow_ops sfc_flow_ops = { .validate = sfc_flow_validate, .create = sfc_flow_create, @@ -2783,6 +2905,9 @@ const struct rte_flow_ops sfc_flow_ops = { .flush = sfc_flow_flush, .query = sfc_flow_query, .isolate = sfc_flow_isolate, + .action_handle_create = sfc_flow_action_handle_create, + .action_handle_destroy = sfc_flow_action_handle_destroy, + .action_handle_query = sfc_flow_action_handle_query, .tunnel_decap_set = sfc_ft_decap_set, .tunnel_match = sfc_ft_match, .tunnel_action_decap_release = sfc_ft_action_decap_release, @@ -2796,6 +2921,7 @@ sfc_flow_init(struct sfc_adapter *sa) { SFC_ASSERT(sfc_adapter_is_locked(sa)); + TAILQ_INIT(&sa->flow_indir_actions); TAILQ_INIT(&sa->flow_list); } diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 8f706fc589..af94d0654a 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -88,6 +88,20 @@ struct sfc_flow_spec_mae { sfc_mae_conntrack_key_t ct_key; }; +/* PMD-specific definition of the opaque type from rte_flow.h */ +struct rte_flow_action_handle { + TAILQ_ENTRY(rte_flow_action_handle) entries; + + bool transfer; + enum rte_flow_action_type type; + + union { + struct sfc_mae_counter *counter; + }; +}; + +TAILQ_HEAD(sfc_flow_indir_actions, rte_flow_action_handle); + /* Flow specification */ struct sfc_flow_spec { /* Flow specification type (engine-based) */ diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c index 4d3778eaba..e79df3b56a 100644 --- a/drivers/net/sfc/sfc_mae.c +++ b/drivers/net/sfc/sfc_mae.c @@ -4003,6 +4003,58 @@ sfc_mae_rule_parse_action_count(struct sfc_adapter *sa, return rc; } +static int +sfc_mae_rule_parse_action_indirect(struct sfc_adapter *sa, + const struct rte_flow_action_handle *handle, + enum sfc_ft_rule_type ft_rule_type, + struct sfc_mae_aset_ctx *ctx, + struct rte_flow_error *error) +{ + struct rte_flow_action_handle *entry; + int rc; + + TAILQ_FOREACH(entry, &sa->flow_indir_actions, entries) { + if (entry == handle) { + sfc_dbg(sa, "attaching to indirect_action=%p", entry); + + switch (entry->type) { + case RTE_FLOW_ACTION_TYPE_COUNT: + if (ft_rule_type != SFC_FT_RULE_NONE) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "cannot use indirect count action in tunnel model"); + } + + if (ctx->counter != NULL) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "cannot have multiple actions COUNT in one flow"); + } + + rc = efx_mae_action_set_populate_count(ctx->spec); + if (rc != 0) { + return rte_flow_error_set(error, rc, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "failed to add COUNT to MAE action set"); + } + + ctx->counter = entry->counter; + ++(ctx->counter->refcnt); + break; + default: + SFC_ASSERT(B_FALSE); + break; + } + + return 0; + } + } + + return rte_flow_error_set(error, ENOENT, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "indirect action handle not found"); +} + static int sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa, const struct rte_flow_action_vf *vf_conf, @@ -4141,6 +4193,7 @@ static const char * const action_names[] = { [RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP", [RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = "VXLAN_ENCAP", [RTE_FLOW_ACTION_TYPE_COUNT] = "COUNT", + [RTE_FLOW_ACTION_TYPE_INDIRECT] = "INDIRECT", [RTE_FLOW_ACTION_TYPE_FLAG] = "FLAG", [RTE_FLOW_ACTION_TYPE_MARK] = "MARK", [RTE_FLOW_ACTION_TYPE_PF] = "PF", @@ -4256,6 +4309,14 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa, rc = sfc_mae_rule_parse_action_count(sa, action->conf, counterp, spec_ptr); break; + case RTE_FLOW_ACTION_TYPE_INDIRECT: + SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_INDIRECT, + bundle->actions_mask); + rc = sfc_mae_rule_parse_action_indirect(sa, action->conf, + spec_mae->ft_rule_type, + ctx, error); + custom_error = B_TRUE; + break; case RTE_FLOW_ACTION_TYPE_FLAG: SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG, bundle->actions_mask); @@ -4811,7 +4872,9 @@ sfc_mae_query_counter(struct sfc_adapter *sa, struct sfc_mae_counter *counter; int rc; - if (action_rule == NULL || action_rule->action_set->counter == NULL) { + if (action_rule == NULL || action_rule->action_set == NULL || + action_rule->action_set->counter == NULL || + action_rule->action_set->counter->indirect) { return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, action, "Queried flow rule does not have count actions"); @@ -4922,3 +4985,105 @@ sfc_mae_switchdev_fini(struct sfc_adapter *sa) sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_pf_to_ext); sfc_mae_repr_flow_destroy(sa, mae->switchdev_rule_ext_to_pf); } + +int +sfc_mae_indir_action_create(struct sfc_adapter *sa, + const struct rte_flow_action *action, + struct rte_flow_action_handle *handle, + struct rte_flow_error *error) +{ + int ret; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + SFC_ASSERT(handle != NULL); + + switch (action->type) { + case RTE_FLOW_ACTION_TYPE_COUNT: + ret = sfc_mae_rule_parse_action_count(sa, action->conf, + &handle->counter, NULL); + if (ret == 0) + handle->counter->indirect = true; + break; + default: + ret = ENOTSUP; + } + + if (ret != 0) { + return rte_flow_error_set(error, ret, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, + "failed to parse indirect action to mae object"); + } + + handle->type = action->type; + + return 0; +} + +int +sfc_mae_indir_action_destroy(struct sfc_adapter *sa, + const struct rte_flow_action_handle *handle, + struct rte_flow_error *error) +{ + SFC_ASSERT(sfc_adapter_is_locked(sa)); + SFC_ASSERT(handle != NULL); + + switch (handle->type) { + case RTE_FLOW_ACTION_TYPE_COUNT: + if (handle->counter->refcnt != 1) + goto fail; + + sfc_mae_counter_del(sa, handle->counter); + break; + default: + SFC_ASSERT(B_FALSE); + break; + } + + return 0; + +fail: + return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "indirect action is still in use"); +} + +int +sfc_mae_indir_action_query(struct sfc_adapter *sa, + const struct rte_flow_action_handle *handle, + void *data, struct rte_flow_error *error) +{ + int ret; + + SFC_ASSERT(sfc_adapter_is_locked(sa)); + SFC_ASSERT(handle != NULL); + + switch (handle->type) { + case RTE_FLOW_ACTION_TYPE_COUNT: + SFC_ASSERT(handle->counter != NULL); + + if (handle->counter->fw_rsrc.refcnt == 0) + goto fail_not_in_use; + + ret = sfc_mae_counter_get(&sa->mae.counter_registry.counters, + handle->counter, data); + if (ret != 0) + goto fail_counter_get; + + break; + default: + goto fail_unsup; + } + + return 0; + +fail_not_in_use: + return rte_flow_error_set(error, EIO, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "indirect action is not in use"); + +fail_counter_get: + return rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "failed to collect indirect action COUNT data"); + +fail_unsup: + return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "indirect action of this type cannot be queried"); +} diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h index c73ce0a5e6..e7b7d3a35e 100644 --- a/drivers/net/sfc/sfc_mae.h +++ b/drivers/net/sfc/sfc_mae.h @@ -84,6 +84,8 @@ struct sfc_mae_counter { struct sfc_ft_ctx *ft_ctx; struct sfc_mae_fw_rsrc fw_rsrc; + + bool indirect; }; TAILQ_HEAD(sfc_mae_counters, sfc_mae_counter); @@ -401,6 +403,19 @@ void sfc_mae_repr_flow_destroy(struct sfc_adapter *sa, struct rte_flow *flow); int sfc_mae_switchdev_init(struct sfc_adapter *sa); void sfc_mae_switchdev_fini(struct sfc_adapter *sa); +int sfc_mae_indir_action_create(struct sfc_adapter *sa, + const struct rte_flow_action *action, + struct rte_flow_action_handle *handle, + struct rte_flow_error *error); + +int sfc_mae_indir_action_destroy(struct sfc_adapter *sa, + const struct rte_flow_action_handle *handle, + struct rte_flow_error *error); + +int sfc_mae_indir_action_query(struct sfc_adapter *sa, + const struct rte_flow_action_handle *handle, + void *data, struct rte_flow_error *error); + #ifdef __cplusplus } #endif