From 662286ae61d29fc6fa26ce131f378ac8905eaff9 Mon Sep 17 00:00:00 2001 From: Ivan Malov Date: Tue, 20 Oct 2020 10:12:55 +0100 Subject: [PATCH] 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 Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton --- drivers/net/sfc/sfc_flow.c | 8 ++- drivers/net/sfc/sfc_flow.h | 2 + drivers/net/sfc/sfc_mae.c | 133 +++++++++++++++++++++++++++++++++++++ drivers/net/sfc/sfc_mae.h | 15 +++++ 4 files changed, 157 insertions(+), 1 deletion(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index f69dd6ac5d..f4d53bf770 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -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; } diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index 164e9f9a9a..7d15f47e60 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -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 */ diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c index 42200c3f7e..de2c6b26e4 100644 --- a/drivers/net/sfc/sfc_mae.c +++ b/drivers/net/sfc/sfc_mae.c @@ -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, diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h index 4c5bc4c6ce..5727962a0b 100644 --- a/drivers/net/sfc/sfc_mae.h +++ b/drivers/net/sfc/sfc_mae.h @@ -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 -- 2.20.1