[dpdk-dev] [PATCH v2 13/62] net/sfc: add verify method to flow validate path
Andrew Rybchenko
arybchenko at solarflare.com
Tue Oct 20 11:12:53 CEST 2020
From: Ivan Malov <ivan.malov at oktetlabs.ru>
The new method is needed to make sure that a flow being
validated will have a chance to be accepted by the FW.
MAE-specific implementation of the method should
compare the class of a rule being validated with
the corresponding classes of active rules, and,
if no matches found, make a request to the FW.
Support for the latter will be added in future.
Signed-off-by: Ivan Malov <ivan.malov at oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko at solarflare.com>
Reviewed-by: Andy Moreton <amoreton at xilinx.com>
---
drivers/net/sfc/sfc_flow.c | 40 ++++++++++++++++++++
drivers/net/sfc/sfc_flow.h | 3 ++
drivers/net/sfc/sfc_mae.c | 75 ++++++++++++++++++++++++++++++++++++++
drivers/net/sfc/sfc_mae.h | 1 +
4 files changed, 119 insertions(+)
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index 634818cdf2..f69dd6ac5d 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -27,6 +27,7 @@
struct sfc_flow_ops_by_spec {
sfc_flow_parse_cb_t *parse;
+ sfc_flow_verify_cb_t *verify;
sfc_flow_cleanup_cb_t *cleanup;
sfc_flow_insert_cb_t *insert;
sfc_flow_remove_cb_t *remove;
@@ -39,6 +40,7 @@ static sfc_flow_remove_cb_t sfc_flow_filter_remove;
static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
.parse = sfc_flow_parse_rte_to_filter,
+ .verify = NULL,
.cleanup = NULL,
.insert = sfc_flow_filter_insert,
.remove = sfc_flow_filter_remove,
@@ -46,6 +48,7 @@ static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
static const struct sfc_flow_ops_by_spec sfc_flow_ops_mae = {
.parse = sfc_flow_parse_rte_to_mae,
+ .verify = sfc_mae_flow_verify,
.cleanup = sfc_mae_flow_cleanup,
.insert = NULL,
.remove = NULL,
@@ -2543,6 +2546,41 @@ sfc_flow_remove(struct sfc_adapter *sa, struct rte_flow *flow,
return rc;
}
+static int
+sfc_flow_verify(struct sfc_adapter *sa, struct rte_flow *flow,
+ struct rte_flow_error *error)
+{
+ const struct sfc_flow_ops_by_spec *ops;
+ int rc = 0;
+
+ ops = sfc_flow_get_ops_by_spec(flow);
+ if (ops == NULL) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "No backend to handle this flow");
+ return -rte_errno;
+ }
+
+ if (ops->verify != NULL) {
+ /*
+ * Use locking since verify method may need to
+ * access the list of already created rules.
+ */
+ sfc_adapter_lock(sa);
+ rc = ops->verify(sa, flow);
+ sfc_adapter_unlock(sa);
+ }
+
+ if (rc != 0) {
+ rte_flow_error_set(error, rc,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Failed to verify flow validity with FW");
+ return -rte_errno;
+ }
+
+ return 0;
+}
+
static int
sfc_flow_validate(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -2559,6 +2597,8 @@ sfc_flow_validate(struct rte_eth_dev *dev,
return -rte_errno;
rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
+ if (rc == 0)
+ rc = sfc_flow_verify(sa, flow, error);
sfc_flow_free(sa, flow);
diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h
index 03a68d8633..164e9f9a9a 100644
--- a/drivers/net/sfc/sfc_flow.h
+++ b/drivers/net/sfc/sfc_flow.h
@@ -159,6 +159,9 @@ typedef int (sfc_flow_parse_cb_t)(struct rte_eth_dev *dev,
struct rte_flow *flow,
struct rte_flow_error *error);
+typedef int (sfc_flow_verify_cb_t)(struct sfc_adapter *sa,
+ struct rte_flow *flow);
+
typedef void (sfc_flow_cleanup_cb_t)(struct sfc_adapter *sa,
struct rte_flow *flow);
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 7e4397762b..42200c3f7e 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -148,3 +148,78 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
fail_init_match_spec_action:
return rc;
}
+
+static bool
+sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
+ const efx_mae_match_spec_t *left,
+ const efx_mae_match_spec_t *right)
+{
+ bool have_same_class;
+ int rc;
+
+ rc = efx_mae_match_specs_class_cmp(sa->nic, left, right,
+ &have_same_class);
+
+ return (rc == 0) ? have_same_class : false;
+}
+
+static int
+sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
+ struct sfc_flow_spec_mae *spec)
+{
+ const struct rte_flow *entry;
+
+ TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {
+ const struct sfc_flow_spec *entry_spec = &entry->spec;
+ const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;
+ const efx_mae_match_spec_t *left = es_mae->match_spec;
+ const efx_mae_match_spec_t *right = spec->match_spec;
+
+ switch (entry_spec->type) {
+ case SFC_FLOW_SPEC_FILTER:
+ /* Ignore VNIC-level flows */
+ break;
+ case SFC_FLOW_SPEC_MAE:
+ if (sfc_mae_rules_class_cmp(sa, left, right))
+ return 0;
+ break;
+ default:
+ SFC_ASSERT(false);
+ }
+ }
+
+ sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
+ "support for inner frame pattern items is not guaranteed; "
+ "other than that, the items are valid from SW standpoint");
+ return 0;
+}
+
+/**
+ * Confirm that a given flow can be accepted by the FW.
+ *
+ * @param sa
+ * Software adapter context
+ * @param flow
+ * Flow to be verified
+ * @return
+ * Zero on success and non-zero in the case of error.
+ * A special value of EAGAIN indicates that the adapter is
+ * not in started state. This state is compulsory because
+ * it only makes sense to compare the rule class of the flow
+ * being validated with classes of the active rules.
+ * Such classes are wittingly supported by the FW.
+ */
+int
+sfc_mae_flow_verify(struct sfc_adapter *sa,
+ struct rte_flow *flow)
+{
+ struct sfc_flow_spec *spec = &flow->spec;
+ struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+
+ SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+ if (sa->state != SFC_ADAPTER_STARTED)
+ return EAGAIN;
+
+ return sfc_mae_action_rule_class_verify(sa, spec_mae);
+}
diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h
index 536dadd092..4c5bc4c6ce 100644
--- a/drivers/net/sfc/sfc_mae.h
+++ b/drivers/net/sfc/sfc_mae.h
@@ -46,6 +46,7 @@ int sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
const struct rte_flow_item pattern[],
struct sfc_flow_spec_mae *spec,
struct rte_flow_error *error);
+sfc_flow_verify_cb_t sfc_mae_flow_verify;
#ifdef __cplusplus
}
--
2.17.1
More information about the dev
mailing list