From: Vijay Kumar Srivastava Date: Wed, 3 Nov 2021 13:57:52 +0000 (+0530) Subject: vdpa/sfc: support MAC filter config X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=cfeed08a0b0c2e74a87f5300152c308e32d9db4f;p=dpdk.git vdpa/sfc: support MAC filter config Add support for unicast and broadcast MAC filter configuration. Signed-off-by: Vijay Kumar Srivastava Acked-by: Andrew Rybchenko Reviewed-by: Maxime Coquelin --- diff --git a/doc/guides/vdpadevs/sfc.rst b/doc/guides/vdpadevs/sfc.rst index d06c427309..512f23ed37 100644 --- a/doc/guides/vdpadevs/sfc.rst +++ b/doc/guides/vdpadevs/sfc.rst @@ -71,6 +71,10 @@ boolean parameters value. **vdpa** device will work as vdpa device and will be probed by vdpa/sfc driver. If this parameter is not specified then ef100 device will operate as network device. +- ``mac`` [mac address] + + Configures MAC address which would be used to setup MAC filters. + Dynamic Logging Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/drivers/vdpa/sfc/meson.build b/drivers/vdpa/sfc/meson.build index 458cfe3aa6..b55f9cd691 100644 --- a/drivers/vdpa/sfc/meson.build +++ b/drivers/vdpa/sfc/meson.build @@ -23,4 +23,5 @@ sources = files( 'sfc_vdpa_hw.c', 'sfc_vdpa_mcdi.c', 'sfc_vdpa_ops.c', + 'sfc_vdpa_filter.c', ) diff --git a/drivers/vdpa/sfc/sfc_vdpa.c b/drivers/vdpa/sfc/sfc_vdpa.c index 1eba114a3a..fccdd8c687 100644 --- a/drivers/vdpa/sfc/sfc_vdpa.c +++ b/drivers/vdpa/sfc/sfc_vdpa.c @@ -7,7 +7,9 @@ #include #include +#include #include +#include #include #include #include @@ -197,6 +199,31 @@ sfc_vdpa_register_logtype(const struct rte_pci_addr *pci_addr, return ret < 0 ? RTE_LOGTYPE_PMD : ret; } +static int +sfc_vdpa_kvargs_parse(struct sfc_vdpa_adapter *sva) +{ + struct rte_pci_device *pci_dev = sva->pdev; + struct rte_devargs *devargs = pci_dev->device.devargs; + /* + * To get the device class a mandatory param 'class' is being + * used so included SFC_EFX_KVARG_DEV_CLASS in the param list. + */ + const char **params = (const char *[]){ + RTE_DEVARGS_KEY_CLASS, + SFC_VDPA_MAC_ADDR, + NULL, + }; + + if (devargs == NULL) + return 0; + + sva->kvargs = rte_kvargs_parse(devargs->args, params); + if (sva->kvargs == NULL) + return -EINVAL; + + return 0; +} + static struct rte_pci_id pci_id_sfc_vdpa_efx_map[] = { { RTE_PCI_DEVICE(EFX_PCI_VENID_XILINX, EFX_PCI_DEVID_RIVERHEAD_VF) }, { .vendor_id = 0, /* sentinel */ }, @@ -239,6 +266,10 @@ sfc_vdpa_pci_probe(struct rte_pci_driver *pci_drv __rte_unused, if (ret != 0) goto fail_set_log_prefix; + ret = sfc_vdpa_kvargs_parse(sva); + if (ret != 0) + goto fail_kvargs_parse; + sfc_vdpa_log_init(sva, "entry"); sfc_vdpa_adapter_lock_init(sva); @@ -279,6 +310,7 @@ fail_hw_init: fail_vfio_setup: sfc_vdpa_adapter_lock_fini(sva); +fail_kvargs_parse: fail_set_log_prefix: rte_free(sva); diff --git a/drivers/vdpa/sfc/sfc_vdpa.h b/drivers/vdpa/sfc/sfc_vdpa.h index 83766e586d..b4d43a8dea 100644 --- a/drivers/vdpa/sfc/sfc_vdpa.h +++ b/drivers/vdpa/sfc/sfc_vdpa.h @@ -16,8 +16,29 @@ #include "sfc_vdpa_log.h" #include "sfc_vdpa_ops.h" +#define SFC_VDPA_MAC_ADDR "mac" #define SFC_VDPA_DEFAULT_MCDI_IOVA 0x200000000000 +/* Broadcast & Unicast MAC filters are supported */ +#define SFC_MAX_SUPPORTED_FILTERS 2 + +/* + * Get function-local index of the associated VI from the + * virtqueue number. Queue 0 is reserved for MCDI + */ +#define SFC_VDPA_GET_VI_INDEX(vq_num) (((vq_num) / 2) + 1) + +enum sfc_vdpa_filter_type { + SFC_VDPA_BCAST_MAC_FILTER = 0, + SFC_VDPA_UCAST_MAC_FILTER = 1, + SFC_VDPA_FILTER_NTYPE +}; + +typedef struct sfc_vdpa_filter_s { + int filter_cnt; + efx_filter_spec_t spec[SFC_MAX_SUPPORTED_FILTERS]; +} sfc_vdpa_filter_t; + /* Adapter private data */ struct sfc_vdpa_adapter { TAILQ_ENTRY(sfc_vdpa_adapter) next; @@ -30,6 +51,8 @@ struct sfc_vdpa_adapter { rte_spinlock_t lock; struct rte_pci_device *pdev; + struct rte_kvargs *kvargs; + efx_family_t family; efx_nic_t *nic; rte_spinlock_t nic_lock; @@ -44,6 +67,8 @@ struct sfc_vdpa_adapter { char log_prefix[SFC_VDPA_LOG_PREFIX_MAX]; uint32_t logtype_main; + sfc_vdpa_filter_t filters; + int vfio_group_fd; int vfio_dev_fd; int vfio_container_fd; @@ -81,6 +106,11 @@ sfc_vdpa_dma_free(struct sfc_vdpa_adapter *sva, efsys_mem_t *esmp); int sfc_vdpa_dma_map(struct sfc_vdpa_ops_data *vdpa_data, bool do_map); +int +sfc_vdpa_filter_remove(struct sfc_vdpa_ops_data *ops_data); +int +sfc_vdpa_filter_config(struct sfc_vdpa_ops_data *ops_data); + static inline struct sfc_vdpa_adapter * sfc_vdpa_adapter_by_dev_handle(void *dev_handle) { diff --git a/drivers/vdpa/sfc/sfc_vdpa_filter.c b/drivers/vdpa/sfc/sfc_vdpa_filter.c new file mode 100644 index 0000000000..6d884a572a --- /dev/null +++ b/drivers/vdpa/sfc/sfc_vdpa_filter.c @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020-2021 Xilinx, Inc. + */ + +#include +#include +#include + +#include "efx.h" +#include "efx_impl.h" +#include "sfc_vdpa.h" + +static inline int +sfc_vdpa_get_eth_addr(const char *key __rte_unused, + const char *value, void *extra_args) +{ + struct rte_ether_addr *mac_addr = extra_args; + + if (value == NULL || extra_args == NULL) + return -EINVAL; + + /* Convert string with Ethernet address to an ether_addr */ + rte_ether_unformat_addr(value, mac_addr); + + return 0; +} + +static int +sfc_vdpa_set_mac_filter(efx_nic_t *nic, efx_filter_spec_t *spec, + int qid, uint8_t *eth_addr) +{ + int rc; + + if (nic == NULL || spec == NULL) + return -1; + + spec->efs_priority = EFX_FILTER_PRI_MANUAL; + spec->efs_flags = EFX_FILTER_FLAG_RX; + spec->efs_dmaq_id = qid; + + rc = efx_filter_spec_set_eth_local(spec, EFX_FILTER_SPEC_VID_UNSPEC, + eth_addr); + if (rc != 0) + return rc; + + rc = efx_filter_insert(nic, spec); + if (rc != 0) + return rc; + + return rc; +} + +int sfc_vdpa_filter_config(struct sfc_vdpa_ops_data *ops_data) +{ + int rc; + int qid; + efx_nic_t *nic; + struct rte_ether_addr bcast_eth_addr; + struct rte_ether_addr ucast_eth_addr; + struct sfc_vdpa_adapter *sva = ops_data->dev_handle; + efx_filter_spec_t *spec; + + sfc_vdpa_log_init(sva, "entry"); + + nic = sva->nic; + + sfc_vdpa_log_init(sva, "process kvarg"); + + /* skip MAC filter configuration if mac address is not provided */ + if (rte_kvargs_count(sva->kvargs, SFC_VDPA_MAC_ADDR) == 0) { + sfc_vdpa_warn(sva, + "MAC address is not provided, skipping MAC Filter Config"); + return -1; + } + + rc = rte_kvargs_process(sva->kvargs, SFC_VDPA_MAC_ADDR, + &sfc_vdpa_get_eth_addr, + &ucast_eth_addr); + if (rc < 0) + return -1; + + /* create filters on the base queue */ + qid = SFC_VDPA_GET_VI_INDEX(0); + + sfc_vdpa_log_init(sva, "insert broadcast mac filter"); + + EFX_MAC_BROADCAST_ADDR_SET(bcast_eth_addr.addr_bytes); + spec = &sva->filters.spec[SFC_VDPA_BCAST_MAC_FILTER]; + + rc = sfc_vdpa_set_mac_filter(nic, spec, qid, + bcast_eth_addr.addr_bytes); + if (rc != 0) + sfc_vdpa_err(ops_data->dev_handle, + "broadcast MAC filter insertion failed: %s", + rte_strerror(rc)); + else + sva->filters.filter_cnt++; + + sfc_vdpa_log_init(sva, "insert unicast mac filter"); + spec = &sva->filters.spec[SFC_VDPA_UCAST_MAC_FILTER]; + + rc = sfc_vdpa_set_mac_filter(nic, spec, qid, + ucast_eth_addr.addr_bytes); + if (rc != 0) + sfc_vdpa_err(sva, + "unicast MAC filter insertion failed: %s", + rte_strerror(rc)); + else + sva->filters.filter_cnt++; + + sfc_vdpa_log_init(sva, "done"); + + return rc; +} + +int sfc_vdpa_filter_remove(struct sfc_vdpa_ops_data *ops_data) +{ + int i, rc = 0; + struct sfc_vdpa_adapter *sva = ops_data->dev_handle; + efx_nic_t *nic; + + nic = sva->nic; + + for (i = 0; i < sva->filters.filter_cnt; i++) { + rc = efx_filter_remove(nic, &(sva->filters.spec[i])); + if (rc != 0) + sfc_vdpa_err(sva, + "remove HW filter failed for entry %d: %s", + i, rte_strerror(rc)); + } + + sva->filters.filter_cnt = 0; + + return rc; +} diff --git a/drivers/vdpa/sfc/sfc_vdpa_hw.c b/drivers/vdpa/sfc/sfc_vdpa_hw.c index 7911c5d933..fd1fee7e32 100644 --- a/drivers/vdpa/sfc/sfc_vdpa_hw.c +++ b/drivers/vdpa/sfc/sfc_vdpa_hw.c @@ -352,10 +352,20 @@ sfc_vdpa_hw_init(struct sfc_vdpa_adapter *sva) goto fail_virtio_init; } + sfc_vdpa_log_init(sva, "init filter"); + rc = efx_filter_init(enp); + if (rc != 0) { + sfc_vdpa_err(sva, "filter init failed: %s", rte_strerror(rc)); + goto fail_filter_init; + } + sfc_vdpa_log_init(sva, "done"); return 0; +fail_filter_init: + efx_virtio_fini(enp); + fail_virtio_init: efx_nic_fini(enp); diff --git a/drivers/vdpa/sfc/sfc_vdpa_ops.c b/drivers/vdpa/sfc/sfc_vdpa_ops.c index 40e2d1e71e..4d8e675905 100644 --- a/drivers/vdpa/sfc/sfc_vdpa_ops.c +++ b/drivers/vdpa/sfc/sfc_vdpa_ops.c @@ -421,6 +421,8 @@ sfc_vdpa_stop(struct sfc_vdpa_ops_data *ops_data) sfc_vdpa_disable_vfio_intr(ops_data); + sfc_vdpa_filter_remove(ops_data); + ops_data->state = SFC_VDPA_STATE_CONFIGURED; } @@ -460,12 +462,27 @@ sfc_vdpa_start(struct sfc_vdpa_ops_data *ops_data) goto fail_vq_start; } + ops_data->vq_count = i; + + sfc_vdpa_log_init(ops_data->dev_handle, + "configure MAC filters"); + rc = sfc_vdpa_filter_config(ops_data); + if (rc != 0) { + sfc_vdpa_err(ops_data->dev_handle, + "MAC filter config failed: %s", + rte_strerror(rc)); + goto fail_filter_cfg; + } + ops_data->state = SFC_VDPA_STATE_STARTED; sfc_vdpa_log_init(ops_data->dev_handle, "done"); return 0; +fail_filter_cfg: + /* remove already created filters */ + sfc_vdpa_filter_remove(ops_data); fail_vq_start: /* stop already started virtqueues */ for (j = 0; j < i; j++)