From: Igor Romanov Date: Mon, 11 Oct 2021 14:48:22 +0000 (+0300) Subject: net/sfc: add switch mode device argument X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=f8778b16d1978c1161714cb01edb4af36fb073a0;p=dpdk.git net/sfc: add switch mode device argument 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 Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton Reviewed-by: Ivan Malov --- 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 ace66d435c..bb582d3aff 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -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 * diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index 6c8fd3a249..60ca6f3959 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -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 " " 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);