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:
parent
799889bada
commit
662286ae61
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user