net/sfc: implement flow insert/remove in MAE backend
authorIvan Malov <ivan.malov@oktetlabs.ru>
Tue, 20 Oct 2020 09:13:04 +0000 (10:13 +0100)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 3 Nov 2020 22:24:25 +0000 (23:24 +0100)
Exercise action set allocation / release and action rule
insertion / removal in order to let flow API callers
actually get created flows functioning.

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 f4d53bf..3af95ac 100644 (file)
@@ -50,8 +50,8 @@ 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,
+       .insert = sfc_mae_flow_insert,
+       .remove = sfc_mae_flow_remove,
 };
 
 static const struct sfc_flow_ops_by_spec *
@@ -1202,6 +1202,7 @@ sfc_flow_parse_attr(struct sfc_adapter *sa,
                spec_mae->priority = attr->priority;
                spec_mae->match_spec = NULL;
                spec_mae->action_set = NULL;
+               spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
        }
 
        return 0;
index 7d15f47..d3bdbd5 100644 (file)
@@ -67,6 +67,8 @@ struct sfc_flow_spec_mae {
        efx_mae_match_spec_t            *match_spec;
        /* Action set registry entry */
        struct sfc_mae_action_set       *action_set;
+       /* Firmware-allocated rule ID */
+       efx_mae_rule_id_t               rule_id;
 };
 
 /* Flow specification */
index 057eef5..ea15cca 100644 (file)
@@ -113,6 +113,8 @@ sfc_mae_action_set_add(struct sfc_adapter *sa,
        action_set->refcnt = 1;
        action_set->spec = spec;
 
+       action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
+
        TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
 
        *action_setp = action_set;
@@ -134,11 +136,62 @@ sfc_mae_action_set_del(struct sfc_adapter *sa,
        if (action_set->refcnt != 0)
                return;
 
+       SFC_ASSERT(action_set->fw_rsrc.aset_id.id == EFX_MAE_RSRC_ID_INVALID);
+       SFC_ASSERT(action_set->fw_rsrc.refcnt == 0);
+
        efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
        TAILQ_REMOVE(&mae->action_sets, action_set, entries);
        rte_free(action_set);
 }
 
+static int
+sfc_mae_action_set_enable(struct sfc_adapter *sa,
+                         struct sfc_mae_action_set *action_set)
+{
+       struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+       int rc;
+
+       SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+       if (fw_rsrc->refcnt == 0) {
+               SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
+               SFC_ASSERT(action_set->spec != NULL);
+
+               rc = efx_mae_action_set_alloc(sa->nic, action_set->spec,
+                                             &fw_rsrc->aset_id);
+               if (rc != 0)
+                       return rc;
+       }
+
+       ++(fw_rsrc->refcnt);
+
+       return 0;
+}
+
+static int
+sfc_mae_action_set_disable(struct sfc_adapter *sa,
+                          struct sfc_mae_action_set *action_set)
+{
+       struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+       int rc;
+
+       SFC_ASSERT(sfc_adapter_is_locked(sa));
+       SFC_ASSERT(fw_rsrc->aset_id.id != EFX_MAE_RSRC_ID_INVALID);
+       SFC_ASSERT(fw_rsrc->refcnt != 0);
+
+       if (fw_rsrc->refcnt == 1) {
+               rc = efx_mae_action_set_free(sa->nic, &fw_rsrc->aset_id);
+               if (rc != 0)
+                       return rc;
+
+               fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
+       }
+
+       --(fw_rsrc->refcnt);
+
+       return 0;
+}
+
 void
 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
                     struct rte_flow *flow)
@@ -156,6 +209,8 @@ sfc_mae_flow_cleanup(struct sfc_adapter *sa,
 
        spec_mae = &spec->mae;
 
+       SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
+
        if (spec_mae->action_set != NULL)
                sfc_mae_action_set_del(sa, spec_mae->action_set);
 
@@ -563,3 +618,56 @@ sfc_mae_flow_verify(struct sfc_adapter *sa,
 
        return sfc_mae_action_rule_class_verify(sa, spec_mae);
 }
+
+int
+sfc_mae_flow_insert(struct sfc_adapter *sa,
+                   struct rte_flow *flow)
+{
+       struct sfc_flow_spec *spec = &flow->spec;
+       struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+       struct sfc_mae_action_set *action_set = spec_mae->action_set;
+       struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
+       int rc;
+
+       SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
+       SFC_ASSERT(action_set != NULL);
+
+       rc = sfc_mae_action_set_enable(sa, action_set);
+       if (rc != 0)
+               goto fail_action_set_enable;
+
+       rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
+                                       NULL, &fw_rsrc->aset_id,
+                                       &spec_mae->rule_id);
+       if (rc != 0)
+               goto fail_action_rule_insert;
+
+       return 0;
+
+fail_action_rule_insert:
+       (void)sfc_mae_action_set_disable(sa, action_set);
+
+fail_action_set_enable:
+       return rc;
+}
+
+int
+sfc_mae_flow_remove(struct sfc_adapter *sa,
+                   struct rte_flow *flow)
+{
+       struct sfc_flow_spec *spec = &flow->spec;
+       struct sfc_flow_spec_mae *spec_mae = &spec->mae;
+       struct sfc_mae_action_set *action_set = spec_mae->action_set;
+       int rc;
+
+       SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
+       SFC_ASSERT(action_set != NULL);
+
+       rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
+       if (rc != 0)
+               return rc;
+
+       spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
+
+       return sfc_mae_action_set_disable(sa, action_set);
+}
index 1ef582e..d9f0ee3 100644 (file)
 extern "C" {
 #endif
 
+/** FW-allocatable resource context */
+struct sfc_mae_fw_rsrc {
+       unsigned int                    refcnt;
+       RTE_STD_C11
+       union {
+               efx_mae_aset_id_t       aset_id;
+       };
+};
+
 /** Action set registry entry */
 struct sfc_mae_action_set {
        TAILQ_ENTRY(sfc_mae_action_set) entries;
        unsigned int                    refcnt;
        efx_mae_actions_t               *spec;
+       struct sfc_mae_fw_rsrc          fw_rsrc;
 };
 
 TAILQ_HEAD(sfc_mae_action_sets, sfc_mae_action_set);
@@ -63,6 +73,8 @@ int sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
                               struct sfc_mae_action_set **action_setp,
                               struct rte_flow_error *error);
 sfc_flow_verify_cb_t sfc_mae_flow_verify;
+sfc_flow_insert_cb_t sfc_mae_flow_insert;
+sfc_flow_remove_cb_t sfc_mae_flow_remove;
 
 #ifdef __cplusplus
 }