net/sfc: add switch mode device argument
authorIgor Romanov <igor.romanov@oktetlabs.ru>
Mon, 11 Oct 2021 14:48:22 +0000 (17:48 +0300)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 12 Oct 2021 16:44:10 +0000 (18:44 +0200)
Add the argument that allows user to choose either switchdev or legacy
mode. Legacy mode enables switching by using Ethernet virtual bridging
(EVB) API. In switchdev mode, VF traffic goes via port representor
(if any) on PF, and software virtual switch (for example, Open vSwitch)
steers the traffic.

Signed-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
Reviewed-by: Ivan Malov <ivan.malov@oktetlabs.ru>
doc/guides/nics/sfc_efx.rst
drivers/net/sfc/sfc.h
drivers/net/sfc/sfc_ethdev.c
drivers/net/sfc/sfc_kvargs.c
drivers/net/sfc/sfc_kvargs.h
drivers/net/sfc/sfc_sriov.c

index 163bc25..d66cb76 100644 (file)
@@ -371,6 +371,19 @@ boolean parameters value.
   If this parameter is not specified then ef100 device will operate as
   network device.
 
+- ``switch_mode`` [legacy|switchdev] (see below for default)
+
+  In legacy mode, NIC firmware provides Ethernet virtual bridging (EVB) API
+  to configure switching inside NIC to deliver traffic to physical (PF) and
+  virtual (VF) PCI functions. PF driver is responsible to build the
+  infrastructure for VFs, and traffic goes to/from VF by default in accordance
+  with MAC address assigned, permissions and filters installed by VF drivers.
+  In switchdev mode VF traffic goes via port representor (if any) on PF, and
+  software virtual switch (for example, Open vSwitch) makes the decision.
+  Software virtual switch may install MAE rules to pass established traffic
+  flows via hardware and offload software datapath as the result.
+  Default is legacy.
+
 - ``rx_datapath`` [auto|efx|ef10|ef10_essb] (default **auto**)
 
   Choose receive datapath implementation.
index ace66d4..bb582d3 100644 (file)
@@ -335,6 +335,8 @@ struct sfc_adapter {
        boolean_t                       tso_encap;
 
        uint32_t                        rxd_wait_timeout_ns;
+
+       bool                            switchdev;
 };
 
 static inline struct sfc_adapter_shared *
index 6c8fd3a..60ca6f3 100644 (file)
@@ -2242,6 +2242,46 @@ sfc_register_dp(void)
        }
 }
 
