@@ -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.
@@ -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 *
@@ -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 " "
@@ -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,
@@ -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"
@@ -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);