Skip to content

Commit

Permalink
net/sfc: add port representors infrastructure
Browse files Browse the repository at this point in the history
Provide minimal implementation for port representors that only can be
configured and can provide device information.

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>
  • Loading branch information
ol-igorrom authored and Ferruh Yigit committed Oct 12, 2021
1 parent 94ddd50 commit a62ec90
Show file tree
Hide file tree
Showing 8 changed files with 662 additions and 7 deletions.
13 changes: 12 additions & 1 deletion doc/guides/nics/sfc_efx.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ SFC EFX PMD has support for:

- SR-IOV PF

- Port representors (see :ref: switch_representation)


Non-supported Features
----------------------
Expand Down Expand Up @@ -382,7 +384,16 @@ boolean parameters value.
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.
Default is legacy, unless representors are specified, in which case switchdev
is chosen.

- ``representor`` parameter [list]

Instantiate port representor Ethernet devices for specified Virtual
Functions list.

It is a standard parameter whose format is described in
:ref:`ethernet_device_standard_device_arguments`.

- ``rx_datapath`` [auto|efx|ef10|ef10_essb] (default **auto**)

Expand Down
1 change: 1 addition & 0 deletions drivers/net/sfc/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,5 @@ sources = files(
'sfc_ef100_tx.c',
'sfc_service.c',
'sfc_repr_proxy.c',
'sfc_repr.c',
)
153 changes: 147 additions & 6 deletions drivers/net/sfc/sfc_ethdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "sfc_flow.h"
#include "sfc_dp.h"
#include "sfc_dp_rx.h"
#include "sfc_repr.h"
#include "sfc_sw_stats.h"

#define SFC_XSTAT_ID_INVALID_VAL UINT64_MAX
Expand Down Expand Up @@ -1964,6 +1965,10 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {
.pool_ops_supported = sfc_pool_ops_supported,
};

struct sfc_ethdev_init_data {
uint16_t nb_representors;
};

/**
* Duplicate a string in potentially shared memory required for
* multi-process support.
Expand Down Expand Up @@ -2243,7 +2248,7 @@ sfc_register_dp(void)
}

static int
sfc_parse_switch_mode(struct sfc_adapter *sa)
sfc_parse_switch_mode(struct sfc_adapter *sa, bool has_representors)
{
const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
const char *switch_mode = NULL;
Expand All @@ -2258,7 +2263,8 @@ sfc_parse_switch_mode(struct sfc_adapter *sa)

if (switch_mode == NULL) {
sa->switchdev = encp->enc_mae_supported &&
!encp->enc_datapath_cap_evb;
(!encp->enc_datapath_cap_evb ||
has_representors);
} else if (strcasecmp(switch_mode, SFC_KVARG_SWITCH_MODE_LEGACY) == 0) {
sa->switchdev = false;
} else if (strcasecmp(switch_mode,
Expand All @@ -2283,10 +2289,11 @@ sfc_parse_switch_mode(struct sfc_adapter *sa)
}

static int
sfc_eth_dev_init(struct rte_eth_dev *dev)
sfc_eth_dev_init(struct rte_eth_dev *dev, void *init_params)
{
struct sfc_adapter_shared *sas = sfc_adapter_shared_by_eth_dev(dev);
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct sfc_ethdev_init_data *init_data = init_params;
uint32_t logtype_main;
struct sfc_adapter *sa;
int rc;
Expand Down Expand Up @@ -2377,7 +2384,7 @@ sfc_eth_dev_init(struct rte_eth_dev *dev)
* Selecting a default switch mode requires the NIC to be probed and
* to have its capabilities filled in.
*/
rc = sfc_parse_switch_mode(sa);
rc = sfc_parse_switch_mode(sa, init_data->nb_representors > 0);
if (rc != 0)
goto fail_switch_mode;

Expand Down Expand Up @@ -2462,11 +2469,145 @@ static const struct rte_pci_id pci_id_sfc_efx_map[] = {
{ .vendor_id = 0 /* sentinel */ }
};

static int
sfc_parse_rte_devargs(const char *args, struct rte_eth_devargs *devargs)
{
struct rte_eth_devargs eth_da = { .nb_representor_ports = 0 };
int rc;

if (args != NULL) {
rc = rte_eth_devargs_parse(args, &eth_da);
if (rc != 0) {
SFC_GENERIC_LOG(ERR,
"Failed to parse generic devargs '%s'",
args);
return rc;
}
}

*devargs = eth_da;

return 0;
}

