[03/38] net/sfc: add switch mode device argument

Message ID 20210827065717.1838258-4-andrew.rybchenko@oktetlabs.ru (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series net/sfc: support port representors |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Andrew Rybchenko Aug. 27, 2021, 6:56 a.m. UTC
  From: Igor Romanov <igor.romanov@oktetlabs.ru>

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  | 13 +++++++++
 drivers/net/sfc/sfc.h        |  2 ++
 drivers/net/sfc/sfc_ethdev.c | 54 ++++++++++++++++++++++++++++++++++++
 drivers/net/sfc/sfc_kvargs.c |  1 +
 drivers/net/sfc/sfc_kvargs.h |  8 ++++++
 drivers/net/sfc/sfc_sriov.c  |  9 ++++--
 6 files changed, 85 insertions(+), 2 deletions(-)
  

Patch

diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst
index 163bc2533f..d66cb76dab 100644
--- a/doc/guides/nics/sfc_efx.rst
+++ b/doc/guides/nics/sfc_efx.rst
@@ -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.
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 331e06bac6..b045baca9e 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -313,6 +313,8 @@  struct sfc_adapter {
 	boolean_t			tso_encap;
 
 	uint32_t			rxd_wait_timeout_ns;
+
+	bool				switchdev;
 };
 
 static inline struct sfc_adapter_shared *
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index 2db0d000c3..41add341a0 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -2188,6 +2188,44 @@  sfc_register_dp(void)
 	}
 }
 
+static int
+sfc_parse_switch_mode(struct sfc_adapter *sa)
+{
+	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;
+
+	/* Check representors when supported */
+	if (switch_mode == NULL ||
+	    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)
 {
@@ -2270,6 +2308,10 @@  sfc_eth_dev_init(struct rte_eth_dev *dev)
 	sfc_adapter_lock_init(sa);
 	sfc_adapter_lock(sa);
 
+	rc = sfc_parse_switch_mode(sa);
+	if (rc != 0)
+		goto fail_switch_mode;
+
 	sfc_log_init(sa, "probing");
 	rc = sfc_probe(sa);
 	if (rc != 0)
@@ -2285,6 +2327,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);
 
 	/*
@@ -2299,6 +2348,9 @@  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);
 
@@ -2306,6 +2358,7 @@  sfc_eth_dev_init(struct rte_eth_dev *dev)
 	sfc_unprobe(sa);
 
 fail_probe:
+fail_switch_mode:
 	sfc_adapter_unlock(sa);
 	sfc_adapter_lock_fini(sa);
 	rte_free(dev->data->mac_addrs);
@@ -2370,6 +2423,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 " "
diff --git a/drivers/net/sfc/sfc_kvargs.c b/drivers/net/sfc/sfc_kvargs.c
index 974c05e68e..cd16213637 100644
--- a/drivers/net/sfc/sfc_kvargs.c
+++ b/drivers/net/sfc/sfc_kvargs.c
@@ -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,
diff --git a/drivers/net/sfc/sfc_kvargs.h b/drivers/net/sfc/sfc_kvargs.h
index ff76e7d9fc..8e34ec92a2 100644
--- a/drivers/net/sfc/sfc_kvargs.h
+++ b/drivers/net/sfc/sfc_kvargs.h
@@ -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"
diff --git a/drivers/net/sfc/sfc_sriov.c b/drivers/net/sfc/sfc_sriov.c
index baa0242433..385b172e2e 100644
--- a/drivers/net/sfc/sfc_sriov.c
+++ b/drivers/net/sfc/sfc_sriov.c
@@ -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);