+static int
+sfc_parse_switch_mode(struct sfc_adapter *sa)
+{
+       const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+       const char *switch_mode = NULL;
+       int rc;
+
+       sfc_log_init(sa, "entry");
+
+       rc = sfc_kvargs_process(sa, SFC_KVARG_SWITCH_MODE,
+                               sfc_kvarg_string_handler, &switch_mode);
+       if (rc != 0)
+               goto fail_kvargs;
+
+       if (switch_mode == NULL) {
+               sa->switchdev = encp->enc_mae_supported &&
+                               !encp->enc_datapath_cap_evb;
+       } else if (strcasecmp(switch_mode, SFC_KVARG_SWITCH_MODE_LEGACY) == 0) {
+               sa->switchdev = false;
+       } else if (strcasecmp(switch_mode,
+                             SFC_KVARG_SWITCH_MODE_SWITCHDEV) == 0) {
+               sa->switchdev = true;
+       } else {
+               sfc_err(sa, "invalid switch mode device argument '%s'",
+                       switch_mode);
+               rc = EINVAL;
+               goto fail_mode;
+       }
+
+       sfc_log_init(sa, "done");
+
+       return 0;
+
+fail_mode:
+fail_kvargs:
+       sfc_log_init(sa, "failed: %s", rte_strerror(rc));
+
+       return rc;
+}
+
 static int
 sfc_eth_dev_init(struct rte_eth_dev *dev)
 {
@@ -2329,6 +2369,14 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
        if (rc != 0)
                goto fail_probe;
 
+       /*
+        * Selecting a default switch mode requires the NIC to be probed and
+        * to have its capabilities filled in.
+        */
+       rc = sfc_parse_switch_mode(sa);
+       if (rc != 0)
+               goto fail_switch_mode;
+
        sfc_log_init(sa, "set device ops");
        rc = sfc_eth_dev_set_ops(dev);
        if (rc != 0)
@@ -2339,6 +2387,13 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
        if (rc != 0)
                goto fail_attach;
 
+       if (sa->switchdev && sa->mae.status != SFC_MAE_STATUS_SUPPORTED) {
+               sfc_err(sa,
+                       "failed to enable switchdev mode without MAE support");
+               rc = ENOTSUP;
+               goto fail_switchdev_no_mae;
+       }
+
        encp = efx_nic_cfg_get(sa->nic);
 
        /*
@@ -2353,10 +2408,14 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
        sfc_log_init(sa, "done");
        return 0;
 
+fail_switchdev_no_mae:
+       sfc_detach(sa);
+
 fail_attach:
        sfc_eth_dev_clear_ops(dev);
 
 fail_set_ops:
+fail_switch_mode:
        sfc_unprobe(sa);
 
 fail_probe:
@@ -2424,6 +2483,7 @@ RTE_PMD_REGISTER_PCI(net_sfc_efx, sfc_efx_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_sfc_efx, "* igb_uio | uio_pci_generic | vfio-pci");
 RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx,
+       SFC_KVARG_SWITCH_MODE "=" SFC_KVARG_VALUES_SWITCH_MODE " "
        SFC_KVARG_RX_DATAPATH "=" SFC_KVARG_VALUES_RX_DATAPATH " "
        SFC_KVARG_TX_DATAPATH "=" SFC_KVARG_VALUES_TX_DATAPATH " "
        SFC_KVARG_PERF_PROFILE "=" SFC_KVARG_VALUES_PERF_PROFILE " "
index 974c05e..cd16213 100644 (file)
@@ -22,6 +22,7 @@ sfc_kvargs_parse(struct sfc_adapter *sa)
        struct rte_eth_dev *eth_dev = (sa)->eth_dev;
        struct rte_devargs *devargs = eth_dev->device->devargs;
        const char **params = (const char *[]){
+               SFC_KVARG_SWITCH_MODE,
                SFC_KVARG_STATS_UPDATE_PERIOD_MS,
                SFC_KVARG_PERF_PROFILE,
                SFC_KVARG_RX_DATAPATH,
index ff76e7d..8e34ec9 100644 (file)
@@ -18,6 +18,14 @@ extern "C" {
 
 #define SFC_KVARG_VALUES_BOOL          "[1|y|yes|on|0|n|no|off]"
 
+#define SFC_KVARG_SWITCH_MODE_LEGACY   "legacy"
+#define SFC_KVARG_SWITCH_MODE_SWITCHDEV        "switchdev"
+
+#define SFC_KVARG_SWITCH_MODE          "switch_mode"
+#define SFC_KVARG_VALUES_SWITCH_MODE \
+       "[" SFC_KVARG_SWITCH_MODE_LEGACY "|" \
+           SFC_KVARG_SWITCH_MODE_SWITCHDEV "]"
+
 #define SFC_KVARG_PERF_PROFILE         "perf_profile"
 
 #define SFC_KVARG_PERF_PROFILE_AUTO            "auto"
index baa0242..385b172 100644 (file)
@@ -53,7 +53,7 @@ sfc_sriov_attach(struct sfc_adapter *sa)
        sfc_log_init(sa, "entry");
 
        sriov->num_vfs = pci_dev->max_vfs;
-       if (sriov->num_vfs == 0)
+       if (sa->switchdev || sriov->num_vfs == 0)
                goto done;
 
        vport_config = calloc(sriov->num_vfs + 1, sizeof(*vport_config));
@@ -110,6 +110,11 @@ sfc_sriov_vswitch_create(struct sfc_adapter *sa)
 
        sfc_log_init(sa, "entry");
 
+       if (sa->switchdev) {
+               sfc_log_init(sa, "don't create vswitch in switchdev mode");
+               goto done;
+       }
+
        if (sriov->num_vfs == 0) {
                sfc_log_init(sa, "no VFs enabled");
                goto done;
@@ -152,7 +157,7 @@ sfc_sriov_vswitch_destroy(struct sfc_adapter *sa)
 
        sfc_log_init(sa, "entry");
 
-       if (sriov->num_vfs == 0)
+       if (sa->switchdev || sriov->num_vfs == 0)
                goto done;
 
        rc = efx_evb_vswitch_destroy(sa->nic, sriov->vswitch);