In the case of VF <--> VF representor pairs, these flows can
only collect VF traffic, so let them use generic flow action
PORT_REPRESENTOR, as part of re-using generic flow mechanism.

Currently, it does not allow to access VF representors since
they have no unique HW logical ports (m-ports). They all sit
on the same (representor proxy) m-port, while demultiplexing
of traffic uses ingress (VF) m-port value in packet metadata.
Traffic from arbitrary sources cannot be identified this way.
But, for VF traffic, it should be right to make an exception.

Signed-off-by: Ivan Malov <ivan.ma...@arknetworks.am>
Reviewed-by: Andy Moreton <amore...@xilinx.com>
---
 drivers/net/sfc/sfc_mae.c            | 25 +++++++++++++++++++------
 drivers/net/sfc/sfc_repr.c           | 20 ++++++++++++++++----
 drivers/net/sfc/sfc_repr_proxy.c     | 15 +++++++++++++++
 drivers/net/sfc/sfc_repr_proxy_api.h |  3 +++
 drivers/net/sfc/sfc_switch.c         |  7 ++-----
 drivers/net/sfc/sfc_switch.h         | 10 ++++++++++
 6 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c
index 1928d58779..89fa75281f 100644
--- a/drivers/net/sfc/sfc_mae.c
+++ b/drivers/net/sfc/sfc_mae.c
@@ -1525,6 +1525,7 @@ sfc_mae_rule_parse_item_port_id(const struct 
rte_flow_item *item,
        const struct rte_flow_item_port_id *spec = NULL;
        const struct rte_flow_item_port_id *mask = NULL;
        efx_mport_sel_t mport_sel;
+       unsigned int type_mask;
        int rc;
 
        if (ctx_mae->match_mport_set) {
@@ -1556,8 +1557,10 @@ sfc_mae_rule_parse_item_port_id(const struct 
rte_flow_item *item,
                                          "The port ID is too large");
        }
 
+       type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
        rc = sfc_mae_switch_get_ethdev_mport(ctx_mae->sa->mae.switch_domain_id,
-                                            spec->id, &mport_sel);
+                                            spec->id, type_mask, &mport_sel);
        if (rc != 0) {
                return rte_flow_error_set(error, rc,
                                RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -1590,6 +1593,7 @@ sfc_mae_rule_parse_item_ethdev_based(const struct 
rte_flow_item *item,
        const struct rte_flow_item_ethdev *spec = NULL;
        const struct rte_flow_item_ethdev *mask = NULL;
        efx_mport_sel_t mport_sel;
+       unsigned int type_mask;
        int rc;
 
        if (ctx_mae->match_mport_set) {
@@ -1617,9 +1621,11 @@ sfc_mae_rule_parse_item_ethdev_based(const struct 
rte_flow_item *item,
 
        switch (item->type) {
        case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
+               type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
                rc = sfc_mae_switch_get_ethdev_mport(
                                ctx_mae->sa->mae.switch_domain_id,
-                               spec->port_id, &mport_sel);
+                               spec->port_id, type_mask, &mport_sel);
                if (rc != 0) {
                        return rte_flow_error_set(error, rc,
                                        RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -3529,6 +3535,7 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 {
        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
        struct sfc_mae *mae = &sa->mae;
+       unsigned int type_mask;
        efx_mport_sel_t mport;
        uint16_t port_id;
        int rc;
@@ -3538,8 +3545,10 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
 
        port_id = (conf->original != 0) ? sas->port_id : conf->id;
 
+       type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
        rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-                                            port_id, &mport);
+                                            port_id, type_mask, &mport);
        if (rc != 0) {
                sfc_err(sa, "failed to get m-port for the given ethdev 
(port_id=%u): %s",
                        port_id, strerror(rc));
@@ -3558,14 +3567,14 @@ sfc_mae_rule_parse_action_port_id(struct sfc_adapter 
*sa,
 static int
 sfc_mae_rule_parse_action_port_representor(struct sfc_adapter *sa,
                const struct rte_flow_action_ethdev *conf,
-               efx_mae_actions_t *spec)
+               unsigned int type_mask, efx_mae_actions_t *spec)
 {
        struct sfc_mae *mae = &sa->mae;
        efx_mport_sel_t mport;
        int rc;
 
        rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
-                                            conf->port_id, &mport);
+                                            conf->port_id, type_mask, &mport);
        if (rc != 0) {
                sfc_err(sa, "failed to get m-port for the given ethdev 
(port_id=%u): %s",
                        conf->port_id, strerror(rc));
@@ -3641,6 +3650,7 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
        const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
        const uint64_t rx_metadata = sa->negotiated_rx_metadata;
        efx_mae_actions_t *spec = ctx->spec;
+       unsigned int switch_port_type_mask;
        bool custom_error = B_FALSE;
        int rc = 0;
 
@@ -3757,8 +3767,11 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
        case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
                SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
                                       bundle->actions_mask);
+
+               switch_port_type_mask = 1U << SFC_MAE_SWITCH_PORT_INDEPENDENT;
+
                rc = sfc_mae_rule_parse_action_port_representor(sa,
-                               action->conf, spec);
+                               action->conf, switch_port_type_mask, spec);
                break;
        case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
                SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c
index d4134ec91b..6c7727d569 100644
--- a/drivers/net/sfc/sfc_repr.c
+++ b/drivers/net/sfc/sfc_repr.c
@@ -933,15 +933,26 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void 
*init_params)
        struct sfc_repr_shared *srs = sfc_repr_shared_by_eth_dev(dev);
        struct sfc_mae_switch_port_request switch_port_request;
        efx_mport_sel_t ethdev_mport_sel;
+       efx_mport_id_t proxy_mport_id;
        struct sfc_repr *sr;
        int ret;
 
        /*
-        * Currently there is no mport we can use for representor's
-        * ethdev. Use an invalid one for now. This way representors
-        * can be instantiated.
+        * For each representor, a driver-internal flow has to be installed
+        * in order to direct traffic coming from the represented entity to
+        * the "representor proxy". Such internal flows need to find ethdev
+        * mport by ethdev ID of the representors in question to specify in
+        * delivery action. So set the representor ethdev's mport to that
+        * of the "representor proxy" in below switch port request.
         */
-       efx_mae_mport_invalid(&ethdev_mport_sel);
+       sfc_repr_proxy_mport_alias_get(repr_data->pf_port_id, &proxy_mport_id);
+
+       ret = efx_mae_mport_by_id(&proxy_mport_id, &ethdev_mport_sel);
+       if (ret != 0) {
+               SFC_GENERIC_LOG(ERR,
+                       "%s() failed to get repr proxy mport by ID", __func__);
+               goto fail_get_selector;
+       }
 
        memset(&switch_port_request, 0, sizeof(switch_port_request));
        switch_port_request.type = SFC_MAE_SWITCH_PORT_REPRESENTOR;
@@ -1033,6 +1044,7 @@ sfc_repr_eth_dev_init(struct rte_eth_dev *dev, void 
*init_params)
 
 fail_create_port:
 fail_mae_assign_switch_port:
+fail_get_selector:
        SFC_GENERIC_LOG(ERR, "%s() failed: %s", __func__, rte_strerror(-ret));
        return ret;
 }
diff --git a/drivers/net/sfc/sfc_repr_proxy.c b/drivers/net/sfc/sfc_repr_proxy.c
index 4ba7683370..74c3494c35 100644
--- a/drivers/net/sfc/sfc_repr_proxy.c
+++ b/drivers/net/sfc/sfc_repr_proxy.c
@@ -1708,3 +1708,18 @@ sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t 
pf_port_id, uint16_t repr_id,
 
        return rc;
 }
+
+void
+sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id, efx_mport_id_t 
*mport_alias)
+{
+       const struct sfc_repr_proxy *rp;
+       struct sfc_adapter *sa;
+
+       sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
+       sfc_adapter_lock(sa);
+       rp = sfc_repr_proxy_by_adapter(sa);
+
+       memcpy(mport_alias, &rp->mport_alias, sizeof(*mport_alias));
+
+       sfc_adapter_unlock(sa);
+}
diff --git a/drivers/net/sfc/sfc_repr_proxy_api.h 
b/drivers/net/sfc/sfc_repr_proxy_api.h
index 1d38ab2451..07d79a50cb 100644
--- a/drivers/net/sfc/sfc_repr_proxy_api.h
+++ b/drivers/net/sfc/sfc_repr_proxy_api.h
@@ -46,6 +46,9 @@ int sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t 
repr_id);
 int sfc_repr_proxy_repr_entity_mac_addr_set(uint16_t pf_port_id,
                uint16_t repr_id, const struct rte_ether_addr *mac_addr);
 
