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;
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,
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,
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,
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);
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);
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);
+}
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
}