On 1/8/2018 2:37 PM, Remy Horton wrote:
> Port Representors provide a logical presentation in DPDK of VF (virtual
> function) ports for the purposes of control and monitoring. Each port
> representor device represents a single VF and is associated with it's
> parent physical function (PF) PMD which provides the back-end hooks for
> the representor device ops and defines the control domain to which that
> port belongs. This allows to use existing DPDK APIs to monitor and control
> the port without the need to create and maintain VF specific APIs.
>
> The library provides the broker infrastructure to be instantiated by
> base driver and corresponding methods to manage the broker
> infrastructure. The broker keeps records of list of representor PMDs.
> The library also provides methods to manage the representor PMDs by the
> broker.
>
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
> Signed-off-by: Remy Horton <remy.horton@intel.com>
<...>
> @@ -788,7 +795,6 @@ F: doc/guides/sample_app_ug/test_pipeline.rst
> F: examples/ip_pipeline/
> F: doc/guides/sample_app_ug/ip_pipeline.rst
>
> -
Can drop this. Two line break is intentional I think.
<...>
> @@ -820,3 +820,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y
> # Compile the eventdev application
> #
> CONFIG_RTE_APP_EVENTDEV=y
> +
> +#
> +# Compile representor PMD
> +#
> +CONFIG_RTE_LIBRTE_REPRESENTOR=y
Last section of the config is for apps, can you please group this with libraries?
> diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
> index 3492702..5020a40 100644
> --- a/doc/api/doxy-api-index.md
> +++ b/doc/api/doxy-api-index.md
> @@ -50,7 +50,8 @@ The public API headers are grouped by topics:
> [bitrate] (@ref rte_bitrate.h),
> [latency] (@ref rte_latencystats.h),
> [devargs] (@ref rte_devargs.h),
> - [PCI] (@ref rte_pci.h)
> + [PCI] (@ref rte_pci.h),
> + [Port Representor] (@ref rte_port_representor.h)
Since this is related to the ethdev, I would put this after rte_mtr.
<....>
> @@ -41,6 +41,15 @@ New Features
> Also, make sure to start the actual text at the margin.
> =========================================================
>
> +* **Added Port Representor functionality.**
> +
> + Port Representors provide a logical presentation in DPDK of VF (virtual
> + function) ports for the purposes of control and monitoring. Each port
> + representor device represents a single VF and is associated with it's
> + parent PF (physical function) PMD which provides the back-end hooks for
> + the representor device ops and defines the control domain to which that
> + port belongs.
> +
Can you please add new library to the "Shared Library Versions" section of the
release notes?
<...>
> @@ -0,0 +1,26 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2017 Intel Corporation. All rights reserved.
Can drop "All rights reserved." part, for all files.
<...>
> + RTE_LOG(INFO, EAL, "Registered [%s_%s] broker.\n", broker->bus,
> + broker->device);
Shouldn't use EAL type, this is a new library and it should dynamically register
its new type. Same for all log occurrence.
<...>
> + TAILQ_FOREACH(broker, &broker_list, next) {
> + if ((strcmp(broker->bus, bus) == 0) &&
> + (strcmp(broker->device, device) == 0))
> + break;
> + }
Is there any type of synchronization required to protect the list?
<...>
> +#define RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(ethdev, retval) do { \
> + if (!strstr(ethdev->data->name, RTE_PORT_REPRESENTOR_DEVICE_NAME)) { \
> + RTE_PMD_DEBUG_TRACE("port %d is not a representor port", \
RTE_PMD_DEBUG_TRACE prints in PMD type, please don't use it in this library.
<...>
> + RTE_LOG(INFO, PMD, "Creating representor for VF %i from %s\n",
> + vport_id, pf_addr_str);
Please don't use PMD type logs in library.
<...>
> + /* Allocate private ethdev data for Port Representor info */
> + rep_ethdev->data->dev_private = rte_malloc("rte_representor_port",
> + sizeof(struct rte_representor_port), 0);
> + if (rep_ethdev == NULL) {
> + RTE_LOG(ERR, PMD, "Unable to allocate Port Representor"
> + " private ethdev data\n");
> + rte_eth_dev_release_port(rep_ethdev);
free rep_ethdev->data->mac_addrs ?
> + return -ENOMEM;
> + }
> +
> + /* Allocate an rte_device & rte_driver for the ethdev. */
> + rep_port->rep_pcidev = rte_zmalloc_socket("rte_device",
> + sizeof(struct rte_device), 0, rte_socket_id());
> + if (rep_port->rep_pcidev == NULL) {
> + RTE_LOG(ERR, PMD, "Unable to allocate Port Representor"
> + " devive\n");
> + return -ENOMEM;
> + }
> + rep_port->rep_pcidrv = rte_zmalloc_socket("rte_driver",
> + sizeof(struct rte_driver), 0, rte_socket_id());
> + if (rep_port->rep_pcidrv == NULL) {
> + RTE_LOG(ERR, PMD, "Unable to allocate Port Representor"
> + " driver\n");
> + return -ENOMEM;
> + }
> + rep_port->rep_pcidrv->name = RTE_PORT_REPRESENTOR_DEVICE_NAME;
> + rep_port->rep_pcidev->driver = rep_port->rep_pcidrv;
> + rep_ethdev->device = rep_port->rep_pcidev;
> +
> + /* Register representor with broker */
> + RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(rep_ethdev, -EINVAL);
> + rep_port->vport_id = vport_id;
> + rep_port->ethdev = rep_ethdev;
> + rep_port->broker = broker;
> + rep_port->state = RTE_REPRESENTOR_PORT_VALID;
> + rep_ethdev->data->dev_private = rep_port;
If so why allocated rep_ethdev->data->dev_private a few lines above? Am I
missing something?
> +
> + RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_init, -ENOTSUP);
Do we need to free anything in case error?
> + retval = broker->ops->port_init(broker, rep_ethdev);
> + if (retval) {
> + rte_eth_dev_release_port(rep_ethdev);
Need to free allocated mem.
<...>
> + /* Free up representor */
> + RTE_FUNC_PTR_OR_ERR_RET(rep_port->broker->ops->port_uninit, -ENOTSUP);
> + rep_port->broker->ops->port_uninit(rep_port->broker, rep_port->ethdev);
> + rep_port->state = RTE_REPRESENTOR_PORT_INVALID;
> + rte_eth_dev_release_port(rep_port->ethdev);
I guess need to free data->mac_addrs too
<...>
> +/**
> + * Unregister a representor port, called during destruction of representor
> + * ethdev context. Freeing any allocated memory for the representor port.
> + *
> + * @param pf_addr_str Address of parent PF in Bus_DomBDF format
> + * @param vport_id Virtual port ID to deregister
> + *
> + * @return
> + * - 0 on success
> + * - errno on failure
> + */
> +int
> +rte_representor_port_unregister(char *pf_addr_str, uint32_t vport_id);
There was discussion about having new APIs as EXPERIMENTAL for a release, is it
agreed on. John, Luca do you remember?
<...>
> +struct rte_representor_broker {
> + TAILQ_ENTRY(rte_representor_broker) next;
> + /**< Next broker object in linked list */
> +
> + const char *bus; /**< bus name */
> + const char *device; /**< device name */
> +
> + uint16_t nb_virtual_ports;
> + /**< number of virtual ports supported by device */
> +
> + struct rte_representor_port *vports;
> + /**< Representor port contexts */
> +
> + struct rte_representor_broker_port_ops *ops;
> + /**< broker port operations functions */
> + void *private_data;
> + /**< broker private data */
Is this private_data used?
> +};
> +
> +/** Port Representor */
> +struct rte_representor_port {
> + uint16_t vport_id;
> + /**< Virtual Port Identifier */
> + struct rte_eth_dev *ethdev;
> + /**< ethdev handle of representor port */
> + struct rte_representor_broker *broker;
> + /**< Broker handle to allow reverse lookup */
> + enum {
> + RTE_REPRESENTOR_PORT_INVALID,
> + /**< No ethdev instantiated for virtual port */
> + RTE_REPRESENTOR_PORT_VALID
> + /**< ethdev active for virtual port */
> + } state;
What do you think moving enum decleration out of struct, for simplicity?
> + /**< port state */
> + void *priv_data;
> + /**< port private data */
> + /**< Representor ethdev device */
> + struct rte_device *rep_pcidev;
> + /**< Representor ethdev driver */
> + struct rte_driver *rep_pcidrv;
Is this only for pci bus? If not it can be good to rename.
@@ -775,6 +775,13 @@ F: doc/guides/prog_guide/pdump_lib.rst
F: app/pdump/
F: doc/guides/tools/pdump.rst
+Port Representors
+M: Declan Doherty <declan.doherty@intel.com>
+M: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_representor
+F: doc/guides/prog_guide/representor_lib.rst
+
Packet Framework
----------------
M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
@@ -788,7 +795,6 @@ F: doc/guides/sample_app_ug/test_pipeline.rst
F: examples/ip_pipeline/
F: doc/guides/sample_app_ug/ip_pipeline.rst
-
Algorithms
----------
@@ -820,3 +820,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y
# Compile the eventdev application
#
CONFIG_RTE_APP_EVENTDEV=y
+
+#
+# Compile representor PMD
+#
+CONFIG_RTE_LIBRTE_REPRESENTOR=y
@@ -50,7 +50,8 @@ The public API headers are grouped by topics:
[bitrate] (@ref rte_bitrate.h),
[latency] (@ref rte_latencystats.h),
[devargs] (@ref rte_devargs.h),
- [PCI] (@ref rte_pci.h)
+ [PCI] (@ref rte_pci.h),
+ [Port Representor] (@ref rte_port_representor.h)
- **device specific**:
[softnic] (@ref rte_eth_softnic.h),
@@ -70,6 +70,7 @@ INPUT = doc/api/doxy-api-index.md \
lib/librte_port \
lib/librte_power \
lib/librte_reorder \
+ lib/librte_representor \
lib/librte_ring \
lib/librte_sched \
lib/librte_security \
@@ -71,6 +71,7 @@ Programmer's Guide
power_man
packet_classif_access_ctrl
packet_framework
+ representor_lib
vhost_lib
metrics_lib
port_hotplug_framework
new file mode 100644
@@ -0,0 +1,62 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright(c) 2017 Intel Corporation. All rights reserved.
+
+.. _Representor_Library:
+
+Port Representor Library
+========================
+
+Port representors provide a logical presentation in DPDK of VF (virtual
+function) ports for the purposes of control and monitoring. Each port
+representor device represents a single VF and is associated with it's
+parent physical function (PF) PMD which provides the back-end hooks for
+the representor device ops and defines the control domain to which that
+port belongs. This allows to use existing DPDK APIs to monitor and control
+the port without the need to create and maintain VF specific APIs.
+
+Initialising the library
+------------------------
+
+Before port representors can be used, the port broker infrastructure
+has to be enabled within the EAL. This is done by passing the
+``--enable-representor`` EAL command-line parameter:
+
+.. code-block:: c
+
+ ./testpmd --enable-representor -- -i
+
+
+Registering a Port Representor
+------------------------------
+Before use, port representors have to be individually *registered*
+with the broker associated with the physical function. This requires
+the physical function's address in *DomBDF* (domain bus device function)
+format and the zero-based index of the virtual function. For instance, to
+create port representors for the first two virtual functions associated
+with physical function with device address ``0000:81:00.0`` on the PCI
+bus, the following code could be used:
+
+.. code-block:: c
+
+ uint16_t port_id_0;
+ uint16_t port_id_1;
+
+ rte_representor_port_register("pci_0000:81:00.0", 0, &port_id_0);
+ rte_representor_port_register("pci_0000:81:00.0", 1, &port_id_1);
+
+Upon successful registration, these functions return zero, and the
+passed-in pointer to integer is set to the ethdev port ID for the
+created port representor.
+
+Unregistering a Port Representor
+--------------------------------
+
+Unregistering a port representor that is no longer required uses the
+same parameters used to register it, namely the physical function address
+and virtual function index. There is no need for port representors to be
+unregistered in any particular order:
+
+.. code-block:: c
+
+ rte_representor_port_unregister("pci_0000:81:00.0", 0);
+ rte_representor_port_unregister("pci_0000:81:00.0", 1);
@@ -41,6 +41,15 @@ New Features
Also, make sure to start the actual text at the margin.
=========================================================
+* **Added Port Representor functionality.**
+
+ Port Representors provide a logical presentation in DPDK of VF (virtual
+ function) ports for the purposes of control and monitoring. Each port
+ representor device represents a single VF and is associated with it's
+ parent PF (physical function) PMD which provides the back-end hooks for
+ the representor device ops and defines the control domain to which that
+ port belongs.
+
API Changes
-----------
@@ -73,6 +73,9 @@ DEPDIRS-librte_distributor := librte_eal librte_mbuf librte_ether
DIRS-$(CONFIG_RTE_LIBRTE_PORT) += librte_port
DEPDIRS-librte_port := librte_eal librte_mempool librte_mbuf librte_ether
DEPDIRS-librte_port += librte_ip_frag librte_sched
+DIRS-$(CONFIG_RTE_LIBRTE_REPRESENTOR) += librte_representor
+DEPDIRS-librte_representor += librte_ether
+
ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
DEPDIRS-librte_port += librte_kni
endif
new file mode 100644
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation. All rights reserved.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_representor.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+EXPORT_MAP := rte_port_representor_version.map
+
+LIBABIVER := 1
+
+SRCS-$(CONFIG_RTE_LIBRTE_REPRESENTOR) += rte_port_representor.c
+
+#
+# Export include files
+#
+SYMLINK-$(CONFIG_RTE_LIBRTE_REPRESENTOR)-include += rte_port_representor.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_REPRESENTOR)-include += rte_port_representor_driver.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
new file mode 100644
@@ -0,0 +1,326 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#include <rte_port_representor.h>
+#include <rte_port_representor_driver.h>
+
+#include <rte_kvargs.h>
+
+TAILQ_HEAD(rte_broker_list, rte_representor_broker);
+
+struct rte_broker_list broker_list =
+ TAILQ_HEAD_INITIALIZER(broker_list);
+
+struct port_rep_parameters {
+ uint64_t vport_mask;
+ struct {
+ char bus[RTE_DEV_NAME_MAX_LEN];
+ char device[RTE_DEV_NAME_MAX_LEN];
+ } parent;
+};
+
+/* Macros to check for valid id */
+#define RTE_VERIFY_OR_ERR_RET(val, retval) do { \
+ if (!(val)) { \
+ RTE_PMD_DEBUG_TRACE("verify failed, ret= %d", (retval)); \
+ return retval; \
+ } \
+} while (0)
+
+#define RTE_VERIFY_OR_RET(val) do { \
+ if (!(val)) { \
+ RTE_PMD_DEBUG_TRACE("verify failed"); \
+ return; \
+ } \
+} while (0)
+
+int
+rte_representor_broker_init(struct rte_representor_broker *broker)
+{
+ RTE_VERIFY_OR_ERR_RET(broker, -ENODEV);
+
+ RTE_VERIFY_OR_ERR_RET(broker->bus && strlen(broker->bus), -ENXIO);
+ RTE_VERIFY_OR_ERR_RET(broker->device && strlen(broker->device), -ENXIO);
+
+ RTE_VERIFY_OR_ERR_RET(broker->nb_virtual_ports > 0, -EINVAL);
+
+ broker->vports = rte_malloc("rte_representor_ports",
+ sizeof(*(broker->vports)) * broker->nb_virtual_ports, 0);
+ if (broker->vports == NULL)
+ return -ENOMEM;
+
+ RTE_VERIFY_OR_ERR_RET(broker->ops, -EINVAL);
+
+ TAILQ_INSERT_TAIL(&broker_list, broker, next);
+ RTE_LOG(INFO, EAL, "Registered [%s_%s] broker.\n", broker->bus,
+ broker->device);
+
+ return 0;
+}
+
+int
+rte_representor_broker_uninit(struct rte_representor_broker *broker)
+{
+ int i;
+ struct rte_eth_dev *ethdev;
+ char name[RTE_DEV_NAME_MAX_LEN];
+
+ for (i = 0; i < broker->nb_virtual_ports; i++) {
+ if (broker->vports[i].state == RTE_REPRESENTOR_PORT_VALID) {
+ ethdev = broker->vports[i].ethdev;
+ rte_eth_dev_detach(ethdev->data->port_id,
+ name);
+ }
+ }
+
+ rte_free(broker->vports);
+
+ TAILQ_REMOVE(&broker_list, broker, next);
+ RTE_LOG(DEBUG, EAL, "Unregistered [%s_%s] broker.\n", broker->bus,
+ broker->device);
+
+ return 0;
+}
+
+struct rte_representor_broker *
+rte_representor_broker_find(const char *bus, const char *device)
+{
+ struct rte_representor_broker *broker = NULL;
+
+ TAILQ_FOREACH(broker, &broker_list, next) {
+ if ((strcmp(broker->bus, bus) == 0) &&
+ (strcmp(broker->device, device) == 0))
+ break;
+ }
+
+ return broker;
+}
+
+#define RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(ethdev, retval) do { \
+ if (!strstr(ethdev->data->name, RTE_PORT_REPRESENTOR_DEVICE_NAME)) { \
+ RTE_PMD_DEBUG_TRACE("port %d is not a representor port", \
+ ethdev->data.port_id); \
+ return retval; \
+ } \
+} while (0)
+
+#define RTE_REPRESENTOR_PORT_VALID_OR_RET_ERR(vport, retval) do { \
+ if (!(vport->state == RTE_REPRESENTOR_PORT_VALID)) { \
+ RTE_PMD_DEBUG_TRACE("Vport is not a representor port"); \
+ return retval; \
+ } \
+} while (0)
+
+static struct rte_representor_port *
+representor_port_find(struct rte_representor_broker *broker,
+ uint16_t vport_id)
+{
+ if (vport_id >= broker->nb_virtual_ports)
+ return NULL;
+
+ return &broker->vports[vport_id];
+}
+
+int
+rte_representor_port_register(char *pf_addr_str,
+ uint32_t vport_id, uint16_t *port_id)
+{
+ struct rte_eth_dev *rep_ethdev;
+ struct rte_representor_port *rep_port;
+ struct rte_representor_broker *broker;
+ char str_device_name[RTE_ETH_NAME_MAX_LEN];
+ int len_name;
+ int retval;
+ char *addr_delim;
+ int addr_len;
+ char addr_bus[RTE_ETH_NAME_MAX_LEN];
+ char addr_dev[RTE_ETH_NAME_MAX_LEN];
+
+ RTE_LOG(INFO, PMD, "Creating representor for VF %i from %s\n",
+ vport_id, pf_addr_str);
+
+ /* the parent param has to be provided with type_name formatted */
+ memset(addr_bus, 0, sizeof(addr_bus));
+ memset(addr_dev, 0, sizeof(addr_dev));
+ addr_delim = strchr(pf_addr_str, '_');
+ if (addr_delim) {
+ addr_len = addr_delim - pf_addr_str;
+ strncpy(addr_bus, pf_addr_str, addr_len);
+ strncpy(addr_dev, addr_delim + 1,
+ strlen(pf_addr_str) - addr_len);
+ } else {
+ RTE_LOG(ERR, PMD, "parent address '%s' has invalid format\n",
+ pf_addr_str);
+ return -EINVAL;
+ }
+
+ /* Fetch broker for PF */
+ broker = rte_representor_broker_find(addr_bus, addr_dev);
+ if (broker == NULL) {
+ RTE_LOG(ERR, PMD, "Unable to find broker for %s on bus %s\n",
+ addr_dev, addr_bus);
+ return -EINVAL;
+ }
+
+ /* Fetch representor slot for VF */
+ rep_port = representor_port_find(broker, vport_id);
+ if (rep_port == NULL) {
+ RTE_LOG(ERR, PMD, "vport_id %i exceeds number of VF ports %i",
+ vport_id, broker->nb_virtual_ports);
+ return -EINVAL;
+ }
+ if (rep_port->state == RTE_REPRESENTOR_PORT_VALID)
+ return -EEXIST;
+
+ /* Create representor ethdev */
+ len_name = snprintf(str_device_name, RTE_ETH_NAME_MAX_LEN, "%s.%s.%i",
+ RTE_PORT_REPRESENTOR_DEVICE_NAME, addr_dev, vport_id);
+ if (len_name == RTE_ETH_NAME_MAX_LEN) {
+ RTE_LOG(ERR, PMD, "Port Representor name"
+ " exceeds RTE_ETH_NAME_MAX_LEN\n");
+ return -EIO;
+ }
+ RTE_LOG(INFO, PMD, "Port Representor ethdev name: %s\n",
+ str_device_name);
+ rep_ethdev = rte_eth_dev_allocate(str_device_name);
+ if (rep_ethdev == NULL) {
+ RTE_LOG(ERR, PMD, "Unable to allocate Port Representor"
+ " ethdev\n");
+ return -ENOMEM;
+ }
+ rep_ethdev->data->mac_addrs = rte_malloc("representor_port_mac_addrs",
+ sizeof(struct ether_addr), 0);
+ if (rep_ethdev->data->mac_addrs == NULL) {
+ RTE_LOG(ERR, PMD, "Unable to allocate Port Representor"
+ " mac_addrs\n");
+ rte_eth_dev_release_port(rep_ethdev);
+ return -ENOMEM;
+ }
+
+ /* Allocate private ethdev data for Port Representor info */
+ rep_ethdev->data->dev_private = rte_malloc("rte_representor_port",
+ sizeof(struct rte_representor_port), 0);
+ if (rep_ethdev == NULL) {
+ RTE_LOG(ERR, PMD, "Unable to allocate Port Representor"
+ " private ethdev data\n");
+ rte_eth_dev_release_port(rep_ethdev);
+ return -ENOMEM;
+ }
+
+ /* Allocate an rte_device & rte_driver for the ethdev. */
+ rep_port->rep_pcidev = rte_zmalloc_socket("rte_device",
+ sizeof(struct rte_device), 0, rte_socket_id());
+ if (rep_port->rep_pcidev == NULL) {
+ RTE_LOG(ERR, PMD, "Unable to allocate Port Representor"
+ " devive\n");
+ return -ENOMEM;
+ }
+ rep_port->rep_pcidrv = rte_zmalloc_socket("rte_driver",
+ sizeof(struct rte_driver), 0, rte_socket_id());
+ if (rep_port->rep_pcidrv == NULL) {
+ RTE_LOG(ERR, PMD, "Unable to allocate Port Representor"
+ " driver\n");
+ return -ENOMEM;
+ }
+ rep_port->rep_pcidrv->name = RTE_PORT_REPRESENTOR_DEVICE_NAME;
+ rep_port->rep_pcidev->driver = rep_port->rep_pcidrv;
+ rep_ethdev->device = rep_port->rep_pcidev;
+
+ /* Register representor with broker */
+ RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(rep_ethdev, -EINVAL);
+ rep_port->vport_id = vport_id;
+ rep_port->ethdev = rep_ethdev;
+ rep_port->broker = broker;
+ rep_port->state = RTE_REPRESENTOR_PORT_VALID;
+ rep_ethdev->data->dev_private = rep_port;
+
+ RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_init, -ENOTSUP);
+ retval = broker->ops->port_init(broker, rep_ethdev);
+ if (retval) {
+ rte_eth_dev_release_port(rep_ethdev);
+ return retval;
+ }
+ RTE_LOG(INFO, EAL, "Registered port representor "
+ "<broker=%s_%s, vport_id=%u>\n",
+ broker->bus, broker->device, vport_id);
+
+ *port_id = rep_ethdev->data->port_id;
+ return 0;
+}
+
+int
+rte_representor_port_unregister(char *pf_addr_str, uint32_t vport_id)
+{
+ struct rte_representor_port *rep_port;
+ struct rte_representor_broker *broker;
+ char *addr_delim;
+ char addr_bus[RTE_ETH_NAME_MAX_LEN];
+ char addr_dev[RTE_ETH_NAME_MAX_LEN];
+ int addr_len;
+
+ RTE_LOG(INFO, PMD, "Deleting representor for VF %i from %s\n",
+ vport_id, pf_addr_str);
+
+ /* The parent param has to be provided with type_name formatted */
+ memset(addr_bus, 0, sizeof(addr_bus));
+ memset(addr_dev, 0, sizeof(addr_dev));
+ addr_delim = strchr(pf_addr_str, '_');
+ if (addr_delim) {
+ addr_len = addr_delim - pf_addr_str;
+ strncpy(addr_bus, pf_addr_str, addr_len);
+ strncpy(addr_dev, addr_delim + 1,
+ strlen(pf_addr_str) - addr_len);
+ } else {
+ RTE_LOG(ERR, PMD, "Parent address '%s' has invalid format\n",
+ pf_addr_str);
+ return -EINVAL;
+ }
+
+ /* Fetch broker for PF */
+ broker = rte_representor_broker_find(addr_bus, addr_dev);
+ if (broker == NULL) {
+ RTE_LOG(ERR, PMD, "Unable to find broker for %s on bus %s\n",
+ addr_dev, addr_bus);
+ return -EINVAL;
+ }
+
+ /* Fetch representor slot for VF */
+ rep_port = representor_port_find(broker, vport_id);
+ if (rep_port == NULL) {
+ RTE_LOG(ERR, PMD, "Unable to fetch Port Representor handle\n");
+ return -EINVAL;
+ }
+ if (rep_port->state != RTE_REPRESENTOR_PORT_VALID) {
+ RTE_LOG(ERR, PMD, "Representor vport %i is not active\n",
+ vport_id);
+ return -EINVAL;
+ }
+
+ /* Free up representor */
+ RTE_FUNC_PTR_OR_ERR_RET(rep_port->broker->ops->port_uninit, -ENOTSUP);
+ rep_port->broker->ops->port_uninit(rep_port->broker, rep_port->ethdev);
+ rep_port->state = RTE_REPRESENTOR_PORT_INVALID;
+ rte_eth_dev_release_port(rep_port->ethdev);
+
+ /* Cannot pass the pointers ethdev->device & ethdev->device->driver to
+ * rte_free() so have to store the allocated pointers in separate
+ * non-const variables.
+ */
+ rte_free(rep_port->rep_pcidrv);
+ rte_free(rep_port->rep_pcidev);
+
+ return 0;
+}
+
+int
+rte_representor_port_get_vport_id(struct rte_eth_dev *ethdev)
+{
+ struct rte_representor_port *port;
+
+ RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(ethdev, -EINVAL);
+
+ port = (struct rte_representor_port *)ethdev->data->dev_private;
+
+ return port->vport_id;
+}
new file mode 100644
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _RTE_PORT_REPRESENTOR_H_
+#define _RTE_PORT_REPRESENTOR_H_
+
+/**
+ * @file
+ * RTE Port Representor API
+ *
+ * Driver APIs for management and support of port representor
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_flow.h>
+
+struct rte_representor_port;
+struct rte_representor_broker;
+
+/**
+ * Registers a representor ethdev with the broker, allocating a port representor
+ * context and calling the representor port initialization function.
+ *
+ * @param pf_addr_str Address of parent PF in Bus_DomBDF format
+ * @param vport_id Virtual port ID to register ethdev against
+ * @param port_id Pointer to integer that receives port_id
+ *
+ * @return
+ * - 0 on successful registration and initialization of representor port
+ * - errno on failure
+ */
+int
+rte_representor_port_register(char *pf_addr_str,
+ uint32_t vport_id, uint16_t *port_id);
+
+/**
+ * Unregister a representor port, called during destruction of representor
+ * ethdev context. Freeing any allocated memory for the representor port.
+ *
+ * @param pf_addr_str Address of parent PF in Bus_DomBDF format
+ * @param vport_id Virtual port ID to deregister
+ *
+ * @return
+ * - 0 on success
+ * - errno on failure
+ */
+int
+rte_representor_port_unregister(char *pf_addr_str, uint32_t vport_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_PORT_REPRESENTOR_H_ */
new file mode 100644
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _RTE_PORT_REPRESENTOR_DRIVER_H_
+#define _RTE_PORT_REPRESENTOR_DRIVER_H_
+
+#include <rte_port_representor.h>
+
+/**
+ * @file
+ * RTE Port Representor Driver API
+ *
+ * Driver APIs for management and support of port representor
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_PORT_REPRESENTOR_DEVICE_NAME "net_representor"
+
+struct rte_representor_port;
+
+struct rte_representor_broker {
+ TAILQ_ENTRY(rte_representor_broker) next;
+ /**< Next broker object in linked list */
+
+ const char *bus; /**< bus name */
+ const char *device; /**< device name */
+
+ uint16_t nb_virtual_ports;
+ /**< number of virtual ports supported by device */
+
+ struct rte_representor_port *vports;
+ /**< Representor port contexts */
+
+ struct rte_representor_broker_port_ops *ops;
+ /**< broker port operations functions */
+ void *private_data;
+ /**< broker private data */
+};
+
+/** Port Representor */
+struct rte_representor_port {
+ uint16_t vport_id;
+ /**< Virtual Port Identifier */
+ struct rte_eth_dev *ethdev;
+ /**< ethdev handle of representor port */
+ struct rte_representor_broker *broker;
+ /**< Broker handle to allow reverse lookup */
+ enum {
+ RTE_REPRESENTOR_PORT_INVALID,
+ /**< No ethdev instantiated for virtual port */
+ RTE_REPRESENTOR_PORT_VALID
+ /**< ethdev active for virtual port */
+ } state;
+ /**< port state */
+ void *priv_data;
+ /**< port private data */
+ /**< Representor ethdev device */
+ struct rte_device *rep_pcidev;
+ /**< Representor ethdev driver */
+ struct rte_driver *rep_pcidrv;
+};
+
+typedef int (*representor_broker_port_init_t)(
+ struct rte_representor_broker *broker,
+ struct rte_eth_dev *ethdev);
+
+typedef int (*representor_broker_port_uninit_t)(
+ struct rte_representor_broker *broker,
+ struct rte_eth_dev *ethdev);
+
+struct rte_representor_broker_port_ops {
+ representor_broker_port_init_t port_init;
+ representor_broker_port_init_t port_uninit;
+};
+
+/**
+ * Initialize port representor broker
+ *
+ * This function is called by the PMDs initialization routine if the port
+ * representor is enabled by EAL command line argument.
+ *
+ * Verifies broker context parameters and initialises required resources.
+ *
+ * @param broker port representor broker context
+ *
+ * @return
+ * - 0 on success
+ * - errno on failure
+ */
+int
+rte_representor_broker_init(struct rte_representor_broker *broker);
+
+/**
+ * Un-initialize the port representor broker freeing all associated resources.
+ *
+ * @param broker port representor broker
+ *
+ * @return
+ * - 0 on success
+ * - errno on failure
+ */
+int
+rte_representor_broker_uninit(struct rte_representor_broker *broker);
+
+/**
+ * Fetch a port representor broker
+ *
+ * @param bus Bus parent PF is on
+ * @param device Address of PF
+ *
+ * @return
+ * - Pointer to port representor broker on success
+ * - NULL on failure
+ */
+struct rte_representor_broker *
+rte_representor_broker_find(const char *bus, const char *device);
+
+/**
+ * Get the virtual port ID of given representor port ethdev context
+ *
+ * @param ethdev Port representor ethdev handle
+ *
+ * @return
+ * - Virtual port ID
+ * - errno on failure
+ */
+int
+rte_representor_port_get_vport_id(struct rte_eth_dev *ethdev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_PORT_REPRESENTOR_DRIVER_H_ */
new file mode 100644
@@ -0,0 +1,8 @@
+DPDK_18.02 {
+ global:
+
+ rte_representor_port_register;
+ rte_representor_port_unregister;
+
+ local: *;
+};
@@ -104,6 +104,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal
_LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline
_LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder
_LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrte_sched
+_LDLIBS-$(CONFIG_RTE_LIBRTE_REPRESENTOR) += -lrte_representor
ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
_LDLIBS-$(CONFIG_RTE_LIBRTE_KNI) += -lrte_kni