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:
parent
bb71f7e0a3
commit
8b61dd99a1
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user