From: Viacheslav Galaktionov <viacheslav.galaktio...@oktetlabs.ru>

In sfc, MAE admin serves as a transfer proxy. In order to track which
ethdev is privileged, augment every independent switch port structure
with information about its MAE privilege.

Signed-off-by: Viacheslav Galaktionov <viacheslav.galaktio...@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <andrew.rybche...@oktetlabs.ru>
Reviewed-by: Andy Moreton <amore...@xilinx.com>
---
 doc/guides/rel_notes/release_21_11.rst |  1 +
 drivers/net/sfc/sfc.c                  |  4 ++
 drivers/net/sfc/sfc_flow.c             | 21 ++++++++
 drivers/net/sfc/sfc_mae.c              |  2 +
 drivers/net/sfc/sfc_switch.c           | 68 ++++++++++++++++++++++++--
 drivers/net/sfc/sfc_switch.h           | 11 +++++
 6 files changed, 104 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rel_notes/release_21_11.rst 
b/doc/guides/rel_notes/release_21_11.rst
index d35ca4fe82..ae0d2d1ffa 100644
--- a/doc/guides/rel_notes/release_21_11.rst
+++ b/doc/guides/rel_notes/release_21_11.rst
@@ -136,6 +136,7 @@ New Features
   Updated the Solarflare ``sfc_efx`` driver with changes including:
 
   * Added port representors support on SN1000 SmartNICs
+  * Added flow API transfer proxy support
 
 * **Updated Marvell cnxk crypto PMD.**
 
diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index f79f4d5ffc..431c42f508 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -25,6 +25,7 @@
 #include "sfc_kvargs.h"
 #include "sfc_tweak.h"
 #include "sfc_sw_stats.h"
+#include "sfc_switch.h"
 
 bool
 sfc_repr_supported(const struct sfc_adapter *sa)
@@ -1329,6 +1330,9 @@ sfc_unprobe(struct sfc_adapter *sa)
         */
        rte_eal_alarm_cancel(sfc_restart_if_required, sa);
 
+       sfc_mae_clear_switch_port(sa->mae.switch_domain_id,
+                                 sa->mae.switch_port_id);
+
        sfc_log_init(sa, "destroy nic");
        sa->nic = NULL;
        efx_nic_destroy(enp);
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index d57235f358..8096af5673 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -26,6 +26,7 @@
 #include "sfc_log.h"
 #include "sfc_dp_rx.h"
 #include "sfc_mae_counter.h"
