net/sfc: add actions parsing stub to MAE backend
authorIvan Malov <ivan.malov@oktetlabs.ru>
Tue, 20 Oct 2020 09:12:55 +0000 (10:12 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 3 Nov 2020 22:24:24 +0000 (23:24 +0100)
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>
drivers/net/sfc/sfc_flow.c
drivers/net/sfc/sfc_flow.h
drivers/net/sfc/sfc_mae.c
drivers/net/sfc/sfc_mae.h

index f69dd6a..f4d53bf 100644 (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;
 }
 
index 164e9f9..7d15f47 100644 (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 */
index 42200c3..de2c6b2 100644 (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,
index 4c5bc4c..5727962 100644 (file)
 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