+void sfc_repr_proxy_mport_alias_get(uint16_t pf_port_id,
+                                   efx_mport_id_t *mport_alias);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c
index 8f1ee97fa8..f80de4e889 100644
--- a/drivers/net/sfc/sfc_switch.c
+++ b/drivers/net/sfc/sfc_switch.c
@@ -551,6 +551,7 @@ sfc_mae_find_switch_port_by_ethdev(uint16_t 
switch_domain_id,
 int
 sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
                                uint16_t ethdev_port_id,
+                               unsigned int allowed_mae_switch_port_types,
                                efx_mport_sel_t *mport_sel)
 {
        struct sfc_mae_switch_port *port;
@@ -562,11 +563,7 @@ sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
        if (rc != 0)
                goto unlock;
 
-       if (port->type != SFC_MAE_SWITCH_PORT_INDEPENDENT) {
-               /*
-                * The ethdev is a "VF representor". It does not own
-                * a dedicated m-port suitable for use in flow rules.
-                */
+       if (((1U << port->type) & allowed_mae_switch_port_types) == 0) {
                rc = ENOTSUP;
                goto unlock;
        }
diff --git a/drivers/net/sfc/sfc_switch.h b/drivers/net/sfc/sfc_switch.h
index 62aea9b785..6a85ce4dcf 100644
--- a/drivers/net/sfc/sfc_switch.h
+++ b/drivers/net/sfc/sfc_switch.h
@@ -102,8 +102,18 @@ int sfc_mae_assign_switch_port(uint16_t switch_domain_id,
 int sfc_mae_clear_switch_port(uint16_t switch_domain_id,
                              uint16_t switch_port_id);
 
+/*
+ * For user flows, allowed_mae_switch_port_types can only contain bit
+ * SFC_MAE_SWITCH_PORT_INDEPENDENT, meaning that only those ethdevs
+ * that have their own MAE m-ports can be accessed by a port-based
+ * action. For driver-internal flows, this mask can also contain
+ * bit SFC_MAE_SWITCH_PORT_REPRESENTOR to allow VF traffic to be
+ * sent to the common MAE m-port of all such REPRESENTOR ports
+ * via a port-based action, for default switch interconnection.
+ */
 int sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
                                    uint16_t ethdev_port_id,
+                                   unsigned int allowed_mae_switch_port_types,
                                    efx_mport_sel_t *mport_sel);
 
 int sfc_mae_switch_get_entity_mport(uint16_t switch_domain_id,
-- 
2.30.2

Reply via email to