+#include "sfc_switch.h"
 
 struct sfc_flow_ops_by_spec {
        sfc_flow_parse_cb_t     *parse;
@@ -2924,6 +2925,25 @@ sfc_flow_isolate(struct rte_eth_dev *dev, int enable,
        return ret;
 }
 
+static int
+sfc_flow_pick_transfer_proxy(struct rte_eth_dev *dev,
+                            uint16_t *transfer_proxy_port,
+                            struct rte_flow_error *error)
+{
+       struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
+       int ret;
+
+       ret = sfc_mae_get_switch_domain_admin(sa->mae.switch_domain_id,
+                                             transfer_proxy_port);
+       if (ret != 0) {
+               return rte_flow_error_set(error, ret,
+                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                                         NULL, NULL);
+       }
+
+       return 0;
+}
+
 const struct rte_flow_ops sfc_flow_ops = {
        .validate = sfc_flow_validate,
        .create = sfc_flow_create,
@@ -2936,6 +2956,7 @@ const struct rte_flow_ops sfc_flow_ops = {
        .tunnel_action_decap_release = sfc_flow_tunnel_action_decap_release,
        .tunnel_item_release = sfc_flow_tunnel_item_release,
        .get_restore_info = sfc_flow_tunnel_get_restore_info,
+       .pick_transfer_proxy = sfc_flow_pick_transfer_proxy,
 };
 
 void
diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 6a1385283b..455744c570 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -234,6 +234,8 @@ sfc_mae_attach(struct sfc_adapter *sa)
        /* RTE ethdev MPORT matches that of the entity for independent ports. */
        switch_port_request.ethdev_mportp = &entity_mport;
        switch_port_request.ethdev_port_id = sas->port_id;
+       switch_port_request.port_data.indep.mae_admin =
+               encp->enc_mae_admin == B_TRUE;
        rc = sfc_mae_assign_switch_port(mae->switch_domain_id,
                                        &switch_port_request,
                                        &mae->switch_port_id);
diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c
index dc5b9a676c..a28e861de5 100644
--- a/drivers/net/sfc/sfc_switch.c
+++ b/drivers/net/sfc/sfc_switch.c
@@ -93,6 +93,8 @@ struct sfc_mae_switch_domain {
        efx_pcie_interface_t                    *controllers;
        /** Number of DPDK controllers and EFX interfaces */
        size_t                                  nb_controllers;
+       /** MAE admin port */
+       struct sfc_mae_switch_port              *mae_admin_port;
 };
 
 TAILQ_HEAD(sfc_mae_switch_domains, sfc_mae_switch_domain);
@@ -454,13 +456,17 @@ sfc_mae_assign_switch_port(uint16_t switch_domain_id,
        port->ethdev_mport = *req->ethdev_mportp;
        port->ethdev_port_id = req->ethdev_port_id;
 
+       memcpy(&port->data, &req->port_data,
+              sizeof(port->data));
+
        switch (req->type) {
        case SFC_MAE_SWITCH_PORT_INDEPENDENT:
-               /* No data */
+               if (port->data.indep.mae_admin) {
+                       SFC_ASSERT(domain->mae_admin_port == NULL);
+                       domain->mae_admin_port = port;
+               }
                break;
        case SFC_MAE_SWITCH_PORT_REPRESENTOR:
-               memcpy(&port->data.repr, &req->port_data,
-                      sizeof(port->data.repr));
                break;
        default:
                SFC_ASSERT(B_FALSE);
@@ -478,6 +484,30 @@ sfc_mae_assign_switch_port(uint16_t switch_domain_id,
        return rc;
 }
 
+int
+sfc_mae_clear_switch_port(uint16_t switch_domain_id,
+                         uint16_t switch_port_id)
+{
+       struct sfc_mae_switch_domain *domain;
+
+       rte_spinlock_lock(&sfc_mae_switch.lock);
+
+       domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
+       if (domain == NULL) {
+               rte_spinlock_unlock(&sfc_mae_switch.lock);
+               return EINVAL;
+       }
+
+       if (domain->mae_admin_port != NULL &&
+           domain->mae_admin_port->id == switch_port_id) {
+               domain->mae_admin_port->data.indep.mae_admin = B_FALSE;
+               domain->mae_admin_port = NULL;
+       }
+
+       rte_spinlock_unlock(&sfc_mae_switch.lock);
+       return 0;
+}
+
 /* This function expects to be called only when the lock is held */
 static int
 sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id,
@@ -537,3 +567,35 @@ sfc_mae_switch_port_id_by_entity(uint16_t switch_domain_id,
 
        return rc;
 }
+
+static int
+sfc_mae_get_switch_domain_admin_locked(uint16_t switch_domain_id,
+                                      uint16_t *port_id)
+{
+       struct sfc_mae_switch_domain *domain;
+
+       SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
+
+       domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
+       if (domain == NULL)
+               return EINVAL;
+
+       if (domain->mae_admin_port != NULL) {
+               *port_id = domain->mae_admin_port->ethdev_port_id;
+               return 0;
+       }
+
+       return ENOENT;
+}
+
+int
+sfc_mae_get_switch_domain_admin(uint16_t switch_domain_id,
+                               uint16_t *port_id)
+{
+       int rc;
+
+       rte_spinlock_lock(&sfc_mae_switch.lock);
+       rc = sfc_mae_get_switch_domain_admin_locked(switch_domain_id, port_id);
+       rte_spinlock_unlock(&sfc_mae_switch.lock);
+       return rc;
+}
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
index a77d2e6f28..7917141038 100644
--- a/drivers/net/sfc/sfc_switch.h
+++ b/drivers/net/sfc/sfc_switch.h
@@ -34,6 +34,10 @@ enum sfc_mae_switch_port_type {
        SFC_MAE_SWITCH_PORT_REPRESENTOR,
 };
 
+struct sfc_mae_switch_port_indep_data {
+       bool                                    mae_admin;
+};
+
 struct sfc_mae_switch_port_repr_data {
        efx_pcie_interface_t                    intf;
        uint16_t                                pf;
@@ -41,6 +45,7 @@ struct sfc_mae_switch_port_repr_data {
 };
 
 union sfc_mae_switch_port_data {
+       struct sfc_mae_switch_port_indep_data   indep;
        struct sfc_mae_switch_port_repr_data    repr;
 };
 
@@ -94,6 +99,9 @@ int sfc_mae_assign_switch_port(uint16_t switch_domain_id,
                               const struct sfc_mae_switch_port_request *req,
                               uint16_t *switch_port_id);
 
+int sfc_mae_clear_switch_port(uint16_t switch_domain_id,
+                             uint16_t switch_port_id);
+
 int sfc_mae_switch_port_by_ethdev(uint16_t switch_domain_id,
                                  uint16_t ethdev_port_id,
                                  efx_mport_sel_t *mport_sel);
@@ -103,6 +111,9 @@ int sfc_mae_switch_port_id_by_entity(uint16_t 
switch_domain_id,
                                     enum sfc_mae_switch_port_type type,
                                     uint16_t *switch_port_id);
 
+int sfc_mae_get_switch_domain_admin(uint16_t switch_domain_id,
+                                   uint16_t *port_id);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.30.2

Reply via email to