net/sfc: add actions parsing stub to MAE backend

If parsing a flow results in an action set specification
identical to an already existing one, duplication will
be avoided by reusing the list entry of the latter.
Using an attach helper and a reference counter
is meant to serve the said purpose.

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:55 +01:00 committed by Ferruh Yigit
parent 799889bada
commit 662286ae61
4 changed files with 157 additions and 1 deletions

View File

@ -1201,6 +1201,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
spec->type = SFC_FLOW_SPEC_MAE;
spec_mae->priority = attr->priority;
spec_mae->match_spec = NULL;
spec_mae->action_set = NULL;
}
return 0;
@ -2428,7 +2429,7 @@ fail_bad_value:
static int
sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
const struct rte_flow_item pattern[],
__rte_unused const struct rte_flow_action actions[],
const struct rte_flow_action actions[],
struct rte_flow *flow,
struct rte_flow_error *error)
{
@ -2441,6 +2442,11 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
if (rc != 0)
return rc;
rc = sfc_mae_rule_parse_actions(sa, actions, &spec_mae->action_set,
error);
if (rc != 0)
return rc;
return 0;
}

View File

@ -65,6 +65,8 @@ struct sfc_flow_spec_mae {
unsigned int priority;
/* EFX match specification */
efx_mae_match_spec_t *match_spec;
/* Action set registry entry */
struct sfc_mae_action_set *action_set;
};
/* Flow specification */

View File

@ -43,6 +43,7 @@ sfc_mae_attach(struct sfc_adapter *sa)
mae->status = SFC_MAE_STATUS_SUPPORTED;
mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
TAILQ_INIT(&mae->action_sets);
sfc_log_init(sa, "done");
@ -76,6 +77,68 @@ sfc_mae_detach(struct sfc_adapter *sa)
sfc_log_init(sa, "done");
}
static struct sfc_mae_action_set *
sfc_mae_action_set_attach(struct sfc_adapter *sa,
const efx_mae_actions_t *spec)
{
struct sfc_mae_action_set *action_set;
struct sfc_mae *mae = &sa->mae;
SFC_ASSERT(sfc_adapter_is_locked(sa));
TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
if (efx_mae_action_set_specs_equal(action_set->spec, spec)) {
++(action_set->refcnt);
return action_set;
}
}
return NULL;
}
static int
sfc_mae_action_set_add(struct sfc_adapter *sa,
efx_mae_actions_t *spec,
struct sfc_mae_action_set **action_setp)
{
struct sfc_mae_action_set *action_set;
struct sfc_mae *mae = &sa->mae;
SFC_ASSERT(sfc_adapter_is_locked(sa));
action_set = rte_zmalloc("sfc_mae_action_set", sizeof(*action_set), 0);
if (action_set == NULL)
return ENOMEM;
action_set->refcnt = 1;
action_set->spec = spec;
TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
*action_setp = action_set;
return 0;
}
static void
sfc_mae_action_set_del(struct sfc_adapter *sa,
struct sfc_mae_action_set *action_set)
{
struct sfc_mae *mae = &sa->mae;
SFC_ASSERT(sfc_adapter_is_locked(sa));
SFC_ASSERT(action_set->refcnt != 0);
--(action_set->refcnt);
if (action_set->refcnt != 0)
return;
efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
TAILQ_REMOVE(&mae->action_sets, action_set, entries);
rte_free(action_set);
}
void
sfc_mae_flow_cleanup(struct sfc_adapter *sa,
struct rte_flow *flow)
@ -93,6 +156,9 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
spec_mae = &spec->mae;
if (spec_mae->action_set != NULL)
sfc_mae_action_set_del(sa, spec_mae->action_set);
if (spec_mae->match_spec != NULL)
efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
}
@ -149,6 +215,73 @@ fail_init_match_spec_action:
return rc;
}
static int
sfc_mae_rule_parse_action(const struct rte_flow_action *action,
__rte_unused efx_mae_actions_t *spec,
struct rte_flow_error *error)
{
switch (action->type) {
default:
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"Unsupported action");
}
return 0;
}
int
sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
const struct rte_flow_action actions[],
struct sfc_mae_action_set **action_setp,
struct rte_flow_error *error)
{
const struct rte_flow_action *action;
efx_mae_actions_t *spec;
int rc;
if (actions == NULL) {
return rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
"NULL actions");
}
rc = efx_mae_action_set_spec_init(sa->nic, &spec);
if (rc != 0)
goto fail_action_set_spec_init;
for (action = actions;
action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
rc = sfc_mae_rule_parse_action(action, spec, error);
if (rc != 0)
goto fail_rule_parse_action;
}
*action_setp = sfc_mae_action_set_attach(sa, spec);
if (*action_setp != NULL) {
efx_mae_action_set_spec_fini(sa->nic, spec);
return 0;
}
rc = sfc_mae_action_set_add(sa, spec, action_setp);
if (rc != 0)
goto fail_action_set_add;
return 0;
fail_action_set_add:
fail_rule_parse_action:
efx_mae_action_set_spec_fini(sa->nic, spec);
fail_action_set_spec_init:
if (rc > 0) {
rc = rte_flow_error_set(error, rc,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
NULL, "Failed to process the action");
}
return rc;
}
static bool
sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
const efx_mae_match_spec_t *left,

View File

@ -18,6 +18,15 @@
extern "C" {
#endif
/** Action set registry entry */
struct sfc_mae_action_set {
TAILQ_ENTRY(sfc_mae_action_set) entries;
unsigned int refcnt;
efx_mae_actions_t *spec;
};
TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
/** Options for MAE support status */
enum sfc_mae_status {
SFC_MAE_STATUS_UNKNOWN = 0,
@ -30,6 +39,8 @@ struct sfc_mae {
enum sfc_mae_status status;
/** Priority level limit for MAE action rules */
unsigned int nb_action_rule_prios_max;
/** Action set registry */
struct sfc_mae_action_sets action_sets;
};
struct sfc_adapter;
@ -46,6 +57,10 @@ 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);
int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
const struct rte_flow_action actions[],
struct sfc_mae_action_set **action_setp,
struct rte_flow_error *error);
sfc_flow_verify_cb_t sfc_mae_flow_verify;
#ifdef __cplusplus