[PATCH 30/34] net/sfc: support indirect count action in transfer flows
Ivan Malov
ivan.malov at arknetworks.am
Thu Jun 1 21:55:34 CEST 2023
Indirect count action is useful to applications that
need to gather aggregated statistics for many flows.
Signed-off-by: Ivan Malov <ivan.malov at arknetworks.am>
Reviewed-by: Andy Moreton <amoreton at xilinx.com>
---
doc/guides/nics/features/sfc.ini | 1 +
doc/guides/nics/sfc_efx.rst | 2 +
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, 325 insertions(+), 1 deletion(-)
diff --git a/doc/guides/nics/features/sfc.ini b/doc/guides/nics/features/sfc.ini
index 19d4935ce6..15a97ce8cd 100644
--- a/doc/guides/nics/features/sfc.ini
+++ b/doc/guides/nics/features/sfc.ini
@@ -62,6 +62,7 @@ count = Y
dec_ttl = Y
drop = Y
flag = Y
+indirect = P
jump = P
mark = Y
of_dec_nw_ttl = Y
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/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 6f366c1b06..283f672d6d 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 d44e066493..9851690f58 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -4005,6 +4005,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,
@@ -4143,6 +4195,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",
@@ -4258,6 +4311,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);
@@ -4813,7 +4874,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");
@@ -4924,3 +4987,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
--
2.17.1
More information about the dev
mailing list