static int
sfc_eth_dev_create(struct rte_pci_device *pci_dev,
struct sfc_ethdev_init_data *init_data,
struct rte_eth_dev **devp)
{
struct rte_eth_dev *dev;
int rc;

rc = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
sizeof(struct sfc_adapter_shared),
eth_dev_pci_specific_init, pci_dev,
sfc_eth_dev_init, init_data);
if (rc != 0) {
SFC_GENERIC_LOG(ERR, "Failed to create sfc ethdev '%s'",
pci_dev->device.name);
return rc;
}

dev = rte_eth_dev_allocated(pci_dev->device.name);
if (dev == NULL) {
SFC_GENERIC_LOG(ERR, "Failed to find allocated sfc ethdev '%s'",
pci_dev->device.name);
return -ENODEV;
}

*devp = dev;

return 0;
}

static int
sfc_eth_dev_create_representors(struct rte_eth_dev *dev,
const struct rte_eth_devargs *eth_da)
{
struct sfc_adapter *sa;
unsigned int i;
int rc;

if (eth_da->nb_representor_ports == 0)
return 0;

sa = sfc_adapter_by_eth_dev(dev);

if (!sa->switchdev) {
sfc_err(sa, "cannot create representors in non-switchdev mode");
return -EINVAL;
}

if (!sfc_repr_available(sfc_sa2shared(sa))) {
sfc_err(sa, "cannot create representors: unsupported");

return -ENOTSUP;
}

for (i = 0; i < eth_da->nb_representor_ports; ++i) {
const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
efx_mport_sel_t mport_sel;

rc = efx_mae_mport_by_pcie_function(encp->enc_pf,
eth_da->representor_ports[i], &mport_sel);
if (rc != 0) {
sfc_err(sa,
"failed to get representor %u m-port: %s - ignore",
eth_da->representor_ports[i],
rte_strerror(-rc));
continue;
}

rc = sfc_repr_create(dev, eth_da->representor_ports[i],
sa->mae.switch_domain_id, &mport_sel);
if (rc != 0) {
sfc_err(sa, "cannot create representor %u: %s - ignore",
eth_da->representor_ports[i],
rte_strerror(-rc));
}
}

return 0;
}

static int sfc_eth_dev_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
struct rte_pci_device *pci_dev)
{
return rte_eth_dev_pci_generic_probe(pci_dev,
sizeof(struct sfc_adapter_shared), sfc_eth_dev_init);
struct sfc_ethdev_init_data init_data;
struct rte_eth_devargs eth_da;
struct rte_eth_dev *dev;
int rc;

if (pci_dev->device.devargs != NULL) {
rc = sfc_parse_rte_devargs(pci_dev->device.devargs->args,
&eth_da);
if (rc != 0)
return rc;
} else {
memset(&eth_da, 0, sizeof(eth_da));
}

init_data.nb_representors = eth_da.nb_representor_ports;

if (eth_da.nb_representor_ports > 0 &&
rte_eal_process_type() != RTE_PROC_PRIMARY) {
SFC_GENERIC_LOG(ERR,
"Create representors from secondary process not supported, dev '%s'",
pci_dev->device.name);
return -ENOTSUP;
}

rc = sfc_eth_dev_create(pci_dev, &init_data, &dev);
if (rc != 0)
return rc;

rc = sfc_eth_dev_create_representors(dev, &eth_da);
if (rc != 0) {
(void)rte_eth_dev_destroy(dev, sfc_eth_dev_uninit);
return rc;
}

return 0;
}

static int sfc_eth_dev_pci_remove(struct rte_pci_device *pci_dev)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/sfc/sfc_kvargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ sfc_kvargs_parse(struct sfc_adapter *sa)
struct rte_devargs *devargs = eth_dev->device->devargs;
const char **params = (const char *[]){
SFC_KVARG_SWITCH_MODE,
SFC_KVARG_REPRESENTOR,
SFC_KVARG_STATS_UPDATE_PERIOD_MS,
SFC_KVARG_PERF_PROFILE,
SFC_KVARG_RX_DATAPATH,
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/sfc/sfc_kvargs.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ extern "C" {
"[" SFC_KVARG_SWITCH_MODE_LEGACY "|" \
SFC_KVARG_SWITCH_MODE_SWITCHDEV "]"

#define SFC_KVARG_REPRESENTOR "representor"

#define SFC_KVARG_PERF_PROFILE "perf_profile"

#define SFC_KVARG_PERF_PROFILE_AUTO "auto"
Expand Down

0 comments on commit a62ec90

Please sign in to comment.