net/sfc: add verify method to flow validate path

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@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
This commit is contained in:
Ivan Malov 2020-10-20 10:12:53 +01:00 committed by Ferruh Yigit
parent bb71f7e0a3
commit 8b61dd99a1
4 changed files with 119 additions and 0 deletions

View File

@ -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);

View File

@ -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);

View File

@ -148,3 +148,78 @@ fail_parse_pattern:
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);
}

View File

@ -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
}