DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag
@ 2017-11-17 14:42 Mohammad Abdul Awal
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs Mohammad Abdul Awal
                   ` (7 more replies)
  0 siblings, 8 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-11-17 14:42 UTC (permalink / raw)
  To: dev; +Cc: Mohammad Abdul Awal, Declan Doherty

switch_domain attribute has been added to specify that a rte_eth_dev
instance belongs to a switch domain in the software switch.

RTE_ETH_DEV_REPRESENTOR_PORT has been defined to specify that a
rte_eth_dev instance is a representor device.

Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Signed-off-by: Declan Doherty <declan.doherty@intel.com>
---
 lib/librte_ether/rte_ethdev.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 341c2d6..7e82c70 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1047,6 +1047,7 @@ struct rte_eth_dev_info {
 	/** Configured number of rx/tx queues */
 	uint16_t nb_rx_queues; /**< Number of RX queues. */
 	uint16_t nb_tx_queues; /**< Number of TX queues. */
+	uint16_t switch_domain; /**< Switch domain which port belongs to. */
 };
 
 /**
@@ -1810,6 +1811,7 @@ struct rte_eth_dev_data {
 	int numa_node;  /**< NUMA node connection */
 	struct rte_vlan_filter_conf vlan_filter_conf;
 	/**< VLAN filter configuration. */
+	uint16_t switch_domain; /**< Switch domain which port belongs to. */
 };
 
 /** Device supports link state interrupt */
@@ -1818,6 +1820,8 @@ struct rte_eth_dev_data {
 #define RTE_ETH_DEV_BONDED_SLAVE 0x0004
 /** Device supports device removal interrupt */
 #define RTE_ETH_DEV_INTR_RMV     0x0008
+/** Device is a port representor */
+#define RTE_ETH_DEV_REPRESENTOR_PORT 0x0010
 
 /**
  * @internal
-- 
2.7.4

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v2 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs
  2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
@ 2017-11-17 14:42 ` Mohammad Abdul Awal
  2017-11-17 23:03   ` Ferruh Yigit
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 3/6] eal: added --enable-representor command line argument in EAL to load representor broker infrastructure Mohammad Abdul Awal
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-11-17 14:42 UTC (permalink / raw)
  To: dev; +Cc: Mohammad Abdul Awal, Remy Horton, Declan Doherty

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: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Declan Doherty <declan.doherty@intel.com>
---
 config/common_base                                 |   5 +
 lib/Makefile                                       |   3 +
 lib/librte_representor/Makefile                    |  53 ++++++
 lib/librte_representor/rte_port_representor.c      | 212 +++++++++++++++++++++
 .../rte_port_representor_driver.h                  | 183 ++++++++++++++++++
 .../rte_port_representor_version.map               |  12 ++
 mk/rte.app.mk                                      |   1 +
 7 files changed, 469 insertions(+)
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

diff --git a/config/common_base b/config/common_base
index e74febe..febb80a 100644
--- a/config/common_base
+++ b/config/common_base
@@ -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
diff --git a/lib/Makefile b/lib/Makefile
index dc4e8df..b9202ff 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -101,6 +101,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
diff --git a/lib/librte_representor/Makefile b/lib/librte_representor/Makefile
new file mode 100644
index 0000000..09d29f7
--- /dev/null
+++ b/lib/librte_representor/Makefile
@@ -0,0 +1,53 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+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_driver.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_representor/rte_port_representor.c b/lib/librte_representor/rte_port_representor.c
new file mode 100644
index 0000000..f8debea
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.c
@@ -0,0 +1,212 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "rte_port_representor_driver.h"
+
+TAILQ_HEAD(rte_broker_list, rte_representor_broker);
+
+struct rte_broker_list broker_list =
+	TAILQ_HEAD_INITIALIZER(broker_list);
+
+/* 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 (!(ethdev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR_PORT)) { \
+		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("port %d is not a representor port", \
+				ethdev->data.port_id); \
+		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(struct rte_representor_broker *broker,
+		uint32_t vport_id, struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port;
+
+	int retval = 0;
+
+	RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(ethdev, -EINVAL);
+
+	port = representor_port_find(broker, vport_id);
+	if (port == NULL)
+		return -EINVAL;
+
+	if (port->state == RTE_REPRESENTOR_PORT_VALID)
+		return -EEXIST;
+
+	port->vport_id = vport_id;
+	port->ethdev = ethdev;
+	port->broker = broker;
+	port->state = RTE_REPRESENTOR_PORT_VALID;
+
+	/**
+	 * Set representor port ethdev's private data context as allocate
+	 * representor.
+	 */
+	ethdev->data->dev_private = port;
+
+	RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_init, -ENOTSUP);
+	retval = broker->ops->port_init(broker, ethdev);
+	if (retval)
+		return retval;
+
+	RTE_LOG(INFO, EAL, "Registered port representor "
+			"<broker=%s_%s, vport_id=%u>\n",
+			broker->bus, broker->device, vport_id);
+
+	return 0;
+}
+
+int
+rte_representor_port_unregister(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;
+	RTE_REPRESENTOR_PORT_VALID_OR_RET_ERR(port, -ENODEV);
+
+
+	RTE_FUNC_PTR_OR_ERR_RET(port->broker->ops->port_uninit, -ENOTSUP);
+	port->broker->ops->port_uninit(port->broker, ethdev);
+
+	port->state = RTE_REPRESENTOR_PORT_INVALID;
+
+	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;
+}
diff --git a/lib/librte_representor/rte_port_representor_driver.h b/lib/librte_representor/rte_port_representor_driver.h
new file mode 100644
index 0000000..559361d
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_driver.h
@@ -0,0 +1,183 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_PORT_REPRESENTOR_DRIVER_H_
+#define _RTE_PORT_REPRESENTOR_DRIVER_H_
+
+/**
+ * @file
+ * RTE Port Representor Driver 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 {
+	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 */
+};
+
+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);
+
+struct rte_representor_broker *
+rte_representor_broker_find(const char *bus, const char *device);
+
+/**
+ * Registers a representor ethdev with the broker, allocating a port representor
+ * context and calling the representor port initialization function.
+ *
+ * @param	broker		Port representor broker to register with
+ * @param	vport_id	Virtual port ID to register ethdev against
+ * @param	ethdev		Port representor ethdev handle
+ *
+ * @return
+ * - 0 on successful registration and initialization of representor port
+ * - errno on failure
+ */
+int
+rte_representor_port_register(struct rte_representor_broker *broker,
+	uint32_t vport_id, struct rte_eth_dev *ethdev);
+
+/**
+ * Unregister a representor port, called during destruction of representor
+ * ethdev context. Freeing any allocated memory for the representor port.
+ *
+ * @param	ethdev		Port representor ethdev handle
+ *
+ * @return
+ * - 0 on success
+ * - errno on failure
+ */
+int
+rte_representor_port_unregister(struct rte_eth_dev *ethdev);
+
+/**
+ * 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_ */
diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
new file mode 100644
index 0000000..09ed768
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_version.map
@@ -0,0 +1,12 @@
+DPDK_18.02 {2 {
+	global:
+
+	rte_representor_broker_find;
+	rte_representor_broker_init;
+	rte_representor_broker_uninit;
+	rte_representor_port_get_vport_id;
+	rte_representor_port_register;
+	rte_representor_port_unregister;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6a6a745..67266bf 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -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
-- 
2.7.4

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v2 3/6] eal: added --enable-representor command line argument in EAL to load representor broker infrastructure
  2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs Mohammad Abdul Awal
@ 2017-11-17 14:42 ` Mohammad Abdul Awal
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD Mohammad Abdul Awal
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-11-17 14:42 UTC (permalink / raw)
  To: dev; +Cc: Mohammad Abdul Awal, Declan Doherty

Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Signed-off-by: Declan Doherty <declan.doherty@intel.com>
---
 lib/librte_eal/bsdapp/eal/eal.c            | 6 ++++++
 lib/librte_eal/common/eal_common_options.c | 1 +
 lib/librte_eal/common/eal_internal_cfg.h   | 2 ++
 lib/librte_eal/common/eal_options.h        | 2 ++
 lib/librte_eal/common/include/rte_eal.h    | 8 ++++++++
 lib/librte_eal/linuxapp/eal/eal.c          | 9 +++++++++
 6 files changed, 28 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 369a682..002200a 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -778,3 +778,9 @@ int rte_vfio_noiommu_is_enabled(void)
 {
 	return 0;
 }
+
+/* return non-zero if port-representor is enabled. */
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 996a034..6f2cc05 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -78,6 +78,7 @@ const struct option
 eal_long_options[] = {
 	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
 	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
+	{OPT_ENABLE_REPRESENTOR, 0, NULL, OPT_ENABLE_REPRESENTOR_NUM   },
 	{OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
 	{OPT_HELP,              0, NULL, OPT_HELP_NUM             },
 	{OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index fa6ccbe..55cae8c 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -71,6 +71,8 @@ struct internal_config {
 										* instead of native TSC */
 	volatile unsigned no_shconf;      /**< true if there is no shared config */
 	volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */
+	volatile unsigned enable_representor;
+	/**< true to enable port representor broker for all PFs */
 	volatile enum rte_proc_type_t process_type; /**< multi-process proc type */
 	/** true to try allocating memory on specific sockets */
 	volatile unsigned force_sockets;
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 30e6bb4..c2b2162 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -83,6 +83,8 @@ enum {
 	OPT_VFIO_INTR_NUM,
 #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
 	OPT_VMWARE_TSC_MAP_NUM,
+#define OPT_ENABLE_REPRESENTOR    "enable-representor"
+	OPT_ENABLE_REPRESENTOR_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
index 8e4e71c..c4e61d1 100644
--- a/lib/librte_eal/common/include/rte_eal.h
+++ b/lib/librte_eal/common/include/rte_eal.h
@@ -335,6 +335,14 @@ enum rte_iova_mode rte_eal_iova_mode(void);
 const char *
 rte_eal_mbuf_default_mempool_ops(void);
 
+/**
+ * Get flag for port representor should be enabled or not.
+ *
+ * @return
+ *   Returns the enable-representor flag.
+ */
+int rte_representor_enabled(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 229eec9..364a8b2 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -612,6 +612,10 @@ eal_parse_args(int argc, char **argv)
 			internal_config.mbuf_pool_ops_name = optarg;
 			break;
 
+		case OPT_ENABLE_REPRESENTOR_NUM:
+			internal_config.enable_representor = 1;
+			break;
+
 		default:
 			if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
 				RTE_LOG(ERR, EAL, "Option %c is not supported "
@@ -1041,3 +1045,8 @@ rte_eal_check_module(const char *module_name)
 	/* Module has been found */
 	return 1;
 }
+
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
-- 
2.7.4

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD
  2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs Mohammad Abdul Awal
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 3/6] eal: added --enable-representor command line argument in EAL to load representor broker infrastructure Mohammad Abdul Awal
@ 2017-11-17 14:42 ` Mohammad Abdul Awal
  2017-11-20  7:46   ` Ferruh Yigit
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 5/6] net/i40e: Enable port representor PMD and broker for fortville PMD driver Mohammad Abdul Awal
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-11-17 14:42 UTC (permalink / raw)
  To: dev; +Cc: Mohammad Abdul Awal, Remy Horton, Declan Doherty

V2:
Update rte_bus_vdev.h header file instead of rte_vdev.h file.

V1:
Representor PMD is a virtual PMD which provides a logical representation
in DPDK for ports of a multi port device. This supports configuration,
management, and monitoring of VFs of a physical function bound to a
userspace control plane application.

Change-Id: I5a7834bbc05bc9037e3218f69f10c1bd1e787236
Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Declan Doherty <declan.doherty@intel.com>
---
 drivers/net/Makefile                               |   1 +
 drivers/net/representor/Makefile                   |  52 ++++
 drivers/net/representor/port_representor.c         | 323 +++++++++++++++++++++
 .../representor/rte_pmd_representor_version.map    |   4 +
 mk/rte.app.mk                                      |   1 +
 5 files changed, 381 insertions(+)
 create mode 100644 drivers/net/representor/Makefile
 create mode 100644 drivers/net/representor/port_representor.c
 create mode 100644 drivers/net/representor/rte_pmd_representor_version.map

diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index ef09b4e..068a254 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -68,6 +68,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap
 DIRS-$(CONFIG_RTE_LIBRTE_THUNDERX_NICVF_PMD) += thunderx
 DIRS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio
 DIRS-$(CONFIG_RTE_LIBRTE_VMXNET3_PMD) += vmxnet3
+DIRS-$(CONFIG_RTE_LIBRTE_REPRESENTOR) += representor
 
 ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_KNI) += kni
diff --git a/drivers/net/representor/Makefile b/drivers/net/representor/Makefile
new file mode 100644
index 0000000..5647045
--- /dev/null
+++ b/drivers/net/representor/Makefile
@@ -0,0 +1,52 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 Intel Corporation. All rights reserved.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_pmd_representor.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+LDLIBS += -lrte_representor
+
+EXPORT_MAP := rte_pmd_representor_version.map
+
+LIBABIVER := 1
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_REPRESENTOR) += port_representor.c
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/representor/port_representor.c b/drivers/net/representor/port_representor.c
new file mode 100644
index 0000000..8e75b21
--- /dev/null
+++ b/drivers/net/representor/port_representor.c
@@ -0,0 +1,323 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_ethdev_vdev.h>
+#include <rte_bus_vdev.h>
+#include <rte_kvargs.h>
+#include <rte_flow_driver.h>
+
+#include <rte_port_representor_driver.h>
+
+struct port_rep_parameters {
+	uint64_t vport_mask;
+	struct {
+		char bus[RTE_DEV_NAME_MAX_LEN];
+		char device[RTE_DEV_NAME_MAX_LEN];
+	} parent;
+};
+
+static int
+representor_port_create(struct rte_vdev_device *vdev,
+	struct port_rep_parameters *params,
+	const uint16_t vport_id)
+{
+	struct rte_eth_dev *ethdev;
+	struct rte_representor_broker *broker;
+
+	int32_t ret = 0;
+
+
+	if (vdev->device.numa_node == SOCKET_ID_ANY)
+		vdev->device.numa_node = rte_socket_id();
+
+	RTE_LOG(INFO, PMD,
+		"Creating representor port %s ethdev on numa socket %u\n",
+		vdev->device.name, vdev->device.numa_node);
+
+	ethdev = rte_eth_vdev_allocate(vdev,
+		sizeof(struct rte_representor_port));
+	if (!ethdev)
+		return -ENOMEM;
+
+	/*
+	 * Allocate memory for MAC address of port, this should be configured by
+	 * broker
+	 */
+	ethdev->data->mac_addrs = rte_malloc("representor_port_mac",
+			sizeof(struct ether_addr), 0);
+
+	ethdev->data->dev_flags = RTE_ETH_DEV_REPRESENTOR_PORT;
+
+	broker = rte_representor_broker_find(params->parent.bus,
+			params->parent.device);
+	if (!broker)
+		goto create_err;
+
+	ret = rte_representor_port_register(broker,	vport_id, ethdev);
+	if (ret)
+		goto create_err;
+
+	return 0;
+
+create_err:
+	if (broker)
+		rte_representor_port_unregister(ethdev);
+
+	if (ethdev)
+		rte_eth_dev_release_port(ethdev);
+
+	return -ENODEV;
+}
+
+
+static inline void
+apply_range_to_mask(int lower, int upper, uint64_t *mask)
+{
+	int idx_mask;
+
+	for (idx_mask = lower; idx_mask <= upper; idx_mask++)
+		*mask = *mask | (0x01ULL << idx_mask);
+}
+
+static int
+range_to_mask(const char *range_str, uint64_t *mask)
+{
+	int value;
+	int state;
+	int lower_bound;
+
+	state = 0;
+	while (1) {
+		switch (state) {
+		case 0: /* Initial */
+			if (!isdigit(*range_str))
+				return -EINVAL;
+			value = *range_str - '0';
+			state = 1;
+			break;
+
+		case 1: /* Parsing lower bound */
+			if (isdigit(*range_str)) {
+				value *= 10;
+				value += *range_str - '0';
+			} else if (*range_str == '-') {
+				state = '-';
+				lower_bound = value;
+				value = 0;
+			} else if (*range_str == '\0') {
+				apply_range_to_mask(value, value, mask);
+				return 0;
+			} else if (*range_str == ':') {
+				apply_range_to_mask(value, value, mask);
+				value = 0;
+				state = 0;
+			} else {
+				return -EINVAL;
+			}
+			break;
+
+		case '-': /* Parsing upper bound */
+			if (isdigit(*range_str)) {
+				value *= 10;
+				value += *range_str - '0';
+			} else if (*range_str == '\0') {
+				apply_range_to_mask(lower_bound, value, mask);
+				return 0;
+			} else if (*range_str == ':') {
+				apply_range_to_mask(lower_bound, value, mask);
+				value = 0;
+				state = 0;
+			} else {
+				return -EINVAL;
+			}
+			break;
+		}
+		range_str++;
+	}
+
+	return -EINVAL;
+}
+
+
+static int
+port_rep_kvargs_parent(__rte_unused const char *key,
+	const char *value, void *ptr)
+{
+	struct port_rep_parameters *params = ptr;
+	int ret = 0;
+	char *pivot;
+	uint32_t len;
+
+	/* the parent param has to be provided with type_name formatted */
+	pivot = strchr(value, '_');
+	if (pivot) {
+		len = pivot - value;
+		strncpy(params->parent.bus, value, len);
+		strncpy(params->parent.device, pivot + 1, strlen(value) - len);
+	} else {
+		RTE_LOG(ERR, PMD, "'parent=%s' has invalid format\n", value);
+	}
+
+	return ret;
+}
+
+
+static int
+port_rep_kvargs_vport_id(__rte_unused const char *key,
+	const char *value, void *ptr)
+{
+	struct port_rep_parameters *params = ptr;
+	int ret;
+
+	ret = range_to_mask(value, &params->vport_mask);
+	if (ret != 0)
+		RTE_LOG(ERR, PMD, "'vport_id=%s' does not give a valid device "
+			"name\n", value);
+	return ret;
+}
+
+typedef int (*port_rep_arg_func_t)(const char*, const char*, void*);
+
+static const char * const port_rep_kvargs_codes[] = {
+	"parent", "vport_id", NULL
+};
+
+static port_rep_arg_func_t port_rep_kvargs_callbacks[] = {
+	&port_rep_kvargs_parent,
+	&port_rep_kvargs_vport_id,
+	NULL
+};
+
+static int
+port_rep_probe(struct rte_vdev_device *dev)
+{
+	struct rte_kvargs *kvlist = NULL;
+	struct port_rep_parameters params;
+	const char *args;
+	int ret, idx;
+
+	uint16_t vport_id = 0;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!rte_representor_enabled()) {
+		RTE_LOG(ERR, PMD,
+			"Tried creating representor port pmd without"
+			" --enable-representor\n");
+		return -ENODEV;
+	}
+
+	args = rte_vdev_device_args(dev);
+	RTE_LOG(INFO, PMD, "Initializing representor port pmd for %s\n",
+			rte_vdev_device_name(dev));
+
+	if (args) {
+		kvlist = rte_kvargs_parse(args, port_rep_kvargs_codes);
+		if (!kvlist)
+			return -1;
+
+		idx = 0;
+		while (port_rep_kvargs_codes[idx] != NULL) {
+			ret = rte_kvargs_process(kvlist,
+				port_rep_kvargs_codes[idx],
+				port_rep_kvargs_callbacks[idx],
+				&params);
+			if (ret != 0) {
+				RTE_LOG(ERR, PMD, "port_representor pmd "
+					"parameter error\n");
+				rte_kvargs_free(kvlist);
+				return -1;
+			}
+			idx++;
+		}
+	}
+	RTE_LOG(INFO, PMD, "Configure port_representor pmd with args=\"%s\"\n",
+		args);
+
+	while (params.vport_mask) {
+		if (params.vport_mask & 0x1) {
+			ret = representor_port_create(dev, &params, vport_id);
+			if (ret) {
+				RTE_LOG(ERR, PMD,
+					"representor port create error for "
+					"vport_id (%d)\n", vport_id);
+				break;
+			}
+		}
+		/* Keep bitmask and bit index in sync */
+		params.vport_mask = params.vport_mask << 1;
+		vport_id++;
+	}
+
+	if (kvlist)
+		rte_kvargs_free(kvlist);
+
+	return ret;
+}
+
+static int
+port_rep_remove(struct rte_vdev_device *dev)
+{
+	struct rte_eth_dev *eth_dev = NULL;
+	int32_t ret = 0;
+
+	if (!dev)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Closing representor port on numa socket %u\n",
+			rte_socket_id());
+
+	eth_dev = rte_eth_dev_allocated(
+			rte_vdev_device_name(dev));
+	if (!eth_dev)
+		return -EINVAL;
+
+	ret = rte_representor_port_unregister(eth_dev);
+	if (ret)
+		return ret;
+
+	rte_eth_dev_release_port(eth_dev);
+
+	return 0;
+}
+
+static struct rte_vdev_driver port_rep_vdev_drv = {
+	.probe = port_rep_probe,
+	.remove = port_rep_remove,
+};
+
+RTE_PMD_REGISTER_VDEV(net_representor, port_rep_vdev_drv);
+RTE_PMD_REGISTER_ALIAS(net_representor, eth_representor);
+RTE_PMD_REGISTER_PARAM_STRING(net_representor,
+	"parent=<bus_device>,vport_id=<uint range>");
diff --git a/drivers/net/representor/rte_pmd_representor_version.map b/drivers/net/representor/rte_pmd_representor_version.map
new file mode 100644
index 0000000..ef35398
--- /dev/null
+++ b/drivers/net/representor/rte_pmd_representor_version.map
@@ -0,0 +1,4 @@
+DPDK_2.0 {
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 67266bf..4590be0 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -147,6 +147,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += -lrte_pmd_mlx5 -libverbs -lmlx5
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MRVL_PMD)       += -lrte_pmd_mrvl -L$(LIBMUSDK_PATH)/lib -lmusdk
 _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD)        += -lrte_pmd_nfp
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL)       += -lrte_pmd_null
+_LDLIBS-$(CONFIG_RTE_LIBRTE_REPRESENTOR)    += -lrte_pmd_representor
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_PCAP)       += -lrte_pmd_pcap -lpcap
 _LDLIBS-$(CONFIG_RTE_LIBRTE_QEDE_PMD)       += -lrte_pmd_qede
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_RING)       += -lrte_pmd_ring
-- 
2.7.4

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v2 5/6] net/i40e: Enable port representor PMD and broker for fortville PMD driver
  2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
                   ` (2 preceding siblings ...)
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD Mohammad Abdul Awal
@ 2017-11-17 14:42 ` Mohammad Abdul Awal
  2017-11-20  7:48   ` Ferruh Yigit
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 6/6] net/ixgbe: Enable port representor PMD and broker for ixgbe " Mohammad Abdul Awal
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-11-17 14:42 UTC (permalink / raw)
  To: dev; +Cc: Mohammad Abdul Awal, Remy Horton, Declan Doherty

Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Declan Doherty <declan.doherty@intel.com>
---
 drivers/net/i40e/Makefile        |   1 +
 drivers/net/i40e/i40e_ethdev.c   |  16 ++
 drivers/net/i40e/i40e_ethdev.h   |   1 +
 drivers/net/i40e/i40e_prep_ops.c | 472 +++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_prep_ops.h |  46 ++++
 drivers/net/i40e/rte_pmd_i40e.c  |  47 ++++
 drivers/net/i40e/rte_pmd_i40e.h  |  18 ++
 7 files changed, 601 insertions(+)
 create mode 100644 drivers/net/i40e/i40e_prep_ops.c
 create mode 100644 drivers/net/i40e/i40e_prep_ops.h

diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 9ab8c84..641bf26 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -113,6 +113,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_prep_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 811cc9f..65bb320 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -67,6 +67,7 @@
 #include "i40e_pf.h"
 #include "i40e_regs.h"
 #include "rte_pmd_i40e.h"
+#include "i40e_prep_ops.h"
 
 #define ETH_I40E_FLOATING_VEB_ARG	"enable_floating_veb"
 #define ETH_I40E_FLOATING_VEB_LIST_ARG	"floating_veb_list"
@@ -1122,6 +1123,17 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	hw->bus.func = pci_dev->addr.function;
 	hw->adapter_stopped = 0;
 
+	/* init representor broker */
+	if (rte_representor_enabled()) {
+		ret = i40e_port_representor_broker_init(dev, &pf->broker,
+			pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Make sure all is clean before doing PF reset */
 	i40e_clear_hw(hw);
 
@@ -1457,6 +1469,10 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	intr_handle = &pci_dev->intr_handle;
 
+	/* free port representor pmds */
+	if (rte_representor_enabled())
+		rte_representor_broker_uninit(pf->broker);
+
 	if (hw->adapter_stopped == 0)
 		i40e_dev_close(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index cd67453..9e962eb 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -957,6 +957,7 @@ struct i40e_pf {
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
 	struct i40e_tm_conf tm_conf;
+	struct rte_representor_broker *broker;
 
 	/* Dynamic Device Personalization */
 	bool gtp_support; /* 1 - support GTP-C and GTP-U */
diff --git a/drivers/net/i40e/i40e_prep_ops.c b/drivers/net/i40e/i40e_prep_ops.c
new file mode 100644
index 0000000..3261b97
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.c
@@ -0,0 +1,472 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_bus_pci.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "base/i40e_type.h"
+#include "base/virtchnl.h"
+#include "i40e_ethdev.h"
+#include "i40e_rxtx.h"
+#include "rte_pmd_i40e.h"
+
+#include "i40e_prep_ops.h"
+
+struct i40e_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+i40e_representor_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return i40e_dev_link_update(i40e_priv_data->pf_ethdev,
+		wait_to_complete);
+}
+
+static void
+i40e_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (!is_i40e_supported(i40e_priv_data->pf_ethdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(
+		i40e_priv_data->pf_ethdev->data->dev_private);
+	if (representor->vport_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return;
+	}
+
+	vf = &pf->vfs[representor->vport_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return;
+	}
+
+	/* get dev info for the vdev */
+	dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(ethdev);
+	dev_info->max_rx_queues = vsi->nb_qps;
+	dev_info->max_tx_queues = vsi->nb_qps;
+	dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN;
+	dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
+	dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) *
+		sizeof(uint32_t);
+	dev_info->reta_size = ETH_RSS_RETA_SIZE_64;
+	dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL;
+	dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX;
+	dev_info->rx_offload_capa =
+		DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_QINQ_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |
+		DEV_RX_OFFLOAD_UDP_CKSUM |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	dev_info->tx_offload_capa =
+		DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_QINQ_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM |
+		DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM |
+		DEV_TX_OFFLOAD_SCTP_CKSUM;
+
+	dev_info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_thresh = {
+			.pthresh = I40E_DEFAULT_RX_PTHRESH,
+			.hthresh = I40E_DEFAULT_RX_HTHRESH,
+			.wthresh = I40E_DEFAULT_RX_WTHRESH,
+		},
+		.rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH,
+		.rx_drop_en = 0,
+	};
+
+	dev_info->default_txconf = (struct rte_eth_txconf) {
+		.tx_thresh = {
+			.pthresh = I40E_DEFAULT_TX_PTHRESH,
+			.hthresh = I40E_DEFAULT_TX_HTHRESH,
+			.wthresh = I40E_DEFAULT_TX_WTHRESH,
+		},
+		.tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH,
+		.tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH,
+		.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
+				ETH_TXQ_FLAGS_NOOFFLOADS,
+	};
+
+	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+
+	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+}
+
+static int
+i40e_representor_stats_get(struct rte_eth_dev *ethdev,
+		struct rte_eth_stats *stats)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_get_vf_stats(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, stats);
+}
+
+static void
+i40e_representor_stats_reset(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_reset_vf_stats(i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id);
+}
+
+static void
+i40e_representor_promiscuous_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_promiscuous_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_allmulticast_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_allmulticast_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_remove_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, &ethdev->data->mac_addrs[index]);
+}
+
+static void
+i40e_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+		struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, mac_addr);
+}
+
+static int
+i40e_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+		uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	vfid = representor->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_i40e_set_vf_vlan_filter(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		vlan_id, vf_mask, on);
+}
+
+static int
+i40e_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct rte_eth_dev *pdev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+	uint32_t vfid;
+
+	pdev = i40e_priv_data->pf_ethdev;
+	vfid = representor->vport_id;
+
+	if (!is_i40e_supported(pdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return -EINVAL;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(pdev->data->dev_private);
+
+	if (vfid >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return -EINVAL;
+	}
+
+	vf = &pf->vfs[vfid];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Fixme: even though there 3 kinds of hw offloads, hw_vlan_filter,
+	 * hw_vlan_strip, and hw_vlan_extend.
+	 * currently the hw_vlan_extend offload by vsi is not implemented.
+	 */
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		/* Enable or disable VLAN filtering offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_filter)
+			return i40e_vsi_config_vlan_filter(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_filter(vsi, FALSE);
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK) {
+		/* Enable or disable VLAN stripping offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_strip)
+			return i40e_vsi_config_vlan_stripping(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_stripping(vsi, FALSE);
+	}
+
+	return -EINVAL;
+}
+
+static void
+i40e_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_vlan_stripq(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, on);
+}
+
+static int
+i40e_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id,
+	__rte_unused int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_set_vf_vlan_insert(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, vlan_id);
+}
+
+struct eth_dev_ops i40e_representor_dev_ops = {
+	.link_update          = i40e_representor_link_update,
+	.dev_infos_get        = i40e_representor_dev_infos_get,
+
+	.stats_get            = i40e_representor_stats_get,
+	.stats_reset          = i40e_representor_stats_reset,
+
+	.promiscuous_enable   = i40e_representor_promiscuous_enable,
+	.promiscuous_disable  = i40e_representor_promiscuous_disable,
+
+	.allmulticast_enable  = i40e_representor_allmulticast_enable,
+	.allmulticast_disable = i40e_representor_allmulticast_disable,
+
+	.mac_addr_remove      = i40e_representor_mac_addr_remove,
+	.mac_addr_set         = i40e_representor_mac_addr_set,
+
+	.vlan_filter_set      = i40e_representor_vlan_filter_set,
+	.vlan_offload_set     = i40e_representor_vlan_offload_set,
+	.vlan_strip_queue_set = i40e_representor_vlan_strip_queue_set,
+	.vlan_pvid_set        = i40e_representor_vlan_pvid_set
+};
+
+static int
+i40e_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port;
+	struct i40e_pf *i40e_pf;
+	struct i40e_pf_vf *i40e_vf;
+
+	port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("i40e_port_representor_priv_data",
+			sizeof(struct i40e_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct i40e_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+
+	i40e_pf = I40E_DEV_PRIVATE_TO_PF(pf_ethdev->data->dev_private);
+	i40e_vf = &i40e_pf->vfs[port->vport_id];
+
+	if (!i40e_vf->vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &i40e_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = i40e_vf->vsi->nb_qps;
+	ethdev->data->nb_tx_queues = i40e_vf->vsi->nb_qps;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = NULL;
+	ethdev->tx_pkt_burst = NULL;
+
+	return 0;
+}
+
+static int
+i40e_port_representor_uninit(struct rte_representor_broker *broker __rte_unused,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops i40e_broker_port_ops = {
+	.port_init = i40e_port_representor_init,
+	.port_uninit = i40e_port_representor_uninit
+};
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set i40e broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &i40e_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
diff --git a/drivers/net/i40e/i40e_prep_ops.h b/drivers/net/i40e/i40e_prep_ops.h
new file mode 100644
index 0000000..c155da8
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.h
@@ -0,0 +1,46 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _I40E_PREP_OPS_H_
+#define _I40E_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+struct rte_representor_broker_port_ops *rte_i40e_broker_port_ops;
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _I40E_PREP_OPS_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index aeb92af..641a35c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -599,6 +599,53 @@ rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 	return 0;
 }
 
+static const struct ether_addr null_mac_addr;
+
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+		return -EINVAL;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs)
+		return -EINVAL;
+
+	vf = &pf->vfs[vf_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	if (!is_same_ether_addr(mac_addr, &vf->mac_addr)) {
+		PMD_DRV_LOG(ERR, "Mac address does not match.");
+		return -EINVAL;
+	}
+
+	/* reset the mac with null mac */
+	ether_addr_copy(&null_mac_addr, &vf->mac_addr);
+
+	/* Remove the mac */
+	i40e_vsi_delete_mac(vsi, mac_addr);
+
+	return 0;
+}
+
 /* Set vlan strip on/off for specific VF from host */
 int
 rte_pmd_i40e_set_vf_vlan_stripq(uint16_t port, uint16_t vf_id, uint8_t on)
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 580ca4a..1b1f725 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -467,6 +467,24 @@ int rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
 /**
+ * Remove the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf_id
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr);
+
+/**
  * Enable/Disable vf vlan strip for all queues in a pool
  *
  * @param port
-- 
2.7.4

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v2 6/6] net/ixgbe: Enable port representor PMD and broker for ixgbe PMD driver
  2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
                   ` (3 preceding siblings ...)
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 5/6] net/i40e: Enable port representor PMD and broker for fortville PMD driver Mohammad Abdul Awal
@ 2017-11-17 14:42 ` Mohammad Abdul Awal
  2017-11-20 19:57 ` [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Ferruh Yigit
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-11-17 14:42 UTC (permalink / raw)
  To: dev; +Cc: Mohammad Abdul Awal, Remy Horton, Declan Doherty

Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
Signed-off-by: Remy Horton <remy.horton@intel.com>
Signed-off-by: Declan Doherty <declan.doherty@intel.com>
---
 drivers/net/ixgbe/Makefile         |   1 +
 drivers/net/ixgbe/ixgbe_ethdev.c   |  22 +++-
 drivers/net/ixgbe/ixgbe_ethdev.h   |   6 +
 drivers/net/ixgbe/ixgbe_prep_ops.c | 250 +++++++++++++++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_prep_ops.h |  46 +++++++
 5 files changed, 324 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h

diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index 511a64e..4ec2422 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -130,6 +130,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_ipsec.c
 endif
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += rte_pmd_ixgbe.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_prep_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_IXGBE_PMD)-include := rte_pmd_ixgbe.h
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ff19a56..a48b783 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -75,6 +75,7 @@
 #include "base/ixgbe_type.h"
 #include "base/ixgbe_phy.h"
 #include "ixgbe_regs.h"
+#include "ixgbe_prep_ops.h"
 
 /*
  * High threshold controlling when to start sending XOFF frames. Must be at
@@ -1138,6 +1139,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 	uint32_t ctrl_ext;
 	uint16_t csum;
 	int diag, i;
+	int ret;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1261,6 +1265,17 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 		return -EIO;
 	}
 
+	/* Init port representor broker */
+	if (rte_representor_enabled()) {
+		ret = ixgbe_port_representor_broker_init(eth_dev,
+			&eth_adapter->broker, pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Reset the hw statistics */
 	ixgbe_dev_stats_reset(eth_dev);
 
@@ -1363,6 +1378,8 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	struct ixgbe_hw *hw;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1371,6 +1388,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
 
+	if (rte_representor_enabled())
+		rte_representor_broker_uninit(eth_adapter->broker);
+
 	if (hw->adapter_stopped == 0)
 		ixgbe_dev_close(eth_dev);
 
@@ -3962,7 +3982,7 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 }
 
 /* return 0 means link status changed, -1 means not changed */
-static int
+int
 ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 			    int wait_to_complete, int vf)
 {
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 51ddcfd..ae1e790 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -499,6 +499,7 @@ struct ixgbe_adapter {
 	struct rte_timecounter      rx_tstamp_tc;
 	struct rte_timecounter      tx_tstamp_tc;
  	struct ixgbe_tm_conf        tm_conf;
+	struct rte_representor_broker *broker;
 };
 
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
@@ -673,6 +674,11 @@ int ixgbe_fdir_filter_program(struct rte_eth_dev *dev,
 
 void ixgbe_configure_dcb(struct rte_eth_dev *dev);
 
+int
+ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
+			    int wait_to_complete, int vf);
+
+
 /*
  * misc function prototypes
  */
diff --git a/drivers/net/ixgbe/ixgbe_prep_ops.c b/drivers/net/ixgbe/ixgbe_prep_ops.c
new file mode 100644
index 0000000..ac57f8b
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_prep_ops.c
@@ -0,0 +1,250 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "base/ixgbe_type.h"
+#include "base/ixgbe_vf.h"
+#include "ixgbe_ethdev.h"
+#include "ixgbe_rxtx.h"
+#include "rte_pmd_ixgbe.h"
+
+#include "ixgbe_prep_ops.h"
+
+struct ixgbe_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+ixgbe_representor_link_update(struct rte_eth_dev *ethdev,
+	int wait_to_complete)
+{
+	struct rte_representor_port *prep_priv_data =
+			ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+			prep_priv_data->priv_data;
+
+	return ixgbe_dev_link_update_share(ixgbe_priv_data->pf_ethdev,
+		wait_to_complete, 1);
+}
+
+static void
+ixgbe_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+	struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	rte_pmd_ixgbe_set_vf_mac_addr(ixgbe_priv_data->pf_ethdev->data->port_id,
+		prep_priv_data->vport_id, mac_addr);
+}
+
+static void
+ixgbe_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(
+		ixgbe_priv_data->pf_ethdev->data->dev_private);
+
+	dev_info->pci_dev = NULL;
+
+	dev_info->min_rx_bufsize = 1024;
+	/**< Minimum size of RX buffer. */
+	dev_info->max_rx_pktlen = 9728;
+	/**< Maximum configurable length of RX pkt. */
+	dev_info->max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	/**< Maximum number of RX queues. */
+	dev_info->max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+	/**< Maximum number of TX queues. */
+
+	dev_info->max_mac_addrs = hw->mac.num_rar_entries;
+	/**< Maximum number of MAC addresses. */
+
+	dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |	DEV_RX_OFFLOAD_UDP_CKSUM  |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	/**< Device RX offload capabilities. */
+
+	dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_TSO;
+	/**< Device TX offload capabilities. */
+
+	dev_info->speed_capa =
+		ixgbe_priv_data->pf_ethdev->data->dev_link.link_speed;
+	/**< Supported speeds bitmap (ETH_LINK_SPEED_). */
+
+	dev_info->switch_domain = ethdev->data->switch_domain;
+	/**< Switch domain which port belongs to. */
+}
+
+
+static int
+ixgbe_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+	uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_ixgbe_set_vf_vlan_filter(pfid, vlan_id, vf_mask, on);
+}
+
+static void
+ixgbe_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+
+	rte_pmd_ixgbe_set_vf_vlan_stripq(pfid, vfid, on);
+}
+
+struct eth_dev_ops ixgbe_representor_dev_ops = {
+	.link_update                  = ixgbe_representor_link_update,
+	.dev_infos_get                = ixgbe_representor_dev_infos_get,
+	.mac_addr_set                 = ixgbe_representor_mac_addr_set,
+	.vlan_filter_set              = ixgbe_representor_vlan_filter_set,
+	.vlan_strip_queue_set         = ixgbe_representor_vlan_strip_queue_set
+};
+
+static int
+ixgbe_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("ixgbe_port_representor_priv_data",
+			sizeof(struct ixgbe_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct ixgbe_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &ixgbe_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	ethdev->data->nb_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = NULL;
+	ethdev->tx_pkt_burst = NULL;
+
+	return 0;
+}
+
+static int
+ixgbe_port_representor_uninit(
+	__rte_unused struct rte_representor_broker *broker,
+	struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops ixgbe_broker_port_ops = {
+	.port_init = ixgbe_port_representor_init,
+	.port_uninit = ixgbe_port_representor_uninit
+};
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set IXGBE broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &ixgbe_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
diff --git a/drivers/net/ixgbe/ixgbe_prep_ops.h b/drivers/net/ixgbe/ixgbe_prep_ops.h
new file mode 100644
index 0000000..ad34acb
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_prep_ops.h
@@ -0,0 +1,46 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _IXGBE_PREP_OPS_H_
+#define _IXGBE_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+struct rte_representor_broker_port_ops *rte_ixgbe_broker_port_ops;
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _IXGBE_PREP_OPS_H_ */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs Mohammad Abdul Awal
@ 2017-11-17 23:03   ` Ferruh Yigit
  2017-12-08 14:57     ` Mohammad Abdul Awal
  0 siblings, 1 reply; 75+ messages in thread
From: Ferruh Yigit @ 2017-11-17 23:03 UTC (permalink / raw)
  To: Mohammad Abdul Awal, dev; +Cc: Remy Horton, Declan Doherty

On 11/17/2017 6:42 AM, Mohammad Abdul Awal wrote:
> diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
> new file mode 100644
> index 0000000..09ed768
> --- /dev/null
> +++ b/lib/librte_representor/rte_port_representor_version.map
> @@ -0,0 +1,12 @@
> +DPDK_18.02 {2 {
> +	global:
> +
> +	rte_representor_broker_find;
> +	rte_representor_broker_init;
> +	rte_representor_broker_uninit;
> +	rte_representor_port_get_vport_id;
> +	rte_representor_port_register;
> +	rte_representor_port_unregister;

Is any of these APIs intended to be used by application?
>From rest of the patch it looks like these are used by PMDs, if so why creating
a new library?

> +
> +	local: *;
> +};

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD Mohammad Abdul Awal
@ 2017-11-20  7:46   ` Ferruh Yigit
  2017-12-08 15:02     ` Remy Horton
  0 siblings, 1 reply; 75+ messages in thread
From: Ferruh Yigit @ 2017-11-20  7:46 UTC (permalink / raw)
  To: Mohammad Abdul Awal, dev; +Cc: Remy Horton, Declan Doherty

On 11/17/2017 6:42 AM, Mohammad Abdul Awal wrote:
> V2:
> Update rte_bus_vdev.h header file instead of rte_vdev.h file.
> 
> V1:
> Representor PMD is a virtual PMD which provides a logical representation
> in DPDK for ports of a multi port device. This supports configuration,
> management, and monitoring of VFs of a physical function bound to a
> userspace control plane application.

Why we need this PMD?
It looks like this has been used only for parameter parsing.

Can it be possible to rte_representor_broker_init() will allocate ethdevs and
fill brokers with this information?

> 
> Change-Id: I5a7834bbc05bc9037e3218f69f10c1bd1e787236
> Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>

<...>

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] net/i40e: Enable port representor PMD and broker for fortville PMD driver
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 5/6] net/i40e: Enable port representor PMD and broker for fortville PMD driver Mohammad Abdul Awal
@ 2017-11-20  7:48   ` Ferruh Yigit
  0 siblings, 0 replies; 75+ messages in thread
From: Ferruh Yigit @ 2017-11-20  7:48 UTC (permalink / raw)
  To: Mohammad Abdul Awal, dev; +Cc: Remy Horton, Declan Doherty

On 11/17/2017 6:42 AM, Mohammad Abdul Awal wrote:
> +struct eth_dev_ops i40e_representor_dev_ops = {
> +	.link_update          = i40e_representor_link_update,
> +	.dev_infos_get        = i40e_representor_dev_infos_get,
> +
> +	.stats_get            = i40e_representor_stats_get,
> +	.stats_reset          = i40e_representor_stats_reset,
> +
> +	.promiscuous_enable   = i40e_representor_promiscuous_enable,
> +	.promiscuous_disable  = i40e_representor_promiscuous_disable,
> +
> +	.allmulticast_enable  = i40e_representor_allmulticast_enable,
> +	.allmulticast_disable = i40e_representor_allmulticast_disable,
> +
> +	.mac_addr_remove      = i40e_representor_mac_addr_remove,
> +	.mac_addr_set         = i40e_representor_mac_addr_set,
> +
> +	.vlan_filter_set      = i40e_representor_vlan_filter_set,
> +	.vlan_offload_set     = i40e_representor_vlan_offload_set,
> +	.vlan_strip_queue_set = i40e_representor_vlan_strip_queue_set,
> +	.vlan_pvid_set        = i40e_representor_vlan_pvid_set
> +};

Will we able to get rid of VF control related PMD specific APIs when port
representation enabled?

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag
  2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
                   ` (4 preceding siblings ...)
  2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 6/6] net/ixgbe: Enable port representor PMD and broker for ixgbe " Mohammad Abdul Awal
@ 2017-11-20 19:57 ` Ferruh Yigit
  2017-12-08 15:33   ` Mohammad Abdul Awal
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
  7 siblings, 1 reply; 75+ messages in thread
From: Ferruh Yigit @ 2017-11-20 19:57 UTC (permalink / raw)
  To: Mohammad Abdul Awal, dev; +Cc: Declan Doherty

On 11/17/2017 6:42 AM, Mohammad Abdul Awal wrote:
> switch_domain attribute has been added to specify that a rte_eth_dev
> instance belongs to a switch domain in the software switch.
> 
> RTE_ETH_DEV_REPRESENTOR_PORT has been defined to specify that a
> rte_eth_dev instance is a representor device.
> 
> Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> ---
>  lib/librte_ether/rte_ethdev.h | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 341c2d6..7e82c70 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -1047,6 +1047,7 @@ struct rte_eth_dev_info {
>  	/** Configured number of rx/tx queues */
>  	uint16_t nb_rx_queues; /**< Number of RX queues. */
>  	uint16_t nb_tx_queues; /**< Number of TX queues. */
> +	uint16_t switch_domain; /**< Switch domain which port belongs to. */

What to put or not into rte_eth_dev_info is not that clear, but recent
description from Andrew [1] makes sense to me: using more device related static
information in dev_info instead of dynamic data.

There is an option to create a new API for this, what do you think?

[1]
http://dpdk.org/ml/archives/dev/2017-November/081868.html

>  };
>  
>  /**
> @@ -1810,6 +1811,7 @@ struct rte_eth_dev_data {
>  	int numa_node;  /**< NUMA node connection */
>  	struct rte_vlan_filter_conf vlan_filter_conf;
>  	/**< VLAN filter configuration. */
> +	uint16_t switch_domain; /**< Switch domain which port belongs to. */

Can you please describe why "switch_domain" used for? In patchset only ixgbe
uses it, and that is only for assign to dev_info, it is not clear why this is
needed.

>  };
>  
>  /** Device supports link state interrupt */
> @@ -1818,6 +1820,8 @@ struct rte_eth_dev_data {
>  #define RTE_ETH_DEV_BONDED_SLAVE 0x0004
>  /** Device supports device removal interrupt */
>  #define RTE_ETH_DEV_INTR_RMV     0x0008
> +/** Device is a port representor */
> +#define RTE_ETH_DEV_REPRESENTOR_PORT 0x0010

As far as I can see this is not a generic device option, but just a way to mark
a specific virtual PMD. There must be a better way to do this, I think this flag
is not good idea.

>  
>  /**
>   * @internal
> 

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs
  2017-11-17 23:03   ` Ferruh Yigit
@ 2017-12-08 14:57     ` Mohammad Abdul Awal
  0 siblings, 0 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-12-08 14:57 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: Remy Horton, Declan Doherty, dev



On 17/11/2017 23:03, Ferruh Yigit wrote:
> On 11/17/2017 6:42 AM, Mohammad Abdul Awal wrote:
>> diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
>> new file mode 100644
>> index 0000000..09ed768
>> --- /dev/null
>> +++ b/lib/librte_representor/rte_port_representor_version.map
>> @@ -0,0 +1,12 @@
>> +DPDK_18.02 {2 {
>> +	global:
>> +
>> +	rte_representor_broker_find;
>> +	rte_representor_broker_init;
>> +	rte_representor_broker_uninit;
>> +	rte_representor_port_get_vport_id;
>> +	rte_representor_port_register;
>> +	rte_representor_port_unregister;
> Is any of these APIs intended to be used by application?
>  From rest of the patch it looks like these are used by PMDs, if so why creating
> a new library?
These API's are to be used by PMDs only. We will remove them from here.

Thanks,
Awal.
>
>> +
>> +	local: *;
>> +};

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD
  2017-11-20  7:46   ` Ferruh Yigit
@ 2017-12-08 15:02     ` Remy Horton
  2017-12-08 16:56       ` Mohammad Abdul Awal
  0 siblings, 1 reply; 75+ messages in thread
From: Remy Horton @ 2017-12-08 15:02 UTC (permalink / raw)
  To: Ferruh Yigit, Mohammad Abdul Awal, dev; +Cc: Declan Doherty


On 20/11/2017 07:46, Ferruh Yigit wrote:
[..]
> Why we need this PMD?
> It looks like this has been used only for parameter parsing.
>
> Can it be possible to rte_representor_broker_init() will allocate ethdevs and
> fill brokers with this information?

Possible, but not sure it gains much in practice. It would require 
workarounds to avoid pulling in driver code dependencies (e.g. 
drivers/bus/vdev/rte_bus_vdev.h).

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag
  2017-11-20 19:57 ` [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Ferruh Yigit
@ 2017-12-08 15:33   ` Mohammad Abdul Awal
  2017-12-11 13:45     ` Alex Rosenbaum
  0 siblings, 1 reply; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-12-08 15:33 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: Declan Doherty



On 20/11/2017 19:57, Ferruh Yigit wrote:
> On 11/17/2017 6:42 AM, Mohammad Abdul Awal wrote:
>> switch_domain attribute has been added to specify that a rte_eth_dev
>> instance belongs to a switch domain in the software switch.
>>
>> RTE_ETH_DEV_REPRESENTOR_PORT has been defined to specify that a
>> rte_eth_dev instance is a representor device.
>>
>> Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
>> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
>> ---
>>   lib/librte_ether/rte_ethdev.h | 4 ++++
>>   1 file changed, 4 insertions(+)
>>
>> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
>> index 341c2d6..7e82c70 100644
>> --- a/lib/librte_ether/rte_ethdev.h
>> +++ b/lib/librte_ether/rte_ethdev.h
>> @@ -1047,6 +1047,7 @@ struct rte_eth_dev_info {
>>   	/** Configured number of rx/tx queues */
>>   	uint16_t nb_rx_queues; /**< Number of RX queues. */
>>   	uint16_t nb_tx_queues; /**< Number of TX queues. */
>> +	uint16_t switch_domain; /**< Switch domain which port belongs to. */
> What to put or not into rte_eth_dev_info is not that clear, but recent
> description from Andrew [1] makes sense to me: using more device related static
> information in dev_info instead of dynamic data.
>
> There is an option to create a new API for this, what do you think?
>
> [1]
> http://dpdk.org/ml/archives/dev/2017-November/081868.html
>
>>   };
>>   
>>   /**
>> @@ -1810,6 +1811,7 @@ struct rte_eth_dev_data {
>>   	int numa_node;  /**< NUMA node connection */
>>   	struct rte_vlan_filter_conf vlan_filter_conf;
>>   	/**< VLAN filter configuration. */
>> +	uint16_t switch_domain; /**< Switch domain which port belongs to. */
> Can you please describe why "switch_domain" used for? In patchset only ixgbe
> uses it, and that is only for assign to dev_info, it is not clear why this is
> needed.

We kept it keeping in mind for future use, specially for switchdev API 
and OVS support. But for this patch it is not necessary to be here. We 
will remove it from here now. New patch will be submitted if needed in 
future.

>>   };
>>   
>>   /** Device supports link state interrupt */
>> @@ -1818,6 +1820,8 @@ struct rte_eth_dev_data {
>>   #define RTE_ETH_DEV_BONDED_SLAVE 0x0004
>>   /** Device supports device removal interrupt */
>>   #define RTE_ETH_DEV_INTR_RMV     0x0008
>> +/** Device is a port representor */
>> +#define RTE_ETH_DEV_REPRESENTOR_PORT 0x0010
> As far as I can see this is not a generic device option, but just a way to mark
> a specific virtual PMD. There must be a better way to do this, I think this flag
> is not good idea.
Thanks Ferruh. We will also remove this flag option. Without this flag 
option, we can still identify the PMD as a port representor type or not 
by looking at the device name.

>>   
>>   /**
>>    * @internal
>>
>

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD
  2017-12-08 15:02     ` Remy Horton
@ 2017-12-08 16:56       ` Mohammad Abdul Awal
  2017-12-11 10:08         ` Remy Horton
  0 siblings, 1 reply; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-12-08 16:56 UTC (permalink / raw)
  To: Remy Horton, Ferruh Yigit, dev; +Cc: Declan Doherty



On 08/12/2017 15:02, Remy Horton wrote:
>
> On 20/11/2017 07:46, Ferruh Yigit wrote:
> [..]
>> Why we need this PMD?
>> It looks like this has been used only for parameter parsing.
>>
>> Can it be possible to rte_representor_broker_init() will allocate 
>> ethdevs and
>> fill brokers with this information?
>
> Possible, but not sure it gains much in practice. It would require 
> workarounds to avoid pulling in driver code dependencies (e.g. 
> drivers/bus/vdev/rte_bus_vdev.h).

I think it possible to create the representor without pulling in driver 
codes. We probably can avoid using the rte_eth_vdev_allocate by calling 
the rte_eth_dev_allocate() directly.

Right now, the port representor register API looks like

int
rte_representor_port_register(struct rte_representor_broker *broker,
	uint32_t vport_id, struct rte_eth_dev *ethdev);

So, we probably can have that API (and make it public) as below.

int
rte_representor_port_register(const char *devargs);

We can parse the devargs to get all the parameters, create the ethdev 
using rte_eth_dev_allocate(), fill all the private data, pci_device, 
pci_driver etc. and register to the broker.

This way we can avoid having a separate PMD for port representor. This 
comes with a limitation/benefit that user do need need to pass the vdev 
info as EAL argument.

Regards,
Awal.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD
  2017-12-08 16:56       ` Mohammad Abdul Awal
@ 2017-12-11 10:08         ` Remy Horton
  2017-12-11 15:11           ` Mohammad Abdul Awal
  0 siblings, 1 reply; 75+ messages in thread
From: Remy Horton @ 2017-12-11 10:08 UTC (permalink / raw)
  To: Mohammad Abdul Awal, Ferruh Yigit, dev; +Cc: Declan Doherty


On 08/12/2017 16:56, Mohammad Abdul Awal wrote:
> On 08/12/2017 15:02, Remy Horton wrote:
[..]
> I think it possible to create the representor without pulling in driver
> codes. We probably can avoid using the rte_eth_vdev_allocate by calling
> the rte_eth_dev_allocate() directly.

This is my general thinking.


> int
> rte_representor_port_register(const char *devargs);

Question is where this *devargs comes from - I don't think there is 
currently any commandline option to specify a parameter string for PFs.

Could go down the zero-conf route of always creating representors for 
all available VFs, but in that case may as well strip out the parsing code.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag
  2017-12-08 15:33   ` Mohammad Abdul Awal
@ 2017-12-11 13:45     ` Alex Rosenbaum
  2017-12-11 18:00       ` Mohammad Abdul Awal
  0 siblings, 1 reply; 75+ messages in thread
From: Alex Rosenbaum @ 2017-12-11 13:45 UTC (permalink / raw)
  To: Mohammad Abdul Awal; +Cc: Ferruh Yigit, DPDK, Declan Doherty

Mohammad,

I did not see a v2 change log. did I miss it? please send.

I don't understand who this v2 addresses the comments by Alejandro Lucero
 from netronome [1].
These are critical points which your proposal does not handle. It is
related to the switch_domain member exposed here.

thanks,
Alex

[1] http://dpdk.org/ml/archives/dev/2017-September/074904.html

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD
  2017-12-11 10:08         ` Remy Horton
@ 2017-12-11 15:11           ` Mohammad Abdul Awal
  2017-12-11 15:29             ` Remy Horton
  0 siblings, 1 reply; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-12-11 15:11 UTC (permalink / raw)
  To: Remy Horton, Ferruh Yigit, dev; +Cc: Declan Doherty



On 11/12/2017 10:08, Remy Horton wrote:
>> int
>> rte_representor_port_register(const char *devargs);
>
> Question is where this *devargs comes from - I don't think there is 
> currently any commandline option to specify a parameter string for PFs.
>
Remy, devargs will be passed by the application who uses the 
rte_representor_port_register API. We are not talking about the EAL args 
here.

> Could go down the zero-conf route of always creating representors for 
> all available VFs, but in that case may as well strip out the parsing 
> code.
>
No zero-conf please. Application should have the control, at least for 
generic cases.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD
  2017-12-11 15:11           ` Mohammad Abdul Awal
@ 2017-12-11 15:29             ` Remy Horton
  0 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-11 15:29 UTC (permalink / raw)
  To: Mohammad Abdul Awal, Ferruh Yigit, dev; +Cc: Declan Doherty

On 11/12/2017 15:11, Mohammad Abdul Awal wrote:
[..]
> Remy, devargs will be passed by the application who uses the
> rte_representor_port_register API. We are not talking about the EAL args
> here.

Ah ok - it hadn't quite clicked in that Port Representors were not going 
to be transparent to applications :)

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag
  2017-12-11 13:45     ` Alex Rosenbaum
@ 2017-12-11 18:00       ` Mohammad Abdul Awal
  0 siblings, 0 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2017-12-11 18:00 UTC (permalink / raw)
  To: Alex Rosenbaum; +Cc: Ferruh Yigit, DPDK, Declan Doherty

Hi Alex,


On 11/12/2017 13:45, Alex Rosenbaum wrote:
> Mohammad,
>
> I did not see a v2 change log. did I miss it? please send.
>
The V2 change is for vdev handling by the representor PMD as the vdev 
API location changed from DPDK 17.08 to 17.11. So, V2 patch mainly a 
rebased against DPDK 17.11.

> I don't understand who this v2 addresses the comments by Alejandro 
> Lucero from netronome [1].
> These are critical points which your proposal does not handle. It is 
> related to the switch_domain member exposed here.

Since, none of the initial NICs (i40e, ixgbe) is using switch_domain for 
the moment, we are dropping the switch_domain from these patch set. It 
is expected to be address in future patchset with switchdev support.

Regards,
Awal.
>
> thanks,
> Alex
>
> [1] http://dpdk.org/ml/archives/dev/2017-September/074904.html

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [DPDK 0/5] lib: add Port Representors
  2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
                   ` (5 preceding siblings ...)
  2017-11-20 19:57 ` [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Ferruh Yigit
@ 2017-12-22 14:41 ` Remy Horton
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 1/5] lib: add Port Representor library Remy Horton
                     ` (6 more replies)
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
  7 siblings, 7 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:41 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu

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.

+-----------------------------+   +---------------+  +---------------+
|        Control Plane        |   |   Data Plane  |  |   Data Plane  |
|         Application         |   |   Application |  |   Application |
+-----------------------------+   +---------------+  +---------------+
|         eth dev api         |   |  eth dev api  |  |  eth dev api  |
+-----------------------------+   +---------------+  +---------------+
+-------+  +-------+  +-------+   +---------------+  +---------------+
|  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
|  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
|       |  | PMD   |  | PMD   |                             |
+---+--^+  +-------+  +-+-----+                             |
    |  |                |  |                                |
    |  +----------------+  |                                |
    |                      |                                |
    |                      |                                |
+--------------------------------+                          |
|   |  HW (logical view)   |     |                          |
| --+------+ +-------+ +---+---+ |                          |
| |   PF   | |  VF0  | |  VF1  | |                          |
| |        | |       | |       +----------------------------+
| +--------+ +-------+ +-------+ |
| +----------------------------+ |
| |        VEB                 | |
| +----------------------------+ |
| +--------+                     |
| |  Port  |                     |
| |   0    |                     |
| +--------+                     |
+--------------------------------+

The figure above shows a deployment where the PF is bound to a DPDK control
plane application which uses representor ports to manage the configuration and
monitoring of it's VF ports. Each virtual function is represented in the
application by a representor port PMD which enables control of the corresponding
VF through eth dev APIs on the representor PMD such as:

- void rte_eth_promiscuous_enable(uint8_t port_id);
- void rte_eth_promiscuous_disable(uint8_t port_id);
- void rte_eth_allmulticast_enable(uint8_t port_id);
- void rte_eth_allmulticast_disable(uint8_t port_id);
- int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
	uint32_t pool);
- int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);

as well as monitoring through API's like

- void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
- int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);

The port representor infrastructure is enabled through a single common, device
independent, virtual PMD whos context is initialized and enabled through a
broker instance running within the context of the physical function device
driver.

+-------------------------+       +-------------------------+
|        rte_ethdev       |       |       rte_ethdev        |
+-------------------------+       +-------------------------+
|  Physical Function PMD  |       |  Port Reperesentor PMD  |
|         +-------------+ |       | +---------+ +---------+ |
|         | Representor | |       | | dev_data| | dev_ops | |
|         |    Broker   | |       | +----+----+ +----+----+ |
|         | +---------+ | |       +------|-----------|------+
|         | | VF Port | | |              |           |
|         | | Context +------------------+           |
|         | +---------+ | |                          |
|         | +---------+ | |                          |
|         | | Handler +------------------------------+
|         | |   Ops   | | |
|         | +---------+ | |
|         +-------------+ |
+-------------------------+

Creation of representor ports can be achieved either through the --vdev EAL
option or through the rte_vdev_init() API. Each port representor requires the
BDF of it's parent PF and the Virtual Function ID of the port which the
representor will support. During initialization of the representor PMD, it calls
the broker API to register itself with the PF PMD and to get it's context
configured which includes the setting up of it's context and ops function
handlers.

As the port representor model is based around the paradigm of using standard
port based APIs, it will allow future expansion of functionality without the
need to add new APIs. For example it should be possible to support configuration
of egress QoS parameters using existing TM APIs by extending the port
representor PMD/broker infrastructure.


Changes in v2:
Rebased to DPDK 17.11

Changes in v3:
* Removed RTE_ETH_DEV_REPRESENTOR_PORT define
* Removed switch_domain from struct rte_eth_dev_info
  (to be reintroduced seperately when required).
* Port Representor PMD functionality merged into main library
* Removed functions from .map file that are not for use by applications
* Some minor bugfixes (uninitalised variables & NULL terminators)
* Use of SPDX licence headers in new files
* Seperate headers for PMD and application
* SPDX-License-Identifier in new files
* Added test-pmd representor add/del commands


Remy Horton (5):
  lib: add Port Representor library
  eal: add Port Representor command-line option
  drivers/net/i40e: add Port Representor functionality
  drivers/net/ixgbe: add Port Representor functionality
  app/test-pmd: add Port Representor commands

 app/test-pmd/cmdline.c                             |  88 ++++
 config/common_base                                 |   5 +
 drivers/net/i40e/Makefile                          |   1 +
 drivers/net/i40e/i40e_ethdev.c                     |  16 +
 drivers/net/i40e/i40e_ethdev.h                     |   1 +
 drivers/net/i40e/i40e_prep_ops.c                   | 495 +++++++++++++++++++++
 drivers/net/i40e/i40e_prep_ops.h                   |  15 +
 drivers/net/i40e/rte_pmd_i40e.c                    |  47 ++
 drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
 drivers/net/ixgbe/Makefile                         |   1 +
 drivers/net/ixgbe/ixgbe_ethdev.c                   |  22 +-
 drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
 drivers/net/ixgbe/ixgbe_prep_ops.c                 | 259 +++++++++++
 drivers/net/ixgbe/ixgbe_prep_ops.h                 |  15 +
 lib/Makefile                                       |   3 +
 lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
 lib/librte_eal/common/eal_common_options.c         |   1 +
 lib/librte_eal/common/eal_internal_cfg.h           |   2 +
 lib/librte_eal/common/eal_options.h                |   2 +
 lib/librte_eal/common/include/rte_eal.h            |   8 +
 lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 326 ++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 +++
 .../rte_port_representor_driver.h                  | 138 ++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 27 files changed, 1577 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/i40e/i40e_prep_ops.c
 create mode 100644 drivers/net/i40e/i40e_prep_ops.h
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [DPDK 1/5] lib: add Port Representor library
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
@ 2017-12-22 14:41   ` Remy Horton
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 2/5] eal: add Port Representor command-line option Remy Horton
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:41 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu, Declan Doherty, Mohammad Abdul Awal

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>
---
 config/common_base                                 |   5 +
 lib/Makefile                                       |   3 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 326 +++++++++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 ++++
 .../rte_port_representor_driver.h                  | 138 +++++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 8 files changed, 567 insertions(+)
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

diff --git a/config/common_base b/config/common_base
index e74febe..febb80a 100644
--- a/config/common_base
+++ b/config/common_base
@@ -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
diff --git a/lib/Makefile b/lib/Makefile
index dc4e8df..b9202ff 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -101,6 +101,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
diff --git a/lib/librte_representor/Makefile b/lib/librte_representor/Makefile
new file mode 100644
index 0000000..4060cc6
--- /dev/null
+++ b/lib/librte_representor/Makefile
@@ -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
diff --git a/lib/librte_representor/rte_port_representor.c b/lib/librte_representor/rte_port_representor.c
new file mode 100644
index 0000000..69a4bfc
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.c
@@ -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;
+}
diff --git a/lib/librte_representor/rte_port_representor.h b/lib/librte_representor/rte_port_representor.h
new file mode 100644
index 0000000..ff0c567
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.h
@@ -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
+ * @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
+ * @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_ */
diff --git a/lib/librte_representor/rte_port_representor_driver.h b/lib/librte_representor/rte_port_representor_driver.h
new file mode 100644
index 0000000..8827ebb
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_driver.h
@@ -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_ */
diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
new file mode 100644
index 0000000..b26600c
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_version.map
@@ -0,0 +1,8 @@
+DPDK_18.02 {
+	global:
+
+	rte_representor_port_register;
+	rte_representor_port_unregister;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6a6a745..67266bf 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -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
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [DPDK 2/5] eal: add Port Representor command-line option
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 1/5] lib: add Port Representor library Remy Horton
@ 2017-12-22 14:41   ` Remy Horton
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:41 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu, Declan Doherty, Mohammad Abdul Awal

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.

By default the Port Representor infrastructure is not enabled. This
patch implements the --enable-representor EAL command-line parameter
that activates representation functionality.

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>
---
 lib/librte_eal/bsdapp/eal/eal.c            | 6 ++++++
 lib/librte_eal/common/eal_common_options.c | 1 +
 lib/librte_eal/common/eal_internal_cfg.h   | 2 ++
 lib/librte_eal/common/eal_options.h        | 2 ++
 lib/librte_eal/common/include/rte_eal.h    | 8 ++++++++
 lib/librte_eal/linuxapp/eal/eal.c          | 9 +++++++++
 6 files changed, 28 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 369a682..002200a 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -778,3 +778,9 @@ int rte_vfio_noiommu_is_enabled(void)
 {
 	return 0;
 }
+
+/* return non-zero if port-representor is enabled. */
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 996a034..6f2cc05 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -78,6 +78,7 @@ const struct option
 eal_long_options[] = {
 	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
 	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
+	{OPT_ENABLE_REPRESENTOR, 0, NULL, OPT_ENABLE_REPRESENTOR_NUM   },
 	{OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
 	{OPT_HELP,              0, NULL, OPT_HELP_NUM             },
 	{OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index fa6ccbe..55cae8c 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -71,6 +71,8 @@ struct internal_config {
 										* instead of native TSC */
 	volatile unsigned no_shconf;      /**< true if there is no shared config */
 	volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */
+	volatile unsigned enable_representor;
+	/**< true to enable port representor broker for all PFs */
 	volatile enum rte_proc_type_t process_type; /**< multi-process proc type */
 	/** true to try allocating memory on specific sockets */
 	volatile unsigned force_sockets;
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 30e6bb4..c2b2162 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -83,6 +83,8 @@ enum {
 	OPT_VFIO_INTR_NUM,
 #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
 	OPT_VMWARE_TSC_MAP_NUM,
+#define OPT_ENABLE_REPRESENTOR    "enable-representor"
+	OPT_ENABLE_REPRESENTOR_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
index 8e4e71c..c4e61d1 100644
--- a/lib/librte_eal/common/include/rte_eal.h
+++ b/lib/librte_eal/common/include/rte_eal.h
@@ -335,6 +335,14 @@ enum rte_iova_mode rte_eal_iova_mode(void);
 const char *
 rte_eal_mbuf_default_mempool_ops(void);
 
+/**
+ * Get flag for port representor should be enabled or not.
+ *
+ * @return
+ *   Returns the enable-representor flag.
+ */
+int rte_representor_enabled(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 229eec9..364a8b2 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -612,6 +612,10 @@ eal_parse_args(int argc, char **argv)
 			internal_config.mbuf_pool_ops_name = optarg;
 			break;
 
+		case OPT_ENABLE_REPRESENTOR_NUM:
+			internal_config.enable_representor = 1;
+			break;
+
 		default:
 			if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
 				RTE_LOG(ERR, EAL, "Option %c is not supported "
@@ -1041,3 +1045,8 @@ rte_eal_check_module(const char *module_name)
 	/* Module has been found */
 	return 1;
 }
+
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [DPDK 3/5] drivers/net/i40e: add Port Representor functionality
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 1/5] lib: add Port Representor library Remy Horton
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 2/5] eal: add Port Representor command-line option Remy Horton
@ 2017-12-22 14:41   ` Remy Horton
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 4/5] drivers/net/ixgbe: " Remy Horton
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:41 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu, Declan Doherty, Mohammad Abdul Awal

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.

This patch adds to the i40e PMD the functions required to enable port
representor functionality.

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>
---
 drivers/net/i40e/Makefile        |   1 +
 drivers/net/i40e/i40e_ethdev.c   |  16 ++
 drivers/net/i40e/i40e_ethdev.h   |   1 +
 drivers/net/i40e/i40e_prep_ops.c | 495 +++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_prep_ops.h |  15 ++
 drivers/net/i40e/rte_pmd_i40e.c  |  47 ++++
 drivers/net/i40e/rte_pmd_i40e.h  |  18 ++
 7 files changed, 593 insertions(+)
 create mode 100644 drivers/net/i40e/i40e_prep_ops.c
 create mode 100644 drivers/net/i40e/i40e_prep_ops.h

diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 9ab8c84..641bf26 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -113,6 +113,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_prep_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 811cc9f..65bb320 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -67,6 +67,7 @@
 #include "i40e_pf.h"
 #include "i40e_regs.h"
 #include "rte_pmd_i40e.h"
+#include "i40e_prep_ops.h"
 
 #define ETH_I40E_FLOATING_VEB_ARG	"enable_floating_veb"
 #define ETH_I40E_FLOATING_VEB_LIST_ARG	"floating_veb_list"
@@ -1122,6 +1123,17 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	hw->bus.func = pci_dev->addr.function;
 	hw->adapter_stopped = 0;
 
+	/* init representor broker */
+	if (rte_representor_enabled()) {
+		ret = i40e_port_representor_broker_init(dev, &pf->broker,
+			pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Make sure all is clean before doing PF reset */
 	i40e_clear_hw(hw);
 
@@ -1457,6 +1469,10 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	intr_handle = &pci_dev->intr_handle;
 
+	/* free port representor pmds */
+	if (rte_representor_enabled())
+		rte_representor_broker_uninit(pf->broker);
+
 	if (hw->adapter_stopped == 0)
 		i40e_dev_close(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index cd67453..9e962eb 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -957,6 +957,7 @@ struct i40e_pf {
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
 	struct i40e_tm_conf tm_conf;
+	struct rte_representor_broker *broker;
 
 	/* Dynamic Device Personalization */
 	bool gtp_support; /* 1 - support GTP-C and GTP-U */
diff --git a/drivers/net/i40e/i40e_prep_ops.c b/drivers/net/i40e/i40e_prep_ops.c
new file mode 100644
index 0000000..41ce4d4
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.c
@@ -0,0 +1,495 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#include <rte_bus_pci.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "base/i40e_type.h"
+#include "base/virtchnl.h"
+#include "i40e_ethdev.h"
+#include "i40e_rxtx.h"
+#include "rte_pmd_i40e.h"
+
+#include "i40e_prep_ops.h"
+
+struct i40e_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+i40e_representor_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return i40e_dev_link_update(i40e_priv_data->pf_ethdev,
+		wait_to_complete);
+}
+
+static void
+i40e_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (!is_i40e_supported(i40e_priv_data->pf_ethdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(
+		i40e_priv_data->pf_ethdev->data->dev_private);
+	if (representor->vport_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return;
+	}
+
+	vf = &pf->vfs[representor->vport_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return;
+	}
+
+	/* get dev info for the vdev */
+	dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(ethdev);
+	dev_info->max_rx_queues = vsi->nb_qps;
+	dev_info->max_tx_queues = vsi->nb_qps;
+	dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN;
+	dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
+	dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) *
+		sizeof(uint32_t);
+	dev_info->reta_size = ETH_RSS_RETA_SIZE_64;
+	dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL;
+	dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX;
+	dev_info->rx_offload_capa =
+		DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_QINQ_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |
+		DEV_RX_OFFLOAD_UDP_CKSUM |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	dev_info->tx_offload_capa =
+		DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_QINQ_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM |
+		DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM |
+		DEV_TX_OFFLOAD_SCTP_CKSUM;
+
+	dev_info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_thresh = {
+			.pthresh = I40E_DEFAULT_RX_PTHRESH,
+			.hthresh = I40E_DEFAULT_RX_HTHRESH,
+			.wthresh = I40E_DEFAULT_RX_WTHRESH,
+		},
+		.rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH,
+		.rx_drop_en = 0,
+	};
+
+	dev_info->default_txconf = (struct rte_eth_txconf) {
+		.tx_thresh = {
+			.pthresh = I40E_DEFAULT_TX_PTHRESH,
+			.hthresh = I40E_DEFAULT_TX_HTHRESH,
+			.wthresh = I40E_DEFAULT_TX_WTHRESH,
+		},
+		.tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH,
+		.tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH,
+		.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
+				ETH_TXQ_FLAGS_NOOFFLOADS,
+	};
+
+	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+
+	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+}
+
+static int i40e_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int i40e_representor_rx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int i40e_representor_tx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int i40e_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void i40e_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+i40e_representor_stats_get(struct rte_eth_dev *ethdev,
+		struct rte_eth_stats *stats)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_get_vf_stats(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, stats);
+}
+
+static void
+i40e_representor_stats_reset(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_reset_vf_stats(i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id);
+}
+
+static void
+i40e_representor_promiscuous_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_promiscuous_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_allmulticast_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_allmulticast_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_remove_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, &ethdev->data->mac_addrs[index]);
+}
+
+static void
+i40e_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+		struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, mac_addr);
+}
+
+static int
+i40e_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+		uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	vfid = representor->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_i40e_set_vf_vlan_filter(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		vlan_id, vf_mask, on);
+}
+
+static int
+i40e_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct rte_eth_dev *pdev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+	uint32_t vfid;
+
+	pdev = i40e_priv_data->pf_ethdev;
+	vfid = representor->vport_id;
+
+	if (!is_i40e_supported(pdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return -EINVAL;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(pdev->data->dev_private);
+
+	if (vfid >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return -EINVAL;
+	}
+
+	vf = &pf->vfs[vfid];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Fixme: even though there 3 kinds of hw offloads, hw_vlan_filter,
+	 * hw_vlan_strip, and hw_vlan_extend.
+	 * currently the hw_vlan_extend offload by vsi is not implemented.
+	 */
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		/* Enable or disable VLAN filtering offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_filter)
+			return i40e_vsi_config_vlan_filter(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_filter(vsi, FALSE);
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK) {
+		/* Enable or disable VLAN stripping offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_strip)
+			return i40e_vsi_config_vlan_stripping(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_stripping(vsi, FALSE);
+	}
+
+	return -EINVAL;
+}
+
+static void
+i40e_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_vlan_stripq(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, on);
+}
+
+static int
+i40e_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id,
+	__rte_unused int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_set_vf_vlan_insert(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, vlan_id);
+}
+
+struct eth_dev_ops i40e_representor_dev_ops = {
+	.link_update          = i40e_representor_link_update,
+	.dev_infos_get        = i40e_representor_dev_infos_get,
+	.dev_configure        = i40e_representor_dev_configure,
+	.rx_queue_setup       = i40e_representor_rx_queue_setup,
+	.tx_queue_setup       = i40e_representor_tx_queue_setup,
+	.dev_start            = i40e_representor_dev_start,
+	.dev_stop             = i40e_representor_dev_stop,
+
+	.stats_get            = i40e_representor_stats_get,
+	.stats_reset          = i40e_representor_stats_reset,
+
+	.promiscuous_enable   = i40e_representor_promiscuous_enable,
+	.promiscuous_disable  = i40e_representor_promiscuous_disable,
+
+	.allmulticast_enable  = i40e_representor_allmulticast_enable,
+	.allmulticast_disable = i40e_representor_allmulticast_disable,
+
+	.mac_addr_remove      = i40e_representor_mac_addr_remove,
+	.mac_addr_set         = i40e_representor_mac_addr_set,
+
+	.vlan_filter_set      = i40e_representor_vlan_filter_set,
+	.vlan_offload_set     = i40e_representor_vlan_offload_set,
+	.vlan_strip_queue_set = i40e_representor_vlan_strip_queue_set,
+	.vlan_pvid_set        = i40e_representor_vlan_pvid_set
+};
+
+static uint16_t i40e_prep_rx_burst(__rte_unused void *rxq,
+	__rte_unused struct rte_mbuf **rx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static uint16_t i40e_prep_tx_burst(__rte_unused void *txq,
+	__rte_unused struct rte_mbuf **tx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static int
+i40e_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port;
+	struct i40e_pf *i40e_pf;
+	struct i40e_pf_vf *i40e_vf;
+
+	port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("i40e_port_representor_priv_data",
+			sizeof(struct i40e_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct i40e_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+
+	i40e_pf = I40E_DEV_PRIVATE_TO_PF(pf_ethdev->data->dev_private);
+	i40e_vf = &i40e_pf->vfs[port->vport_id];
+
+	if (!i40e_vf->vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &i40e_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = i40e_vf->vsi->nb_qps;
+	ethdev->data->nb_tx_queues = i40e_vf->vsi->nb_qps;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = i40e_prep_rx_burst;
+	ethdev->tx_pkt_burst = i40e_prep_tx_burst;
+
+	return 0;
+}
+
+static int
+i40e_port_representor_uninit(struct rte_representor_broker *broker __rte_unused,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops i40e_broker_port_ops = {
+	.port_init = i40e_port_representor_init,
+	.port_uninit = i40e_port_representor_uninit
+};
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set i40e broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &i40e_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
diff --git a/drivers/net/i40e/i40e_prep_ops.h b/drivers/net/i40e/i40e_prep_ops.h
new file mode 100644
index 0000000..8e28b9e
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _I40E_PREP_OPS_H_
+#define _I40E_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _I40E_PREP_OPS_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index aeb92af..641a35c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -599,6 +599,53 @@ rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 	return 0;
 }
 
+static const struct ether_addr null_mac_addr;
+
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+		return -EINVAL;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs)
+		return -EINVAL;
+
+	vf = &pf->vfs[vf_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	if (!is_same_ether_addr(mac_addr, &vf->mac_addr)) {
+		PMD_DRV_LOG(ERR, "Mac address does not match.");
+		return -EINVAL;
+	}
+
+	/* reset the mac with null mac */
+	ether_addr_copy(&null_mac_addr, &vf->mac_addr);
+
+	/* Remove the mac */
+	i40e_vsi_delete_mac(vsi, mac_addr);
+
+	return 0;
+}
+
 /* Set vlan strip on/off for specific VF from host */
 int
 rte_pmd_i40e_set_vf_vlan_stripq(uint16_t port, uint16_t vf_id, uint8_t on)
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 580ca4a..1b1f725 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -467,6 +467,24 @@ int rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
 /**
+ * Remove the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf_id
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr);
+
+/**
  * Enable/Disable vf vlan strip for all queues in a pool
  *
  * @param port
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [DPDK 4/5] drivers/net/ixgbe: add Port Representor functionality
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
                     ` (2 preceding siblings ...)
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
@ 2017-12-22 14:41   ` Remy Horton
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 5/5] app/test-pmd: add Port Representor commands Remy Horton
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:41 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu, Declan Doherty, Mohammad Abdul Awal

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.

This patch adds to the ixgbe PMD PMD the functions required to enable
port representor functionality.

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>
---
 drivers/net/ixgbe/Makefile         |   1 +
 drivers/net/ixgbe/ixgbe_ethdev.c   |  22 +++-
 drivers/net/ixgbe/ixgbe_ethdev.h   |   5 +
 drivers/net/ixgbe/ixgbe_prep_ops.c | 259 +++++++++++++++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_prep_ops.h |  15 +++
 5 files changed, 301 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h

diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index 511a64e..4ec2422 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -130,6 +130,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_ipsec.c
 endif
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += rte_pmd_ixgbe.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_prep_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_IXGBE_PMD)-include := rte_pmd_ixgbe.h
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ff19a56..a48b783 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -75,6 +75,7 @@
 #include "base/ixgbe_type.h"
 #include "base/ixgbe_phy.h"
 #include "ixgbe_regs.h"
+#include "ixgbe_prep_ops.h"
 
 /*
  * High threshold controlling when to start sending XOFF frames. Must be at
@@ -1138,6 +1139,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 	uint32_t ctrl_ext;
 	uint16_t csum;
 	int diag, i;
+	int ret;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1261,6 +1265,17 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 		return -EIO;
 	}
 
+	/* Init port representor broker */
+	if (rte_representor_enabled()) {
+		ret = ixgbe_port_representor_broker_init(eth_dev,
+			&eth_adapter->broker, pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Reset the hw statistics */
 	ixgbe_dev_stats_reset(eth_dev);
 
@@ -1363,6 +1378,8 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	struct ixgbe_hw *hw;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1371,6 +1388,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
 
+	if (rte_representor_enabled())
+		rte_representor_broker_uninit(eth_adapter->broker);
+
 	if (hw->adapter_stopped == 0)
 		ixgbe_dev_close(eth_dev);
 
@@ -3962,7 +3982,7 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 }
 
 /* return 0 means link status changed, -1 means not changed */
-static int
+int
 ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 			    int wait_to_complete, int vf)
 {
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 51ddcfd..4cc2cf0 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -499,6 +499,7 @@ struct ixgbe_adapter {
 	struct rte_timecounter      rx_tstamp_tc;
 	struct rte_timecounter      tx_tstamp_tc;
  	struct ixgbe_tm_conf        tm_conf;
+	struct rte_representor_broker *broker;
 };
 
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
@@ -673,6 +674,10 @@ int ixgbe_fdir_filter_program(struct rte_eth_dev *dev,
 
 void ixgbe_configure_dcb(struct rte_eth_dev *dev);
 
+int
+ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
+			    int wait_to_complete, int vf);
+
 /*
  * misc function prototypes
  */
diff --git a/drivers/net/ixgbe/ixgbe_prep_ops.c b/drivers/net/ixgbe/ixgbe_prep_ops.c
new file mode 100644
index 0000000..a06df27
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_prep_ops.c
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+#include <rte_port_representor_driver.h>
+
+#include "base/ixgbe_type.h"
+#include "base/ixgbe_vf.h"
+#include "ixgbe_ethdev.h"
+#include "ixgbe_rxtx.h"
+#include "rte_pmd_ixgbe.h"
+
+#include "ixgbe_prep_ops.h"
+
+struct ixgbe_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+ixgbe_representor_link_update(struct rte_eth_dev *ethdev,
+	int wait_to_complete)
+{
+	struct rte_representor_port *prep_priv_data =
+			ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+			prep_priv_data->priv_data;
+
+	return ixgbe_dev_link_update_share(ixgbe_priv_data->pf_ethdev,
+		wait_to_complete, 1);
+}
+
+static void
+ixgbe_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+	struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	rte_pmd_ixgbe_set_vf_mac_addr(ixgbe_priv_data->pf_ethdev->data->port_id,
+		prep_priv_data->vport_id, mac_addr);
+}
+
+static void
+ixgbe_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(
+		ixgbe_priv_data->pf_ethdev->data->dev_private);
+
+	dev_info->pci_dev = NULL;
+
+	dev_info->min_rx_bufsize = 1024;
+	/**< Minimum size of RX buffer. */
+	dev_info->max_rx_pktlen = 9728;
+	/**< Maximum configurable length of RX pkt. */
+	dev_info->max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	/**< Maximum number of RX queues. */
+	dev_info->max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+	/**< Maximum number of TX queues. */
+
+	dev_info->max_mac_addrs = hw->mac.num_rar_entries;
+	/**< Maximum number of MAC addresses. */
+
+	dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |	DEV_RX_OFFLOAD_UDP_CKSUM  |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	/**< Device RX offload capabilities. */
+
+	dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_TSO;
+	/**< Device TX offload capabilities. */
+
+	dev_info->speed_capa =
+		ixgbe_priv_data->pf_ethdev->data->dev_link.link_speed;
+	/**< Supported speeds bitmap (ETH_LINK_SPEED_). */
+}
+
+static int ixgbe_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int ixgbe_representor_rx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int ixgbe_representor_tx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int ixgbe_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void ixgbe_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+ixgbe_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+	uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_ixgbe_set_vf_vlan_filter(pfid, vlan_id, vf_mask, on);
+}
+
+static void
+ixgbe_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+
+	rte_pmd_ixgbe_set_vf_vlan_stripq(pfid, vfid, on);
+}
+
+struct eth_dev_ops ixgbe_representor_dev_ops = {
+	.link_update                  = ixgbe_representor_link_update,
+	.dev_infos_get                = ixgbe_representor_dev_infos_get,
+	.dev_configure	              = ixgbe_representor_dev_configure,
+	.rx_queue_setup               = ixgbe_representor_rx_queue_setup,
+	.tx_queue_setup               = ixgbe_representor_tx_queue_setup,
+	.dev_start                    = ixgbe_representor_dev_start,
+	.dev_stop                     = ixgbe_representor_dev_stop,
+	.mac_addr_set                 = ixgbe_representor_mac_addr_set,
+	.vlan_filter_set              = ixgbe_representor_vlan_filter_set,
+	.vlan_strip_queue_set         = ixgbe_representor_vlan_strip_queue_set
+};
+
+static int
+ixgbe_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("ixgbe_port_representor_priv_data",
+			sizeof(struct ixgbe_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct ixgbe_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &ixgbe_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	ethdev->data->nb_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = NULL;
+	ethdev->tx_pkt_burst = NULL;
+
+	return 0;
+}
+
+static int
+ixgbe_port_representor_uninit(
+	__rte_unused struct rte_representor_broker *broker,
+	struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops ixgbe_broker_port_ops = {
+	.port_init = ixgbe_port_representor_init,
+	.port_uninit = ixgbe_port_representor_uninit
+};
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set IXGBE broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &ixgbe_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
diff --git a/drivers/net/ixgbe/ixgbe_prep_ops.h b/drivers/net/ixgbe/ixgbe_prep_ops.h
new file mode 100644
index 0000000..744aa3e
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_prep_ops.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _IXGBE_PREP_OPS_H_
+#define _IXGBE_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _IXGBE_PREP_OPS_H_ */
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [DPDK 5/5] app/test-pmd: add Port Representor commands
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
                     ` (3 preceding siblings ...)
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 4/5] drivers/net/ixgbe: " Remy Horton
@ 2017-12-22 14:41   ` Remy Horton
  2017-12-22 15:09   ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
  2017-12-22 16:37   ` Neil Horman
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:41 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu

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.

This patch adds the 'add representor' and 'del representor' commands
to test-pmd, which respectively allow the adding and removing of
port representors.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/cmdline.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f71d963..1a831ba 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -76,6 +76,7 @@
 #include <rte_eth_ctrl.h>
 #include <rte_flow.h>
 #include <rte_gro.h>
+#include <rte_port_representor.h>
 
 #include <cmdline_rdline.h>
 #include <cmdline_parse.h>
@@ -15535,6 +15536,91 @@ cmdline_parse_inst_t cmd_load_from_file = {
 	},
 };
 
+struct cmd_add_representor_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t representor;
+	cmdline_fixed_string_t pf;
+	uint16_t vport;
+};
+
+cmdline_parse_token_string_t cmd_addrepresentor_add =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	cmd, "add");
+cmdline_parse_token_string_t cmd_addrepresentor_del =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	cmd, "del");
+cmdline_parse_token_string_t cmd_addrepresentor_rep =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	representor, "representor");
+cmdline_parse_token_string_t cmd_addrepresentor_pf =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	pf, NULL);
+cmdline_parse_token_num_t cmd_addrepresentor_vport =
+TOKEN_NUM_INITIALIZER(struct cmd_add_representor_result,
+	vport, UINT16);
+
+static void cmd_add_representor_callback(void *parsed_result,
+		__attribute__((unused))  struct cmdline *cl,
+		__attribute__((unused)) void *data)
+{
+	struct cmd_add_representor_result *res = parsed_result;
+	uint16_t port_id;
+	int ret;
+
+	rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "%s(): addr:%s vport:%i\n",
+		__func__, res->pf, res->vport);
+
+	ret = rte_representor_port_register(res->pf, res->vport, &port_id);
+	if (ret != 0)
+		printf("Registering port representor failed\n");
+	else
+		printf("Port Representor registered with port id %i\n",
+			port_id);
+}
+
+static void cmd_del_representor_callback(void *parsed_result,
+		__attribute__((unused))  struct cmdline *cl,
+		__attribute__((unused)) void *data)
+{
+	struct cmd_add_representor_result *res = parsed_result;
+	int ret;
+
+	rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "%s(): port:%i\n", __func__,
+		res->vport);
+	ret = rte_representor_port_unregister(res->pf, res->vport);
+	if (ret != 0)
+		printf("Port %i is not a valid port representor.\n",
+			res->vport);
+}
+
+cmdline_parse_inst_t cmd_add_representor = {
+	.f = cmd_add_representor_callback,
+	.help_str = "add representor <BusName_DomBDF> <vport_id> "
+		"Add a Port Representor",
+	.data = NULL,
+	.tokens = {
+		(void *)&cmd_addrepresentor_add,
+		(void *)&cmd_addrepresentor_rep,
+		(void *)&cmd_addrepresentor_pf,
+		(void *)&cmd_addrepresentor_vport,
+		NULL
+	}
+};
+
+cmdline_parse_inst_t cmd_del_representor = {
+	.f = cmd_del_representor_callback,
+	.help_str = "del representor <BusName_DomBDF> <vport_id> "
+		"Delete a Port Representor",
+	.data = NULL,
+	.tokens = {
+		(void *)&cmd_addrepresentor_del,
+		(void *)&cmd_addrepresentor_rep,
+		(void *)&cmd_addrepresentor_pf,
+		(void *)&cmd_addrepresentor_vport,
+		NULL
+	}
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -15576,6 +15662,8 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *) &cmd_show_bonding_config,
 	(cmdline_parse_inst_t *) &cmd_set_bonding_primary,
 	(cmdline_parse_inst_t *) &cmd_add_bonding_slave,
+	(cmdline_parse_inst_t *) &cmd_add_representor,
+	(cmdline_parse_inst_t *) &cmd_del_representor,
 	(cmdline_parse_inst_t *) &cmd_remove_bonding_slave,
 	(cmdline_parse_inst_t *) &cmd_create_bonded_device,
 	(cmdline_parse_inst_t *) &cmd_set_bond_mac_addr,
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v3 0/5] lib: add Port Representors
  2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
                   ` (6 preceding siblings ...)
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
@ 2017-12-22 14:52 ` Remy Horton
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 1/5] lib: add Port Representor library Remy Horton
                     ` (6 more replies)
  7 siblings, 7 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:52 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu

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.

+-----------------------------+   +---------------+  +---------------+
|        Control Plane        |   |   Data Plane  |  |   Data Plane  |
|         Application         |   |   Application |  |   Application |
+-----------------------------+   +---------------+  +---------------+
|         eth dev api         |   |  eth dev api  |  |  eth dev api  |
+-----------------------------+   +---------------+  +---------------+
+-------+  +-------+  +-------+   +---------------+  +---------------+
|  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
|  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
|       |  | PMD   |  | PMD   |                             |
+---+--^+  +-------+  +-+-----+                             |
    |  |                |  |                                |
    |  +----------------+  |                                |
    |                      |                                |
    |                      |                                |
+--------------------------------+                          |
|   |  HW (logical view)   |     |                          |
| --+------+ +-------+ +---+---+ |                          |
| |   PF   | |  VF0  | |  VF1  | |                          |
| |        | |       | |       +----------------------------+
| +--------+ +-------+ +-------+ |
| +----------------------------+ |
| |        VEB                 | |
| +----------------------------+ |
| +--------+                     |
| |  Port  |                     |
| |   0    |                     |
| +--------+                     |
+--------------------------------+

The figure above shows a deployment where the PF is bound to a DPDK control
plane application which uses representor ports to manage the configuration and
monitoring of it's VF ports. Each virtual function is represented in the
application by a representor port PMD which enables control of the corresponding
VF through eth dev APIs on the representor PMD such as:

- void rte_eth_promiscuous_enable(uint8_t port_id);
- void rte_eth_promiscuous_disable(uint8_t port_id);
- void rte_eth_allmulticast_enable(uint8_t port_id);
- void rte_eth_allmulticast_disable(uint8_t port_id);
- int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
	uint32_t pool);
- int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);

as well as monitoring through API's like

- void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
- int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);

The port representor infrastructure is enabled through a single common, device
independent, virtual PMD whos context is initialized and enabled through a
broker instance running within the context of the physical function device
driver.

+-------------------------+       +-------------------------+
|        rte_ethdev       |       |       rte_ethdev        |
+-------------------------+       +-------------------------+
|  Physical Function PMD  |       |  Port Reperesentor PMD  |
|         +-------------+ |       | +---------+ +---------+ |
|         | Representor | |       | | dev_data| | dev_ops | |
|         |    Broker   | |       | +----+----+ +----+----+ |
|         | +---------+ | |       +------|-----------|------+
|         | | VF Port | | |              |           |
|         | | Context +------------------+           |
|         | +---------+ | |                          |
|         | +---------+ | |                          |
|         | | Handler +------------------------------+
|         | |   Ops   | | |
|         | +---------+ | |
|         +-------------+ |
+-------------------------+

Creation of representor ports can be achieved either through the --vdev EAL
option or through the rte_vdev_init() API. Each port representor requires the
BDF of it's parent PF and the Virtual Function ID of the port which the
representor will support. During initialization of the representor PMD, it calls
the broker API to register itself with the PF PMD and to get it's context
configured which includes the setting up of it's context and ops function
handlers.

As the port representor model is based around the paradigm of using standard
port based APIs, it will allow future expansion of functionality without the
need to add new APIs. For example it should be possible to support configuration
of egress QoS parameters using existing TM APIs by extending the port
representor PMD/broker infrastructure.

Changes in v2:
* Rebased to DPDK 17.11

Changes in v3:
* Removed RTE_ETH_DEV_REPRESENTOR_PORT define
* Removed switch_domain from struct rte_eth_dev_info
  (to be reintroduced seperately when required).
* Port Representor PMD functionality merged into main library
* Removed functions from .map file that are not for use by applications
* Some minor bugfixes (uninitalised variables & NULL terminators)
* Use of SPDX licence headers in new files
* Seperate headers for PMD and application
* SPDX-License-Identifier in new files
* Added test-pmd representor add/del commands


Remy Horton (5):
  lib: add Port Representor library
  eal: add Port Representor command-line option
  drivers/net/i40e: add Port Representor functionality
  drivers/net/ixgbe: add Port Representor functionality
  app/test-pmd: add Port Representor commands

 app/test-pmd/cmdline.c                             |  88 ++++
 config/common_base                                 |   5 +
 drivers/net/i40e/Makefile                          |   1 +
 drivers/net/i40e/i40e_ethdev.c                     |  16 +
 drivers/net/i40e/i40e_ethdev.h                     |   1 +
 drivers/net/i40e/i40e_prep_ops.c                   | 495 +++++++++++++++++++++
 drivers/net/i40e/i40e_prep_ops.h                   |  15 +
 drivers/net/i40e/rte_pmd_i40e.c                    |  47 ++
 drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
 drivers/net/ixgbe/Makefile                         |   1 +
 drivers/net/ixgbe/ixgbe_ethdev.c                   |  22 +-
 drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
 drivers/net/ixgbe/ixgbe_prep_ops.c                 | 259 +++++++++++
 drivers/net/ixgbe/ixgbe_prep_ops.h                 |  15 +
 lib/Makefile                                       |   3 +
 lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
 lib/librte_eal/common/eal_common_options.c         |   1 +
 lib/librte_eal/common/eal_internal_cfg.h           |   2 +
 lib/librte_eal/common/eal_options.h                |   2 +
 lib/librte_eal/common/include/rte_eal.h            |   8 +
 lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 326 ++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 +++
 .../rte_port_representor_driver.h                  | 138 ++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 27 files changed, 1577 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/i40e/i40e_prep_ops.c
 create mode 100644 drivers/net/i40e/i40e_prep_ops.h
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v3 1/5] lib: add Port Representor library
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
@ 2017-12-22 14:52   ` Remy Horton
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 2/5] eal: add Port Representor command-line option Remy Horton
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:52 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu, Declan Doherty, Mohammad Abdul Awal

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>
---
 config/common_base                                 |   5 +
 lib/Makefile                                       |   3 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 326 +++++++++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 ++++
 .../rte_port_representor_driver.h                  | 138 +++++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 8 files changed, 567 insertions(+)
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

diff --git a/config/common_base b/config/common_base
index e74febe..febb80a 100644
--- a/config/common_base
+++ b/config/common_base
@@ -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
diff --git a/lib/Makefile b/lib/Makefile
index dc4e8df..b9202ff 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -101,6 +101,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
diff --git a/lib/librte_representor/Makefile b/lib/librte_representor/Makefile
new file mode 100644
index 0000000..4060cc6
--- /dev/null
+++ b/lib/librte_representor/Makefile
@@ -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
diff --git a/lib/librte_representor/rte_port_representor.c b/lib/librte_representor/rte_port_representor.c
new file mode 100644
index 0000000..69a4bfc
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.c
@@ -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;
+}
diff --git a/lib/librte_representor/rte_port_representor.h b/lib/librte_representor/rte_port_representor.h
new file mode 100644
index 0000000..ff0c567
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.h
@@ -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
+ * @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
+ * @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_ */
diff --git a/lib/librte_representor/rte_port_representor_driver.h b/lib/librte_representor/rte_port_representor_driver.h
new file mode 100644
index 0000000..8827ebb
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_driver.h
@@ -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_ */
diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
new file mode 100644
index 0000000..b26600c
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_version.map
@@ -0,0 +1,8 @@
+DPDK_18.02 {
+	global:
+
+	rte_representor_port_register;
+	rte_representor_port_unregister;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6a6a745..67266bf 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -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
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v3 2/5] eal: add Port Representor command-line option
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 1/5] lib: add Port Representor library Remy Horton
@ 2017-12-22 14:52   ` Remy Horton
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:52 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu, Declan Doherty, Mohammad Abdul Awal

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.

By default the Port Representor infrastructure is not enabled. This
patch implements the --enable-representor EAL command-line parameter
that activates representation functionality.

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>
---
 lib/librte_eal/bsdapp/eal/eal.c            | 6 ++++++
 lib/librte_eal/common/eal_common_options.c | 1 +
 lib/librte_eal/common/eal_internal_cfg.h   | 2 ++
 lib/librte_eal/common/eal_options.h        | 2 ++
 lib/librte_eal/common/include/rte_eal.h    | 8 ++++++++
 lib/librte_eal/linuxapp/eal/eal.c          | 9 +++++++++
 6 files changed, 28 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 369a682..002200a 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -778,3 +778,9 @@ int rte_vfio_noiommu_is_enabled(void)
 {
 	return 0;
 }
+
+/* return non-zero if port-representor is enabled. */
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 996a034..6f2cc05 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -78,6 +78,7 @@ const struct option
 eal_long_options[] = {
 	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
 	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
+	{OPT_ENABLE_REPRESENTOR, 0, NULL, OPT_ENABLE_REPRESENTOR_NUM   },
 	{OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
 	{OPT_HELP,              0, NULL, OPT_HELP_NUM             },
 	{OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index fa6ccbe..55cae8c 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -71,6 +71,8 @@ struct internal_config {
 										* instead of native TSC */
 	volatile unsigned no_shconf;      /**< true if there is no shared config */
 	volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */
+	volatile unsigned enable_representor;
+	/**< true to enable port representor broker for all PFs */
 	volatile enum rte_proc_type_t process_type; /**< multi-process proc type */
 	/** true to try allocating memory on specific sockets */
 	volatile unsigned force_sockets;
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 30e6bb4..c2b2162 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -83,6 +83,8 @@ enum {
 	OPT_VFIO_INTR_NUM,
 #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
 	OPT_VMWARE_TSC_MAP_NUM,
+#define OPT_ENABLE_REPRESENTOR    "enable-representor"
+	OPT_ENABLE_REPRESENTOR_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
index 8e4e71c..c4e61d1 100644
--- a/lib/librte_eal/common/include/rte_eal.h
+++ b/lib/librte_eal/common/include/rte_eal.h
@@ -335,6 +335,14 @@ enum rte_iova_mode rte_eal_iova_mode(void);
 const char *
 rte_eal_mbuf_default_mempool_ops(void);
 
+/**
+ * Get flag for port representor should be enabled or not.
+ *
+ * @return
+ *   Returns the enable-representor flag.
+ */
+int rte_representor_enabled(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 229eec9..364a8b2 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -612,6 +612,10 @@ eal_parse_args(int argc, char **argv)
 			internal_config.mbuf_pool_ops_name = optarg;
 			break;
 
+		case OPT_ENABLE_REPRESENTOR_NUM:
+			internal_config.enable_representor = 1;
+			break;
+
 		default:
 			if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
 				RTE_LOG(ERR, EAL, "Option %c is not supported "
@@ -1041,3 +1045,8 @@ rte_eal_check_module(const char *module_name)
 	/* Module has been found */
 	return 1;
 }
+
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v3 3/5] drivers/net/i40e: add Port Representor functionality
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 1/5] lib: add Port Representor library Remy Horton
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 2/5] eal: add Port Representor command-line option Remy Horton
@ 2017-12-22 14:52   ` Remy Horton
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 4/5] drivers/net/ixgbe: " Remy Horton
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:52 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu, Declan Doherty, Mohammad Abdul Awal

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.

This patch adds to the i40e PMD the functions required to enable port
representor functionality.

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>
---
 drivers/net/i40e/Makefile        |   1 +
 drivers/net/i40e/i40e_ethdev.c   |  16 ++
 drivers/net/i40e/i40e_ethdev.h   |   1 +
 drivers/net/i40e/i40e_prep_ops.c | 495 +++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_prep_ops.h |  15 ++
 drivers/net/i40e/rte_pmd_i40e.c  |  47 ++++
 drivers/net/i40e/rte_pmd_i40e.h  |  18 ++
 7 files changed, 593 insertions(+)
 create mode 100644 drivers/net/i40e/i40e_prep_ops.c
 create mode 100644 drivers/net/i40e/i40e_prep_ops.h

diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 9ab8c84..641bf26 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -113,6 +113,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_prep_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 811cc9f..65bb320 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -67,6 +67,7 @@
 #include "i40e_pf.h"
 #include "i40e_regs.h"
 #include "rte_pmd_i40e.h"
+#include "i40e_prep_ops.h"
 
 #define ETH_I40E_FLOATING_VEB_ARG	"enable_floating_veb"
 #define ETH_I40E_FLOATING_VEB_LIST_ARG	"floating_veb_list"
@@ -1122,6 +1123,17 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	hw->bus.func = pci_dev->addr.function;
 	hw->adapter_stopped = 0;
 
+	/* init representor broker */
+	if (rte_representor_enabled()) {
+		ret = i40e_port_representor_broker_init(dev, &pf->broker,
+			pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Make sure all is clean before doing PF reset */
 	i40e_clear_hw(hw);
 
@@ -1457,6 +1469,10 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	intr_handle = &pci_dev->intr_handle;
 
+	/* free port representor pmds */
+	if (rte_representor_enabled())
+		rte_representor_broker_uninit(pf->broker);
+
 	if (hw->adapter_stopped == 0)
 		i40e_dev_close(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index cd67453..9e962eb 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -957,6 +957,7 @@ struct i40e_pf {
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
 	struct i40e_tm_conf tm_conf;
+	struct rte_representor_broker *broker;
 
 	/* Dynamic Device Personalization */
 	bool gtp_support; /* 1 - support GTP-C and GTP-U */
diff --git a/drivers/net/i40e/i40e_prep_ops.c b/drivers/net/i40e/i40e_prep_ops.c
new file mode 100644
index 0000000..41ce4d4
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.c
@@ -0,0 +1,495 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#include <rte_bus_pci.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "base/i40e_type.h"
+#include "base/virtchnl.h"
+#include "i40e_ethdev.h"
+#include "i40e_rxtx.h"
+#include "rte_pmd_i40e.h"
+
+#include "i40e_prep_ops.h"
+
+struct i40e_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+i40e_representor_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return i40e_dev_link_update(i40e_priv_data->pf_ethdev,
+		wait_to_complete);
+}
+
+static void
+i40e_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (!is_i40e_supported(i40e_priv_data->pf_ethdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(
+		i40e_priv_data->pf_ethdev->data->dev_private);
+	if (representor->vport_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return;
+	}
+
+	vf = &pf->vfs[representor->vport_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return;
+	}
+
+	/* get dev info for the vdev */
+	dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(ethdev);
+	dev_info->max_rx_queues = vsi->nb_qps;
+	dev_info->max_tx_queues = vsi->nb_qps;
+	dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN;
+	dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
+	dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) *
+		sizeof(uint32_t);
+	dev_info->reta_size = ETH_RSS_RETA_SIZE_64;
+	dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL;
+	dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX;
+	dev_info->rx_offload_capa =
+		DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_QINQ_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |
+		DEV_RX_OFFLOAD_UDP_CKSUM |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	dev_info->tx_offload_capa =
+		DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_QINQ_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM |
+		DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM |
+		DEV_TX_OFFLOAD_SCTP_CKSUM;
+
+	dev_info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_thresh = {
+			.pthresh = I40E_DEFAULT_RX_PTHRESH,
+			.hthresh = I40E_DEFAULT_RX_HTHRESH,
+			.wthresh = I40E_DEFAULT_RX_WTHRESH,
+		},
+		.rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH,
+		.rx_drop_en = 0,
+	};
+
+	dev_info->default_txconf = (struct rte_eth_txconf) {
+		.tx_thresh = {
+			.pthresh = I40E_DEFAULT_TX_PTHRESH,
+			.hthresh = I40E_DEFAULT_TX_HTHRESH,
+			.wthresh = I40E_DEFAULT_TX_WTHRESH,
+		},
+		.tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH,
+		.tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH,
+		.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
+				ETH_TXQ_FLAGS_NOOFFLOADS,
+	};
+
+	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+
+	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+}
+
+static int i40e_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int i40e_representor_rx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int i40e_representor_tx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int i40e_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void i40e_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+i40e_representor_stats_get(struct rte_eth_dev *ethdev,
+		struct rte_eth_stats *stats)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_get_vf_stats(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, stats);
+}
+
+static void
+i40e_representor_stats_reset(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_reset_vf_stats(i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id);
+}
+
+static void
+i40e_representor_promiscuous_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_promiscuous_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_allmulticast_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_allmulticast_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_remove_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, &ethdev->data->mac_addrs[index]);
+}
+
+static void
+i40e_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+		struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, mac_addr);
+}
+
+static int
+i40e_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+		uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	vfid = representor->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_i40e_set_vf_vlan_filter(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		vlan_id, vf_mask, on);
+}
+
+static int
+i40e_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct rte_eth_dev *pdev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+	uint32_t vfid;
+
+	pdev = i40e_priv_data->pf_ethdev;
+	vfid = representor->vport_id;
+
+	if (!is_i40e_supported(pdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return -EINVAL;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(pdev->data->dev_private);
+
+	if (vfid >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return -EINVAL;
+	}
+
+	vf = &pf->vfs[vfid];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Fixme: even though there 3 kinds of hw offloads, hw_vlan_filter,
+	 * hw_vlan_strip, and hw_vlan_extend.
+	 * currently the hw_vlan_extend offload by vsi is not implemented.
+	 */
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		/* Enable or disable VLAN filtering offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_filter)
+			return i40e_vsi_config_vlan_filter(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_filter(vsi, FALSE);
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK) {
+		/* Enable or disable VLAN stripping offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_strip)
+			return i40e_vsi_config_vlan_stripping(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_stripping(vsi, FALSE);
+	}
+
+	return -EINVAL;
+}
+
+static void
+i40e_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_vlan_stripq(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, on);
+}
+
+static int
+i40e_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id,
+	__rte_unused int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_set_vf_vlan_insert(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, vlan_id);
+}
+
+struct eth_dev_ops i40e_representor_dev_ops = {
+	.link_update          = i40e_representor_link_update,
+	.dev_infos_get        = i40e_representor_dev_infos_get,
+	.dev_configure        = i40e_representor_dev_configure,
+	.rx_queue_setup       = i40e_representor_rx_queue_setup,
+	.tx_queue_setup       = i40e_representor_tx_queue_setup,
+	.dev_start            = i40e_representor_dev_start,
+	.dev_stop             = i40e_representor_dev_stop,
+
+	.stats_get            = i40e_representor_stats_get,
+	.stats_reset          = i40e_representor_stats_reset,
+
+	.promiscuous_enable   = i40e_representor_promiscuous_enable,
+	.promiscuous_disable  = i40e_representor_promiscuous_disable,
+
+	.allmulticast_enable  = i40e_representor_allmulticast_enable,
+	.allmulticast_disable = i40e_representor_allmulticast_disable,
+
+	.mac_addr_remove      = i40e_representor_mac_addr_remove,
+	.mac_addr_set         = i40e_representor_mac_addr_set,
+
+	.vlan_filter_set      = i40e_representor_vlan_filter_set,
+	.vlan_offload_set     = i40e_representor_vlan_offload_set,
+	.vlan_strip_queue_set = i40e_representor_vlan_strip_queue_set,
+	.vlan_pvid_set        = i40e_representor_vlan_pvid_set
+};
+
+static uint16_t i40e_prep_rx_burst(__rte_unused void *rxq,
+	__rte_unused struct rte_mbuf **rx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static uint16_t i40e_prep_tx_burst(__rte_unused void *txq,
+	__rte_unused struct rte_mbuf **tx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static int
+i40e_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port;
+	struct i40e_pf *i40e_pf;
+	struct i40e_pf_vf *i40e_vf;
+
+	port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("i40e_port_representor_priv_data",
+			sizeof(struct i40e_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct i40e_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+
+	i40e_pf = I40E_DEV_PRIVATE_TO_PF(pf_ethdev->data->dev_private);
+	i40e_vf = &i40e_pf->vfs[port->vport_id];
+
+	if (!i40e_vf->vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &i40e_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = i40e_vf->vsi->nb_qps;
+	ethdev->data->nb_tx_queues = i40e_vf->vsi->nb_qps;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = i40e_prep_rx_burst;
+	ethdev->tx_pkt_burst = i40e_prep_tx_burst;
+
+	return 0;
+}
+
+static int
+i40e_port_representor_uninit(struct rte_representor_broker *broker __rte_unused,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops i40e_broker_port_ops = {
+	.port_init = i40e_port_representor_init,
+	.port_uninit = i40e_port_representor_uninit
+};
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set i40e broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &i40e_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
diff --git a/drivers/net/i40e/i40e_prep_ops.h b/drivers/net/i40e/i40e_prep_ops.h
new file mode 100644
index 0000000..8e28b9e
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _I40E_PREP_OPS_H_
+#define _I40E_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _I40E_PREP_OPS_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index aeb92af..641a35c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -599,6 +599,53 @@ rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 	return 0;
 }
 
+static const struct ether_addr null_mac_addr;
+
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+		return -EINVAL;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs)
+		return -EINVAL;
+
+	vf = &pf->vfs[vf_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	if (!is_same_ether_addr(mac_addr, &vf->mac_addr)) {
+		PMD_DRV_LOG(ERR, "Mac address does not match.");
+		return -EINVAL;
+	}
+
+	/* reset the mac with null mac */
+	ether_addr_copy(&null_mac_addr, &vf->mac_addr);
+
+	/* Remove the mac */
+	i40e_vsi_delete_mac(vsi, mac_addr);
+
+	return 0;
+}
+
 /* Set vlan strip on/off for specific VF from host */
 int
 rte_pmd_i40e_set_vf_vlan_stripq(uint16_t port, uint16_t vf_id, uint8_t on)
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 580ca4a..1b1f725 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -467,6 +467,24 @@ int rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
 /**
+ * Remove the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf_id
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr);
+
+/**
  * Enable/Disable vf vlan strip for all queues in a pool
  *
  * @param port
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v3 4/5] drivers/net/ixgbe: add Port Representor functionality
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
                     ` (2 preceding siblings ...)
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
@ 2017-12-22 14:52   ` Remy Horton
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 5/5] app/test-pmd: add Port Representor commands Remy Horton
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:52 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu, Declan Doherty, Mohammad Abdul Awal

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.

This patch adds to the ixgbe PMD PMD the functions required to enable
port representor functionality.

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>
---
 drivers/net/ixgbe/Makefile         |   1 +
 drivers/net/ixgbe/ixgbe_ethdev.c   |  22 +++-
 drivers/net/ixgbe/ixgbe_ethdev.h   |   5 +
 drivers/net/ixgbe/ixgbe_prep_ops.c | 259 +++++++++++++++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_prep_ops.h |  15 +++
 5 files changed, 301 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h

diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index 511a64e..4ec2422 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -130,6 +130,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_ipsec.c
 endif
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += rte_pmd_ixgbe.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_prep_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_IXGBE_PMD)-include := rte_pmd_ixgbe.h
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ff19a56..a48b783 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -75,6 +75,7 @@
 #include "base/ixgbe_type.h"
 #include "base/ixgbe_phy.h"
 #include "ixgbe_regs.h"
+#include "ixgbe_prep_ops.h"
 
 /*
  * High threshold controlling when to start sending XOFF frames. Must be at
@@ -1138,6 +1139,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 	uint32_t ctrl_ext;
 	uint16_t csum;
 	int diag, i;
+	int ret;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1261,6 +1265,17 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 		return -EIO;
 	}
 
+	/* Init port representor broker */
+	if (rte_representor_enabled()) {
+		ret = ixgbe_port_representor_broker_init(eth_dev,
+			&eth_adapter->broker, pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Reset the hw statistics */
 	ixgbe_dev_stats_reset(eth_dev);
 
@@ -1363,6 +1378,8 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	struct ixgbe_hw *hw;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1371,6 +1388,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
 
+	if (rte_representor_enabled())
+		rte_representor_broker_uninit(eth_adapter->broker);
+
 	if (hw->adapter_stopped == 0)
 		ixgbe_dev_close(eth_dev);
 
@@ -3962,7 +3982,7 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 }
 
 /* return 0 means link status changed, -1 means not changed */
-static int
+int
 ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 			    int wait_to_complete, int vf)
 {
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 51ddcfd..4cc2cf0 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -499,6 +499,7 @@ struct ixgbe_adapter {
 	struct rte_timecounter      rx_tstamp_tc;
 	struct rte_timecounter      tx_tstamp_tc;
  	struct ixgbe_tm_conf        tm_conf;
+	struct rte_representor_broker *broker;
 };
 
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
@@ -673,6 +674,10 @@ int ixgbe_fdir_filter_program(struct rte_eth_dev *dev,
 
 void ixgbe_configure_dcb(struct rte_eth_dev *dev);
 
+int
+ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
+			    int wait_to_complete, int vf);
+
 /*
  * misc function prototypes
  */
diff --git a/drivers/net/ixgbe/ixgbe_prep_ops.c b/drivers/net/ixgbe/ixgbe_prep_ops.c
new file mode 100644
index 0000000..a06df27
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_prep_ops.c
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+#include <rte_port_representor_driver.h>
+
+#include "base/ixgbe_type.h"
+#include "base/ixgbe_vf.h"
+#include "ixgbe_ethdev.h"
+#include "ixgbe_rxtx.h"
+#include "rte_pmd_ixgbe.h"
+
+#include "ixgbe_prep_ops.h"
+
+struct ixgbe_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+ixgbe_representor_link_update(struct rte_eth_dev *ethdev,
+	int wait_to_complete)
+{
+	struct rte_representor_port *prep_priv_data =
+			ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+			prep_priv_data->priv_data;
+
+	return ixgbe_dev_link_update_share(ixgbe_priv_data->pf_ethdev,
+		wait_to_complete, 1);
+}
+
+static void
+ixgbe_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+	struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	rte_pmd_ixgbe_set_vf_mac_addr(ixgbe_priv_data->pf_ethdev->data->port_id,
+		prep_priv_data->vport_id, mac_addr);
+}
+
+static void
+ixgbe_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(
+		ixgbe_priv_data->pf_ethdev->data->dev_private);
+
+	dev_info->pci_dev = NULL;
+
+	dev_info->min_rx_bufsize = 1024;
+	/**< Minimum size of RX buffer. */
+	dev_info->max_rx_pktlen = 9728;
+	/**< Maximum configurable length of RX pkt. */
+	dev_info->max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	/**< Maximum number of RX queues. */
+	dev_info->max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+	/**< Maximum number of TX queues. */
+
+	dev_info->max_mac_addrs = hw->mac.num_rar_entries;
+	/**< Maximum number of MAC addresses. */
+
+	dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |	DEV_RX_OFFLOAD_UDP_CKSUM  |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	/**< Device RX offload capabilities. */
+
+	dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_TSO;
+	/**< Device TX offload capabilities. */
+
+	dev_info->speed_capa =
+		ixgbe_priv_data->pf_ethdev->data->dev_link.link_speed;
+	/**< Supported speeds bitmap (ETH_LINK_SPEED_). */
+}
+
+static int ixgbe_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int ixgbe_representor_rx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int ixgbe_representor_tx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int ixgbe_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void ixgbe_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+ixgbe_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+	uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_ixgbe_set_vf_vlan_filter(pfid, vlan_id, vf_mask, on);
+}
+
+static void
+ixgbe_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+
+	rte_pmd_ixgbe_set_vf_vlan_stripq(pfid, vfid, on);
+}
+
+struct eth_dev_ops ixgbe_representor_dev_ops = {
+	.link_update                  = ixgbe_representor_link_update,
+	.dev_infos_get                = ixgbe_representor_dev_infos_get,
+	.dev_configure	              = ixgbe_representor_dev_configure,
+	.rx_queue_setup               = ixgbe_representor_rx_queue_setup,
+	.tx_queue_setup               = ixgbe_representor_tx_queue_setup,
+	.dev_start                    = ixgbe_representor_dev_start,
+	.dev_stop                     = ixgbe_representor_dev_stop,
+	.mac_addr_set                 = ixgbe_representor_mac_addr_set,
+	.vlan_filter_set              = ixgbe_representor_vlan_filter_set,
+	.vlan_strip_queue_set         = ixgbe_representor_vlan_strip_queue_set
+};
+
+static int
+ixgbe_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("ixgbe_port_representor_priv_data",
+			sizeof(struct ixgbe_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct ixgbe_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &ixgbe_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	ethdev->data->nb_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = NULL;
+	ethdev->tx_pkt_burst = NULL;
+
+	return 0;
+}
+
+static int
+ixgbe_port_representor_uninit(
+	__rte_unused struct rte_representor_broker *broker,
+	struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops ixgbe_broker_port_ops = {
+	.port_init = ixgbe_port_representor_init,
+	.port_uninit = ixgbe_port_representor_uninit
+};
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set IXGBE broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &ixgbe_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
diff --git a/drivers/net/ixgbe/ixgbe_prep_ops.h b/drivers/net/ixgbe/ixgbe_prep_ops.h
new file mode 100644
index 0000000..744aa3e
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_prep_ops.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _IXGBE_PREP_OPS_H_
+#define _IXGBE_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _IXGBE_PREP_OPS_H_ */
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v3 5/5] app/test-pmd: add Port Representor commands
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
                     ` (3 preceding siblings ...)
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 4/5] drivers/net/ixgbe: " Remy Horton
@ 2017-12-22 14:52   ` Remy Horton
  2017-12-26 13:54   ` [dpdk-dev] [PATCH v3 0/5] lib: add Port Representors Neil Horman
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 14:52 UTC (permalink / raw)
  To: dev; +Cc: Wenzhuo Lu, Jingjing Wu

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.

This patch adds the 'add representor' and 'del representor' commands
to test-pmd, which respectively allow the adding and removing of
port representors.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/cmdline.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f71d963..1a831ba 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -76,6 +76,7 @@
 #include <rte_eth_ctrl.h>
 #include <rte_flow.h>
 #include <rte_gro.h>
+#include <rte_port_representor.h>
 
 #include <cmdline_rdline.h>
 #include <cmdline_parse.h>
@@ -15535,6 +15536,91 @@ cmdline_parse_inst_t cmd_load_from_file = {
 	},
 };
 
+struct cmd_add_representor_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t representor;
+	cmdline_fixed_string_t pf;
+	uint16_t vport;
+};
+
+cmdline_parse_token_string_t cmd_addrepresentor_add =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	cmd, "add");
+cmdline_parse_token_string_t cmd_addrepresentor_del =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	cmd, "del");
+cmdline_parse_token_string_t cmd_addrepresentor_rep =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	representor, "representor");
+cmdline_parse_token_string_t cmd_addrepresentor_pf =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	pf, NULL);
+cmdline_parse_token_num_t cmd_addrepresentor_vport =
+TOKEN_NUM_INITIALIZER(struct cmd_add_representor_result,
+	vport, UINT16);
+
+static void cmd_add_representor_callback(void *parsed_result,
+		__attribute__((unused))  struct cmdline *cl,
+		__attribute__((unused)) void *data)
+{
+	struct cmd_add_representor_result *res = parsed_result;
+	uint16_t port_id;
+	int ret;
+
+	rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "%s(): addr:%s vport:%i\n",
+		__func__, res->pf, res->vport);
+
+	ret = rte_representor_port_register(res->pf, res->vport, &port_id);
+	if (ret != 0)
+		printf("Registering port representor failed\n");
+	else
+		printf("Port Representor registered with port id %i\n",
+			port_id);
+}
+
+static void cmd_del_representor_callback(void *parsed_result,
+		__attribute__((unused))  struct cmdline *cl,
+		__attribute__((unused)) void *data)
+{
+	struct cmd_add_representor_result *res = parsed_result;
+	int ret;
+
+	rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "%s(): port:%i\n", __func__,
+		res->vport);
+	ret = rte_representor_port_unregister(res->pf, res->vport);
+	if (ret != 0)
+		printf("Port %i is not a valid port representor.\n",
+			res->vport);
+}
+
+cmdline_parse_inst_t cmd_add_representor = {
+	.f = cmd_add_representor_callback,
+	.help_str = "add representor <BusName_DomBDF> <vport_id> "
+		"Add a Port Representor",
+	.data = NULL,
+	.tokens = {
+		(void *)&cmd_addrepresentor_add,
+		(void *)&cmd_addrepresentor_rep,
+		(void *)&cmd_addrepresentor_pf,
+		(void *)&cmd_addrepresentor_vport,
+		NULL
+	}
+};
+
+cmdline_parse_inst_t cmd_del_representor = {
+	.f = cmd_del_representor_callback,
+	.help_str = "del representor <BusName_DomBDF> <vport_id> "
+		"Delete a Port Representor",
+	.data = NULL,
+	.tokens = {
+		(void *)&cmd_addrepresentor_del,
+		(void *)&cmd_addrepresentor_rep,
+		(void *)&cmd_addrepresentor_pf,
+		(void *)&cmd_addrepresentor_vport,
+		NULL
+	}
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -15576,6 +15662,8 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *) &cmd_show_bonding_config,
 	(cmdline_parse_inst_t *) &cmd_set_bonding_primary,
 	(cmdline_parse_inst_t *) &cmd_add_bonding_slave,
+	(cmdline_parse_inst_t *) &cmd_add_representor,
+	(cmdline_parse_inst_t *) &cmd_del_representor,
 	(cmdline_parse_inst_t *) &cmd_remove_bonding_slave,
 	(cmdline_parse_inst_t *) &cmd_create_bonded_device,
 	(cmdline_parse_inst_t *) &cmd_set_bond_mac_addr,
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [DPDK 0/5] lib: add Port Representors
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
                     ` (4 preceding siblings ...)
  2017-12-22 14:41   ` [dpdk-dev] [DPDK 5/5] app/test-pmd: add Port Representor commands Remy Horton
@ 2017-12-22 15:09   ` Remy Horton
  2017-12-22 16:37   ` Neil Horman
  6 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2017-12-22 15:09 UTC (permalink / raw)
  To: dev


On 22/12/2017 14:41, Remy Horton wrote:
> Port Representors provide a logical presentation in DPDK of VF (virtual
[..]
> Remy Horton (5):
>   lib: add Port Representor library
>   eal: add Port Representor command-line option
>   drivers/net/i40e: add Port Representor functionality
>   drivers/net/ixgbe: add Port Representor functionality
>   app/test-pmd: add Port Representor commands

Opps, misconfigured patch script. Self-NAK on this patchset, and resent 
with correct subject headers.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [DPDK 0/5] lib: add Port Representors
  2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
                     ` (5 preceding siblings ...)
  2017-12-22 15:09   ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
@ 2017-12-22 16:37   ` Neil Horman
  2018-01-03 12:14     ` Mohammad Abdul Awal
  6 siblings, 1 reply; 75+ messages in thread
From: Neil Horman @ 2017-12-22 16:37 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Wenzhuo Lu, Jingjing Wu

On Fri, Dec 22, 2017 at 02:41:16PM +0000, 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.
> 
> +-----------------------------+   +---------------+  +---------------+
> |        Control Plane        |   |   Data Plane  |  |   Data Plane  |
> |         Application         |   |   Application |  |   Application |
> +-----------------------------+   +---------------+  +---------------+
> |         eth dev api         |   |  eth dev api  |  |  eth dev api  |
> +-----------------------------+   +---------------+  +---------------+
> +-------+  +-------+  +-------+   +---------------+  +---------------+
> |  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
> |  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
> |       |  | PMD   |  | PMD   |                             |
> +---+--^+  +-------+  +-+-----+                             |
>     |  |                |  |                                |
>     |  +----------------+  |                                |
>     |                      |                                |
>     |                      |                                |
> +--------------------------------+                          |
> |   |  HW (logical view)   |     |                          |
> | --+------+ +-------+ +---+---+ |                          |
> | |   PF   | |  VF0  | |  VF1  | |                          |
> | |        | |       | |       +----------------------------+
> | +--------+ +-------+ +-------+ |
> | +----------------------------+ |
> | |        VEB                 | |
> | +----------------------------+ |
> | +--------+                     |
> | |  Port  |                     |
> | |   0    |                     |
> | +--------+                     |
> +--------------------------------+
> 

How does this mesh with the notion of port ownership that we've been discussing
in other threads?  In that thread, we've been discussing the need for a single
execution context to have exclusive access to the hardware for the purposes of
configuration and data i/o, and for the application/execution context to be
responsible for co-ordination of any shared use of a device.  In this feature
however, the notion of a Port Representor creates an alias to the same hardware
funciton (VF), where both aliases (in the control and data plan) have parallel
access to the hardware, in such a way that co-ordination between the two is
largely impossible (unless you want to make the data plane application explicity
aware of control plane actiivy).

Neil

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/5] lib: add Port Representors
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
                     ` (4 preceding siblings ...)
  2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 5/5] app/test-pmd: add Port Representor commands Remy Horton
@ 2017-12-26 13:54   ` Neil Horman
  2018-01-03 12:12     ` Mohammad Abdul Awal
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
  6 siblings, 1 reply; 75+ messages in thread
From: Neil Horman @ 2017-12-26 13:54 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Wenzhuo Lu, Jingjing Wu

On Fri, Dec 22, 2017 at 02:52:16PM +0000, 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.
> 
> +-----------------------------+   +---------------+  +---------------+
> |        Control Plane        |   |   Data Plane  |  |   Data Plane  |
> |         Application         |   |   Application |  |   Application |
> +-----------------------------+   +---------------+  +---------------+
> |         eth dev api         |   |  eth dev api  |  |  eth dev api  |
> +-----------------------------+   +---------------+  +---------------+
> +-------+  +-------+  +-------+   +---------------+  +---------------+
> |  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
> |  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
> |       |  | PMD   |  | PMD   |                             |
> +---+--^+  +-------+  +-+-----+                             |
>     |  |                |  |                                |
>     |  +----------------+  |                                |
>     |                      |                                |
>     |                      |                                |
> +--------------------------------+                          |
> |   |  HW (logical view)   |     |                          |
> | --+------+ +-------+ +---+---+ |                          |
> | |   PF   | |  VF0  | |  VF1  | |                          |
> | |        | |       | |       +----------------------------+
> | +--------+ +-------+ +-------+ |
> | +----------------------------+ |
> | |        VEB                 | |
> | +----------------------------+ |
> | +--------+                     |
> | |  Port  |                     |
> | |   0    |                     |
> | +--------+                     |
> +--------------------------------+
> 
> The figure above shows a deployment where the PF is bound to a DPDK control
> plane application which uses representor ports to manage the configuration and
> monitoring of it's VF ports. Each virtual function is represented in the
> application by a representor port PMD which enables control of the corresponding
> VF through eth dev APIs on the representor PMD such as:
> 
> - void rte_eth_promiscuous_enable(uint8_t port_id);
> - void rte_eth_promiscuous_disable(uint8_t port_id);
> - void rte_eth_allmulticast_enable(uint8_t port_id);
> - void rte_eth_allmulticast_disable(uint8_t port_id);
> - int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
> 	uint32_t pool);
> - int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);
> 
> as well as monitoring through API's like
> 
> - void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
> - int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
> 
> The port representor infrastructure is enabled through a single common, device
> independent, virtual PMD whos context is initialized and enabled through a
> broker instance running within the context of the physical function device
> driver.
> 
> +-------------------------+       +-------------------------+
> |        rte_ethdev       |       |       rte_ethdev        |
> +-------------------------+       +-------------------------+
> |  Physical Function PMD  |       |  Port Reperesentor PMD  |
> |         +-------------+ |       | +---------+ +---------+ |
> |         | Representor | |       | | dev_data| | dev_ops | |
> |         |    Broker   | |       | +----+----+ +----+----+ |
> |         | +---------+ | |       +------|-----------|------+
> |         | | VF Port | | |              |           |
> |         | | Context +------------------+           |
> |         | +---------+ | |                          |
> |         | +---------+ | |                          |
> |         | | Handler +------------------------------+
> |         | |   Ops   | | |
> |         | +---------+ | |
> |         +-------------+ |
> +-------------------------+
> 
> Creation of representor ports can be achieved either through the --vdev EAL
> option or through the rte_vdev_init() API. Each port representor requires the
> BDF of it's parent PF and the Virtual Function ID of the port which the
> representor will support. During initialization of the representor PMD, it calls
> the broker API to register itself with the PF PMD and to get it's context
> configured which includes the setting up of it's context and ops function
> handlers.
> 
> As the port representor model is based around the paradigm of using standard
> port based APIs, it will allow future expansion of functionality without the
> need to add new APIs. For example it should be possible to support configuration
> of egress QoS parameters using existing TM APIs by extending the port
> representor PMD/broker infrastructure.
> 
> Changes in v2:
> * Rebased to DPDK 17.11
> 
> Changes in v3:
> * Removed RTE_ETH_DEV_REPRESENTOR_PORT define
> * Removed switch_domain from struct rte_eth_dev_info
>   (to be reintroduced seperately when required).
> * Port Representor PMD functionality merged into main library
> * Removed functions from .map file that are not for use by applications
> * Some minor bugfixes (uninitalised variables & NULL terminators)
> * Use of SPDX licence headers in new files
> * Seperate headers for PMD and application
> * SPDX-License-Identifier in new files
> * Added test-pmd representor add/del commands
> 
> 
> Remy Horton (5):
>   lib: add Port Representor library
>   eal: add Port Representor command-line option
>   drivers/net/i40e: add Port Representor functionality
>   drivers/net/ixgbe: add Port Representor functionality
>   app/test-pmd: add Port Representor commands
> 
>  app/test-pmd/cmdline.c                             |  88 ++++
>  config/common_base                                 |   5 +
>  drivers/net/i40e/Makefile                          |   1 +
>  drivers/net/i40e/i40e_ethdev.c                     |  16 +
>  drivers/net/i40e/i40e_ethdev.h                     |   1 +
>  drivers/net/i40e/i40e_prep_ops.c                   | 495 +++++++++++++++++++++
>  drivers/net/i40e/i40e_prep_ops.h                   |  15 +
>  drivers/net/i40e/rte_pmd_i40e.c                    |  47 ++
>  drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
>  drivers/net/ixgbe/Makefile                         |   1 +
>  drivers/net/ixgbe/ixgbe_ethdev.c                   |  22 +-
>  drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
>  drivers/net/ixgbe/ixgbe_prep_ops.c                 | 259 +++++++++++
>  drivers/net/ixgbe/ixgbe_prep_ops.h                 |  15 +
>  lib/Makefile                                       |   3 +
>  lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
>  lib/librte_eal/common/eal_common_options.c         |   1 +
>  lib/librte_eal/common/eal_internal_cfg.h           |   2 +
>  lib/librte_eal/common/eal_options.h                |   2 +
>  lib/librte_eal/common/include/rte_eal.h            |   8 +
>  lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
>  lib/librte_representor/Makefile                    |  26 ++
>  lib/librte_representor/rte_port_representor.c      | 326 ++++++++++++++
>  lib/librte_representor/rte_port_representor.h      |  60 +++
>  .../rte_port_representor_driver.h                  | 138 ++++++
>  .../rte_port_representor_version.map               |   8 +
>  mk/rte.app.mk                                      |   1 +
>  27 files changed, 1577 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/net/i40e/i40e_prep_ops.c
>  create mode 100644 drivers/net/i40e/i40e_prep_ops.h
>  create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
>  create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h
>  create mode 100644 lib/librte_representor/Makefile
>  create mode 100644 lib/librte_representor/rte_port_representor.c
>  create mode 100644 lib/librte_representor/rte_port_representor.h
>  create mode 100644 lib/librte_representor/rte_port_representor_driver.h
>  create mode 100644 lib/librte_representor/rte_port_representor_version.map
> 
> -- 
> 2.9.5
> 
> 
Same question as in V1, how does this patch mesh with the notion of port
ownership?  The consensus from that thread was that, because the DPDK considers
itself lockless, that the application(s) managing/using a given port need to
enforce their own mutual exclusion.  The design of this feature explicitly
creates an alias effect, in that the same hardware (a VF in this case), can be
accessed via two different port structures by two different applications without
being aware of the shared nature of the port.  Given that one is in a vm,
co-ordination between applications is going to be awkward at best.  How do you
plan to enforce mutual exclusion in this environment, given that you don't have
any shared memory between the vm and the host?

Neil

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/5] lib: add Port Representors
  2017-12-26 13:54   ` [dpdk-dev] [PATCH v3 0/5] lib: add Port Representors Neil Horman
@ 2018-01-03 12:12     ` Mohammad Abdul Awal
  0 siblings, 0 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2018-01-03 12:12 UTC (permalink / raw)
  To: Neil Horman, Remy Horton; +Cc: dev, Wenzhuo Lu, Jingjing Wu

Hi Neil,


On 26/12/2017 13:54, Neil Horman wrote:
> On Fri, Dec 22, 2017 at 02:52:16PM +0000, 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.
>>
>> +-----------------------------+   +---------------+  +---------------+
>> |        Control Plane        |   |   Data Plane  |  |   Data Plane  |
>> |         Application         |   |   Application |  |   Application |
>> +-----------------------------+   +---------------+  +---------------+
>> |         eth dev api         |   |  eth dev api  |  |  eth dev api  |
>> +-----------------------------+   +---------------+  +---------------+
>> +-------+  +-------+  +-------+   +---------------+  +---------------+
>> |  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
>> |  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
>> |       |  | PMD   |  | PMD   |                             |
>> +---+--^+  +-------+  +-+-----+                             |
>>      |  |                |  |                                |
>>      |  +----------------+  |                                |
>>      |                      |                                |
>>      |                      |                                |
>> +--------------------------------+                          |
>> |   |  HW (logical view)   |     |                          |
>> | --+------+ +-------+ +---+---+ |                          |
>> | |   PF   | |  VF0  | |  VF1  | |                          |
>> | |        | |       | |       +----------------------------+
>> | +--------+ +-------+ +-------+ |
>> | +----------------------------+ |
>> | |        VEB                 | |
>> | +----------------------------+ |
>> | +--------+                     |
>> | |  Port  |                     |
>> | |   0    |                     |
>> | +--------+                     |
>> +--------------------------------+
>>
>> The figure above shows a deployment where the PF is bound to a DPDK control
>> plane application which uses representor ports to manage the configuration and
>> monitoring of it's VF ports. Each virtual function is represented in the
>> application by a representor port PMD which enables control of the corresponding
>> VF through eth dev APIs on the representor PMD such as:
>>
>> - void rte_eth_promiscuous_enable(uint8_t port_id);
>> - void rte_eth_promiscuous_disable(uint8_t port_id);
>> - void rte_eth_allmulticast_enable(uint8_t port_id);
>> - void rte_eth_allmulticast_disable(uint8_t port_id);
>> - int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
>> 	uint32_t pool);
>> - int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);
>>
>> as well as monitoring through API's like
>>
>> - void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
>> - int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
>>
>> The port representor infrastructure is enabled through a single common, device
>> independent, virtual PMD whos context is initialized and enabled through a
>> broker instance running within the context of the physical function device
>> driver.
>>
>> +-------------------------+       +-------------------------+
>> |        rte_ethdev       |       |       rte_ethdev        |
>> +-------------------------+       +-------------------------+
>> |  Physical Function PMD  |       |  Port Reperesentor PMD  |
>> |         +-------------+ |       | +---------+ +---------+ |
>> |         | Representor | |       | | dev_data| | dev_ops | |
>> |         |    Broker   | |       | +----+----+ +----+----+ |
>> |         | +---------+ | |       +------|-----------|------+
>> |         | | VF Port | | |              |           |
>> |         | | Context +------------------+           |
>> |         | +---------+ | |                          |
>> |         | +---------+ | |                          |
>> |         | | Handler +------------------------------+
>> |         | |   Ops   | | |
>> |         | +---------+ | |
>> |         +-------------+ |
>> +-------------------------+
>>
>> Creation of representor ports can be achieved either through the --vdev EAL
>> option or through the rte_vdev_init() API. Each port representor requires the
>> BDF of it's parent PF and the Virtual Function ID of the port which the
>> representor will support. During initialization of the representor PMD, it calls
>> the broker API to register itself with the PF PMD and to get it's context
>> configured which includes the setting up of it's context and ops function
>> handlers.
>>
>> As the port representor model is based around the paradigm of using standard
>> port based APIs, it will allow future expansion of functionality without the
>> need to add new APIs. For example it should be possible to support configuration
>> of egress QoS parameters using existing TM APIs by extending the port
>> representor PMD/broker infrastructure.
>>
>> Changes in v2:
>> * Rebased to DPDK 17.11
>>
>> Changes in v3:
>> * Removed RTE_ETH_DEV_REPRESENTOR_PORT define
>> * Removed switch_domain from struct rte_eth_dev_info
>>    (to be reintroduced seperately when required).
>> * Port Representor PMD functionality merged into main library
>> * Removed functions from .map file that are not for use by applications
>> * Some minor bugfixes (uninitalised variables & NULL terminators)
>> * Use of SPDX licence headers in new files
>> * Seperate headers for PMD and application
>> * SPDX-License-Identifier in new files
>> * Added test-pmd representor add/del commands
>>
>>
>> Remy Horton (5):
>>    lib: add Port Representor library
>>    eal: add Port Representor command-line option
>>    drivers/net/i40e: add Port Representor functionality
>>    drivers/net/ixgbe: add Port Representor functionality
>>    app/test-pmd: add Port Representor commands
>>
>>   app/test-pmd/cmdline.c                             |  88 ++++
>>   config/common_base                                 |   5 +
>>   drivers/net/i40e/Makefile                          |   1 +
>>   drivers/net/i40e/i40e_ethdev.c                     |  16 +
>>   drivers/net/i40e/i40e_ethdev.h                     |   1 +
>>   drivers/net/i40e/i40e_prep_ops.c                   | 495 +++++++++++++++++++++
>>   drivers/net/i40e/i40e_prep_ops.h                   |  15 +
>>   drivers/net/i40e/rte_pmd_i40e.c                    |  47 ++
>>   drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
>>   drivers/net/ixgbe/Makefile                         |   1 +
>>   drivers/net/ixgbe/ixgbe_ethdev.c                   |  22 +-
>>   drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
>>   drivers/net/ixgbe/ixgbe_prep_ops.c                 | 259 +++++++++++
>>   drivers/net/ixgbe/ixgbe_prep_ops.h                 |  15 +
>>   lib/Makefile                                       |   3 +
>>   lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
>>   lib/librte_eal/common/eal_common_options.c         |   1 +
>>   lib/librte_eal/common/eal_internal_cfg.h           |   2 +
>>   lib/librte_eal/common/eal_options.h                |   2 +
>>   lib/librte_eal/common/include/rte_eal.h            |   8 +
>>   lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
>>   lib/librte_representor/Makefile                    |  26 ++
>>   lib/librte_representor/rte_port_representor.c      | 326 ++++++++++++++
>>   lib/librte_representor/rte_port_representor.h      |  60 +++
>>   .../rte_port_representor_driver.h                  | 138 ++++++
>>   .../rte_port_representor_version.map               |   8 +
>>   mk/rte.app.mk                                      |   1 +
>>   27 files changed, 1577 insertions(+), 1 deletion(-)
>>   create mode 100644 drivers/net/i40e/i40e_prep_ops.c
>>   create mode 100644 drivers/net/i40e/i40e_prep_ops.h
>>   create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
>>   create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h
>>   create mode 100644 lib/librte_representor/Makefile
>>   create mode 100644 lib/librte_representor/rte_port_representor.c
>>   create mode 100644 lib/librte_representor/rte_port_representor.h
>>   create mode 100644 lib/librte_representor/rte_port_representor_driver.h
>>   create mode 100644 lib/librte_representor/rte_port_representor_version.map
>>
>> -- 
>> 2.9.5
>>
>>
> Same question as in V1, how does this patch mesh with the notion of port
> ownership?  The consensus from that thread was that, because the DPDK considers
> itself lockless, that the application(s) managing/using a given port need to
> enforce their own mutual exclusion.  The design of this feature explicitly
> creates an alias effect, in that the same hardware (a VF in this case), can be
> accessed via two different port structures by two different applications without
> being aware of the shared nature of the port.  Given that one is in a vm,
> co-ordination between applications is going to be awkward at best.  How do you
> plan to enforce mutual exclusion in this environment, given that you don't have
> any shared memory between the vm and the host?

Without the port representor model, it is possible that both PF and VF 
can have shared access of the VF hardware. Lets take an example of i40e 
drivers [1]. Application running in host can modify the hardware 
configuration using the provided APIs in the reference [1]. Applications 
running on the VF can modify the hardware configuration using mailbox 
mechanism and with privileged mode.

With the port representor model, we still have the same shared access 
model. Only important difference is that, with port representor, we do 
not have to make those device specific private APIs public, as all can 
be accessed by eth_dev_ops.

In an OVS like scenario, it is expected that the control application 
will have sole privilege to modify the hardware configuration. 
Currently, we cannot stop the application running on VF to modify the 
hardware (hence your concern is valid but still accepted scenario as in 
reference [1]). If we do not want to allow the applications running on 
VF to modify the hardware, one idea is to intercept the interrupts 
regarding the malibox requested coming from the VF, and redirect to the 
port representor model. But this is out of the scope of port representor 
itself.

[1] http://dpdk.org/ml/archives/dev/2017-April/063642.html

> Neil
>

Regards,
Awal.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [DPDK 0/5] lib: add Port Representors
  2017-12-22 16:37   ` Neil Horman
@ 2018-01-03 12:14     ` Mohammad Abdul Awal
  0 siblings, 0 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2018-01-03 12:14 UTC (permalink / raw)
  To: Neil Horman, Remy Horton; +Cc: dev, Wenzhuo Lu, Jingjing Wu

Hi Neil,


On 22/12/2017 16:37, Neil Horman wrote:
> On Fri, Dec 22, 2017 at 02:41:16PM +0000, 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.
>>
>> +-----------------------------+   +---------------+  +---------------+
>> |        Control Plane        |   |   Data Plane  |  |   Data Plane  |
>> |         Application         |   |   Application |  |   Application |
>> +-----------------------------+   +---------------+  +---------------+
>> |         eth dev api         |   |  eth dev api  |  |  eth dev api  |
>> +-----------------------------+   +---------------+  +---------------+
>> +-------+  +-------+  +-------+   +---------------+  +---------------+
>> |  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
>> |  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
>> |       |  | PMD   |  | PMD   |                             |
>> +---+--^+  +-------+  +-+-----+                             |
>>      |  |                |  |                                |
>>      |  +----------------+  |                                |
>>      |                      |                                |
>>      |                      |                                |
>> +--------------------------------+                          |
>> |   |  HW (logical view)   |     |                          |
>> | --+------+ +-------+ +---+---+ |                          |
>> | |   PF   | |  VF0  | |  VF1  | |                          |
>> | |        | |       | |       +----------------------------+
>> | +--------+ +-------+ +-------+ |
>> | +----------------------------+ |
>> | |        VEB                 | |
>> | +----------------------------+ |
>> | +--------+                     |
>> | |  Port  |                     |
>> | |   0    |                     |
>> | +--------+                     |
>> +--------------------------------+
>>
> How does this mesh with the notion of port ownership that we've been discussing
> in other threads?  In that thread, we've been discussing the need for a single
> execution context to have exclusive access to the hardware for the purposes of
> configuration and data i/o, and for the application/execution context to be
> responsible for co-ordination of any shared use of a device.  In this feature
> however, the notion of a Port Representor creates an alias to the same hardware
> funciton (VF), where both aliases (in the control and data plan) have parallel
> access to the hardware, in such a way that co-ordination between the two is
> largely impossible (unless you want to make the data plane application explicity
> aware of control plane actiivy).
>
> Neil

I have just replied to your mail in other thread of V3 patch.

Regards,
Awal.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
                     ` (5 preceding siblings ...)
  2017-12-26 13:54   ` [dpdk-dev] [PATCH v3 0/5] lib: add Port Representors Neil Horman
@ 2018-01-08 14:37   ` Remy Horton
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 1/5] lib: add Port Representor library Remy Horton
                       ` (8 more replies)
  6 siblings, 9 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-08 14:37 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Wenzhuo Lu, Jingjing Wu

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.

+-----------------------------+   +---------------+  +---------------+
|        Control Plane        |   |   Data Plane  |  |   Data Plane  |
|         Application         |   |   Application |  |   Application |
+-----------------------------+   +---------------+  +---------------+
|         eth dev api         |   |  eth dev api  |  |  eth dev api  |
+-----------------------------+   +---------------+  +---------------+
+-------+  +-------+  +-------+   +---------------+  +---------------+
|  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
|  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
|       |  | PMD   |  | PMD   |                             |
+---+--^+  +-------+  +-+-----+                             |
    |  |                |  |                                |
    |  +----------------+  |                                |
    |                      |                                |
    |                      |                                |
+--------------------------------+                          |
|   |  HW (logical view)   |     |                          |
| --+------+ +-------+ +---+---+ |                          |
| |   PF   | |  VF0  | |  VF1  | |                          |
| |        | |       | |       +----------------------------+
| +--------+ +-------+ +-------+ |
| +----------------------------+ |
| |        VEB                 | |
| +----------------------------+ |
| +--------+                     |
| |  Port  |                     |
| |   0    |                     |
| +--------+                     |
+--------------------------------+

The figure above shows a deployment where the PF is bound to a DPDK control
plane application which uses representor ports to manage the configuration and
monitoring of it's VF ports. Each virtual function is represented in the
application by a representor port PMD which enables control of the corresponding
VF through eth dev APIs on the representor PMD such as:

- void rte_eth_promiscuous_enable(uint8_t port_id);
- void rte_eth_promiscuous_disable(uint8_t port_id);
- void rte_eth_allmulticast_enable(uint8_t port_id);
- void rte_eth_allmulticast_disable(uint8_t port_id);
- int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
	uint32_t pool);
- int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);

as well as monitoring through API's like

- void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
- int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);

The port representor infrastructure is enabled through a single common, device
independent, virtual PMD whos context is initialized and enabled through a
broker instance running within the context of the physical function device
driver.

+-------------------------+       +-------------------------+
|        rte_ethdev       |       |       rte_ethdev        |
+-------------------------+       +-------------------------+
|  Physical Function PMD  |       |  Port Reperesentor PMD  |
|         +-------------+ |       | +---------+ +---------+ |
|         | Representor | |       | | dev_data| | dev_ops | |
|         |    Broker   | |       | +----+----+ +----+----+ |
|         | +---------+ | |       +------|-----------|------+
|         | | VF Port | | |              |           |
|         | | Context +------------------+           |
|         | +---------+ | |                          |
|         | +---------+ | |                          |
|         | | Handler +------------------------------+
|         | |   Ops   | | |
|         | +---------+ | |
|         +-------------+ |
+-------------------------+

Creation of representor ports can be achieved either through the --vdev EAL
option or through the rte_vdev_init() API. Each port representor requires the
BDF of it's parent PF and the Virtual Function ID of the port which the
representor will support. During initialization of the representor PMD, it calls
the broker API to register itself with the PF PMD and to get it's context
configured which includes the setting up of it's context and ops function
handlers.

As the port representor model is based around the paradigm of using standard
port based APIs, it will allow future expansion of functionality without the
need to add new APIs. For example it should be possible to support configuration
of egress QoS parameters using existing TM APIs by extending the port
representor PMD/broker infrastructure.

Changes in v2:
* Rebased to DPDK 17.11

Changes in v3:
* Removed RTE_ETH_DEV_REPRESENTOR_PORT define
* Removed switch_domain from struct rte_eth_dev_info
  (to be reintroduced seperately when required).
* Port Representor PMD functionality merged into main library
* Removed functions from .map file that are not for use by applications
* Some minor bugfixes (uninitalised variables & NULL terminators)
* Use of SPDX licence headers in new files
* Seperate headers for PMD and application
* SPDX-License-Identifier in new files
* Added test-pmd representor add/del commands

Changes in v4:
* Added documentation
* Rebased to a12f22678915


Remy Horton (5):
  lib: add Port Representor library
  eal: add Port Representor command-line option
  drivers/net/i40e: add Port Representor functionality
  drivers/net/ixgbe: add Port Representor functionality
  app/test-pmd: add Port Representor commands

 MAINTAINERS                                        |  12 +-
 app/test-pmd/cmdline.c                             |  88 ++++
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   3 +-
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/index.rst                    |   1 +
 doc/guides/prog_guide/representor_lib.rst          |  62 +++
 doc/guides/rel_notes/release_18_02.rst             |   9 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  25 ++
 drivers/net/i40e/Makefile                          |   1 +
 drivers/net/i40e/i40e_ethdev.c                     |  16 +
 drivers/net/i40e/i40e_ethdev.h                     |   1 +
 drivers/net/i40e/i40e_prep_ops.c                   | 495 +++++++++++++++++++++
 drivers/net/i40e/i40e_prep_ops.h                   |  15 +
 drivers/net/i40e/rte_pmd_i40e.c                    |  47 ++
 drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
 drivers/net/ixgbe/Makefile                         |   1 +
 drivers/net/ixgbe/ixgbe_ethdev.c                   |  22 +-
 drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
 drivers/net/ixgbe/ixgbe_prep_ops.c                 | 259 +++++++++++
 drivers/net/ixgbe/ixgbe_prep_ops.h                 |  15 +
 lib/Makefile                                       |   3 +
 lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
 lib/librte_eal/common/eal_common_options.c         |   1 +
 lib/librte_eal/common/eal_internal_cfg.h           |   2 +
 lib/librte_eal/common/eal_options.h                |   2 +
 lib/librte_eal/common/include/rte_eal.h            |   8 +
 lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 326 ++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 +++
 .../rte_port_representor_driver.h                  | 138 ++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 34 files changed, 1688 insertions(+), 3 deletions(-)
 create mode 100644 doc/guides/prog_guide/representor_lib.rst
 create mode 100644 drivers/net/i40e/i40e_prep_ops.c
 create mode 100644 drivers/net/i40e/i40e_prep_ops.h
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v4 1/5] lib: add Port Representor library
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
@ 2018-01-08 14:37     ` Remy Horton
  2018-01-09 22:06       ` Ferruh Yigit
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 2/5] eal: add Port Representor command-line option Remy Horton
                       ` (7 subsequent siblings)
  8 siblings, 1 reply; 75+ messages in thread
From: Remy Horton @ 2018-01-08 14:37 UTC (permalink / raw)
  To: dev
  Cc: John McNamara, Wenzhuo Lu, Jingjing Wu, Declan Doherty,
	Mohammad Abdul Awal

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>
---
 MAINTAINERS                                        |   8 +-
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   3 +-
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/index.rst                    |   1 +
 doc/guides/prog_guide/representor_lib.rst          |  62 ++++
 doc/guides/rel_notes/release_18_02.rst             |   9 +
 lib/Makefile                                       |   3 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 326 +++++++++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 ++++
 .../rte_port_representor_driver.h                  | 138 +++++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 14 files changed, 649 insertions(+), 2 deletions(-)
 create mode 100644 doc/guides/prog_guide/representor_lib.rst
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index e0199b1..5828b94 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -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
 ----------
 
diff --git a/config/common_base b/config/common_base
index e74febe..febb80a 100644
--- a/config/common_base
+++ b/config/common_base
@@ -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
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)
 
 - **device specific**:
   [softnic]            (@ref rte_eth_softnic.h),
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b2cbe94..4d1b89f 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -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 \
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c4beb34..380d5c9 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -71,6 +71,7 @@ Programmer's Guide
     power_man
     packet_classif_access_ctrl
     packet_framework
+    representor_lib
     vhost_lib
     metrics_lib
     port_hotplug_framework
diff --git a/doc/guides/prog_guide/representor_lib.rst b/doc/guides/prog_guide/representor_lib.rst
new file mode 100644
index 0000000..aaac6c9
--- /dev/null
+++ b/doc/guides/prog_guide/representor_lib.rst
@@ -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);
diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst
index 24b67bb..10fe433 100644
--- a/doc/guides/rel_notes/release_18_02.rst
+++ b/doc/guides/rel_notes/release_18_02.rst
@@ -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
 -----------
diff --git a/lib/Makefile b/lib/Makefile
index 4202702..42932a9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -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
diff --git a/lib/librte_representor/Makefile b/lib/librte_representor/Makefile
new file mode 100644
index 0000000..4060cc6
--- /dev/null
+++ b/lib/librte_representor/Makefile
@@ -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
diff --git a/lib/librte_representor/rte_port_representor.c b/lib/librte_representor/rte_port_representor.c
new file mode 100644
index 0000000..69a4bfc
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.c
@@ -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;
+}
diff --git a/lib/librte_representor/rte_port_representor.h b/lib/librte_representor/rte_port_representor.h
new file mode 100644
index 0000000..f7903fd
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.h
@@ -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_ */
diff --git a/lib/librte_representor/rte_port_representor_driver.h b/lib/librte_representor/rte_port_representor_driver.h
new file mode 100644
index 0000000..8827ebb
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_driver.h
@@ -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_ */
diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
new file mode 100644
index 0000000..b26600c
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_version.map
@@ -0,0 +1,8 @@
+DPDK_18.02 {
+	global:
+
+	rte_representor_port_register;
+	rte_representor_port_unregister;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6a6a745..67266bf 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -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
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v4 2/5] eal: add Port Representor command-line option
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 1/5] lib: add Port Representor library Remy Horton
@ 2018-01-08 14:37     ` Remy Horton
  2018-01-09 22:07       ` Ferruh Yigit
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
                       ` (6 subsequent siblings)
  8 siblings, 1 reply; 75+ messages in thread
From: Remy Horton @ 2018-01-08 14:37 UTC (permalink / raw)
  To: dev
  Cc: John McNamara, Wenzhuo Lu, Jingjing Wu, Declan Doherty,
	Mohammad Abdul Awal

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.

By default the Port Representor infrastructure is not enabled. This
patch implements the --enable-representor EAL command-line parameter
that activates representation functionality.

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>
---
 lib/librte_eal/bsdapp/eal/eal.c            | 6 ++++++
 lib/librte_eal/common/eal_common_options.c | 1 +
 lib/librte_eal/common/eal_internal_cfg.h   | 2 ++
 lib/librte_eal/common/eal_options.h        | 2 ++
 lib/librte_eal/common/include/rte_eal.h    | 8 ++++++++
 lib/librte_eal/linuxapp/eal/eal.c          | 9 +++++++++
 6 files changed, 28 insertions(+)

diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 369a682..002200a 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -778,3 +778,9 @@ int rte_vfio_noiommu_is_enabled(void)
 {
 	return 0;
 }
+
+/* return non-zero if port-representor is enabled. */
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 996a034..6f2cc05 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -78,6 +78,7 @@ const struct option
 eal_long_options[] = {
 	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
 	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
+	{OPT_ENABLE_REPRESENTOR, 0, NULL, OPT_ENABLE_REPRESENTOR_NUM   },
 	{OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
 	{OPT_HELP,              0, NULL, OPT_HELP_NUM             },
 	{OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index c67685c..b4befe6 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -42,6 +42,8 @@ struct internal_config {
 										* instead of native TSC */
 	volatile unsigned no_shconf;      /**< true if there is no shared config */
 	volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */
+	volatile unsigned enable_representor;
+	/**< true to enable port representor broker for all PFs */
 	volatile enum rte_proc_type_t process_type; /**< multi-process proc type */
 	/** true to try allocating memory on specific sockets */
 	volatile unsigned force_sockets;
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 30e6bb4..c2b2162 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -83,6 +83,8 @@ enum {
 	OPT_VFIO_INTR_NUM,
 #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
 	OPT_VMWARE_TSC_MAP_NUM,
+#define OPT_ENABLE_REPRESENTOR    "enable-representor"
+	OPT_ENABLE_REPRESENTOR_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
index 02fa109..d21f704 100644
--- a/lib/librte_eal/common/include/rte_eal.h
+++ b/lib/librte_eal/common/include/rte_eal.h
@@ -306,6 +306,14 @@ enum rte_iova_mode rte_eal_iova_mode(void);
 const char *
 rte_eal_mbuf_default_mempool_ops(void);
 
+/**
+ * Get flag for port representor should be enabled or not.
+ *
+ * @return
+ *   Returns the enable-representor flag.
+ */
+int rte_representor_enabled(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 229eec9..364a8b2 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -612,6 +612,10 @@ eal_parse_args(int argc, char **argv)
 			internal_config.mbuf_pool_ops_name = optarg;
 			break;
 
+		case OPT_ENABLE_REPRESENTOR_NUM:
+			internal_config.enable_representor = 1;
+			break;
+
 		default:
 			if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
 				RTE_LOG(ERR, EAL, "Option %c is not supported "
@@ -1041,3 +1045,8 @@ rte_eal_check_module(const char *module_name)
 	/* Module has been found */
 	return 1;
 }
+
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 1/5] lib: add Port Representor library Remy Horton
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 2/5] eal: add Port Representor command-line option Remy Horton
@ 2018-01-08 14:37     ` Remy Horton
  2018-01-09 22:09       ` Ferruh Yigit
  2018-01-10  7:56       ` Xing, Beilei
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 4/5] drivers/net/ixgbe: " Remy Horton
                       ` (5 subsequent siblings)
  8 siblings, 2 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-08 14:37 UTC (permalink / raw)
  To: dev
  Cc: John McNamara, Wenzhuo Lu, Jingjing Wu, Declan Doherty,
	Mohammad Abdul Awal

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.

This patch adds to the i40e PMD the functions required to enable port
representor functionality.

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>
---
 MAINTAINERS                      |   2 +
 drivers/net/i40e/Makefile        |   1 +
 drivers/net/i40e/i40e_ethdev.c   |  16 ++
 drivers/net/i40e/i40e_ethdev.h   |   1 +
 drivers/net/i40e/i40e_prep_ops.c | 495 +++++++++++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_prep_ops.h |  15 ++
 drivers/net/i40e/rte_pmd_i40e.c  |  47 ++++
 drivers/net/i40e/rte_pmd_i40e.h  |  18 ++
 8 files changed, 595 insertions(+)
 create mode 100644 drivers/net/i40e/i40e_prep_ops.c
 create mode 100644 drivers/net/i40e/i40e_prep_ops.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5828b94..08a8e97 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -781,6 +781,8 @@ 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
+F: drivers/net/i40e/i40e_prep_ops.c
+F: drivers/net/i40e/i40e_prep_ops.h
 
 Packet Framework
 ----------------
diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 4b9634d..0e7254d 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -85,6 +85,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_prep_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 285d92b..7787d17 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -38,6 +38,7 @@
 #include "i40e_pf.h"
 #include "i40e_regs.h"
 #include "rte_pmd_i40e.h"
+#include "i40e_prep_ops.h"
 
 #define ETH_I40E_FLOATING_VEB_ARG	"enable_floating_veb"
 #define ETH_I40E_FLOATING_VEB_LIST_ARG	"floating_veb_list"
@@ -1093,6 +1094,17 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	hw->bus.func = pci_dev->addr.function;
 	hw->adapter_stopped = 0;
 
+	/* init representor broker */
+	if (rte_representor_enabled()) {
+		ret = i40e_port_representor_broker_init(dev, &pf->broker,
+			pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Make sure all is clean before doing PF reset */
 	i40e_clear_hw(hw);
 
@@ -1428,6 +1440,10 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	intr_handle = &pci_dev->intr_handle;
 
+	/* free port representor pmds */
+	if (rte_representor_enabled())
+		rte_representor_broker_uninit(pf->broker);
+
 	if (hw->adapter_stopped == 0)
 		i40e_dev_close(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index f2b4b70..cadecbf 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -928,6 +928,7 @@ struct i40e_pf {
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
 	struct i40e_tm_conf tm_conf;
+	struct rte_representor_broker *broker;
 
 	/* Dynamic Device Personalization */
 	bool gtp_support; /* 1 - support GTP-C and GTP-U */
diff --git a/drivers/net/i40e/i40e_prep_ops.c b/drivers/net/i40e/i40e_prep_ops.c
new file mode 100644
index 0000000..41ce4d4
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.c
@@ -0,0 +1,495 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#include <rte_bus_pci.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "base/i40e_type.h"
+#include "base/virtchnl.h"
+#include "i40e_ethdev.h"
+#include "i40e_rxtx.h"
+#include "rte_pmd_i40e.h"
+
+#include "i40e_prep_ops.h"
+
+struct i40e_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+i40e_representor_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return i40e_dev_link_update(i40e_priv_data->pf_ethdev,
+		wait_to_complete);
+}
+
+static void
+i40e_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (!is_i40e_supported(i40e_priv_data->pf_ethdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(
+		i40e_priv_data->pf_ethdev->data->dev_private);
+	if (representor->vport_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return;
+	}
+
+	vf = &pf->vfs[representor->vport_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return;
+	}
+
+	/* get dev info for the vdev */
+	dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(ethdev);
+	dev_info->max_rx_queues = vsi->nb_qps;
+	dev_info->max_tx_queues = vsi->nb_qps;
+	dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN;
+	dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
+	dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) *
+		sizeof(uint32_t);
+	dev_info->reta_size = ETH_RSS_RETA_SIZE_64;
+	dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL;
+	dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX;
+	dev_info->rx_offload_capa =
+		DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_QINQ_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |
+		DEV_RX_OFFLOAD_UDP_CKSUM |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	dev_info->tx_offload_capa =
+		DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_QINQ_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM |
+		DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM |
+		DEV_TX_OFFLOAD_SCTP_CKSUM;
+
+	dev_info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_thresh = {
+			.pthresh = I40E_DEFAULT_RX_PTHRESH,
+			.hthresh = I40E_DEFAULT_RX_HTHRESH,
+			.wthresh = I40E_DEFAULT_RX_WTHRESH,
+		},
+		.rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH,
+		.rx_drop_en = 0,
+	};
+
+	dev_info->default_txconf = (struct rte_eth_txconf) {
+		.tx_thresh = {
+			.pthresh = I40E_DEFAULT_TX_PTHRESH,
+			.hthresh = I40E_DEFAULT_TX_HTHRESH,
+			.wthresh = I40E_DEFAULT_TX_WTHRESH,
+		},
+		.tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH,
+		.tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH,
+		.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
+				ETH_TXQ_FLAGS_NOOFFLOADS,
+	};
+
+	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+
+	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+}
+
+static int i40e_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int i40e_representor_rx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int i40e_representor_tx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int i40e_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void i40e_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+i40e_representor_stats_get(struct rte_eth_dev *ethdev,
+		struct rte_eth_stats *stats)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_get_vf_stats(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, stats);
+}
+
+static void
+i40e_representor_stats_reset(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_reset_vf_stats(i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id);
+}
+
+static void
+i40e_representor_promiscuous_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_promiscuous_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_allmulticast_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_allmulticast_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_remove_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, &ethdev->data->mac_addrs[index]);
+}
+
+static void
+i40e_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+		struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, mac_addr);
+}
+
+static int
+i40e_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+		uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	vfid = representor->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_i40e_set_vf_vlan_filter(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		vlan_id, vf_mask, on);
+}
+
+static int
+i40e_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct rte_eth_dev *pdev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+	uint32_t vfid;
+
+	pdev = i40e_priv_data->pf_ethdev;
+	vfid = representor->vport_id;
+
+	if (!is_i40e_supported(pdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return -EINVAL;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(pdev->data->dev_private);
+
+	if (vfid >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return -EINVAL;
+	}
+
+	vf = &pf->vfs[vfid];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Fixme: even though there 3 kinds of hw offloads, hw_vlan_filter,
+	 * hw_vlan_strip, and hw_vlan_extend.
+	 * currently the hw_vlan_extend offload by vsi is not implemented.
+	 */
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		/* Enable or disable VLAN filtering offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_filter)
+			return i40e_vsi_config_vlan_filter(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_filter(vsi, FALSE);
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK) {
+		/* Enable or disable VLAN stripping offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_strip)
+			return i40e_vsi_config_vlan_stripping(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_stripping(vsi, FALSE);
+	}
+
+	return -EINVAL;
+}
+
+static void
+i40e_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_vlan_stripq(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, on);
+}
+
+static int
+i40e_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id,
+	__rte_unused int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_set_vf_vlan_insert(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, vlan_id);
+}
+
+struct eth_dev_ops i40e_representor_dev_ops = {
+	.link_update          = i40e_representor_link_update,
+	.dev_infos_get        = i40e_representor_dev_infos_get,
+	.dev_configure        = i40e_representor_dev_configure,
+	.rx_queue_setup       = i40e_representor_rx_queue_setup,
+	.tx_queue_setup       = i40e_representor_tx_queue_setup,
+	.dev_start            = i40e_representor_dev_start,
+	.dev_stop             = i40e_representor_dev_stop,
+
+	.stats_get            = i40e_representor_stats_get,
+	.stats_reset          = i40e_representor_stats_reset,
+
+	.promiscuous_enable   = i40e_representor_promiscuous_enable,
+	.promiscuous_disable  = i40e_representor_promiscuous_disable,
+
+	.allmulticast_enable  = i40e_representor_allmulticast_enable,
+	.allmulticast_disable = i40e_representor_allmulticast_disable,
+
+	.mac_addr_remove      = i40e_representor_mac_addr_remove,
+	.mac_addr_set         = i40e_representor_mac_addr_set,
+
+	.vlan_filter_set      = i40e_representor_vlan_filter_set,
+	.vlan_offload_set     = i40e_representor_vlan_offload_set,
+	.vlan_strip_queue_set = i40e_representor_vlan_strip_queue_set,
+	.vlan_pvid_set        = i40e_representor_vlan_pvid_set
+};
+
+static uint16_t i40e_prep_rx_burst(__rte_unused void *rxq,
+	__rte_unused struct rte_mbuf **rx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static uint16_t i40e_prep_tx_burst(__rte_unused void *txq,
+	__rte_unused struct rte_mbuf **tx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static int
+i40e_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port;
+	struct i40e_pf *i40e_pf;
+	struct i40e_pf_vf *i40e_vf;
+
+	port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("i40e_port_representor_priv_data",
+			sizeof(struct i40e_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct i40e_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+
+	i40e_pf = I40E_DEV_PRIVATE_TO_PF(pf_ethdev->data->dev_private);
+	i40e_vf = &i40e_pf->vfs[port->vport_id];
+
+	if (!i40e_vf->vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &i40e_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = i40e_vf->vsi->nb_qps;
+	ethdev->data->nb_tx_queues = i40e_vf->vsi->nb_qps;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = i40e_prep_rx_burst;
+	ethdev->tx_pkt_burst = i40e_prep_tx_burst;
+
+	return 0;
+}
+
+static int
+i40e_port_representor_uninit(struct rte_representor_broker *broker __rte_unused,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops i40e_broker_port_ops = {
+	.port_init = i40e_port_representor_init,
+	.port_uninit = i40e_port_representor_uninit
+};
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set i40e broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &i40e_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
diff --git a/drivers/net/i40e/i40e_prep_ops.h b/drivers/net/i40e/i40e_prep_ops.h
new file mode 100644
index 0000000..8e28b9e
--- /dev/null
+++ b/drivers/net/i40e/i40e_prep_ops.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _I40E_PREP_OPS_H_
+#define _I40E_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _I40E_PREP_OPS_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 947f13b..bd7c2b2 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -570,6 +570,53 @@ rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 	return 0;
 }
 
+static const struct ether_addr null_mac_addr;
+
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+		return -EINVAL;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs)
+		return -EINVAL;
+
+	vf = &pf->vfs[vf_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	if (!is_same_ether_addr(mac_addr, &vf->mac_addr)) {
+		PMD_DRV_LOG(ERR, "Mac address does not match.");
+		return -EINVAL;
+	}
+
+	/* reset the mac with null mac */
+	ether_addr_copy(&null_mac_addr, &vf->mac_addr);
+
+	/* Remove the mac */
+	i40e_vsi_delete_mac(vsi, mac_addr);
+
+	return 0;
+}
+
 /* Set vlan strip on/off for specific VF from host */
 int
 rte_pmd_i40e_set_vf_vlan_stripq(uint16_t port, uint16_t vf_id, uint8_t on)
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 7ca37b1..cd4e9e0 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -439,6 +439,24 @@ int rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
 /**
+ * Remove the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf_id
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr);
+
+/**
  * Enable/Disable vf vlan strip for all queues in a pool
  *
  * @param port
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v4 4/5] drivers/net/ixgbe: add Port Representor functionality
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
                       ` (2 preceding siblings ...)
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
@ 2018-01-08 14:37     ` Remy Horton
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 5/5] app/test-pmd: add Port Representor commands Remy Horton
                       ` (4 subsequent siblings)
  8 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-08 14:37 UTC (permalink / raw)
  To: dev
  Cc: John McNamara, Wenzhuo Lu, Jingjing Wu, Declan Doherty,
	Mohammad Abdul Awal

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.

This patch adds to the ixgbe PMD PMD the functions required to enable
port representor functionality.

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>
---
 MAINTAINERS                        |   2 +
 drivers/net/ixgbe/Makefile         |   1 +
 drivers/net/ixgbe/ixgbe_ethdev.c   |  22 +++-
 drivers/net/ixgbe/ixgbe_ethdev.h   |   5 +
 drivers/net/ixgbe/ixgbe_prep_ops.c | 259 +++++++++++++++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_prep_ops.h |  15 +++
 6 files changed, 303 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 08a8e97..f18438e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -783,6 +783,8 @@ F: lib/librte_representor
 F: doc/guides/prog_guide/representor_lib.rst
 F: drivers/net/i40e/i40e_prep_ops.c
 F: drivers/net/i40e/i40e_prep_ops.h
+F: drivers/net/ixgbe/ixgbe_prep_ops.c
+F: drivers/net/ixgbe/ixgbe_prep_ops.h
 
 Packet Framework
 ----------------
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index 9efa5a4..94f2ccd 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -102,6 +102,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_ipsec.c
 endif
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += rte_pmd_ixgbe.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_prep_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_IXGBE_PMD)-include := rte_pmd_ixgbe.h
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 43e0132..f8d2918 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -46,6 +46,7 @@
 #include "base/ixgbe_type.h"
 #include "base/ixgbe_phy.h"
 #include "ixgbe_regs.h"
+#include "ixgbe_prep_ops.h"
 
 /*
  * High threshold controlling when to start sending XOFF frames. Must be at
@@ -1109,6 +1110,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 	uint32_t ctrl_ext;
 	uint16_t csum;
 	int diag, i;
+	int ret;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1232,6 +1236,17 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 		return -EIO;
 	}
 
+	/* Init port representor broker */
+	if (rte_representor_enabled()) {
+		ret = ixgbe_port_representor_broker_init(eth_dev,
+			&eth_adapter->broker, pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Reset the hw statistics */
 	ixgbe_dev_stats_reset(eth_dev);
 
@@ -1334,6 +1349,8 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	struct ixgbe_hw *hw;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1342,6 +1359,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
 
+	if (rte_representor_enabled())
+		rte_representor_broker_uninit(eth_adapter->broker);
+
 	if (hw->adapter_stopped == 0)
 		ixgbe_dev_close(eth_dev);
 
@@ -3933,7 +3953,7 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 }
 
 /* return 0 means link status changed, -1 means not changed */
-static int
+int
 ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 			    int wait_to_complete, int vf)
 {
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 1db29bd..c2df08e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -470,6 +470,7 @@ struct ixgbe_adapter {
 	struct rte_timecounter      rx_tstamp_tc;
 	struct rte_timecounter      tx_tstamp_tc;
  	struct ixgbe_tm_conf        tm_conf;
+	struct rte_representor_broker *broker;
 };
 
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
@@ -644,6 +645,10 @@ int ixgbe_fdir_filter_program(struct rte_eth_dev *dev,
 
 void ixgbe_configure_dcb(struct rte_eth_dev *dev);
 
+int
+ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
+			    int wait_to_complete, int vf);
+
 /*
  * misc function prototypes
  */
diff --git a/drivers/net/ixgbe/ixgbe_prep_ops.c b/drivers/net/ixgbe/ixgbe_prep_ops.c
new file mode 100644
index 0000000..a06df27
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_prep_ops.c
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+#include <rte_port_representor_driver.h>
+
+#include "base/ixgbe_type.h"
+#include "base/ixgbe_vf.h"
+#include "ixgbe_ethdev.h"
+#include "ixgbe_rxtx.h"
+#include "rte_pmd_ixgbe.h"
+
+#include "ixgbe_prep_ops.h"
+
+struct ixgbe_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+ixgbe_representor_link_update(struct rte_eth_dev *ethdev,
+	int wait_to_complete)
+{
+	struct rte_representor_port *prep_priv_data =
+			ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+			prep_priv_data->priv_data;
+
+	return ixgbe_dev_link_update_share(ixgbe_priv_data->pf_ethdev,
+		wait_to_complete, 1);
+}
+
+static void
+ixgbe_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+	struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	rte_pmd_ixgbe_set_vf_mac_addr(ixgbe_priv_data->pf_ethdev->data->port_id,
+		prep_priv_data->vport_id, mac_addr);
+}
+
+static void
+ixgbe_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(
+		ixgbe_priv_data->pf_ethdev->data->dev_private);
+
+	dev_info->pci_dev = NULL;
+
+	dev_info->min_rx_bufsize = 1024;
+	/**< Minimum size of RX buffer. */
+	dev_info->max_rx_pktlen = 9728;
+	/**< Maximum configurable length of RX pkt. */
+	dev_info->max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	/**< Maximum number of RX queues. */
+	dev_info->max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+	/**< Maximum number of TX queues. */
+
+	dev_info->max_mac_addrs = hw->mac.num_rar_entries;
+	/**< Maximum number of MAC addresses. */
+
+	dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |	DEV_RX_OFFLOAD_UDP_CKSUM  |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	/**< Device RX offload capabilities. */
+
+	dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_TSO;
+	/**< Device TX offload capabilities. */
+
+	dev_info->speed_capa =
+		ixgbe_priv_data->pf_ethdev->data->dev_link.link_speed;
+	/**< Supported speeds bitmap (ETH_LINK_SPEED_). */
+}
+
+static int ixgbe_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int ixgbe_representor_rx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int ixgbe_representor_tx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int ixgbe_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void ixgbe_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+ixgbe_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+	uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_ixgbe_set_vf_vlan_filter(pfid, vlan_id, vf_mask, on);
+}
+
+static void
+ixgbe_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+
+	rte_pmd_ixgbe_set_vf_vlan_stripq(pfid, vfid, on);
+}
+
+struct eth_dev_ops ixgbe_representor_dev_ops = {
+	.link_update                  = ixgbe_representor_link_update,
+	.dev_infos_get                = ixgbe_representor_dev_infos_get,
+	.dev_configure	              = ixgbe_representor_dev_configure,
+	.rx_queue_setup               = ixgbe_representor_rx_queue_setup,
+	.tx_queue_setup               = ixgbe_representor_tx_queue_setup,
+	.dev_start                    = ixgbe_representor_dev_start,
+	.dev_stop                     = ixgbe_representor_dev_stop,
+	.mac_addr_set                 = ixgbe_representor_mac_addr_set,
+	.vlan_filter_set              = ixgbe_representor_vlan_filter_set,
+	.vlan_strip_queue_set         = ixgbe_representor_vlan_strip_queue_set
+};
+
+static int
+ixgbe_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("ixgbe_port_representor_priv_data",
+			sizeof(struct ixgbe_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct ixgbe_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &ixgbe_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	ethdev->data->nb_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = NULL;
+	ethdev->tx_pkt_burst = NULL;
+
+	return 0;
+}
+
+static int
+ixgbe_port_representor_uninit(
+	__rte_unused struct rte_representor_broker *broker,
+	struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops ixgbe_broker_port_ops = {
+	.port_init = ixgbe_port_representor_init,
+	.port_uninit = ixgbe_port_representor_uninit
+};
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set IXGBE broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &ixgbe_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
diff --git a/drivers/net/ixgbe/ixgbe_prep_ops.h b/drivers/net/ixgbe/ixgbe_prep_ops.h
new file mode 100644
index 0000000..744aa3e
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_prep_ops.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ */
+
+#ifndef _IXGBE_PREP_OPS_H_
+#define _IXGBE_PREP_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+#endif /* _IXGBE_PREP_OPS_H_ */
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v4 5/5] app/test-pmd: add Port Representor commands
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
                       ` (3 preceding siblings ...)
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 4/5] drivers/net/ixgbe: " Remy Horton
@ 2018-01-08 14:37     ` Remy Horton
  2018-01-09 22:10       ` Ferruh Yigit
  2018-01-09 22:01     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Ferruh Yigit
                       ` (3 subsequent siblings)
  8 siblings, 1 reply; 75+ messages in thread
From: Remy Horton @ 2018-01-08 14:37 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Wenzhuo Lu, Jingjing Wu

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.

This patch adds the 'add representor' and 'del representor' commands
to test-pmd, which respectively allow the adding and removing of
port representors.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/cmdline.c                      | 88 +++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 25 ++++++++
 2 files changed, 113 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f71d963..1a831ba 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -76,6 +76,7 @@
 #include <rte_eth_ctrl.h>
 #include <rte_flow.h>
 #include <rte_gro.h>
+#include <rte_port_representor.h>
 
 #include <cmdline_rdline.h>
 #include <cmdline_parse.h>
@@ -15535,6 +15536,91 @@ cmdline_parse_inst_t cmd_load_from_file = {
 	},
 };
 
+struct cmd_add_representor_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t representor;
+	cmdline_fixed_string_t pf;
+	uint16_t vport;
+};
+
+cmdline_parse_token_string_t cmd_addrepresentor_add =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	cmd, "add");
+cmdline_parse_token_string_t cmd_addrepresentor_del =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	cmd, "del");
+cmdline_parse_token_string_t cmd_addrepresentor_rep =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	representor, "representor");
+cmdline_parse_token_string_t cmd_addrepresentor_pf =
+TOKEN_STRING_INITIALIZER(struct cmd_add_representor_result,
+	pf, NULL);
+cmdline_parse_token_num_t cmd_addrepresentor_vport =
+TOKEN_NUM_INITIALIZER(struct cmd_add_representor_result,
+	vport, UINT16);
+
+static void cmd_add_representor_callback(void *parsed_result,
+		__attribute__((unused))  struct cmdline *cl,
+		__attribute__((unused)) void *data)
+{
+	struct cmd_add_representor_result *res = parsed_result;
+	uint16_t port_id;
+	int ret;
+
+	rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "%s(): addr:%s vport:%i\n",
+		__func__, res->pf, res->vport);
+
+	ret = rte_representor_port_register(res->pf, res->vport, &port_id);
+	if (ret != 0)
+		printf("Registering port representor failed\n");
+	else
+		printf("Port Representor registered with port id %i\n",
+			port_id);
+}
+
+static void cmd_del_representor_callback(void *parsed_result,
+		__attribute__((unused))  struct cmdline *cl,
+		__attribute__((unused)) void *data)
+{
+	struct cmd_add_representor_result *res = parsed_result;
+	int ret;
+
+	rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "%s(): port:%i\n", __func__,
+		res->vport);
+	ret = rte_representor_port_unregister(res->pf, res->vport);
+	if (ret != 0)
+		printf("Port %i is not a valid port representor.\n",
+			res->vport);
+}
+
+cmdline_parse_inst_t cmd_add_representor = {
+	.f = cmd_add_representor_callback,
+	.help_str = "add representor <BusName_DomBDF> <vport_id> "
+		"Add a Port Representor",
+	.data = NULL,
+	.tokens = {
+		(void *)&cmd_addrepresentor_add,
+		(void *)&cmd_addrepresentor_rep,
+		(void *)&cmd_addrepresentor_pf,
+		(void *)&cmd_addrepresentor_vport,
+		NULL
+	}
+};
+
+cmdline_parse_inst_t cmd_del_representor = {
+	.f = cmd_del_representor_callback,
+	.help_str = "del representor <BusName_DomBDF> <vport_id> "
+		"Delete a Port Representor",
+	.data = NULL,
+	.tokens = {
+		(void *)&cmd_addrepresentor_del,
+		(void *)&cmd_addrepresentor_rep,
+		(void *)&cmd_addrepresentor_pf,
+		(void *)&cmd_addrepresentor_vport,
+		NULL
+	}
+};
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -15576,6 +15662,8 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *) &cmd_show_bonding_config,
 	(cmdline_parse_inst_t *) &cmd_set_bonding_primary,
 	(cmdline_parse_inst_t *) &cmd_add_bonding_slave,
+	(cmdline_parse_inst_t *) &cmd_add_representor,
+	(cmdline_parse_inst_t *) &cmd_del_representor,
 	(cmdline_parse_inst_t *) &cmd_remove_bonding_slave,
 	(cmdline_parse_inst_t *) &cmd_create_bonded_device,
 	(cmdline_parse_inst_t *) &cmd_set_bond_mac_addr,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 9789139..0eaeb38 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3481,3 +3481,28 @@ Validate and create a QinQ rule on port 0 to steer traffic to a queue on the hos
    ID      Group   Prio    Attr    Rule
    0       0       0       i-      ETH VLAN VLAN=>VF QUEUE
    1       0       0       i-      ETH VLAN VLAN=>PF QUEUE
+
+Port Representors
+-----------------
+
+Adding and removal of port representors (*rte_representor*) is done via the
+``add representor`` and ``del representor`` commands. Once created these
+can take the same control commands as the underlying VF (Virtual Function).
+
+
+Adding a representor
+~~~~~~~~~~~~~~~~~~~~
+
+Adding a representor for a VF requires specifying the PF in
+``Bus_DomBDF`` format alongside the index number of the VF::
+
+   testpmd> add representor pci_0000:81:00.0 0
+
+
+Removing a representor
+~~~~~~~~~~~~~~~~~~~~~~
+
+To remove a representor, the same parameters are required as were used to
+create it::
+
+    testpmd> del representor pci_0000:81:00.0 0
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
                       ` (4 preceding siblings ...)
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 5/5] app/test-pmd: add Port Representor commands Remy Horton
@ 2018-01-09 22:01     ` Ferruh Yigit
  2018-01-10 14:17       ` Mohammad Abdul Awal
  2018-01-09 23:22     ` Thomas Monjalon
                       ` (2 subsequent siblings)
  8 siblings, 1 reply; 75+ messages in thread
From: Ferruh Yigit @ 2018-01-09 22:01 UTC (permalink / raw)
  To: Remy Horton, dev; +Cc: John McNamara, Wenzhuo Lu, Jingjing Wu

<...>

> The port representor infrastructure is enabled through a single common, device
> independent, virtual PMD whos context is initialized and enabled through a
> broker instance running within the context of the physical function device
> driver.>
> +-------------------------+       +-------------------------+
> |        rte_ethdev       |       |       rte_ethdev        |
> +-------------------------+       +-------------------------+
> |  Physical Function PMD  |       |  Port Reperesentor PMD  |
> |         +-------------+ |       | +---------+ +---------+ |
> |         | Representor | |       | | dev_data| | dev_ops | |
> |         |    Broker   | |       | +----+----+ +----+----+ |
> |         | +---------+ | |       +------|-----------|------+
> |         | | VF Port | | |              |           |
> |         | | Context +------------------+           |
> |         | +---------+ | |                          |
> |         | +---------+ | |                          |
> |         | | Handler +------------------------------+
> |         | |   Ops   | | |
> |         | +---------+ | |
> |         +-------------+ |
> +-------------------------+
> 
> Creation of representor ports can be achieved either through the --vdev EAL
> option or through the rte_vdev_init() API. Each port representor requires the
> BDF of it's parent PF and the Virtual Function ID of the port which the
> representor will support. During initialization of the representor PMD, it calls
> the broker API to register itself with the PF PMD and to get it's context
> configured which includes the setting up of it's context and ops function
> handlers.

Above no more true, right?

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 1/5] lib: add Port Representor library
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 1/5] lib: add Port Representor library Remy Horton
@ 2018-01-09 22:06       ` Ferruh Yigit
  2018-01-10 11:40         ` Remy Horton
  0 siblings, 1 reply; 75+ messages in thread
From: Ferruh Yigit @ 2018-01-09 22:06 UTC (permalink / raw)
  To: Remy Horton, dev
  Cc: John McNamara, Wenzhuo Lu, Jingjing Wu, Declan Doherty,
	Mohammad Abdul Awal, Luca Boccassi

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.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 2/5] eal: add Port Representor command-line option
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 2/5] eal: add Port Representor command-line option Remy Horton
@ 2018-01-09 22:07       ` Ferruh Yigit
  0 siblings, 0 replies; 75+ messages in thread
From: Ferruh Yigit @ 2018-01-09 22:07 UTC (permalink / raw)
  To: Remy Horton, dev
  Cc: John McNamara, Wenzhuo Lu, Jingjing Wu, Declan Doherty,
	Mohammad Abdul Awal

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.
> 
> By default the Port Representor infrastructure is not enabled. This
> patch implements the --enable-representor EAL command-line parameter
> that activates representation functionality.>
> 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>

<...>

> @@ -78,6 +78,7 @@ const struct option
>  eal_long_options[] = {
>  	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
>  	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
> +	{OPT_ENABLE_REPRESENTOR, 0, NULL, OPT_ENABLE_REPRESENTOR_NUM   },

There must be some kind of documentation to document new eal option.

<...>

> @@ -83,6 +83,8 @@ enum {
>  	OPT_VFIO_INTR_NUM,
>  #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
>  	OPT_VMWARE_TSC_MAP_NUM,
> +#define OPT_ENABLE_REPRESENTOR    "enable-representor"
> +	OPT_ENABLE_REPRESENTOR_NUM,

In this context the meaning is clear. But when a newcomer checking the source
code from scratch I believe it may not be very clear what "enable-representor"
does, what is represented etc. What do you think?

Overall there are mixed usage, but I would vote for using port-representor
everywhere just representor used, will it be too long? Also I have seen this
shorten as "prep" which where looks like short of "prepare", what do you think
about another keyword?

<...>

> +
> +int rte_representor_enabled(void)
> +{
> +	return internal_config.enable_representor;
> +}

Isn't this need to be in .map file. I didn't test but will it work when build
for shared library?

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
@ 2018-01-09 22:09       ` Ferruh Yigit
  2018-01-10  7:56       ` Xing, Beilei
  1 sibling, 0 replies; 75+ messages in thread
From: Ferruh Yigit @ 2018-01-09 22:09 UTC (permalink / raw)
  To: Remy Horton, dev
  Cc: John McNamara, Wenzhuo Lu, Jingjing Wu, Declan Doherty,
	Mohammad Abdul Awal

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.
> 
> This patch adds to the i40e PMD the functions required to enable port
> representor functionality.
> 
> 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>

<...>

> @@ -85,6 +85,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
>  SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
>  SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c
>  SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_tm.c
> +SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_prep_ops.c

This library should be a dependency to the driver now right? May need to update
both LDLIBS here.

<...>

> @@ -1428,6 +1440,10 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
>  	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
>  	intr_handle = &pci_dev->intr_handle;
>  
> +	/* free port representor pmds */
> +	if (rte_representor_enabled())
> +		rte_representor_broker_uninit(pf->broker);

Shouldn't this free the "broker" allocated by i40e_port_representor_broker_init?

<...>

> +int
> +rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
> +	struct ether_addr *mac_addr)

port_id should be uint16_t

<...>

>  /**
> + * Remove the VF MAC address.
> + *
> + * @param port
> + *   The port identifier of the Ethernet device.
> + * @param vf_id
> + *   VF id.
> + * @param mac_addr
> + *   VF MAC address.
> + * @return
> + *   - (0) if successful.
> + *   - (-ENODEV) if *port* invalid.
> + *   - (-EINVAL) if *vf* or *mac_addr* is invalid.
> + */
> +int
> +rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
> +	struct ether_addr *mac_addr);
> +

New PMD specific API requires updating .map file for shared library.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 5/5] app/test-pmd: add Port Representor commands
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 5/5] app/test-pmd: add Port Representor commands Remy Horton
@ 2018-01-09 22:10       ` Ferruh Yigit
  2018-01-10  7:22         ` Remy Horton
  0 siblings, 1 reply; 75+ messages in thread
From: Ferruh Yigit @ 2018-01-09 22:10 UTC (permalink / raw)
  To: Remy Horton, dev; +Cc: John McNamara, Wenzhuo Lu, Jingjing Wu

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.
> 
> This patch adds the 'add representor' and 'del representor' commands
> to test-pmd, which respectively allow the adding and removing of
> port representors.
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>

<...>

> +
> +	rte_log(RTE_LOG_INFO, RTE_LOGTYPE_USER1, "%s(): addr:%s vport:%i\n",
> +		__func__, res->pf, res->vport);

this file tends to use printf for logs.
<...>

> @@ -15576,6 +15662,8 @@ cmdline_parse_ctx_t main_ctx[] = {
>  	(cmdline_parse_inst_t *) &cmd_show_bonding_config,
>  	(cmdline_parse_inst_t *) &cmd_set_bonding_primary,
>  	(cmdline_parse_inst_t *) &cmd_add_bonding_slave,
> +	(cmdline_parse_inst_t *) &cmd_add_representor,
> +	(cmdline_parse_inst_t *) &cmd_del_representor,

Please update cmd_help_long_parsed() to add new commands.

<...>

> +Adding a representor for a VF requires specifying the PF in
> +``Bus_DomBDF`` format alongside the index number of the VF::
> +
> +   testpmd> add representor pci_0000:81:00.0 0

I am for grouping port related commands under "port" command, these are all OK
in their context, but when you look into all testpmd command it turns into mess.

What do you think for:
port representor add <pf_address> <vport_id>
port representor del <pf_address> <vport_id>

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
                       ` (5 preceding siblings ...)
  2018-01-09 22:01     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Ferruh Yigit
@ 2018-01-09 23:22     ` Thomas Monjalon
  2018-01-10 13:46       ` Doherty, Declan
  2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
  2018-01-11  3:18     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Yuanhan Liu
  8 siblings, 1 reply; 75+ messages in thread
From: Thomas Monjalon @ 2018-01-09 23:22 UTC (permalink / raw)
  To: Remy Horton, Mohammad Abdul Awal, Declan Doherty
  Cc: dev, John McNamara, Wenzhuo Lu, Jingjing Wu, Alejandro Lucero,
	vincent.jardin

Hi,

08/01/2018 15:37, Remy Horton:
> 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.

Extending control plane ability of DPDK has been discussed
multiple times.
The current agreed policy is:
"
The primary goal of DPDK is to provide a userspace dataplane.
Managing VFs from a PF driver is a control plane feature and developers
should generally rely on the Linux Kernel for that.
"
http://dpdk.org/doc/guides/contributing/design.html#pf-and-vf-considerations

If we relax this policy, I think the representor solution should be
a real port, not only "for the purposes of control and monitoring".
It has been asked several times as replies to this series,
but it is kindly ignored, saying it will be thought later.

I don't see a general agreement on this series so far.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 5/5] app/test-pmd: add Port Representor commands
  2018-01-09 22:10       ` Ferruh Yigit
@ 2018-01-10  7:22         ` Remy Horton
  0 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10  7:22 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: John McNamara, Wenzhuo Lu, Jingjing Wu


On 09/01/2018 22:10, Ferruh Yigit wrote:
[..]
>> +Adding a representor for a VF requires specifying the PF in
>> +``Bus_DomBDF`` format alongside the index number of the VF::
>> +
>> +   testpmd> add representor pci_0000:81:00.0 0
>
> I am for grouping port related commands under "port" command, these are all OK
> in their context, but when you look into all testpmd command it turns into mess.
>
> What do you think for:
> port representor add <pf_address> <vport_id>
> port representor del <pf_address> <vport_id>

Seems good to me - did notice some of the interactive help screens were 
a bit on the long side..

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality
  2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
  2018-01-09 22:09       ` Ferruh Yigit
@ 2018-01-10  7:56       ` Xing, Beilei
  2018-01-10 10:11         ` Mohammad Abdul Awal
  1 sibling, 1 reply; 75+ messages in thread
From: Xing, Beilei @ 2018-01-10  7:56 UTC (permalink / raw)
  To: Horton, Remy, dev
  Cc: Mcnamara, John, Lu, Wenzhuo, Wu, Jingjing, Doherty, Declan, Awal,
	Mohammad Abdul



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Monday, January 8, 2018 10:37 PM
> To: dev@dpdk.org
> Cc: Mcnamara, John <john.mcnamara@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>; Doherty,
> Declan <declan.doherty@intel.com>; Awal, Mohammad Abdul
> <mohammad.abdul.awal@intel.com>
> Subject: [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add 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
> 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.
> 
> This patch adds to the i40e PMD the functions required to enable port
> representor functionality.
> 
> 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>
> ---
>  MAINTAINERS                      |   2 +
>  drivers/net/i40e/Makefile        |   1 +
>  drivers/net/i40e/i40e_ethdev.c   |  16 ++
>  drivers/net/i40e/i40e_ethdev.h   |   1 +
>  drivers/net/i40e/i40e_prep_ops.c | 495
> +++++++++++++++++++++++++++++++++++++++
>  drivers/net/i40e/i40e_prep_ops.h |  15 ++
> drivers/net/i40e/rte_pmd_i40e.c  |  47 ++++
> drivers/net/i40e/rte_pmd_i40e.h  |  18 ++
>  8 files changed, 595 insertions(+)
>  create mode 100644 drivers/net/i40e/i40e_prep_ops.c  create mode 100644
> drivers/net/i40e/i40e_prep_ops.h

<...>

> +	dev_info->rx_offload_capa =
> +		DEV_RX_OFFLOAD_VLAN_STRIP |
> +		DEV_RX_OFFLOAD_QINQ_STRIP |
> +		DEV_RX_OFFLOAD_IPV4_CKSUM |
> +		DEV_RX_OFFLOAD_UDP_CKSUM |
> +		DEV_RX_OFFLOAD_TCP_CKSUM;
> +	dev_info->tx_offload_capa =
> +		DEV_TX_OFFLOAD_VLAN_INSERT |
> +		DEV_TX_OFFLOAD_QINQ_INSERT |
> +		DEV_TX_OFFLOAD_IPV4_CKSUM |
> +		DEV_TX_OFFLOAD_UDP_CKSUM |
> +		DEV_TX_OFFLOAD_TCP_CKSUM |
> +		DEV_TX_OFFLOAD_SCTP_CKSUM;

Tunnel TSO and outer IP checksum are also supported.

<...>

> +static const struct ether_addr null_mac_addr;
> +
> +int
> +rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
> +	struct ether_addr *mac_addr)
> +{
> +	struct rte_eth_dev *dev;
> +	struct i40e_pf_vf *vf;
> +	struct i40e_vsi *vsi;
> +	struct i40e_pf *pf;
> +
> +	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
> +		return -EINVAL;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
> +
> +	dev = &rte_eth_devices[port];
> +
> +	if (!is_i40e_supported(dev))
> +		return -ENOTSUP;
> +
> +	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +
> +	if (vf_id >= pf->vf_num || !pf->vfs)
> +		return -EINVAL;
> +
> +	vf = &pf->vfs[vf_id];
> +	vsi = vf->vsi;
> +	if (!vsi) {
> +		PMD_DRV_LOG(ERR, "Invalid VSI.");
> +		return -EINVAL;
> +	}
> +
> +	if (!is_same_ether_addr(mac_addr, &vf->mac_addr)) {
> +		PMD_DRV_LOG(ERR, "Mac address does not match.");
> +		return -EINVAL;
> +	}

Not very understand why only vf->mac_addr can be moved? I think any mac address in vsi->mac_list can be removed.

> +
> +	/* reset the mac with null mac */
> +	ether_addr_copy(&null_mac_addr, &vf->mac_addr);
> +
> +	/* Remove the mac */
> +	i40e_vsi_delete_mac(vsi, mac_addr);
> +
> +	return 0;
> +}
> +

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality
  2018-01-10  7:56       ` Xing, Beilei
@ 2018-01-10 10:11         ` Mohammad Abdul Awal
  2018-01-10 12:37           ` Xing, Beilei
  0 siblings, 1 reply; 75+ messages in thread
From: Mohammad Abdul Awal @ 2018-01-10 10:11 UTC (permalink / raw)
  To: Xing, Beilei, Horton, Remy, dev
  Cc: Mcnamara, John, Lu, Wenzhuo, Wu, Jingjing, Doherty, Declan



On 10/01/2018 07:56, Xing, Beilei wrote:
>
>> -----Original Message-----
>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
>> +	dev_info->rx_offload_capa =
>> +		DEV_RX_OFFLOAD_VLAN_STRIP |
>> +		DEV_RX_OFFLOAD_QINQ_STRIP |
>> +		DEV_RX_OFFLOAD_IPV4_CKSUM |
>> +		DEV_RX_OFFLOAD_UDP_CKSUM |
>> +		DEV_RX_OFFLOAD_TCP_CKSUM;
>> +	dev_info->tx_offload_capa =
>> +		DEV_TX_OFFLOAD_VLAN_INSERT |
>> +		DEV_TX_OFFLOAD_QINQ_INSERT |
>> +		DEV_TX_OFFLOAD_IPV4_CKSUM |
>> +		DEV_TX_OFFLOAD_UDP_CKSUM |
>> +		DEV_TX_OFFLOAD_TCP_CKSUM |
>> +		DEV_TX_OFFLOAD_SCTP_CKSUM;
> Tunnel TSO and outer IP checksum are also supported.
Correct. Fixed.
>
> <...>
>
>> +static const struct ether_addr null_mac_addr;
>> +
>> +int
>> +rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
>> +	struct ether_addr *mac_addr)
>> +{
>> +	struct rte_eth_dev *dev;
>> +	struct i40e_pf_vf *vf;
>> +	struct i40e_vsi *vsi;
>> +	struct i40e_pf *pf;
>> +
>> +	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
>> +		return -EINVAL;
>> +
>> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
>> +
>> +	dev = &rte_eth_devices[port];
>> +
>> +	if (!is_i40e_supported(dev))
>> +		return -ENOTSUP;
>> +
>> +	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
>> +
>> +	if (vf_id >= pf->vf_num || !pf->vfs)
>> +		return -EINVAL;
>> +
>> +	vf = &pf->vfs[vf_id];
>> +	vsi = vf->vsi;
>> +	if (!vsi) {
>> +		PMD_DRV_LOG(ERR, "Invalid VSI.");
>> +		return -EINVAL;
>> +	}
>> +
>> +	if (!is_same_ether_addr(mac_addr, &vf->mac_addr)) {
>> +		PMD_DRV_LOG(ERR, "Mac address does not match.");
>> +		return -EINVAL;
>> +	}
> Not very understand why only vf->mac_addr can be moved?
It it checks if the mac address we want to delete, similar to the 
function rte_pmd_i40e_set_vf_mac_addr where we set the mac address of a VF.
> I think any mac address in vsi->mac_list can be removed.
Yes, it is removed from the vsi->mac_list in the next line if the mac 
address is matched in the previous checking.

>> +
>> +	/* reset the mac with null mac */
>> +	ether_addr_copy(&null_mac_addr, &vf->mac_addr);
Here we reset the mac address of a VF with null address, reverting the 
operation of function rte_pmd_i40e_set_vf_mac_addr where we set the mac 
address of a VF.
>> +
>> +	/* Remove the mac */
>> +	i40e_vsi_delete_mac(vsi, mac_addr);
>> +
>> +	return 0;
>> +}
>> +

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 1/5] lib: add Port Representor library
  2018-01-09 22:06       ` Ferruh Yigit
@ 2018-01-10 11:40         ` Remy Horton
  0 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 11:40 UTC (permalink / raw)
  To: Ferruh Yigit, dev
  Cc: John McNamara, Wenzhuo Lu, Jingjing Wu, Declan Doherty,
	Mohammad Abdul Awal, Luca Boccassi


On 09/01/2018 22:06, Ferruh Yigit wrote:
> On 1/8/2018 2:37 PM, Remy Horton wrote:
[..]

>> +	TAILQ_FOREACH(broker, &broker_list, next) {
> Is there any type of synchronization required to protect the list?

Might be required if an app decides to call the functions from multiple 
lcores, but in that circumstance locking probably should be the 
responsibility of the app.


> There was discussion about having new APIs as EXPERIMENTAL for a release, is it
> agreed on. John, Luca do you remember?

I also remember some discussion along those lines, but not sure what the 
final outcome was.


>> +	void *private_data;
>> +	/**< broker private data */
>
> Is this private_data used?

The PMD-specific port representor support functions use it.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality
  2018-01-10 10:11         ` Mohammad Abdul Awal
@ 2018-01-10 12:37           ` Xing, Beilei
  2018-01-10 14:04             ` Mohammad Abdul Awal
  0 siblings, 1 reply; 75+ messages in thread
From: Xing, Beilei @ 2018-01-10 12:37 UTC (permalink / raw)
  To: Awal, Mohammad Abdul, Horton, Remy, dev
  Cc: Mcnamara, John, Lu, Wenzhuo, Wu, Jingjing, Doherty, Declan


> -----Original Message-----
> From: Awal, Mohammad Abdul
> Sent: Wednesday, January 10, 2018 6:11 PM
> To: Xing, Beilei <beilei.xing@intel.com>; Horton, Remy
> <remy.horton@intel.com>; dev@dpdk.org
> Cc: Mcnamara, John <john.mcnamara@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>; Doherty,
> Declan <declan.doherty@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port
> Representor functionality
> 
> 
> 
> On 10/01/2018 07:56, Xing, Beilei wrote:
> >
> >> -----Original Message-----
> >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> >> +	dev_info->rx_offload_capa =
> >> +		DEV_RX_OFFLOAD_VLAN_STRIP |
> >> +		DEV_RX_OFFLOAD_QINQ_STRIP |
> >> +		DEV_RX_OFFLOAD_IPV4_CKSUM |
> >> +		DEV_RX_OFFLOAD_UDP_CKSUM |
> >> +		DEV_RX_OFFLOAD_TCP_CKSUM;
> >> +	dev_info->tx_offload_capa =
> >> +		DEV_TX_OFFLOAD_VLAN_INSERT |
> >> +		DEV_TX_OFFLOAD_QINQ_INSERT |
> >> +		DEV_TX_OFFLOAD_IPV4_CKSUM |
> >> +		DEV_TX_OFFLOAD_UDP_CKSUM |
> >> +		DEV_TX_OFFLOAD_TCP_CKSUM |
> >> +		DEV_TX_OFFLOAD_SCTP_CKSUM;
> > Tunnel TSO and outer IP checksum are also supported.
> Correct. Fixed.
> >
> > <...>
> >
> >> +static const struct ether_addr null_mac_addr;
> >> +
> >> +int
> >> +rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
> >> +	struct ether_addr *mac_addr)
> >> +{
> >> +	struct rte_eth_dev *dev;
> >> +	struct i40e_pf_vf *vf;
> >> +	struct i40e_vsi *vsi;
> >> +	struct i40e_pf *pf;
> >> +
> >> +	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
> >> +		return -EINVAL;
> >> +
> >> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
> >> +
> >> +	dev = &rte_eth_devices[port];
> >> +
> >> +	if (!is_i40e_supported(dev))
> >> +		return -ENOTSUP;
> >> +
> >> +	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> >> +
> >> +	if (vf_id >= pf->vf_num || !pf->vfs)
> >> +		return -EINVAL;
> >> +
> >> +	vf = &pf->vfs[vf_id];
> >> +	vsi = vf->vsi;
> >> +	if (!vsi) {
> >> +		PMD_DRV_LOG(ERR, "Invalid VSI.");
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	if (!is_same_ether_addr(mac_addr, &vf->mac_addr)) {
> >> +		PMD_DRV_LOG(ERR, "Mac address does not match.");
> >> +		return -EINVAL;
> >> +	}
> > Not very understand why only vf->mac_addr can be moved?
> It it checks if the mac address we want to delete, similar to the function
> rte_pmd_i40e_set_vf_mac_addr where we set the mac address of a VF.

But in this way, seems we can't delete the mac address added by rte_pmd_i40e_add_vf_mac_addr.
set_vf_mac_addr should be used for setting default mac address, right?

> > I think any mac address in vsi->mac_list can be removed.
> Yes, it is removed from the vsi->mac_list in the next line if the mac address is
> matched in the previous checking.
> 
> >> +
> >> +	/* reset the mac with null mac */
> >> +	ether_addr_copy(&null_mac_addr, &vf->mac_addr);
> Here we reset the mac address of a VF with null address, reverting the
> operation of function rte_pmd_i40e_set_vf_mac_addr where we set the
> mac address of a VF.
> >> +
> >> +	/* Remove the mac */
> >> +	i40e_vsi_delete_mac(vsi, mac_addr);
> >> +
> >> +	return 0;
> >> +}
> >> +


^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-09 23:22     ` Thomas Monjalon
@ 2018-01-10 13:46       ` Doherty, Declan
  2018-01-10 19:26         ` Thomas Monjalon
  0 siblings, 1 reply; 75+ messages in thread
From: Doherty, Declan @ 2018-01-10 13:46 UTC (permalink / raw)
  To: Thomas Monjalon, Remy Horton, Mohammad Abdul Awal
  Cc: dev, John McNamara, Wenzhuo Lu, Jingjing Wu, Alejandro Lucero,
	vincent.jardin

On 09/01/2018 11:22 PM, Thomas Monjalon wrote:
> Hi,
> 
> 08/01/2018 15:37, Remy Horton:
>> 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.
> 
> Extending control plane ability of DPDK has been discussed
> multiple times.

It has, and I have yet to see a really strong reason as to why we would 
not support control plane functions within DPDK, many of which are 
already support today implicitly anyway through our ethdev APIs.

> The current agreed policy is:
> "
> The primary goal of DPDK is to provide a userspace dataplane.
> Managing VFs from a PF driver is a control plane feature and developers
> should generally rely on the Linux Kernel for that.
> "
> http://dpdk.org/doc/guides/contributing/design.html#pf-and-vf-considerations
> 

My understanding is that this particular entry was based around the
discussion on the divergence of functionality between the Linux kernel
PF driver and the DPDK PF driver. I also don't really think the above
statement is valid as a blanket statement for the project as it makes 
the assumption that DPDK is only deployed on Linux hosts, what about 
FreeBSD? or in the future Windows?

A number of presentations at both Userspace in Dublin and the Summit
in San Jose discussed the support of control plane functionality by
DPDK and there wasn't any strong arguments or opposition against using
DPDK for control plane functions that I saw.

In any case this patchset is not introducing any new control plane APIs 
that don't already exist within DPDK today, it only enables the creation 
of a new type of virtual PMDs which are linked to the same base 
infrastructure and which can be used to represent VFs in a control plane 
application as we have implemented in this patch set.

> If we relax this policy, I think the representor solution should be
> a real port, not only "for the purposes of control and monitoring".
> It has been asked several times as replies to this series,
> but it is kindly ignored, saying it will be thought later.
> 

I think we have stated in multiple discussions, especially during the
userspace presentation back in September that this solution supports
data path on the representors PMDs, and we have used the
infrastructure proposed here to do exactly what you are asking. As the
representor infrastructure doesn't preclude the support of a data
path, we have used it as it is presented here to implement a data path 
for exception path packets for a prototype vswitch offload implementation.


> I don't see a general agreement on this series so far.
> 

I think the main issue of contention is that there is a
misunderstanding that this implementation only supports control plane
management and monitoring, but that is not the case and it can be used
for full data path representors, with limited or no control plane
functionality if required, at the end of the day the only limitations
are based on what is implemented by the backend base driver were the 
broker is running for the representor ports.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality
  2018-01-10 12:37           ` Xing, Beilei
@ 2018-01-10 14:04             ` Mohammad Abdul Awal
  0 siblings, 0 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2018-01-10 14:04 UTC (permalink / raw)
  To: Xing, Beilei, Horton, Remy, dev
  Cc: Mcnamara, John, Lu, Wenzhuo, Wu, Jingjing, Doherty, Declan



On 10/01/2018 12:37, Xing, Beilei wrote:
> -----Original Message-----
>> From: Awal, Mohammad Abdul
>> On 10/01/2018 07:56, Xing, Beilei wrote:
>>> <...>
>>>
>>>> +static const struct ether_addr null_mac_addr;
>>>> +
>>>> +int
>>>> +rte_pmd_i40e_remove_vf_mac_addr(uint8_t port, uint16_t vf_id,
>>>> +	struct ether_addr *mac_addr)
>>>> +{
>>>> +	struct rte_eth_dev *dev;
>>>> +	struct i40e_pf_vf *vf;
>>>> +	struct i40e_vsi *vsi;
>>>> +	struct i40e_pf *pf;
>>>> +
>>>> +	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
>>>> +		return -EINVAL;
>>>> +
>>>> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
>>>> +
>>>> +	dev = &rte_eth_devices[port];
>>>> +
>>>> +	if (!is_i40e_supported(dev))
>>>> +		return -ENOTSUP;
>>>> +
>>>> +	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
>>>> +
>>>> +	if (vf_id >= pf->vf_num || !pf->vfs)
>>>> +		return -EINVAL;
>>>> +
>>>> +	vf = &pf->vfs[vf_id];
>>>> +	vsi = vf->vsi;
>>>> +	if (!vsi) {
>>>> +		PMD_DRV_LOG(ERR, "Invalid VSI.");
>>>> +		return -EINVAL;
>>>> +	}
>>>> +
>>>> +	if (!is_same_ether_addr(mac_addr, &vf->mac_addr)) {
>>>> +		PMD_DRV_LOG(ERR, "Mac address does not match.");
>>>> +		return -EINVAL;
>>>> +	}
>>> Not very understand why only vf->mac_addr can be moved?
>> It it checks if the mac address we want to delete, similar to the function
>> rte_pmd_i40e_set_vf_mac_addr where we set the mac address of a VF.
> But in this way, seems we can't delete the mac address added by rte_pmd_i40e_add_vf_mac_addr.
> set_vf_mac_addr should be used for setting default mac address, right?
OK, I understand what you mean.
I have fixed it now. We reset the vf->mac_addr only if the mac address 
is matched.
Then we delete it from the vsi->mac_list.

Thanks,
Awal.

>
>>> I think any mac address in vsi->mac_list can be removed.
>> Yes, it is removed from the vsi->mac_list in the next line if the mac address is
>> matched in the previous checking.
>>
>>>> +
>>>> +	/* reset the mac with null mac */
>>>> +	ether_addr_copy(&null_mac_addr, &vf->mac_addr);
>> Here we reset the mac address of a VF with null address, reverting the
>> operation of function rte_pmd_i40e_set_vf_mac_addr where we set the
>> mac address of a VF.
>>>> +
>>>> +	/* Remove the mac */
>>>> +	i40e_vsi_delete_mac(vsi, mac_addr);
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-09 22:01     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Ferruh Yigit
@ 2018-01-10 14:17       ` Mohammad Abdul Awal
  0 siblings, 0 replies; 75+ messages in thread
From: Mohammad Abdul Awal @ 2018-01-10 14:17 UTC (permalink / raw)
  To: Ferruh Yigit, Remy Horton, dev; +Cc: John McNamara, Wenzhuo Lu, Jingjing Wu



On 09/01/2018 22:01, Ferruh Yigit wrote:
> <...>
>
>> The port representor infrastructure is enabled through a single common, device
>> independent, virtual PMD whos context is initialized and enabled through a
>> broker instance running within the context of the physical function device
>> driver.>
>> +-------------------------+       +-------------------------+
>> |        rte_ethdev       |       |       rte_ethdev        |
>> +-------------------------+       +-------------------------+
>> |  Physical Function PMD  |       |  Port Reperesentor PMD  |
>> |         +-------------+ |       | +---------+ +---------+ |
>> |         | Representor | |       | | dev_data| | dev_ops | |
>> |         |    Broker   | |       | +----+----+ +----+----+ |
>> |         | +---------+ | |       +------|-----------|------+
>> |         | | VF Port | | |              |           |
>> |         | | Context +------------------+           |
>> |         | +---------+ | |                          |
>> |         | +---------+ | |                          |
>> |         | | Handler +------------------------------+
>> |         | |   Ops   | | |
>> |         | +---------+ | |
>> |         +-------------+ |
>> +-------------------------+
>>
>> Creation of representor ports can be achieved either through the --vdev EAL
>> option or through the rte_vdev_init() API. Each port representor requires the
>> BDF of it's parent PF and the Virtual Function ID of the port which the
>> representor will support. During initialization of the representor PMD, it calls
>> the broker API to register itself with the PF PMD and to get it's context
>> configured which includes the setting up of it's context and ops function
>> handlers.
> Above no more true, right?
Right. We will rewrite these parts.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
                       ` (6 preceding siblings ...)
  2018-01-09 23:22     ` Thomas Monjalon
@ 2018-01-10 15:54     ` Remy Horton
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
                         ` (5 more replies)
  2018-01-11  3:18     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Yuanhan Liu
  8 siblings, 6 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 15:54 UTC (permalink / raw)
  To: dev; +Cc: John McNamara

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.

+-----------------------------+   +---------------+  +---------------+
|        Control Plane        |   |   Data Plane  |  |   Data Plane  |
|         Application         |   |   Application |  |   Application |
+-----------------------------+   +---------------+  +---------------+
|         eth dev api         |   |  eth dev api  |  |  eth dev api  |
+-----------------------------+   +---------------+  +---------------+
+-------+  +-------+  +-------+   +---------------+  +---------------+
|  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
|  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
|       |  | PMD   |  | PMD   |                             |
+---+--^+  +-------+  +-+-----+                             |
    |  |                |  |                                |
    |  +----------------+  |                                |
    |                      |                                |
    |                      |                                |
+--------------------------------+                          |
|   |  HW (logical view)   |     |                          |
| --+------+ +-------+ +---+---+ |                          |
| |   PF   | |  VF0  | |  VF1  | |                          |
| |        | |       | |       +----------------------------+
| +--------+ +-------+ +-------+ |
| +----------------------------+ |
| |        VEB                 | |
| +----------------------------+ |
| +--------+                     |
| |  Port  |                     |
| |   0    |                     |
| +--------+                     |
+--------------------------------+

The figure above shows a deployment where the PF is bound to a DPDK control
plane application which uses representor ports to manage the configuration and
monitoring of it's VF ports. Each virtual function is represented in the
application by a representor port PMD which enables control of the corresponding
VF through eth dev APIs on the representor PMD such as:

- void rte_eth_promiscuous_enable(uint8_t port_id);
- void rte_eth_promiscuous_disable(uint8_t port_id);
- void rte_eth_allmulticast_enable(uint8_t port_id);
- void rte_eth_allmulticast_disable(uint8_t port_id);
- int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
	uint32_t pool);
- int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);

as well as monitoring through API's like

- void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
- int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);

The port representor infrastructure is enabled through a single common, device
independent, virtual PMD whos context is initialized and enabled through a
broker instance running within the context of the physical function device
driver.

+-------------------------+       +-------------------------+
|        rte_ethdev       |       |       rte_ethdev        |
+-------------------------+       +-------------------------+
|  Physical Function PMD  |       |  Port Reperesentor PMD  |
|         +-------------+ |       | +---------+ +---------+ |
|         | Representor | |       | | dev_data| | dev_ops | |
|         |    Broker   | |       | +----+----+ +----+----+ |
|         | +---------+ | |       +------|-----------|------+
|         | | VF Port | | |              |           |
|         | | Context +------------------+           |
|         | +---------+ | |                          |
|         | +---------+ | |                          |
|         | | Handler +------------------------------+
|         | |   Ops   | | |
|         | +---------+ | |
|         +-------------+ |
+-------------------------+

As the port representor model is based around the paradigm of using standard
port based APIs, it will allow future expansion of functionality without the
need to add new APIs. For example it should be possible to support configuration
of egress QoS parameters using existing TM APIs by extending the port
representor PMD/broker infrastructure.

Changes in v2:
* Rebased to DPDK 17.11

Changes in v3:
* Removed RTE_ETH_DEV_REPRESENTOR_PORT define
* Removed switch_domain from struct rte_eth_dev_info
  (to be reintroduced seperately when required).
* Port Representor PMD functionality merged into main library
* Removed functions from .map file that are not for use by applications
* Some minor bugfixes (uninitalised variables & NULL terminators)
* Use of SPDX licence headers in new files
* Seperate headers for PMD and application
* SPDX-License-Identifier in new files
* Added test-pmd representor add/del commands

Changes in v4:
* Added documentation
* Rebased to a12f22678915

Changes in v5:
* Documentation changes & additions
* Config file correctons
* Logging functions use library-specific tag
* Error-path memory leaks fixed
* Port Rep state enum moved out of struct
* Added rte_representor_enabled to .map
* PMD-specific files renamed for clarity
* In testpmd changed command to "port representor add|del <pf> <vf>"
* Added missing testpmd help
* Minor bugfix in handling of removal of i40e VF MAC addresses
* Removed "All rights reserved" from copyright.


Remy Horton (5):
  lib: add Port Representor library
  eal: add Port Representor command-line option
  drivers/net/i40e: add Port Representor functionality
  drivers/net/ixgbe: add Port Representor functionality
  app/test-pmd: add Port Representor commands

 MAINTAINERS                                        |  13 +-
 app/test-pmd/cmdline.c                             |  80 ++++
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/index.rst                    |   1 +
 doc/guides/prog_guide/representor_lib.rst          |  62 +++
 doc/guides/rel_notes/release_18_02.rst             |  12 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  26 ++
 drivers/net/i40e/Makefile                          |   2 +
 drivers/net/i40e/i40e_ethdev.c                     |  19 +
 drivers/net/i40e/i40e_ethdev.h                     |   1 +
 drivers/net/i40e/i40e_port_representor_ops.c       | 516 +++++++++++++++++++++
 drivers/net/i40e/i40e_port_representor_ops.h       |  19 +
 drivers/net/i40e/rte_pmd_i40e.c                    |  43 ++
 drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
 drivers/net/i40e/rte_pmd_i40e_version.map          |   7 +
 drivers/net/ixgbe/Makefile                         |   2 +
 drivers/net/ixgbe/ixgbe_ethdev.c                   |  29 +-
 drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
 drivers/net/ixgbe/ixgbe_port_representor_ops.c     | 274 +++++++++++
 drivers/net/ixgbe/ixgbe_port_representor_ops.h     |  19 +
 lib/Makefile                                       |   3 +
 lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
 lib/librte_eal/common/eal_common_log.c             |   1 +
 lib/librte_eal/common/eal_common_options.c         |   1 +
 lib/librte_eal/common/eal_internal_cfg.h           |   2 +
 lib/librte_eal/common/eal_options.h                |   2 +
 lib/librte_eal/common/include/rte_eal.h            |   8 +
 lib/librte_eal/common/include/rte_log.h            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
 lib/librte_eal/rte_eal_version.map                 |   1 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 345 ++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 +++
 .../rte_port_representor_driver.h                  | 140 ++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 38 files changed, 1767 insertions(+), 2 deletions(-)
 create mode 100644 doc/guides/prog_guide/representor_lib.rst
 create mode 100644 drivers/net/i40e/i40e_port_representor_ops.c
 create mode 100644 drivers/net/i40e/i40e_port_representor_ops.h
 create mode 100644 drivers/net/ixgbe/ixgbe_port_representor_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_port_representor_ops.h
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library
  2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
@ 2018-01-10 15:54       ` Remy Horton
  2018-01-30  9:23         ` Andrew Rybchenko
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 2/5] eal: add Port Representor command-line option Remy Horton
                         ` (4 subsequent siblings)
  5 siblings, 1 reply; 75+ messages in thread
From: Remy Horton @ 2018-01-10 15:54 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Declan Doherty, Mohammad Abdul Awal

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>
---
 MAINTAINERS                                        |   9 +-
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/index.rst                    |   1 +
 doc/guides/prog_guide/representor_lib.rst          |  62 ++++
 doc/guides/rel_notes/release_18_02.rst             |  10 +
 lib/Makefile                                       |   3 +
 lib/librte_eal/common/eal_common_log.c             |   1 +
 lib/librte_eal/common/include/rte_log.h            |   1 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 345 +++++++++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 ++++
 .../rte_port_representor_driver.h                  | 140 +++++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 16 files changed, 673 insertions(+), 1 deletion(-)
 create mode 100644 doc/guides/prog_guide/representor_lib.rst
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index b51c2d0..c48f1b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -781,6 +781,14 @@ 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>
@@ -794,7 +802,6 @@ F: doc/guides/sample_app_ug/test_pipeline.rst
 F: examples/ip_pipeline/
 F: doc/guides/sample_app_ug/ip_pipeline.rst
 
-
 Algorithms
 ----------
 
diff --git a/config/common_base b/config/common_base
index e74febe..7680397 100644
--- a/config/common_base
+++ b/config/common_base
@@ -793,6 +793,11 @@ CONFIG_RTE_LIBRTE_VHOST_NUMA=n
 CONFIG_RTE_LIBRTE_VHOST_DEBUG=n
 
 #
+# Compile port representor library
+#
+CONFIG_RTE_LIBRTE_REPRESENTOR=y
+
+#
 # Compile vhost PMD
 # To compile, CONFIG_RTE_LIBRTE_VHOST should be enabled.
 #
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 3492702..9954c5a 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -42,6 +42,7 @@ The public API headers are grouped by topics:
   [rte_flow]           (@ref rte_flow.h),
   [rte_tm]             (@ref rte_tm.h),
   [rte_mtr]            (@ref rte_mtr.h),
+  [Port Representor]   (@ref rte_port_representor.h),
   [cryptodev]          (@ref rte_cryptodev.h),
   [security]           (@ref rte_security.h),
   [eventdev]           (@ref rte_eventdev.h),
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b2cbe94..4d1b89f 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -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 \
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c4beb34..380d5c9 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -71,6 +71,7 @@ Programmer's Guide
     power_man
     packet_classif_access_ctrl
     packet_framework
+    representor_lib
     vhost_lib
     metrics_lib
     port_hotplug_framework
diff --git a/doc/guides/prog_guide/representor_lib.rst b/doc/guides/prog_guide/representor_lib.rst
new file mode 100644
index 0000000..dbf6acb
--- /dev/null
+++ b/doc/guides/prog_guide/representor_lib.rst
@@ -0,0 +1,62 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2017 Intel Corporation.
+
+.. _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);
diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst
index 24b67bb..5854d51 100644
--- a/doc/guides/rel_notes/release_18_02.rst
+++ b/doc/guides/rel_notes/release_18_02.rst
@@ -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
 -----------
@@ -157,6 +166,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_port.so.3
      librte_power.so.1
      librte_reorder.so.1
+   + librte_representor.so.1
      librte_ring.so.1
      librte_sched.so.1
      librte_security.so.1
diff --git a/lib/Makefile b/lib/Makefile
index 4202702..42932a9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -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
diff --git a/lib/librte_eal/common/eal_common_log.c b/lib/librte_eal/common/eal_common_log.c
index 08b31e2..5549f50 100644
--- a/lib/librte_eal/common/eal_common_log.c
+++ b/lib/librte_eal/common/eal_common_log.c
@@ -210,6 +210,7 @@ static const struct logtype logtype_strings[] = {
 	{RTE_LOGTYPE_CRYPTODEV,  "cryptodev"},
 	{RTE_LOGTYPE_EFD,        "efd"},
 	{RTE_LOGTYPE_EVENTDEV,   "eventdev"},
+	{RTE_LOGTYPE_PORTREP,    "representor"},
 	{RTE_LOGTYPE_USER1,      "user1"},
 	{RTE_LOGTYPE_USER2,      "user2"},
 	{RTE_LOGTYPE_USER3,      "user3"},
diff --git a/lib/librte_eal/common/include/rte_log.h b/lib/librte_eal/common/include/rte_log.h
index 83faddf..bf79006 100644
--- a/lib/librte_eal/common/include/rte_log.h
+++ b/lib/librte_eal/common/include/rte_log.h
@@ -59,6 +59,7 @@ extern struct rte_logs rte_logs;
 #define RTE_LOGTYPE_EFD       18 /**< Log related to EFD. */
 #define RTE_LOGTYPE_EVENTDEV  19 /**< Log related to eventdev. */
 #define RTE_LOGTYPE_GSO       20 /**< Log related to GSO. */
+#define RTE_LOGTYPE_PORTREP   21 /**< Log related to port representors. */
 
 /* these log types can be used in an application */
 #define RTE_LOGTYPE_USER1     24 /**< User-defined log type 1. */
diff --git a/lib/librte_representor/Makefile b/lib/librte_representor/Makefile
new file mode 100644
index 0000000..9ccd5c9
--- /dev/null
+++ b/lib/librte_representor/Makefile
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation.
+
+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
diff --git a/lib/librte_representor/rte_port_representor.c b/lib/librte_representor/rte_port_representor.c
new file mode 100644
index 0000000..3b10701
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.c
@@ -0,0 +1,345 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#include <rte_pci.h>
+#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_LOG(DEBUG, PORTREP, "verify failed, ret= %d", (retval)); \
+		return retval; \
+	} \
+} while (0)
+
+#define RTE_VERIFY_OR_RET(val) do { \
+	if (!(val)) { \
+		RTE_LOG(DEBUG, PORTREP, "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, PORTREP, "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, PORTREP, "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_LOG(DEBUG, PORTREP,	"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_LOG(DEBUG, PORTREP, "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];
+	struct rte_pci_addr pci_addr;
+
+	RTE_LOG(INFO, PORTREP, "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);
+		retval = eal_parse_pci_DomBDF(addr_dev, &pci_addr);
+		if (retval) {
+			RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+				"has invalid address format\n",
+				pf_addr_str);
+			return retval;
+		}
+	} else {
+		RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+			"has invalid address 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, PORTREP, "Unable to find broker for %s on bus %s\n",
+			addr_dev, addr_bus);
+		return -EINVAL;
+	}
+	RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_init, -ENOTSUP);
+
+	/* Fetch representor slot for VF */
+	rep_port = representor_port_find(broker, vport_id);
+	if (rep_port == NULL) {
+		RTE_LOG(ERR, PORTREP, "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, PORTREP, "Port Representor name"
+			" exceeds RTE_ETH_NAME_MAX_LEN\n");
+		return -EIO;
+	}
+	RTE_LOG(INFO, PORTREP, "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, PORTREP, "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, PORTREP, "Unable to allocate Port Representor"
+			" mac_addrs\n");
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+
+	/* Allocate an rte_device & rte_driver for the ethdev. */
+	rep_port->rep_rtedev = rte_zmalloc_socket("rte_device",
+		sizeof(struct rte_device), 0, rte_socket_id());
+	if (rep_port->rep_rtedev == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to allocate Port Representor"
+			" devive\n");
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+	rep_port->rep_rtedrv = rte_zmalloc_socket("rte_driver",
+		sizeof(struct rte_driver), 0, rte_socket_id());
+	if (rep_port->rep_rtedrv == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to allocate Port Representor"
+			" driver\n");
+		rte_free(rep_port->rep_rtedev);
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+	rep_port->rep_rtedrv->name = RTE_PORT_REPRESENTOR_DEVICE_NAME;
+	rep_port->rep_rtedev->driver = rep_port->rep_rtedrv;
+	rep_ethdev->device = rep_port->rep_rtedev;
+
+	/* 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;
+
+	retval = broker->ops->port_init(broker, rep_ethdev);
+	if (retval) {
+		rte_free(rep_port->rep_rtedev);
+		rte_free(rep_port->rep_rtedrv);
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return retval;
+	}
+	RTE_LOG(INFO, PORTREP, "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];
+	struct rte_pci_addr pci_addr;
+	int addr_len;
+	int retval;
+
+	RTE_LOG(INFO, PORTREP, "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);
+		retval = eal_parse_pci_DomBDF(addr_dev, &pci_addr);
+		if (retval) {
+			RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+				"has invalid address format\n",
+				pf_addr_str);
+			return retval;
+		}
+	} else {
+		RTE_LOG(ERR, PORTREP, "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, PORTREP, "Unable to find broker for %s on bus %s\n",
+			addr_dev, addr_bus);
+		return -EINVAL;
+	}
+	RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_uninit, -ENOTSUP);
+
+	/* Fetch representor slot for VF */
+	rep_port = representor_port_find(broker, vport_id);
+	if (rep_port == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to fetch Port Representor handle\n");
+		return -EINVAL;
+	}
+	if (rep_port->state != RTE_REPRESENTOR_PORT_VALID) {
+		RTE_LOG(ERR, PORTREP, "Representor vport %i is not active\n",
+			vport_id);
+		return -EINVAL;
+	}
+
+	/* Free up representor */
+	rep_port->broker->ops->port_uninit(rep_port->broker, rep_port->ethdev);
+	rep_port->state = RTE_REPRESENTOR_PORT_INVALID;
+	rte_free(rep_port->ethdev->data->mac_addrs);
+	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_rtedrv);
+	rte_free(rep_port->rep_rtedev);
+
+	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;
+}
diff --git a/lib/librte_representor/rte_port_representor.h b/lib/librte_representor/rte_port_representor.h
new file mode 100644
index 0000000..6582cb9
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#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_ */
diff --git a/lib/librte_representor/rte_port_representor_driver.h b/lib/librte_representor/rte_port_representor_driver.h
new file mode 100644
index 0000000..57e527d
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_driver.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#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"
+
+enum rte_representor_port_state {
+	RTE_REPRESENTOR_PORT_INVALID,
+	/**< No ethdev instantiated for virtual port */
+	RTE_REPRESENTOR_PORT_VALID
+	/**< ethdev active for virtual port */
+};
+
+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_state state;
+	/**< port state */
+	void *priv_data;
+	/**<  port private data */
+	/**< Representor ethdev device */
+	struct rte_device *rep_rtedev;
+	/**< Representor ethdev driver */
+	struct rte_driver *rep_rtedrv;
+};
+
+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_ */
diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
new file mode 100644
index 0000000..b26600c
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_version.map
@@ -0,0 +1,8 @@
+DPDK_18.02 {
+	global:
+
+	rte_representor_port_register;
+	rte_representor_port_unregister;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6a6a745..67266bf 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -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
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 2/5] eal: add Port Representor command-line option
  2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
@ 2018-01-10 15:54       ` Remy Horton
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
                         ` (3 subsequent siblings)
  5 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 15:54 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Declan Doherty, Mohammad Abdul Awal

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.

By default the Port Representor infrastructure is not enabled. This
patch implements the --enable-representor EAL command-line parameter
that activates representation functionality.

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>
---
 doc/guides/rel_notes/release_18_02.rst     | 2 ++
 lib/librte_eal/bsdapp/eal/eal.c            | 6 ++++++
 lib/librte_eal/common/eal_common_options.c | 1 +
 lib/librte_eal/common/eal_internal_cfg.h   | 2 ++
 lib/librte_eal/common/eal_options.h        | 2 ++
 lib/librte_eal/common/include/rte_eal.h    | 8 ++++++++
 lib/librte_eal/linuxapp/eal/eal.c          | 9 +++++++++
 lib/librte_eal/rte_eal_version.map         | 1 +
 8 files changed, 31 insertions(+)

diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst
index 5854d51..8479feb 100644
--- a/doc/guides/rel_notes/release_18_02.rst
+++ b/doc/guides/rel_notes/release_18_02.rst
@@ -50,6 +50,8 @@ New Features
   the representor device ops and defines the control domain to which that
   port belongs.
 
+* **Added --enable-representor EAL command-line option
+
 
 API Changes
 -----------
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 369a682..002200a 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -778,3 +778,9 @@ int rte_vfio_noiommu_is_enabled(void)
 {
 	return 0;
 }
+
+/* return non-zero if port-representor is enabled. */
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 996a034..6f2cc05 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -78,6 +78,7 @@ const struct option
 eal_long_options[] = {
 	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
 	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
+	{OPT_ENABLE_REPRESENTOR, 0, NULL, OPT_ENABLE_REPRESENTOR_NUM   },
 	{OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
 	{OPT_HELP,              0, NULL, OPT_HELP_NUM             },
 	{OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index c67685c..b4befe6 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -42,6 +42,8 @@ struct internal_config {
 										* instead of native TSC */
 	volatile unsigned no_shconf;      /**< true if there is no shared config */
 	volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */
+	volatile unsigned enable_representor;
+	/**< true to enable port representor broker for all PFs */
 	volatile enum rte_proc_type_t process_type; /**< multi-process proc type */
 	/** true to try allocating memory on specific sockets */
 	volatile unsigned force_sockets;
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 30e6bb4..c2b2162 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -83,6 +83,8 @@ enum {
 	OPT_VFIO_INTR_NUM,
 #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
 	OPT_VMWARE_TSC_MAP_NUM,
+#define OPT_ENABLE_REPRESENTOR    "enable-representor"
+	OPT_ENABLE_REPRESENTOR_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
index 02fa109..d21f704 100644
--- a/lib/librte_eal/common/include/rte_eal.h
+++ b/lib/librte_eal/common/include/rte_eal.h
@@ -306,6 +306,14 @@ enum rte_iova_mode rte_eal_iova_mode(void);
 const char *
 rte_eal_mbuf_default_mempool_ops(void);
 
+/**
+ * Get flag for port representor should be enabled or not.
+ *
+ * @return
+ *   Returns the enable-representor flag.
+ */
+int rte_representor_enabled(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 229eec9..364a8b2 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -612,6 +612,10 @@ eal_parse_args(int argc, char **argv)
 			internal_config.mbuf_pool_ops_name = optarg;
 			break;
 
+		case OPT_ENABLE_REPRESENTOR_NUM:
+			internal_config.enable_representor = 1;
+			break;
+
 		default:
 			if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
 				RTE_LOG(ERR, EAL, "Option %c is not supported "
@@ -1041,3 +1045,8 @@ rte_eal_check_module(const char *module_name)
 	/* Module has been found */
 	return 1;
 }
+
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index f4f46c1..af3e713 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -227,6 +227,7 @@ EXPERIMENTAL {
 	rte_service_map_lcore_get;
 	rte_service_map_lcore_set;
 	rte_service_probe_capability;
+	rte_service_representor_enabled;
 	rte_service_reset;
 	rte_service_run_iter_on_app_lcore;
 	rte_service_runstate_get;
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality
  2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 2/5] eal: add Port Representor command-line option Remy Horton
@ 2018-01-10 15:54       ` Remy Horton
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 4/5] drivers/net/ixgbe: " Remy Horton
                         ` (2 subsequent siblings)
  5 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 15:54 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Beilei Xing, Declan Doherty, Mohammad Abdul Awal

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.

This patch adds to the i40e PMD the functions required to enable port
representor functionality.

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>
---
 MAINTAINERS                                  |   2 +
 drivers/net/i40e/Makefile                    |   2 +
 drivers/net/i40e/i40e_ethdev.c               |  19 +
 drivers/net/i40e/i40e_ethdev.h               |   1 +
 drivers/net/i40e/i40e_port_representor_ops.c | 516 +++++++++++++++++++++++++++
 drivers/net/i40e/i40e_port_representor_ops.h |  19 +
 drivers/net/i40e/rte_pmd_i40e.c              |  43 +++
 drivers/net/i40e/rte_pmd_i40e.h              |  18 +
 drivers/net/i40e/rte_pmd_i40e_version.map    |   7 +
 9 files changed, 627 insertions(+)
 create mode 100644 drivers/net/i40e/i40e_port_representor_ops.c
 create mode 100644 drivers/net/i40e/i40e_port_representor_ops.h

diff --git a/MAINTAINERS b/MAINTAINERS
index c48f1b5..b720566 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -787,6 +787,8 @@ 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
+F: drivers/net/i40e/i40e_prep_ops.c
+F: drivers/net/i40e/i40e_prep_ops.h
 
 
 Packet Framework
diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 4b9634d..521640b 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -14,6 +14,7 @@ CFLAGS += -DX722_A0_SUPPORT
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_hash
 LDLIBS += -lrte_bus_pci
+LDLIBS += -lrte_representor
 
 EXPORT_MAP := rte_pmd_i40e_version.map
 
@@ -85,6 +86,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_port_representor_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 285d92b..ccf3d38 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -36,6 +36,7 @@
 #include "i40e_ethdev.h"
 #include "i40e_rxtx.h"
 #include "i40e_pf.h"
+#include "i40e_port_representor_ops.h"
 #include "i40e_regs.h"
 #include "rte_pmd_i40e.h"
 
@@ -1093,6 +1094,17 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	hw->bus.func = pci_dev->addr.function;
 	hw->adapter_stopped = 0;
 
+	/* init representor broker */
+	if (rte_representor_enabled()) {
+		ret = i40e_port_representor_broker_init(dev, &pf->broker,
+			pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Make sure all is clean before doing PF reset */
 	i40e_clear_hw(hw);
 
@@ -1428,6 +1440,13 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	intr_handle = &pci_dev->intr_handle;
 
+	/* free port representor pmds */
+	if (rte_representor_enabled()) {
+		ret = i40e_port_representor_broker_uninit(dev, pf->broker);
+		if (ret)
+			PMD_INIT_LOG(ERR, "Representor broker unregister "
+				"failed " "with ret=%d\n", ret);
+	}
 	if (hw->adapter_stopped == 0)
 		i40e_dev_close(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index f2b4b70..cadecbf 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -928,6 +928,7 @@ struct i40e_pf {
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
 	struct i40e_tm_conf tm_conf;
+	struct rte_representor_broker *broker;
 
 	/* Dynamic Device Personalization */
 	bool gtp_support; /* 1 - support GTP-C and GTP-U */
diff --git a/drivers/net/i40e/i40e_port_representor_ops.c b/drivers/net/i40e/i40e_port_representor_ops.c
new file mode 100644
index 0000000..ddd9e77
--- /dev/null
+++ b/drivers/net/i40e/i40e_port_representor_ops.c
@@ -0,0 +1,516 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#include <rte_bus_pci.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "base/i40e_type.h"
+#include "base/virtchnl.h"
+#include "i40e_ethdev.h"
+#include "i40e_port_representor_ops.h"
+#include "i40e_rxtx.h"
+#include "rte_pmd_i40e.h"
+
+
+struct i40e_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+i40e_representor_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return i40e_dev_link_update(i40e_priv_data->pf_ethdev,
+		wait_to_complete);
+}
+
+static void
+i40e_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (!is_i40e_supported(i40e_priv_data->pf_ethdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(
+		i40e_priv_data->pf_ethdev->data->dev_private);
+	if (representor->vport_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return;
+	}
+
+	vf = &pf->vfs[representor->vport_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return;
+	}
+
+	/* get dev info for the vdev */
+	dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(ethdev);
+	dev_info->max_rx_queues = vsi->nb_qps;
+	dev_info->max_tx_queues = vsi->nb_qps;
+	dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN;
+	dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
+	dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) *
+		sizeof(uint32_t);
+	dev_info->reta_size = ETH_RSS_RETA_SIZE_64;
+	dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL;
+	dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX;
+	dev_info->rx_offload_capa =
+		DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_QINQ_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |
+		DEV_RX_OFFLOAD_UDP_CKSUM |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	dev_info->tx_offload_capa =
+		DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_QINQ_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM |
+		DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM |
+		DEV_TX_OFFLOAD_SCTP_CKSUM |
+		DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
+		DEV_TX_OFFLOAD_TCP_TSO |
+		DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
+		DEV_TX_OFFLOAD_GRE_TNL_TSO |
+		DEV_TX_OFFLOAD_IPIP_TNL_TSO |
+		DEV_TX_OFFLOAD_GENEVE_TNL_TSO;
+
+	dev_info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_thresh = {
+			.pthresh = I40E_DEFAULT_RX_PTHRESH,
+			.hthresh = I40E_DEFAULT_RX_HTHRESH,
+			.wthresh = I40E_DEFAULT_RX_WTHRESH,
+		},
+		.rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH,
+		.rx_drop_en = 0,
+	};
+
+	dev_info->default_txconf = (struct rte_eth_txconf) {
+		.tx_thresh = {
+			.pthresh = I40E_DEFAULT_TX_PTHRESH,
+			.hthresh = I40E_DEFAULT_TX_HTHRESH,
+			.wthresh = I40E_DEFAULT_TX_WTHRESH,
+		},
+		.tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH,
+		.tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH,
+		.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
+				ETH_TXQ_FLAGS_NOOFFLOADS,
+	};
+
+	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+
+	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+}
+
+static int i40e_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int i40e_representor_rx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int i40e_representor_tx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int i40e_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void i40e_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+i40e_representor_stats_get(struct rte_eth_dev *ethdev,
+		struct rte_eth_stats *stats)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_get_vf_stats(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, stats);
+}
+
+static void
+i40e_representor_stats_reset(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_reset_vf_stats(i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id);
+}
+
+static void
+i40e_representor_promiscuous_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_promiscuous_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_allmulticast_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_allmulticast_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_remove_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, &ethdev->data->mac_addrs[index]);
+}
+
+static void
+i40e_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+		struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, mac_addr);
+}
+
+static int
+i40e_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+		uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	vfid = representor->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_i40e_set_vf_vlan_filter(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		vlan_id, vf_mask, on);
+}
+
+static int
+i40e_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct rte_eth_dev *pdev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+	uint32_t vfid;
+
+	pdev = i40e_priv_data->pf_ethdev;
+	vfid = representor->vport_id;
+
+	if (!is_i40e_supported(pdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return -EINVAL;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(pdev->data->dev_private);
+
+	if (vfid >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return -EINVAL;
+	}
+
+	vf = &pf->vfs[vfid];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Fixme: even though there 3 kinds of hw offloads, hw_vlan_filter,
+	 * hw_vlan_strip, and hw_vlan_extend.
+	 * currently the hw_vlan_extend offload by vsi is not implemented.
+	 */
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		/* Enable or disable VLAN filtering offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_filter)
+			return i40e_vsi_config_vlan_filter(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_filter(vsi, FALSE);
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK) {
+		/* Enable or disable VLAN stripping offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_strip)
+			return i40e_vsi_config_vlan_stripping(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_stripping(vsi, FALSE);
+	}
+
+	return -EINVAL;
+}
+
+static void
+i40e_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_vlan_stripq(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, on);
+}
+
+static int
+i40e_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id,
+	__rte_unused int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_set_vf_vlan_insert(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, vlan_id);
+}
+
+struct eth_dev_ops i40e_representor_dev_ops = {
+	.link_update          = i40e_representor_link_update,
+	.dev_infos_get        = i40e_representor_dev_infos_get,
+	.dev_configure        = i40e_representor_dev_configure,
+	.rx_queue_setup       = i40e_representor_rx_queue_setup,
+	.tx_queue_setup       = i40e_representor_tx_queue_setup,
+	.dev_start            = i40e_representor_dev_start,
+	.dev_stop             = i40e_representor_dev_stop,
+
+	.stats_get            = i40e_representor_stats_get,
+	.stats_reset          = i40e_representor_stats_reset,
+
+	.promiscuous_enable   = i40e_representor_promiscuous_enable,
+	.promiscuous_disable  = i40e_representor_promiscuous_disable,
+
+	.allmulticast_enable  = i40e_representor_allmulticast_enable,
+	.allmulticast_disable = i40e_representor_allmulticast_disable,
+
+	.mac_addr_remove      = i40e_representor_mac_addr_remove,
+	.mac_addr_set         = i40e_representor_mac_addr_set,
+
+	.vlan_filter_set      = i40e_representor_vlan_filter_set,
+	.vlan_offload_set     = i40e_representor_vlan_offload_set,
+	.vlan_strip_queue_set = i40e_representor_vlan_strip_queue_set,
+	.vlan_pvid_set        = i40e_representor_vlan_pvid_set
+};
+
+static uint16_t i40e_representor_rx_burst(__rte_unused void *rxq,
+	__rte_unused struct rte_mbuf **rx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static uint16_t i40e_representor_tx_burst(__rte_unused void *txq,
+	__rte_unused struct rte_mbuf **tx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static int
+i40e_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port;
+	struct i40e_pf *i40e_pf;
+	struct i40e_pf_vf *i40e_vf;
+
+	port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("i40e_port_representor_priv_data",
+			sizeof(struct i40e_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct i40e_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+
+	i40e_pf = I40E_DEV_PRIVATE_TO_PF(pf_ethdev->data->dev_private);
+	i40e_vf = &i40e_pf->vfs[port->vport_id];
+
+	if (!i40e_vf->vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &i40e_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = i40e_vf->vsi->nb_qps;
+	ethdev->data->nb_tx_queues = i40e_vf->vsi->nb_qps;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = i40e_representor_rx_burst;
+	ethdev->tx_pkt_burst = i40e_representor_tx_burst;
+
+	return 0;
+}
+
+static int
+i40e_port_representor_uninit(struct rte_representor_broker *broker __rte_unused,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops i40e_broker_port_ops = {
+	.port_init = i40e_port_representor_init,
+	.port_uninit = i40e_port_representor_uninit
+};
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set i40e broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &i40e_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
+
+int
+i40e_port_representor_broker_uninit(__rte_unused struct rte_eth_dev *dev,
+	struct rte_representor_broker *broker)
+{
+	int ret;
+
+	ret = rte_representor_broker_uninit(broker);
+	if (ret)
+		return ret;
+
+	rte_free(broker);
+
+	return 0;
+}
diff --git a/drivers/net/i40e/i40e_port_representor_ops.h b/drivers/net/i40e/i40e_port_representor_ops.h
new file mode 100644
index 0000000..b7187ee
--- /dev/null
+++ b/drivers/net/i40e/i40e_port_representor_ops.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#ifndef _I40E_PORT_REPRESENTOR_OPS_H_
+#define _I40E_PORT_REPRESENTOR_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+int
+i40e_port_representor_broker_uninit(struct rte_eth_dev *dev,
+	struct rte_representor_broker *broker);
+
+#endif /* _I40E_PORT_REPRESENTOR_OPS_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 947f13b..afe20a8 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -570,6 +570,49 @@ rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 	return 0;
 }
 
+static const struct ether_addr null_mac_addr;
+
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint16_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+		return -EINVAL;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs)
+		return -EINVAL;
+
+	vf = &pf->vfs[vf_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	if (is_same_ether_addr(mac_addr, &vf->mac_addr))
+		/* Reset the mac with NULL address */
+		ether_addr_copy(&null_mac_addr, &vf->mac_addr);
+
+	/* Remove the mac */
+	i40e_vsi_delete_mac(vsi, mac_addr);
+
+	return 0;
+}
+
 /* Set vlan strip on/off for specific VF from host */
 int
 rte_pmd_i40e_set_vf_vlan_stripq(uint16_t port, uint16_t vf_id, uint8_t on)
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 7ca37b1..89f4fea 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -439,6 +439,24 @@ int rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
 /**
+ * Remove the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf_id
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint16_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr);
+
+/**
  * Enable/Disable vf vlan strip for all queues in a pool
  *
  * @param port
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ebbd24e..4faff5a 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -58,3 +58,10 @@ DPDK_17.11 {
 	rte_pmd_i40e_rss_queue_region_conf;
 
 } DPDK_17.08;
+
+DPDK_18.02 {
+	global:
+
+	rte_pmd_i40e_remove_vf_mac_addr;
+
+}DPDK_17.11;
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 4/5] drivers/net/ixgbe: add Port Representor functionality
  2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
                         ` (2 preceding siblings ...)
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
@ 2018-01-10 15:54       ` Remy Horton
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 5/5] app/test-pmd: add Port Representor commands Remy Horton
  2018-01-10 17:49       ` [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors Remy Horton
  5 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 15:54 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Wenzhuo Lu, Declan Doherty, Mohammad Abdul Awal

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.

This patch adds to the ixgbe PMD PMD the functions required to enable
port representor functionality.

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>
---
 MAINTAINERS                                    |   2 +
 drivers/net/ixgbe/Makefile                     |   2 +
 drivers/net/ixgbe/ixgbe_ethdev.c               |  29 ++-
 drivers/net/ixgbe/ixgbe_ethdev.h               |   5 +
 drivers/net/ixgbe/ixgbe_port_representor_ops.c | 274 +++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_port_representor_ops.h |  19 ++
 6 files changed, 330 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ixgbe/ixgbe_port_representor_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_port_representor_ops.h

diff --git a/MAINTAINERS b/MAINTAINERS
index b720566..b467c6a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -789,6 +789,8 @@ F: lib/librte_representor
 F: doc/guides/prog_guide/representor_lib.rst
 F: drivers/net/i40e/i40e_prep_ops.c
 F: drivers/net/i40e/i40e_prep_ops.h
+F: drivers/net/ixgbe/ixgbe_prep_ops.c
+F: drivers/net/ixgbe/ixgbe_prep_ops.h
 
 
 Packet Framework
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index 9efa5a4..39fe184 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -57,6 +57,7 @@ endif
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_hash
 LDLIBS += -lrte_bus_pci
+LDLIBS += -lrte_representor
 
 #
 # Add extra flags for base driver files (also known as shared code)
@@ -102,6 +103,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_ipsec.c
 endif
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += rte_pmd_ixgbe.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_port_representor_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_IXGBE_PMD)-include := rte_pmd_ixgbe.h
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 43e0132..96c5eaf 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -46,6 +46,7 @@
 #include "base/ixgbe_type.h"
 #include "base/ixgbe_phy.h"
 #include "ixgbe_regs.h"
+#include "ixgbe_port_representor_ops.h"
 
 /*
  * High threshold controlling when to start sending XOFF frames. Must be at
@@ -1109,6 +1110,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 	uint32_t ctrl_ext;
 	uint16_t csum;
 	int diag, i;
+	int ret;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1232,6 +1236,17 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 		return -EIO;
 	}
 
+	/* Init port representor broker */
+	if (rte_representor_enabled()) {
+		ret = ixgbe_port_representor_broker_init(eth_dev,
+			&eth_adapter->broker, pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Reset the hw statistics */
 	ixgbe_dev_stats_reset(eth_dev);
 
@@ -1334,6 +1349,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	struct ixgbe_hw *hw;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
+	int ret;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1342,6 +1360,15 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
 
+	/* free port representor pmds */
+	if (rte_representor_enabled()) {
+		ret = ixgbe_port_representor_broker_uninit(eth_dev,
+			eth_adapter->broker);
+		if (ret)
+			PMD_INIT_LOG(ERR, "Representor broker unregister "
+				"failed " "with ret=%d\n", ret);
+	}
+
 	if (hw->adapter_stopped == 0)
 		ixgbe_dev_close(eth_dev);
 
@@ -3933,7 +3960,7 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 }
 
 /* return 0 means link status changed, -1 means not changed */
-static int
+int
 ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 			    int wait_to_complete, int vf)
 {
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 1db29bd..c2df08e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -470,6 +470,7 @@ struct ixgbe_adapter {
 	struct rte_timecounter      rx_tstamp_tc;
 	struct rte_timecounter      tx_tstamp_tc;
  	struct ixgbe_tm_conf        tm_conf;
+	struct rte_representor_broker *broker;
 };
 
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
@@ -644,6 +645,10 @@ int ixgbe_fdir_filter_program(struct rte_eth_dev *dev,
 
 void ixgbe_configure_dcb(struct rte_eth_dev *dev);
 
+int
+ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
+			    int wait_to_complete, int vf);
+
 /*
  * misc function prototypes
  */
diff --git a/drivers/net/ixgbe/ixgbe_port_representor_ops.c b/drivers/net/ixgbe/ixgbe_port_representor_ops.c
new file mode 100644
index 0000000..4547cbc
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_port_representor_ops.c
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+#include <rte_port_representor_driver.h>
+
+#include "base/ixgbe_type.h"
+#include "base/ixgbe_vf.h"
+#include "ixgbe_ethdev.h"
+#include "ixgbe_port_representor_ops.h"
+#include "ixgbe_rxtx.h"
+#include "rte_pmd_ixgbe.h"
+
+
+struct ixgbe_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+ixgbe_representor_link_update(struct rte_eth_dev *ethdev,
+	int wait_to_complete)
+{
+	struct rte_representor_port *prep_priv_data =
+			ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+			prep_priv_data->priv_data;
+
+	return ixgbe_dev_link_update_share(ixgbe_priv_data->pf_ethdev,
+		wait_to_complete, 1);
+}
+
+static void
+ixgbe_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+	struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	rte_pmd_ixgbe_set_vf_mac_addr(ixgbe_priv_data->pf_ethdev->data->port_id,
+		prep_priv_data->vport_id, mac_addr);
+}
+
+static void
+ixgbe_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(
+		ixgbe_priv_data->pf_ethdev->data->dev_private);
+
+	dev_info->pci_dev = NULL;
+
+	dev_info->min_rx_bufsize = 1024;
+	/**< Minimum size of RX buffer. */
+	dev_info->max_rx_pktlen = 9728;
+	/**< Maximum configurable length of RX pkt. */
+	dev_info->max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	/**< Maximum number of RX queues. */
+	dev_info->max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+	/**< Maximum number of TX queues. */
+
+	dev_info->max_mac_addrs = hw->mac.num_rar_entries;
+	/**< Maximum number of MAC addresses. */
+
+	dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |	DEV_RX_OFFLOAD_UDP_CKSUM  |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	/**< Device RX offload capabilities. */
+
+	dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_TSO;
+	/**< Device TX offload capabilities. */
+
+	dev_info->speed_capa =
+		ixgbe_priv_data->pf_ethdev->data->dev_link.link_speed;
+	/**< Supported speeds bitmap (ETH_LINK_SPEED_). */
+}
+
+static int ixgbe_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int ixgbe_representor_rx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int ixgbe_representor_tx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int ixgbe_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void ixgbe_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+ixgbe_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+	uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_ixgbe_set_vf_vlan_filter(pfid, vlan_id, vf_mask, on);
+}
+
+static void
+ixgbe_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+
+	rte_pmd_ixgbe_set_vf_vlan_stripq(pfid, vfid, on);
+}
+
+struct eth_dev_ops ixgbe_representor_dev_ops = {
+	.link_update                  = ixgbe_representor_link_update,
+	.dev_infos_get                = ixgbe_representor_dev_infos_get,
+	.dev_configure	              = ixgbe_representor_dev_configure,
+	.rx_queue_setup               = ixgbe_representor_rx_queue_setup,
+	.tx_queue_setup               = ixgbe_representor_tx_queue_setup,
+	.dev_start                    = ixgbe_representor_dev_start,
+	.dev_stop                     = ixgbe_representor_dev_stop,
+	.mac_addr_set                 = ixgbe_representor_mac_addr_set,
+	.vlan_filter_set              = ixgbe_representor_vlan_filter_set,
+	.vlan_strip_queue_set         = ixgbe_representor_vlan_strip_queue_set
+};
+
+static int
+ixgbe_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("ixgbe_port_representor_priv_data",
+			sizeof(struct ixgbe_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct ixgbe_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &ixgbe_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	ethdev->data->nb_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = NULL;
+	ethdev->tx_pkt_burst = NULL;
+
+	return 0;
+}
+
+static int
+ixgbe_port_representor_uninit(
+	__rte_unused struct rte_representor_broker *broker,
+	struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops ixgbe_broker_port_ops = {
+	.port_init = ixgbe_port_representor_init,
+	.port_uninit = ixgbe_port_representor_uninit
+};
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set IXGBE broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &ixgbe_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
+
+int
+ixgbe_port_representor_broker_uninit(__rte_unused struct rte_eth_dev *dev,
+	struct rte_representor_broker *broker)
+{
+	int ret;
+
+	ret = rte_representor_broker_uninit(broker);
+	if (ret)
+		return ret;
+
+	rte_free(broker);
+
+	return 0;
+}
diff --git a/drivers/net/ixgbe/ixgbe_port_representor_ops.h b/drivers/net/ixgbe/ixgbe_port_representor_ops.h
new file mode 100644
index 0000000..3c797c4
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_port_representor_ops.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#ifndef _IXGBE_PORT_REPRESENTOR_OPS_H_
+#define _IXGBE_PORT_REPRESENTOR_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+int
+ixgbe_port_representor_broker_uninit(struct rte_eth_dev *dev,
+	struct rte_representor_broker *broker);
+
+#endif /* _IXGBE_PORT_REPRESENTOR_OPS_H_ */
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 5/5] app/test-pmd: add Port Representor commands
  2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
                         ` (3 preceding siblings ...)
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 4/5] drivers/net/ixgbe: " Remy Horton
@ 2018-01-10 15:54       ` Remy Horton
  2018-01-10 17:49       ` [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors Remy Horton
  5 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 15:54 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Wenzhuo Lu, Jingjing Wu

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.

This patch adds the 'port representor add' and 'port representor del'
commands to test-pmd, which respectively allow the adding and removing
of port representors.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/cmdline.c                      | 80 +++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 26 ++++++++++
 2 files changed, 106 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5b2e2ef..5da8cec 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -76,6 +76,7 @@
 #include <rte_eth_ctrl.h>
 #include <rte_flow.h>
 #include <rte_gro.h>
+#include <rte_port_representor.h>
 
 #include <cmdline_rdline.h>
 #include <cmdline_parse.h>
@@ -881,6 +882,12 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"port config (port_id) pctype mapping update"
 			" (pctype_id_0[,pctype_id_1]*) (flow_type_id)\n"
 			"    Update a flow type to pctype mapping item on a port\n\n"
+
+			"port representor add (pf_address) (vport_id)\n"
+			"    Add port representor on PF with VF id\n\n"
+
+			"port representor del (pf_address) (vport_id)\n"
+			"    Remove port representor on PF with VF id\n\n"
 		);
 	}
 
@@ -15552,6 +15559,78 @@ cmdline_parse_inst_t cmd_load_from_file = {
 	},
 };
 
+struct cmd_port_representor_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t op;
+	cmdline_fixed_string_t action;
+	cmdline_fixed_string_t pf;
+	uint16_t vport;
+};
+
+cmdline_parse_token_string_t cmd_portrepresentor_cmd =
+TOKEN_STRING_INITIALIZER(struct cmd_port_representor_result,
+	cmd, "port");
+
+cmdline_parse_token_string_t cmd_portrepresentor_op =
+TOKEN_STRING_INITIALIZER(struct cmd_port_representor_result,
+	op, "representor");
+
+cmdline_parse_token_string_t cmd_portrepresentor_act =
+TOKEN_STRING_INITIALIZER(struct cmd_port_representor_result,
+	action, "add#del");
+
+cmdline_parse_token_string_t cmd_portrepresentor_pf =
+TOKEN_STRING_INITIALIZER(struct cmd_port_representor_result,
+	pf, NULL);
+
+cmdline_parse_token_num_t cmd_portrepresentor_vport =
+TOKEN_NUM_INITIALIZER(struct cmd_port_representor_result,
+	vport, UINT16);
+
+static void cmd_port_representor_callback(void *parsed_result,
+		__attribute__((unused))  struct cmdline *cl,
+		__attribute__((unused)) void *data)
+{
+	struct cmd_port_representor_result *res = parsed_result;
+	uint16_t port_id;
+	int ret;
+
+	printf("%s(): action:%s addr:%s vport:%i\n", __func__,
+		res->action, res->pf, res->vport);
+	if (strcmp("add",res->action) == 0) {
+		ret = rte_representor_port_register(res->pf, res->vport, &port_id);
+		if (ret != 0)
+			printf("Registering port representor failed\n");
+		else
+			printf("Port Representor registered with port id %i\n",
+				port_id);
+	} else {
+		/* assume 'del' */
+		ret = rte_representor_port_unregister(res->pf, res->vport);
+		if (ret != 0)
+			printf("Port %i is not a valid port representor.\n",
+				res->vport);
+
+	}
+}
+
+
+cmdline_parse_inst_t cmd_port_representor = {
+	.f = cmd_port_representor_callback,
+	.help_str = "port representor add|del <BusName_DomBDF> <vport_id> "
+		"Add or remove a Port Representor",
+	.data = NULL,
+	.tokens = {
+		(void *)&cmd_portrepresentor_cmd,
+		(void *)&cmd_portrepresentor_op,
+		(void *)&cmd_portrepresentor_act,
+		(void *)&cmd_portrepresentor_pf,
+		(void *)&cmd_portrepresentor_vport,
+		NULL
+	}
+};
+
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -15593,6 +15672,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *) &cmd_show_bonding_config,
 	(cmdline_parse_inst_t *) &cmd_set_bonding_primary,
 	(cmdline_parse_inst_t *) &cmd_add_bonding_slave,
+	(cmdline_parse_inst_t *) &cmd_port_representor,
 	(cmdline_parse_inst_t *) &cmd_remove_bonding_slave,
 	(cmdline_parse_inst_t *) &cmd_create_bonded_device,
 	(cmdline_parse_inst_t *) &cmd_set_bond_mac_addr,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a8b7913..15907f9 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3654,3 +3654,29 @@ Validate and create a QinQ rule on port 0 to steer traffic to a queue on the hos
    ID      Group   Prio    Attr    Rule
    0       0       0       i-      ETH VLAN VLAN=>VF QUEUE
    1       0       0       i-      ETH VLAN VLAN=>PF QUEUE
+
+Port Representors
+-----------------
+
+Adding and removal of port representors (*rte_representor*) is done via the
+``port representor add`` and ``port representor del`` commands. Once created
+these can take the same control commands as the underlying VF (Virtual
+Function).
+
+
+Adding a representor
+~~~~~~~~~~~~~~~~~~~~
+
+Adding a representor for a VF requires specifying the PF in
+``Bus_DomBDF`` format alongside the index number of the VF::
+
+   testpmd> port representor add pci_0000:81:00.0 0
+
+
+Removing a representor
+~~~~~~~~~~~~~~~~~~~~~~
+
+To remove a representor, the same parameters are required as were used to
+create it::
+
+    testpmd> port representor del pci_0000:81:00.0 0
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors
  2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
                         ` (4 preceding siblings ...)
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 5/5] app/test-pmd: add Port Representor commands Remy Horton
@ 2018-01-10 17:49       ` Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
                           ` (4 more replies)
  5 siblings, 5 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 17:49 UTC (permalink / raw)
  To: dev

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.

+-----------------------------+   +---------------+  +---------------+
|        Control Plane        |   |   Data Plane  |  |   Data Plane  |
|         Application         |   |   Application |  |   Application |
+-----------------------------+   +---------------+  +---------------+
|         eth dev api         |   |  eth dev api  |  |  eth dev api  |
+-----------------------------+   +---------------+  +---------------+
+-------+  +-------+  +-------+   +---------------+  +---------------+
|  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
|  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
|       |  | PMD   |  | PMD   |                             |
+---+--^+  +-------+  +-+-----+                             |
    |  |                |  |                                |
    |  +----------------+  |                                |
    |                      |                                |
    |                      |                                |
+--------------------------------+                          |
|   |  HW (logical view)   |     |                          |
| --+------+ +-------+ +---+---+ |                          |
| |   PF   | |  VF0  | |  VF1  | |                          |
| |        | |       | |       +----------------------------+
| +--------+ +-------+ +-------+ |
| +----------------------------+ |
| |        VEB                 | |
| +----------------------------+ |
| +--------+                     |
| |  Port  |                     |
| |   0    |                     |
| +--------+                     |
+--------------------------------+

The figure above shows a deployment where the PF is bound to a DPDK control
plane application which uses representor ports to manage the configuration and
monitoring of it's VF ports. Each virtual function is represented in the
application by a representor port PMD which enables control of the corresponding
VF through eth dev APIs on the representor PMD such as:

- void rte_eth_promiscuous_enable(uint8_t port_id);
- void rte_eth_promiscuous_disable(uint8_t port_id);
- void rte_eth_allmulticast_enable(uint8_t port_id);
- void rte_eth_allmulticast_disable(uint8_t port_id);
- int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
	uint32_t pool);
- int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);

as well as monitoring through API's like

- void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
- int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);

The port representor infrastructure is enabled through a single common, device
independent, virtual PMD whos context is initialized and enabled through a
broker instance running within the context of the physical function device
driver.

+-------------------------+       +-------------------------+
|        rte_ethdev       |       |       rte_ethdev        |
+-------------------------+       +-------------------------+
|  Physical Function PMD  |       |  Port Reperesentor PMD  |
|         +-------------+ |       | +---------+ +---------+ |
|         | Representor | |       | | dev_data| | dev_ops | |
|         |    Broker   | |       | +----+----+ +----+----+ |
|         | +---------+ | |       +------|-----------|------+
|         | | VF Port | | |              |           |
|         | | Context +------------------+           |
|         | +---------+ | |                          |
|         | +---------+ | |                          |
|         | | Handler +------------------------------+
|         | |   Ops   | | |
|         | +---------+ | |
|         +-------------+ |
+-------------------------+

As the port representor model is based around the paradigm of using standard
port based APIs, it will allow future expansion of functionality without the
need to add new APIs. For example it should be possible to support configuration
of egress QoS parameters using existing TM APIs by extending the port
representor PMD/broker infrastructure.

Changes in v2:
* Rebased to DPDK 17.11

Changes in v3:
* Removed RTE_ETH_DEV_REPRESENTOR_PORT define
* Removed switch_domain from struct rte_eth_dev_info
  (to be reintroduced seperately when required).
* Port Representor PMD functionality merged into main library
* Removed functions from .map file that are not for use by applications
* Some minor bugfixes (uninitalised variables & NULL terminators)
* Use of SPDX licence headers in new files
* Seperate headers for PMD and application
* SPDX-License-Identifier in new files
* Added test-pmd representor add/del commands

Changes in v4:
* Added documentation
* Rebased to a12f22678915

Changes in v5:
* Documentation changes & additions
* Config file correctons
* Logging functions use library-specific tag
* Error-path memory leaks fixed
* Port Rep state enum moved out of struct
* Added rte_representor_enabled to .map
* PMD-specific files renamed for clarity
* In testpmd changed command to "port representor add|del <pf> <vf>"
* Added missing testpmd help
* Minor bugfix in handling of removal of i40e VF MAC addresses
* Removed "All rights reserved" from copyright.

Changes in v6:
 Checkpatch-related corrections


Remy Horton (5):
  lib: add Port Representor library
  eal: add Port Representor command-line option
  drivers/net/i40e: add Port Representor functionality
  drivers/net/ixgbe: add Port Representor functionality
  app/test-pmd: add Port Representor commands

 MAINTAINERS                                        |  13 +-
 app/test-pmd/cmdline.c                             |  81 ++++
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/index.rst                    |   1 +
 doc/guides/prog_guide/representor_lib.rst          |  62 +++
 doc/guides/rel_notes/release_18_02.rst             |  12 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  26 ++
 drivers/net/i40e/Makefile                          |   2 +
 drivers/net/i40e/i40e_ethdev.c                     |  19 +
 drivers/net/i40e/i40e_ethdev.h                     |   1 +
 drivers/net/i40e/i40e_port_representor_ops.c       | 516 +++++++++++++++++++++
 drivers/net/i40e/i40e_port_representor_ops.h       |  19 +
 drivers/net/i40e/rte_pmd_i40e.c                    |  43 ++
 drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
 drivers/net/i40e/rte_pmd_i40e_version.map          |   7 +
 drivers/net/ixgbe/Makefile                         |   2 +
 drivers/net/ixgbe/ixgbe_ethdev.c                   |  29 +-
 drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
 drivers/net/ixgbe/ixgbe_port_representor_ops.c     | 274 +++++++++++
 drivers/net/ixgbe/ixgbe_port_representor_ops.h     |  19 +
 lib/Makefile                                       |   3 +
 lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
 lib/librte_eal/common/eal_common_log.c             |   1 +
 lib/librte_eal/common/eal_common_options.c         |   1 +
 lib/librte_eal/common/eal_internal_cfg.h           |   2 +
 lib/librte_eal/common/eal_options.h                |   2 +
 lib/librte_eal/common/include/rte_eal.h            |   8 +
 lib/librte_eal/common/include/rte_log.h            |   1 +
 lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
 lib/librte_eal/rte_eal_version.map                 |   1 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 350 ++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 +++
 .../rte_port_representor_driver.h                  | 140 ++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 38 files changed, 1773 insertions(+), 2 deletions(-)
 create mode 100644 doc/guides/prog_guide/representor_lib.rst
 create mode 100644 drivers/net/i40e/i40e_port_representor_ops.c
 create mode 100644 drivers/net/i40e/i40e_port_representor_ops.h
 create mode 100644 drivers/net/ixgbe/ixgbe_port_representor_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_port_representor_ops.h
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library
  2018-01-10 17:49       ` [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors Remy Horton
@ 2018-01-10 17:49         ` Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 2/5] eal: add Port Representor command-line option Remy Horton
                           ` (3 subsequent siblings)
  4 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 17:49 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Declan Doherty, Mohammad Abdul Awal

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>
---
 MAINTAINERS                                        |   9 +-
 config/common_base                                 |   5 +
 doc/api/doxy-api-index.md                          |   1 +
 doc/api/doxy-api.conf                              |   1 +
 doc/guides/prog_guide/index.rst                    |   1 +
 doc/guides/prog_guide/representor_lib.rst          |  62 ++++
 doc/guides/rel_notes/release_18_02.rst             |  10 +
 lib/Makefile                                       |   3 +
 lib/librte_eal/common/eal_common_log.c             |   1 +
 lib/librte_eal/common/include/rte_log.h            |   1 +
 lib/librte_representor/Makefile                    |  26 ++
 lib/librte_representor/rte_port_representor.c      | 350 +++++++++++++++++++++
 lib/librte_representor/rte_port_representor.h      |  60 ++++
 .../rte_port_representor_driver.h                  | 140 +++++++++
 .../rte_port_representor_version.map               |   8 +
 mk/rte.app.mk                                      |   1 +
 16 files changed, 678 insertions(+), 1 deletion(-)
 create mode 100644 doc/guides/prog_guide/representor_lib.rst
 create mode 100644 lib/librte_representor/Makefile
 create mode 100644 lib/librte_representor/rte_port_representor.c
 create mode 100644 lib/librte_representor/rte_port_representor.h
 create mode 100644 lib/librte_representor/rte_port_representor_driver.h
 create mode 100644 lib/librte_representor/rte_port_representor_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index b51c2d0..c48f1b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -781,6 +781,14 @@ 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>
@@ -794,7 +802,6 @@ F: doc/guides/sample_app_ug/test_pipeline.rst
 F: examples/ip_pipeline/
 F: doc/guides/sample_app_ug/ip_pipeline.rst
 
-
 Algorithms
 ----------
 
diff --git a/config/common_base b/config/common_base
index e74febe..7680397 100644
--- a/config/common_base
+++ b/config/common_base
@@ -793,6 +793,11 @@ CONFIG_RTE_LIBRTE_VHOST_NUMA=n
 CONFIG_RTE_LIBRTE_VHOST_DEBUG=n
 
 #
+# Compile port representor library
+#
+CONFIG_RTE_LIBRTE_REPRESENTOR=y
+
+#
 # Compile vhost PMD
 # To compile, CONFIG_RTE_LIBRTE_VHOST should be enabled.
 #
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 3492702..9954c5a 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -42,6 +42,7 @@ The public API headers are grouped by topics:
   [rte_flow]           (@ref rte_flow.h),
   [rte_tm]             (@ref rte_tm.h),
   [rte_mtr]            (@ref rte_mtr.h),
+  [Port Representor]   (@ref rte_port_representor.h),
   [cryptodev]          (@ref rte_cryptodev.h),
   [security]           (@ref rte_security.h),
   [eventdev]           (@ref rte_eventdev.h),
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b2cbe94..4d1b89f 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -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 \
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c4beb34..380d5c9 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -71,6 +71,7 @@ Programmer's Guide
     power_man
     packet_classif_access_ctrl
     packet_framework
+    representor_lib
     vhost_lib
     metrics_lib
     port_hotplug_framework
diff --git a/doc/guides/prog_guide/representor_lib.rst b/doc/guides/prog_guide/representor_lib.rst
new file mode 100644
index 0000000..dbf6acb
--- /dev/null
+++ b/doc/guides/prog_guide/representor_lib.rst
@@ -0,0 +1,62 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2017 Intel Corporation.
+
+.. _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);
diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst
index 24b67bb..5854d51 100644
--- a/doc/guides/rel_notes/release_18_02.rst
+++ b/doc/guides/rel_notes/release_18_02.rst
@@ -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
 -----------
@@ -157,6 +166,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_port.so.3
      librte_power.so.1
      librte_reorder.so.1
+   + librte_representor.so.1
      librte_ring.so.1
      librte_sched.so.1
      librte_security.so.1
diff --git a/lib/Makefile b/lib/Makefile
index 4202702..42932a9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -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
diff --git a/lib/librte_eal/common/eal_common_log.c b/lib/librte_eal/common/eal_common_log.c
index 08b31e2..5549f50 100644
--- a/lib/librte_eal/common/eal_common_log.c
+++ b/lib/librte_eal/common/eal_common_log.c
@@ -210,6 +210,7 @@ static const struct logtype logtype_strings[] = {
 	{RTE_LOGTYPE_CRYPTODEV,  "cryptodev"},
 	{RTE_LOGTYPE_EFD,        "efd"},
 	{RTE_LOGTYPE_EVENTDEV,   "eventdev"},
+	{RTE_LOGTYPE_PORTREP,    "representor"},
 	{RTE_LOGTYPE_USER1,      "user1"},
 	{RTE_LOGTYPE_USER2,      "user2"},
 	{RTE_LOGTYPE_USER3,      "user3"},
diff --git a/lib/librte_eal/common/include/rte_log.h b/lib/librte_eal/common/include/rte_log.h
index 83faddf..bf79006 100644
--- a/lib/librte_eal/common/include/rte_log.h
+++ b/lib/librte_eal/common/include/rte_log.h
@@ -59,6 +59,7 @@ extern struct rte_logs rte_logs;
 #define RTE_LOGTYPE_EFD       18 /**< Log related to EFD. */
 #define RTE_LOGTYPE_EVENTDEV  19 /**< Log related to eventdev. */
 #define RTE_LOGTYPE_GSO       20 /**< Log related to GSO. */
+#define RTE_LOGTYPE_PORTREP   21 /**< Log related to port representors. */
 
 /* these log types can be used in an application */
 #define RTE_LOGTYPE_USER1     24 /**< User-defined log type 1. */
diff --git a/lib/librte_representor/Makefile b/lib/librte_representor/Makefile
new file mode 100644
index 0000000..9ccd5c9
--- /dev/null
+++ b/lib/librte_representor/Makefile
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation.
+
+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
diff --git a/lib/librte_representor/rte_port_representor.c b/lib/librte_representor/rte_port_representor.c
new file mode 100644
index 0000000..100d101
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.c
@@ -0,0 +1,350 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#include <rte_pci.h>
+#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_LOG(DEBUG, PORTREP, "verify failed, ret= %d", (retval)); \
+		return retval; \
+	} \
+} while (0)
+
+#define RTE_VERIFY_OR_RET(val) do { \
+	if (!(val)) { \
+		RTE_LOG(DEBUG, PORTREP, "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, PORTREP, "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, PORTREP, "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_LOG(DEBUG, PORTREP,	"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_LOG(DEBUG, PORTREP, "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];
+	struct rte_pci_addr pci_addr;
+
+	RTE_LOG(INFO, PORTREP, "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);
+		retval = eal_parse_pci_DomBDF(addr_dev, &pci_addr);
+		if (retval) {
+			RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+				"has invalid address format\n",
+				pf_addr_str);
+			return retval;
+		}
+	} else {
+		RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+			"has invalid address 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, PORTREP,
+			"Unable to find broker for %s on bus %s\n",
+			addr_dev, addr_bus);
+		return -EINVAL;
+	}
+	RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_init, -ENOTSUP);
+
+	/* Fetch representor slot for VF */
+	rep_port = representor_port_find(broker, vport_id);
+	if (rep_port == NULL) {
+		RTE_LOG(ERR, PORTREP,
+			"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, PORTREP, "Port Representor name"
+			" exceeds RTE_ETH_NAME_MAX_LEN\n");
+		return -EIO;
+	}
+	RTE_LOG(INFO, PORTREP, "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, PORTREP, "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, PORTREP, "Unable to allocate Port Representor"
+			" mac_addrs\n");
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+
+	/* Allocate an rte_device & rte_driver for the ethdev. */
+	rep_port->rep_rtedev = rte_zmalloc_socket("rte_device",
+		sizeof(struct rte_device), 0, rte_socket_id());
+	if (rep_port->rep_rtedev == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to allocate Port Representor"
+			" devive\n");
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+	rep_port->rep_rtedrv = rte_zmalloc_socket("rte_driver",
+		sizeof(struct rte_driver), 0, rte_socket_id());
+	if (rep_port->rep_rtedrv == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to allocate Port Representor"
+			" driver\n");
+		rte_free(rep_port->rep_rtedev);
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+	rep_port->rep_rtedrv->name = RTE_PORT_REPRESENTOR_DEVICE_NAME;
+	rep_port->rep_rtedev->driver = rep_port->rep_rtedrv;
+	rep_ethdev->device = rep_port->rep_rtedev;
+
+	/* 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;
+
+	retval = broker->ops->port_init(broker, rep_ethdev);
+	if (retval) {
+		rte_free(rep_port->rep_rtedev);
+		rte_free(rep_port->rep_rtedrv);
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return retval;
+	}
+	RTE_LOG(INFO, PORTREP, "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];
+	struct rte_pci_addr pci_addr;
+	int addr_len;
+	int retval;
+
+	RTE_LOG(INFO, PORTREP, "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);
+		retval = eal_parse_pci_DomBDF(addr_dev, &pci_addr);
+		if (retval) {
+			RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+				"has invalid address format\n",
+				pf_addr_str);
+			return retval;
+		}
+	} else {
+		RTE_LOG(ERR, PORTREP,
+			"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, PORTREP,
+			"Unable to find broker for %s on bus %s\n",
+			addr_dev, addr_bus);
+		return -EINVAL;
+	}
+	RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_uninit, -ENOTSUP);
+
+	/* Fetch representor slot for VF */
+	rep_port = representor_port_find(broker, vport_id);
+	if (rep_port == NULL) {
+		RTE_LOG(ERR, PORTREP,
+			"Unable to fetch Port Representor handle\n");
+		return -EINVAL;
+	}
+	if (rep_port->state != RTE_REPRESENTOR_PORT_VALID) {
+		RTE_LOG(ERR, PORTREP, "Representor vport %i is not active\n",
+			vport_id);
+		return -EINVAL;
+	}
+
+	/* Free up representor */
+	rep_port->broker->ops->port_uninit(rep_port->broker, rep_port->ethdev);
+	rep_port->state = RTE_REPRESENTOR_PORT_INVALID;
+	rte_free(rep_port->ethdev->data->mac_addrs);
+	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_rtedrv);
+	rte_free(rep_port->rep_rtedev);
+
+	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;
+}
diff --git a/lib/librte_representor/rte_port_representor.h b/lib/librte_representor/rte_port_representor.h
new file mode 100644
index 0000000..6582cb9
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#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_ */
diff --git a/lib/librte_representor/rte_port_representor_driver.h b/lib/librte_representor/rte_port_representor_driver.h
new file mode 100644
index 0000000..57e527d
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_driver.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#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"
+
+enum rte_representor_port_state {
+	RTE_REPRESENTOR_PORT_INVALID,
+	/**< No ethdev instantiated for virtual port */
+	RTE_REPRESENTOR_PORT_VALID
+	/**< ethdev active for virtual port */
+};
+
+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_state state;
+	/**< port state */
+	void *priv_data;
+	/**<  port private data */
+	/**< Representor ethdev device */
+	struct rte_device *rep_rtedev;
+	/**< Representor ethdev driver */
+	struct rte_driver *rep_rtedrv;
+};
+
+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_ */
diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
new file mode 100644
index 0000000..b26600c
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_version.map
@@ -0,0 +1,8 @@
+DPDK_18.02 {
+	global:
+
+	rte_representor_port_register;
+	rte_representor_port_unregister;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6a6a745..67266bf 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -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
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 2/5] eal: add Port Representor command-line option
  2018-01-10 17:49       ` [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
@ 2018-01-10 17:49         ` Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
                           ` (2 subsequent siblings)
  4 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 17:49 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Declan Doherty, Mohammad Abdul Awal

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.

By default the Port Representor infrastructure is not enabled. This
patch implements the --enable-representor EAL command-line parameter
that activates representation functionality.

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>
---
 doc/guides/rel_notes/release_18_02.rst     | 2 ++
 lib/librte_eal/bsdapp/eal/eal.c            | 6 ++++++
 lib/librte_eal/common/eal_common_options.c | 1 +
 lib/librte_eal/common/eal_internal_cfg.h   | 2 ++
 lib/librte_eal/common/eal_options.h        | 2 ++
 lib/librte_eal/common/include/rte_eal.h    | 8 ++++++++
 lib/librte_eal/linuxapp/eal/eal.c          | 9 +++++++++
 lib/librte_eal/rte_eal_version.map         | 1 +
 8 files changed, 31 insertions(+)

diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst
index 5854d51..8479feb 100644
--- a/doc/guides/rel_notes/release_18_02.rst
+++ b/doc/guides/rel_notes/release_18_02.rst
@@ -50,6 +50,8 @@ New Features
   the representor device ops and defines the control domain to which that
   port belongs.
 
+* **Added --enable-representor EAL command-line option
+
 
 API Changes
 -----------
diff --git a/lib/librte_eal/bsdapp/eal/eal.c b/lib/librte_eal/bsdapp/eal/eal.c
index 369a682..002200a 100644
--- a/lib/librte_eal/bsdapp/eal/eal.c
+++ b/lib/librte_eal/bsdapp/eal/eal.c
@@ -778,3 +778,9 @@ int rte_vfio_noiommu_is_enabled(void)
 {
 	return 0;
 }
+
+/* return non-zero if port-representor is enabled. */
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
diff --git a/lib/librte_eal/common/eal_common_options.c b/lib/librte_eal/common/eal_common_options.c
index 996a034..6f2cc05 100644
--- a/lib/librte_eal/common/eal_common_options.c
+++ b/lib/librte_eal/common/eal_common_options.c
@@ -78,6 +78,7 @@ const struct option
 eal_long_options[] = {
 	{OPT_BASE_VIRTADDR,     1, NULL, OPT_BASE_VIRTADDR_NUM    },
 	{OPT_CREATE_UIO_DEV,    0, NULL, OPT_CREATE_UIO_DEV_NUM   },
+	{OPT_ENABLE_REPRESENTOR, 0, NULL, OPT_ENABLE_REPRESENTOR_NUM   },
 	{OPT_FILE_PREFIX,       1, NULL, OPT_FILE_PREFIX_NUM      },
 	{OPT_HELP,              0, NULL, OPT_HELP_NUM             },
 	{OPT_HUGE_DIR,          1, NULL, OPT_HUGE_DIR_NUM         },
diff --git a/lib/librte_eal/common/eal_internal_cfg.h b/lib/librte_eal/common/eal_internal_cfg.h
index c67685c..b4befe6 100644
--- a/lib/librte_eal/common/eal_internal_cfg.h
+++ b/lib/librte_eal/common/eal_internal_cfg.h
@@ -42,6 +42,8 @@ struct internal_config {
 										* instead of native TSC */
 	volatile unsigned no_shconf;      /**< true if there is no shared config */
 	volatile unsigned create_uio_dev; /**< true to create /dev/uioX devices */
+	volatile unsigned enable_representor;
+	/**< true to enable port representor broker for all PFs */
 	volatile enum rte_proc_type_t process_type; /**< multi-process proc type */
 	/** true to try allocating memory on specific sockets */
 	volatile unsigned force_sockets;
diff --git a/lib/librte_eal/common/eal_options.h b/lib/librte_eal/common/eal_options.h
index 30e6bb4..c2b2162 100644
--- a/lib/librte_eal/common/eal_options.h
+++ b/lib/librte_eal/common/eal_options.h
@@ -83,6 +83,8 @@ enum {
 	OPT_VFIO_INTR_NUM,
 #define OPT_VMWARE_TSC_MAP    "vmware-tsc-map"
 	OPT_VMWARE_TSC_MAP_NUM,
+#define OPT_ENABLE_REPRESENTOR    "enable-representor"
+	OPT_ENABLE_REPRESENTOR_NUM,
 	OPT_LONG_MAX_NUM
 };
 
diff --git a/lib/librte_eal/common/include/rte_eal.h b/lib/librte_eal/common/include/rte_eal.h
index 02fa109..d21f704 100644
--- a/lib/librte_eal/common/include/rte_eal.h
+++ b/lib/librte_eal/common/include/rte_eal.h
@@ -306,6 +306,14 @@ enum rte_iova_mode rte_eal_iova_mode(void);
 const char *
 rte_eal_mbuf_default_mempool_ops(void);
 
+/**
+ * Get flag for port representor should be enabled or not.
+ *
+ * @return
+ *   Returns the enable-representor flag.
+ */
+int rte_representor_enabled(void);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 229eec9..364a8b2 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -612,6 +612,10 @@ eal_parse_args(int argc, char **argv)
 			internal_config.mbuf_pool_ops_name = optarg;
 			break;
 
+		case OPT_ENABLE_REPRESENTOR_NUM:
+			internal_config.enable_representor = 1;
+			break;
+
 		default:
 			if (opt < OPT_LONG_MIN_NUM && isprint(opt)) {
 				RTE_LOG(ERR, EAL, "Option %c is not supported "
@@ -1041,3 +1045,8 @@ rte_eal_check_module(const char *module_name)
 	/* Module has been found */
 	return 1;
 }
+
+int rte_representor_enabled(void)
+{
+	return internal_config.enable_representor;
+}
diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map
index f4f46c1..af3e713 100644
--- a/lib/librte_eal/rte_eal_version.map
+++ b/lib/librte_eal/rte_eal_version.map
@@ -227,6 +227,7 @@ EXPERIMENTAL {
 	rte_service_map_lcore_get;
 	rte_service_map_lcore_set;
 	rte_service_probe_capability;
+	rte_service_representor_enabled;
 	rte_service_reset;
 	rte_service_run_iter_on_app_lcore;
 	rte_service_runstate_get;
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality
  2018-01-10 17:49       ` [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 2/5] eal: add Port Representor command-line option Remy Horton
@ 2018-01-10 17:49         ` Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 4/5] drivers/net/ixgbe: " Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 5/5] app/test-pmd: add Port Representor commands Remy Horton
  4 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 17:49 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Beilei Xing, Declan Doherty, Mohammad Abdul Awal

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.

This patch adds to the i40e PMD the functions required to enable port
representor functionality.

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>
---
 MAINTAINERS                                  |   2 +
 drivers/net/i40e/Makefile                    |   2 +
 drivers/net/i40e/i40e_ethdev.c               |  19 +
 drivers/net/i40e/i40e_ethdev.h               |   1 +
 drivers/net/i40e/i40e_port_representor_ops.c | 516 +++++++++++++++++++++++++++
 drivers/net/i40e/i40e_port_representor_ops.h |  19 +
 drivers/net/i40e/rte_pmd_i40e.c              |  43 +++
 drivers/net/i40e/rte_pmd_i40e.h              |  18 +
 drivers/net/i40e/rte_pmd_i40e_version.map    |   7 +
 9 files changed, 627 insertions(+)
 create mode 100644 drivers/net/i40e/i40e_port_representor_ops.c
 create mode 100644 drivers/net/i40e/i40e_port_representor_ops.h

diff --git a/MAINTAINERS b/MAINTAINERS
index c48f1b5..b720566 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -787,6 +787,8 @@ 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
+F: drivers/net/i40e/i40e_prep_ops.c
+F: drivers/net/i40e/i40e_prep_ops.h
 
 
 Packet Framework
diff --git a/drivers/net/i40e/Makefile b/drivers/net/i40e/Makefile
index 4b9634d..521640b 100644
--- a/drivers/net/i40e/Makefile
+++ b/drivers/net/i40e/Makefile
@@ -14,6 +14,7 @@ CFLAGS += -DX722_A0_SUPPORT
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_hash
 LDLIBS += -lrte_bus_pci
+LDLIBS += -lrte_representor
 
 EXPORT_MAP := rte_pmd_i40e_version.map
 
@@ -85,6 +86,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_fdir.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += rte_pmd_i40e.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_port_representor_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_I40E_PMD)-include := rte_pmd_i40e.h
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 285d92b..7e1443c 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -36,6 +36,7 @@
 #include "i40e_ethdev.h"
 #include "i40e_rxtx.h"
 #include "i40e_pf.h"
+#include "i40e_port_representor_ops.h"
 #include "i40e_regs.h"
 #include "rte_pmd_i40e.h"
 
@@ -1093,6 +1094,17 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	hw->bus.func = pci_dev->addr.function;
 	hw->adapter_stopped = 0;
 
+	/* init representor broker */
+	if (rte_representor_enabled()) {
+		ret = i40e_port_representor_broker_init(dev, &pf->broker,
+			pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Make sure all is clean before doing PF reset */
 	i40e_clear_hw(hw);
 
@@ -1428,6 +1440,13 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
 	intr_handle = &pci_dev->intr_handle;
 
+	/* free port representor pmds */
+	if (rte_representor_enabled()) {
+		ret = i40e_port_representor_broker_uninit(dev, pf->broker);
+		if (ret)
+			PMD_INIT_LOG(ERR, "Representor broker unregister"
+				" failed with ret=%d\n", ret);
+	}
 	if (hw->adapter_stopped == 0)
 		i40e_dev_close(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index f2b4b70..cadecbf 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -928,6 +928,7 @@ struct i40e_pf {
 	bool gtp_replace_flag;   /* 1 - GTP-C/U filter replace is done */
 	bool qinq_replace_flag;  /* QINQ filter replace is done */
 	struct i40e_tm_conf tm_conf;
+	struct rte_representor_broker *broker;
 
 	/* Dynamic Device Personalization */
 	bool gtp_support; /* 1 - support GTP-C and GTP-U */
diff --git a/drivers/net/i40e/i40e_port_representor_ops.c b/drivers/net/i40e/i40e_port_representor_ops.c
new file mode 100644
index 0000000..ddd9e77
--- /dev/null
+++ b/drivers/net/i40e/i40e_port_representor_ops.c
@@ -0,0 +1,516 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#include <rte_bus_pci.h>
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+
+#include "base/i40e_type.h"
+#include "base/virtchnl.h"
+#include "i40e_ethdev.h"
+#include "i40e_port_representor_ops.h"
+#include "i40e_rxtx.h"
+#include "rte_pmd_i40e.h"
+
+
+struct i40e_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+i40e_representor_link_update(struct rte_eth_dev *ethdev, int wait_to_complete)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return i40e_dev_link_update(i40e_priv_data->pf_ethdev,
+		wait_to_complete);
+}
+
+static void
+i40e_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (!is_i40e_supported(i40e_priv_data->pf_ethdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(
+		i40e_priv_data->pf_ethdev->data->dev_private);
+	if (representor->vport_id >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return;
+	}
+
+	vf = &pf->vfs[representor->vport_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return;
+	}
+
+	/* get dev info for the vdev */
+	dev_info->pci_dev = RTE_ETH_DEV_TO_PCI(ethdev);
+	dev_info->max_rx_queues = vsi->nb_qps;
+	dev_info->max_tx_queues = vsi->nb_qps;
+	dev_info->min_rx_bufsize = I40E_BUF_SIZE_MIN;
+	dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
+	dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) *
+		sizeof(uint32_t);
+	dev_info->reta_size = ETH_RSS_RETA_SIZE_64;
+	dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL;
+	dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX;
+	dev_info->rx_offload_capa =
+		DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_QINQ_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |
+		DEV_RX_OFFLOAD_UDP_CKSUM |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	dev_info->tx_offload_capa =
+		DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_QINQ_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM |
+		DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM |
+		DEV_TX_OFFLOAD_SCTP_CKSUM |
+		DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
+		DEV_TX_OFFLOAD_TCP_TSO |
+		DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
+		DEV_TX_OFFLOAD_GRE_TNL_TSO |
+		DEV_TX_OFFLOAD_IPIP_TNL_TSO |
+		DEV_TX_OFFLOAD_GENEVE_TNL_TSO;
+
+	dev_info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_thresh = {
+			.pthresh = I40E_DEFAULT_RX_PTHRESH,
+			.hthresh = I40E_DEFAULT_RX_HTHRESH,
+			.wthresh = I40E_DEFAULT_RX_WTHRESH,
+		},
+		.rx_free_thresh = I40E_DEFAULT_RX_FREE_THRESH,
+		.rx_drop_en = 0,
+	};
+
+	dev_info->default_txconf = (struct rte_eth_txconf) {
+		.tx_thresh = {
+			.pthresh = I40E_DEFAULT_TX_PTHRESH,
+			.hthresh = I40E_DEFAULT_TX_HTHRESH,
+			.wthresh = I40E_DEFAULT_TX_WTHRESH,
+		},
+		.tx_free_thresh = I40E_DEFAULT_TX_FREE_THRESH,
+		.tx_rs_thresh = I40E_DEFAULT_TX_RSBIT_THRESH,
+		.txq_flags = ETH_TXQ_FLAGS_NOMULTSEGS |
+				ETH_TXQ_FLAGS_NOOFFLOADS,
+	};
+
+	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+
+	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = I40E_MAX_RING_DESC,
+		.nb_min = I40E_MIN_RING_DESC,
+		.nb_align = I40E_ALIGN_RING_DESC,
+	};
+}
+
+static int i40e_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int i40e_representor_rx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int i40e_representor_tx_queue_setup(__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int i40e_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void i40e_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+i40e_representor_stats_get(struct rte_eth_dev *ethdev,
+		struct rte_eth_stats *stats)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_get_vf_stats(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, stats);
+}
+
+static void
+i40e_representor_stats_reset(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_reset_vf_stats(i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id);
+}
+
+static void
+i40e_representor_promiscuous_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_promiscuous_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_unicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_allmulticast_enable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 1);
+}
+
+static void
+i40e_representor_allmulticast_disable(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_multicast_promisc(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, 0);
+}
+
+static void
+i40e_representor_mac_addr_remove(struct rte_eth_dev *ethdev, uint32_t index)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_remove_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, &ethdev->data->mac_addrs[index]);
+}
+
+static void
+i40e_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+		struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_mac_addr(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, mac_addr);
+}
+
+static int
+i40e_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+		uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	vfid = representor->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_i40e_set_vf_vlan_filter(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		vlan_id, vf_mask, on);
+}
+
+static int
+i40e_representor_vlan_offload_set(struct rte_eth_dev *ethdev, int mask)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+	struct rte_eth_dev *pdev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+	uint32_t vfid;
+
+	pdev = i40e_priv_data->pf_ethdev;
+	vfid = representor->vport_id;
+
+	if (!is_i40e_supported(pdev)) {
+		PMD_DRV_LOG(ERR, "Invalid PF dev.");
+		return -EINVAL;
+	}
+
+	pf = I40E_DEV_PRIVATE_TO_PF(pdev->data->dev_private);
+
+	if (vfid >= pf->vf_num || !pf->vfs) {
+		PMD_DRV_LOG(ERR, "Invalid VF ID.");
+		return -EINVAL;
+	}
+
+	vf = &pf->vfs[vfid];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Fixme: even though there 3 kinds of hw offloads, hw_vlan_filter,
+	 * hw_vlan_strip, and hw_vlan_extend.
+	 * currently the hw_vlan_extend offload by vsi is not implemented.
+	 */
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		/* Enable or disable VLAN filtering offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_filter)
+			return i40e_vsi_config_vlan_filter(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_filter(vsi, FALSE);
+	}
+
+	if (mask & ETH_VLAN_STRIP_MASK) {
+		/* Enable or disable VLAN stripping offload */
+		if (ethdev->data->dev_conf.rxmode.hw_vlan_strip)
+			return i40e_vsi_config_vlan_stripping(vsi, TRUE);
+		else
+			return i40e_vsi_config_vlan_stripping(vsi, FALSE);
+	}
+
+	return -EINVAL;
+}
+
+static void
+i40e_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	rte_pmd_i40e_set_vf_vlan_stripq(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, on);
+}
+
+static int
+i40e_representor_vlan_pvid_set(struct rte_eth_dev *ethdev, uint16_t vlan_id,
+	__rte_unused int on)
+{
+	struct rte_representor_port *representor = ethdev->data->dev_private;
+	struct i40e_representor_private_data *i40e_priv_data =
+		representor->priv_data;
+
+	return rte_pmd_i40e_set_vf_vlan_insert(
+		i40e_priv_data->pf_ethdev->data->port_id,
+		representor->vport_id, vlan_id);
+}
+
+struct eth_dev_ops i40e_representor_dev_ops = {
+	.link_update          = i40e_representor_link_update,
+	.dev_infos_get        = i40e_representor_dev_infos_get,
+	.dev_configure        = i40e_representor_dev_configure,
+	.rx_queue_setup       = i40e_representor_rx_queue_setup,
+	.tx_queue_setup       = i40e_representor_tx_queue_setup,
+	.dev_start            = i40e_representor_dev_start,
+	.dev_stop             = i40e_representor_dev_stop,
+
+	.stats_get            = i40e_representor_stats_get,
+	.stats_reset          = i40e_representor_stats_reset,
+
+	.promiscuous_enable   = i40e_representor_promiscuous_enable,
+	.promiscuous_disable  = i40e_representor_promiscuous_disable,
+
+	.allmulticast_enable  = i40e_representor_allmulticast_enable,
+	.allmulticast_disable = i40e_representor_allmulticast_disable,
+
+	.mac_addr_remove      = i40e_representor_mac_addr_remove,
+	.mac_addr_set         = i40e_representor_mac_addr_set,
+
+	.vlan_filter_set      = i40e_representor_vlan_filter_set,
+	.vlan_offload_set     = i40e_representor_vlan_offload_set,
+	.vlan_strip_queue_set = i40e_representor_vlan_strip_queue_set,
+	.vlan_pvid_set        = i40e_representor_vlan_pvid_set
+};
+
+static uint16_t i40e_representor_rx_burst(__rte_unused void *rxq,
+	__rte_unused struct rte_mbuf **rx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static uint16_t i40e_representor_tx_burst(__rte_unused void *txq,
+	__rte_unused struct rte_mbuf **tx_pkts,
+	__rte_unused uint16_t nb_pkts)
+{
+	return 0;
+}
+
+static int
+i40e_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port;
+	struct i40e_pf *i40e_pf;
+	struct i40e_pf_vf *i40e_vf;
+
+	port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("i40e_port_representor_priv_data",
+			sizeof(struct i40e_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct i40e_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+
+	i40e_pf = I40E_DEV_PRIVATE_TO_PF(pf_ethdev->data->dev_private);
+	i40e_vf = &i40e_pf->vfs[port->vport_id];
+
+	if (!i40e_vf->vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &i40e_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = i40e_vf->vsi->nb_qps;
+	ethdev->data->nb_tx_queues = i40e_vf->vsi->nb_qps;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = i40e_representor_rx_burst;
+	ethdev->tx_pkt_burst = i40e_representor_tx_burst;
+
+	return 0;
+}
+
+static int
+i40e_port_representor_uninit(struct rte_representor_broker *broker __rte_unused,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops i40e_broker_port_ops = {
+	.port_init = i40e_port_representor_init,
+	.port_uninit = i40e_port_representor_uninit
+};
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set i40e broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &i40e_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
+
+int
+i40e_port_representor_broker_uninit(__rte_unused struct rte_eth_dev *dev,
+	struct rte_representor_broker *broker)
+{
+	int ret;
+
+	ret = rte_representor_broker_uninit(broker);
+	if (ret)
+		return ret;
+
+	rte_free(broker);
+
+	return 0;
+}
diff --git a/drivers/net/i40e/i40e_port_representor_ops.h b/drivers/net/i40e/i40e_port_representor_ops.h
new file mode 100644
index 0000000..b7187ee
--- /dev/null
+++ b/drivers/net/i40e/i40e_port_representor_ops.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#ifndef _I40E_PORT_REPRESENTOR_OPS_H_
+#define _I40E_PORT_REPRESENTOR_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+i40e_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+int
+i40e_port_representor_broker_uninit(struct rte_eth_dev *dev,
+	struct rte_representor_broker *broker);
+
+#endif /* _I40E_PORT_REPRESENTOR_OPS_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 947f13b..afe20a8 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -570,6 +570,49 @@ rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 	return 0;
 }
 
+static const struct ether_addr null_mac_addr;
+
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint16_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr)
+{
+	struct rte_eth_dev *dev;
+	struct i40e_pf_vf *vf;
+	struct i40e_vsi *vsi;
+	struct i40e_pf *pf;
+
+	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
+		return -EINVAL;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
+
+	dev = &rte_eth_devices[port];
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+	if (vf_id >= pf->vf_num || !pf->vfs)
+		return -EINVAL;
+
+	vf = &pf->vfs[vf_id];
+	vsi = vf->vsi;
+	if (!vsi) {
+		PMD_DRV_LOG(ERR, "Invalid VSI.");
+		return -EINVAL;
+	}
+
+	if (is_same_ether_addr(mac_addr, &vf->mac_addr))
+		/* Reset the mac with NULL address */
+		ether_addr_copy(&null_mac_addr, &vf->mac_addr);
+
+	/* Remove the mac */
+	i40e_vsi_delete_mac(vsi, mac_addr);
+
+	return 0;
+}
+
 /* Set vlan strip on/off for specific VF from host */
 int
 rte_pmd_i40e_set_vf_vlan_stripq(uint16_t port, uint16_t vf_id, uint8_t on)
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 7ca37b1..89f4fea 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -439,6 +439,24 @@ int rte_pmd_i40e_set_vf_mac_addr(uint16_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
 /**
+ * Remove the VF MAC address.
+ *
+ * @param port
+ *   The port identifier of the Ethernet device.
+ * @param vf_id
+ *   VF id.
+ * @param mac_addr
+ *   VF MAC address.
+ * @return
+ *   - (0) if successful.
+ *   - (-ENODEV) if *port* invalid.
+ *   - (-EINVAL) if *vf* or *mac_addr* is invalid.
+ */
+int
+rte_pmd_i40e_remove_vf_mac_addr(uint16_t port, uint16_t vf_id,
+	struct ether_addr *mac_addr);
+
+/**
  * Enable/Disable vf vlan strip for all queues in a pool
  *
  * @param port
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ebbd24e..4faff5a 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -58,3 +58,10 @@ DPDK_17.11 {
 	rte_pmd_i40e_rss_queue_region_conf;
 
 } DPDK_17.08;
+
+DPDK_18.02 {
+	global:
+
+	rte_pmd_i40e_remove_vf_mac_addr;
+
+}DPDK_17.11;
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 4/5] drivers/net/ixgbe: add Port Representor functionality
  2018-01-10 17:49       ` [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors Remy Horton
                           ` (2 preceding siblings ...)
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
@ 2018-01-10 17:49         ` Remy Horton
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 5/5] app/test-pmd: add Port Representor commands Remy Horton
  4 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 17:49 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Wenzhuo Lu, Declan Doherty, Mohammad Abdul Awal

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.

This patch adds to the ixgbe PMD PMD the functions required to enable
port representor functionality.

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>
---
 MAINTAINERS                                    |   2 +
 drivers/net/ixgbe/Makefile                     |   2 +
 drivers/net/ixgbe/ixgbe_ethdev.c               |  29 ++-
 drivers/net/ixgbe/ixgbe_ethdev.h               |   5 +
 drivers/net/ixgbe/ixgbe_port_representor_ops.c | 274 +++++++++++++++++++++++++
 drivers/net/ixgbe/ixgbe_port_representor_ops.h |  19 ++
 6 files changed, 330 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ixgbe/ixgbe_port_representor_ops.c
 create mode 100644 drivers/net/ixgbe/ixgbe_port_representor_ops.h

diff --git a/MAINTAINERS b/MAINTAINERS
index b720566..b467c6a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -789,6 +789,8 @@ F: lib/librte_representor
 F: doc/guides/prog_guide/representor_lib.rst
 F: drivers/net/i40e/i40e_prep_ops.c
 F: drivers/net/i40e/i40e_prep_ops.h
+F: drivers/net/ixgbe/ixgbe_prep_ops.c
+F: drivers/net/ixgbe/ixgbe_prep_ops.h
 
 
 Packet Framework
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index 9efa5a4..39fe184 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -57,6 +57,7 @@ endif
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_hash
 LDLIBS += -lrte_bus_pci
+LDLIBS += -lrte_representor
 
 #
 # Add extra flags for base driver files (also known as shared code)
@@ -102,6 +103,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_ipsec.c
 endif
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += rte_pmd_ixgbe.c
 SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_IXGBE_PMD) += ixgbe_port_representor_ops.c
 
 # install this header file
 SYMLINK-$(CONFIG_RTE_LIBRTE_IXGBE_PMD)-include := rte_pmd_ixgbe.h
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 43e0132..aab0ca3 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -46,6 +46,7 @@
 #include "base/ixgbe_type.h"
 #include "base/ixgbe_phy.h"
 #include "ixgbe_regs.h"
+#include "ixgbe_port_representor_ops.h"
 
 /*
  * High threshold controlling when to start sending XOFF frames. Must be at
@@ -1109,6 +1110,9 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 	uint32_t ctrl_ext;
 	uint16_t csum;
 	int diag, i;
+	int ret;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1232,6 +1236,17 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev)
 		return -EIO;
 	}
 
+	/* Init port representor broker */
+	if (rte_representor_enabled()) {
+		ret = ixgbe_port_representor_broker_init(eth_dev,
+			&eth_adapter->broker, pci_dev);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Representor broker register failed "
+				"with ret=%d\n", ret);
+			return ret;
+		}
+	}
+
 	/* Reset the hw statistics */
 	ixgbe_dev_stats_reset(eth_dev);
 
@@ -1334,6 +1349,9 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	struct ixgbe_hw *hw;
+	struct ixgbe_adapter *eth_adapter =
+		(struct ixgbe_adapter *)eth_dev->data->dev_private;
+	int ret;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1342,6 +1360,15 @@ eth_ixgbe_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
 
+	/* free port representor pmds */
+	if (rte_representor_enabled()) {
+		ret = ixgbe_port_representor_broker_uninit(eth_dev,
+			eth_adapter->broker);
+		if (ret)
+			PMD_INIT_LOG(ERR, "Representor broker unregister "
+				"failed with ret=%d\n", ret);
+	}
+
 	if (hw->adapter_stopped == 0)
 		ixgbe_dev_close(eth_dev);
 
@@ -3933,7 +3960,7 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 }
 
 /* return 0 means link status changed, -1 means not changed */
-static int
+int
 ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 			    int wait_to_complete, int vf)
 {
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 1db29bd..c2df08e 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -470,6 +470,7 @@ struct ixgbe_adapter {
 	struct rte_timecounter      rx_tstamp_tc;
 	struct rte_timecounter      tx_tstamp_tc;
  	struct ixgbe_tm_conf        tm_conf;
+	struct rte_representor_broker *broker;
 };
 
 #define IXGBE_DEV_PRIVATE_TO_HW(adapter)\
@@ -644,6 +645,10 @@ int ixgbe_fdir_filter_program(struct rte_eth_dev *dev,
 
 void ixgbe_configure_dcb(struct rte_eth_dev *dev);
 
+int
+ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
+			    int wait_to_complete, int vf);
+
 /*
  * misc function prototypes
  */
diff --git a/drivers/net/ixgbe/ixgbe_port_representor_ops.c b/drivers/net/ixgbe/ixgbe_port_representor_ops.c
new file mode 100644
index 0000000..4547cbc
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_port_representor_ops.c
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#include <rte_ethdev.h>
+#include <rte_pci.h>
+#include <rte_port_representor_driver.h>
+
+#include "base/ixgbe_type.h"
+#include "base/ixgbe_vf.h"
+#include "ixgbe_ethdev.h"
+#include "ixgbe_port_representor_ops.h"
+#include "ixgbe_rxtx.h"
+#include "rte_pmd_ixgbe.h"
+
+
+struct ixgbe_representor_private_data {
+	struct rte_eth_dev *pf_ethdev;
+};
+
+static int
+ixgbe_representor_link_update(struct rte_eth_dev *ethdev,
+	int wait_to_complete)
+{
+	struct rte_representor_port *prep_priv_data =
+			ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+			prep_priv_data->priv_data;
+
+	return ixgbe_dev_link_update_share(ixgbe_priv_data->pf_ethdev,
+		wait_to_complete, 1);
+}
+
+static void
+ixgbe_representor_mac_addr_set(struct rte_eth_dev *ethdev,
+	struct ether_addr *mac_addr)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	rte_pmd_ixgbe_set_vf_mac_addr(ixgbe_priv_data->pf_ethdev->data->port_id,
+		prep_priv_data->vport_id, mac_addr);
+}
+
+static void
+ixgbe_representor_dev_infos_get(struct rte_eth_dev *ethdev,
+	struct rte_eth_dev_info *dev_info)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(
+		ixgbe_priv_data->pf_ethdev->data->dev_private);
+
+	dev_info->pci_dev = NULL;
+
+	dev_info->min_rx_bufsize = 1024;
+	/**< Minimum size of RX buffer. */
+	dev_info->max_rx_pktlen = 9728;
+	/**< Maximum configurable length of RX pkt. */
+	dev_info->max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	/**< Maximum number of RX queues. */
+	dev_info->max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+	/**< Maximum number of TX queues. */
+
+	dev_info->max_mac_addrs = hw->mac.num_rar_entries;
+	/**< Maximum number of MAC addresses. */
+
+	dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
+		DEV_RX_OFFLOAD_IPV4_CKSUM |	DEV_RX_OFFLOAD_UDP_CKSUM  |
+		DEV_RX_OFFLOAD_TCP_CKSUM;
+	/**< Device RX offload capabilities. */
+
+	dev_info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
+		DEV_TX_OFFLOAD_IPV4_CKSUM | DEV_TX_OFFLOAD_UDP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_CKSUM | DEV_TX_OFFLOAD_SCTP_CKSUM |
+		DEV_TX_OFFLOAD_TCP_TSO;
+	/**< Device TX offload capabilities. */
+
+	dev_info->speed_capa =
+		ixgbe_priv_data->pf_ethdev->data->dev_link.link_speed;
+	/**< Supported speeds bitmap (ETH_LINK_SPEED_). */
+}
+
+static int ixgbe_representor_dev_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static int ixgbe_representor_rx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_rxconf *rx_conf,
+	__rte_unused struct rte_mempool *mb_pool)
+{
+	return 0;
+}
+
+static int ixgbe_representor_tx_queue_setup(
+	__rte_unused struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id,
+	__rte_unused uint16_t nb_rx_desc,
+	__rte_unused unsigned int socket_id,
+	__rte_unused const struct rte_eth_txconf *tx_conf)
+{
+	return 0;
+}
+
+static int ixgbe_representor_dev_start(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+static void ixgbe_representor_dev_stop(__rte_unused struct rte_eth_dev *dev)
+{
+}
+
+static int
+ixgbe_representor_vlan_filter_set(struct rte_eth_dev *ethdev,
+	uint16_t vlan_id, int on)
+{
+	struct rte_representor_port *prep_priv_data =
+		ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+	uint64_t vf_mask;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+	vf_mask = 1ULL << vfid;
+
+	return rte_pmd_ixgbe_set_vf_vlan_filter(pfid, vlan_id, vf_mask, on);
+}
+
+static void
+ixgbe_representor_vlan_strip_queue_set(struct rte_eth_dev *ethdev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct rte_representor_port *prep_priv_data = ethdev->data->dev_private;
+	struct ixgbe_representor_private_data *ixgbe_priv_data =
+		prep_priv_data->priv_data;
+
+	uint32_t pfid;
+	uint32_t vfid;
+
+	pfid = ixgbe_priv_data->pf_ethdev->data->port_id;
+	vfid = prep_priv_data->vport_id;
+
+	rte_pmd_ixgbe_set_vf_vlan_stripq(pfid, vfid, on);
+}
+
+struct eth_dev_ops ixgbe_representor_dev_ops = {
+	.link_update                  = ixgbe_representor_link_update,
+	.dev_infos_get                = ixgbe_representor_dev_infos_get,
+	.dev_configure	              = ixgbe_representor_dev_configure,
+	.rx_queue_setup               = ixgbe_representor_rx_queue_setup,
+	.tx_queue_setup               = ixgbe_representor_tx_queue_setup,
+	.dev_start                    = ixgbe_representor_dev_start,
+	.dev_stop                     = ixgbe_representor_dev_stop,
+	.mac_addr_set                 = ixgbe_representor_mac_addr_set,
+	.vlan_filter_set              = ixgbe_representor_vlan_filter_set,
+	.vlan_strip_queue_set         = ixgbe_representor_vlan_strip_queue_set
+};
+
+static int
+ixgbe_port_representor_init(struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev)
+{
+	struct rte_eth_dev *pf_ethdev;
+	struct rte_eth_link *link;
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	/**
+	 * Allocate private data for i40e port representor and save the physical
+	 * functions ethdev handle
+	 */
+	port->priv_data = rte_zmalloc_socket("ixgbe_port_representor_priv_data",
+			sizeof(struct ixgbe_representor_private_data),
+			RTE_CACHE_LINE_SIZE, ethdev->device->numa_node);
+	if (!port->priv_data)
+		return -ENOMEM;
+	pf_ethdev = (struct rte_eth_dev *)broker->private_data;
+
+	((struct ixgbe_representor_private_data *)port->priv_data)->pf_ethdev =
+			pf_ethdev;
+
+	/* Set representor device ops */
+	ethdev->dev_ops = &ixgbe_representor_dev_ops;
+
+	/* Setting the number queues allocated to the VF */
+	ethdev->data->nb_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+	ethdev->data->nb_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+	/* Link state. Inherited from PF */
+	link = &pf_ethdev->data->dev_link;
+
+	ethdev->data->dev_link.link_speed = link->link_speed;
+	ethdev->data->dev_link.link_duplex = link->link_duplex;
+	ethdev->data->dev_link.link_status = link->link_status;
+	ethdev->data->dev_link.link_autoneg = link->link_autoneg;
+
+	/* No data-path so no RX/TX functions */
+	ethdev->rx_pkt_burst = NULL;
+	ethdev->tx_pkt_burst = NULL;
+
+	return 0;
+}
+
+static int
+ixgbe_port_representor_uninit(
+	__rte_unused struct rte_representor_broker *broker,
+	struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port = ethdev->data->dev_private;
+
+	rte_free(port->priv_data);
+
+	return 0;
+}
+
+struct rte_representor_broker_port_ops ixgbe_broker_port_ops = {
+	.port_init = ixgbe_port_representor_init,
+	.port_uninit = ixgbe_port_representor_uninit
+};
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev)
+{
+	struct rte_bus *bus;
+
+	*broker = rte_zmalloc_socket("rte_port_representor_broker",
+		sizeof(**broker), RTE_CACHE_LINE_SIZE,
+		rte_socket_id());
+	if (!*broker) {
+		RTE_LOG(ERR, EAL, "Not enough memory for representor "
+			"broker\n");
+		return -ENOMEM;
+	}
+	bus = rte_bus_find_by_device(&pci_dev->device);
+
+	/* Set IXGBE broker parameters */
+	(*broker)->bus = bus->name;
+	(*broker)->device = pci_dev->name;
+	(*broker)->nb_virtual_ports = pci_dev->max_vfs;
+	(*broker)->ops = &ixgbe_broker_port_ops;
+	(*broker)->private_data = dev;
+
+	return rte_representor_broker_init(*broker);
+}
+
+int
+ixgbe_port_representor_broker_uninit(__rte_unused struct rte_eth_dev *dev,
+	struct rte_representor_broker *broker)
+{
+	int ret;
+
+	ret = rte_representor_broker_uninit(broker);
+	if (ret)
+		return ret;
+
+	rte_free(broker);
+
+	return 0;
+}
diff --git a/drivers/net/ixgbe/ixgbe_port_representor_ops.h b/drivers/net/ixgbe/ixgbe_port_representor_ops.h
new file mode 100644
index 0000000..3c797c4
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_port_representor_ops.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#ifndef _IXGBE_PORT_REPRESENTOR_OPS_H_
+#define _IXGBE_PORT_REPRESENTOR_OPS_H_
+
+#include <rte_port_representor_driver.h>
+
+int
+ixgbe_port_representor_broker_init(struct rte_eth_dev *dev,
+	struct rte_representor_broker **broker,
+	const struct rte_pci_device *pci_dev);
+
+int
+ixgbe_port_representor_broker_uninit(struct rte_eth_dev *dev,
+	struct rte_representor_broker *broker);
+
+#endif /* _IXGBE_PORT_REPRESENTOR_OPS_H_ */
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* [dpdk-dev] [PATCH v5 5/5] app/test-pmd: add Port Representor commands
  2018-01-10 17:49       ` [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors Remy Horton
                           ` (3 preceding siblings ...)
  2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 4/5] drivers/net/ixgbe: " Remy Horton
@ 2018-01-10 17:49         ` Remy Horton
  4 siblings, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-10 17:49 UTC (permalink / raw)
  To: dev; +Cc: John McNamara, Wenzhuo Lu, Jingjing Wu

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.

This patch adds the 'port representor add' and 'port representor del'
commands to test-pmd, which respectively allow the adding and removing
of port representors.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/test-pmd/cmdline.c                      | 81 +++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 26 +++++++++
 2 files changed, 107 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5b2e2ef..cbaebbe 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -76,6 +76,7 @@
 #include <rte_eth_ctrl.h>
 #include <rte_flow.h>
 #include <rte_gro.h>
+#include <rte_port_representor.h>
 
 #include <cmdline_rdline.h>
 #include <cmdline_parse.h>
@@ -881,6 +882,12 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"port config (port_id) pctype mapping update"
 			" (pctype_id_0[,pctype_id_1]*) (flow_type_id)\n"
 			"    Update a flow type to pctype mapping item on a port\n\n"
+
+			"port representor add (pf_address) (vport_id)\n"
+			"    Add port representor on PF with VF id\n\n"
+
+			"port representor del (pf_address) (vport_id)\n"
+			"    Remove port representor on PF with VF id\n\n"
 		);
 	}
 
@@ -15552,6 +15559,79 @@ cmdline_parse_inst_t cmd_load_from_file = {
 	},
 };
 
+struct cmd_port_representor_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t op;
+	cmdline_fixed_string_t action;
+	cmdline_fixed_string_t pf;
+	uint16_t vport;
+};
+
+cmdline_parse_token_string_t cmd_portrepresentor_cmd =
+TOKEN_STRING_INITIALIZER(struct cmd_port_representor_result,
+	cmd, "port");
+
+cmdline_parse_token_string_t cmd_portrepresentor_op =
+TOKEN_STRING_INITIALIZER(struct cmd_port_representor_result,
+	op, "representor");
+
+cmdline_parse_token_string_t cmd_portrepresentor_act =
+TOKEN_STRING_INITIALIZER(struct cmd_port_representor_result,
+	action, "add#del");
+
+cmdline_parse_token_string_t cmd_portrepresentor_pf =
+TOKEN_STRING_INITIALIZER(struct cmd_port_representor_result,
+	pf, NULL);
+
+cmdline_parse_token_num_t cmd_portrepresentor_vport =
+TOKEN_NUM_INITIALIZER(struct cmd_port_representor_result,
+	vport, UINT16);
+
+static void cmd_port_representor_callback(void *parsed_result,
+		__attribute__((unused))  struct cmdline *cl,
+		__attribute__((unused)) void *data)
+{
+	struct cmd_port_representor_result *res = parsed_result;
+	uint16_t port_id;
+	int ret;
+
+	printf("%s(): action:%s addr:%s vport:%i\n", __func__,
+		res->action, res->pf, res->vport);
+	if (strcmp("add", res->action) == 0) {
+		ret = rte_representor_port_register(res->pf, res->vport,
+			&port_id);
+		if (ret != 0)
+			printf("Registering port representor failed\n");
+		else
+			printf("Port Representor registered with port id %i\n",
+				port_id);
+	} else {
+		/* assume 'del' */
+		ret = rte_representor_port_unregister(res->pf, res->vport);
+		if (ret != 0)
+			printf("Port %i is not a valid port representor.\n",
+				res->vport);
+
+	}
+}
+
+
+cmdline_parse_inst_t cmd_port_representor = {
+	.f = cmd_port_representor_callback,
+	.help_str = "port representor add|del <BusName_DomBDF> <vport_id> "
+		"Add or remove a Port Representor",
+	.data = NULL,
+	.tokens = {
+		(void *)&cmd_portrepresentor_cmd,
+		(void *)&cmd_portrepresentor_op,
+		(void *)&cmd_portrepresentor_act,
+		(void *)&cmd_portrepresentor_pf,
+		(void *)&cmd_portrepresentor_vport,
+		NULL
+	}
+};
+
+
 /* ******************************************************************************** */
 
 /* list of instructions */
@@ -15593,6 +15673,7 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *) &cmd_show_bonding_config,
 	(cmdline_parse_inst_t *) &cmd_set_bonding_primary,
 	(cmdline_parse_inst_t *) &cmd_add_bonding_slave,
+	(cmdline_parse_inst_t *) &cmd_port_representor,
 	(cmdline_parse_inst_t *) &cmd_remove_bonding_slave,
 	(cmdline_parse_inst_t *) &cmd_create_bonded_device,
 	(cmdline_parse_inst_t *) &cmd_set_bond_mac_addr,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a8b7913..15907f9 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3654,3 +3654,29 @@ Validate and create a QinQ rule on port 0 to steer traffic to a queue on the hos
    ID      Group   Prio    Attr    Rule
    0       0       0       i-      ETH VLAN VLAN=>VF QUEUE
    1       0       0       i-      ETH VLAN VLAN=>PF QUEUE
+
+Port Representors
+-----------------
+
+Adding and removal of port representors (*rte_representor*) is done via the
+``port representor add`` and ``port representor del`` commands. Once created
+these can take the same control commands as the underlying VF (Virtual
+Function).
+
+
+Adding a representor
+~~~~~~~~~~~~~~~~~~~~
+
+Adding a representor for a VF requires specifying the PF in
+``Bus_DomBDF`` format alongside the index number of the VF::
+
+   testpmd> port representor add pci_0000:81:00.0 0
+
+
+Removing a representor
+~~~~~~~~~~~~~~~~~~~~~~
+
+To remove a representor, the same parameters are required as were used to
+create it::
+
+    testpmd> port representor del pci_0000:81:00.0 0
-- 
2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-10 13:46       ` Doherty, Declan
@ 2018-01-10 19:26         ` Thomas Monjalon
  2018-01-15 12:12           ` Doherty, Declan
  0 siblings, 1 reply; 75+ messages in thread
From: Thomas Monjalon @ 2018-01-10 19:26 UTC (permalink / raw)
  To: Doherty, Declan
  Cc: Remy Horton, Mohammad Abdul Awal, dev, John McNamara, Wenzhuo Lu,
	Jingjing Wu, Alejandro Lucero, vincent.jardin

10/01/2018 14:46, Doherty, Declan:
> On 09/01/2018 11:22 PM, Thomas Monjalon wrote:
> > Hi,
> > 
> > 08/01/2018 15:37, Remy Horton:
> >> 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.
> > 
> > Extending control plane ability of DPDK has been discussed
> > multiple times.
> 
> It has, and I have yet to see a really strong reason as to why we would 
> not support control plane functions within DPDK, many of which are 
> already support today implicitly anyway through our ethdev APIs.
> 
> > The current agreed policy is:
> > "
> > The primary goal of DPDK is to provide a userspace dataplane.
> > Managing VFs from a PF driver is a control plane feature and developers
> > should generally rely on the Linux Kernel for that.
> > "
> > http://dpdk.org/doc/guides/contributing/design.html#pf-and-vf-considerations
> > 
> 
> My understanding is that this particular entry was based around the
> discussion on the divergence of functionality between the Linux kernel
> PF driver and the DPDK PF driver. I also don't really think the above
> statement is valid as a blanket statement for the project as it makes 
> the assumption that DPDK is only deployed on Linux hosts, what about 
> FreeBSD? or in the future Windows?

Yes, we must agree on removing this scope limitation while working
on a generic VF representor.

> A number of presentations at both Userspace in Dublin and the Summit
> in San Jose discussed the support of control plane functionality by
> DPDK and there wasn't any strong arguments or opposition against using
> DPDK for control plane functions that I saw.
> 
> In any case this patchset is not introducing any new control plane APIs 
> that don't already exist within DPDK today, it only enables the creation 
> of a new type of virtual PMDs which are linked to the same base 
> infrastructure and which can be used to represent VFs in a control plane 
> application as we have implemented in this patch set.
> 
> > If we relax this policy, I think the representor solution should be
> > a real port, not only "for the purposes of control and monitoring".
> > It has been asked several times as replies to this series,
> > but it is kindly ignored, saying it will be thought later.
> > 
> 
> I think we have stated in multiple discussions, especially during the
> userspace presentation back in September that this solution supports
> data path on the representors PMDs, and we have used the
> infrastructure proposed here to do exactly what you are asking. As the
> representor infrastructure doesn't preclude the support of a data
> path, we have used it as it is presented here to implement a data path 
> for exception path packets for a prototype vswitch offload implementation.
> 
> 
> > I don't see a general agreement on this series so far.
> > 
> 
> I think the main issue of contention is that there is a
> misunderstanding that this implementation only supports control plane
> management and monitoring, but that is not the case and it can be used
> for full data path representors, with limited or no control plane
> functionality if required, at the end of the day the only limitations
> are based on what is implemented by the backend base driver were the 
> broker is running for the representor ports.

The misunderstanding may originates from what you describe (even in v5):
"ports for the purposes of control and monitoring"

I think everybody agree to have VF representors in DPDK.
But there are few things which are not generic enough,
and not easy to use.
I hoped the discussion started at Dublin would continue
on the mailing list but I realize the joint effort with other vendors
did not happen.
I will elaborate quickly below and more detailed in later review.

1/ In order to keep track of the relations between PF, VF and
representor - which are all ethdev - you create a struct outside
of ethdev. I think it should be managed inside ethdev API.
As suggested by others, we could also think whether a switchdev API
is interesting or not.

2/ You create a new library for ethdev device management.
It is the responsibility of the bus to scan and probe devices.
In Intel case, the representor has no real bus so it must rely on
the vdev bus. Note that the new custom scan hook may help.
In Mellanox case, the representor already exists in Linux, and is based
on PCI bus.
Then, as any other port, it must be managed with whitelist or blacklist.

2-bis/ Minor comments about this lib:
	- it is not convenient to ask user or app to enable it
	- it is not using dynamic logging

3/ You are using PCI address + index to identify the representor.
It is a no-go. We have made effort to abstract buses.
As an idea, the identification of a representor could use the new
proposed flexible device syntax.

4/ Such new API must be experimental.

I propose to better think the representor API inside ethdev
with a good multi-vendor collaboration,
and submit a deprecation notice for 18.05 integration.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
                       ` (7 preceding siblings ...)
  2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
@ 2018-01-11  3:18     ` Yuanhan Liu
  2018-01-11  8:37       ` Alex Rosenbaum
  2018-01-11  9:38       ` Remy Horton
  8 siblings, 2 replies; 75+ messages in thread
From: Yuanhan Liu @ 2018-01-11  3:18 UTC (permalink / raw)
  To: Remy Horton
  Cc: dev, John McNamara, Wenzhuo Lu, Jingjing Wu, Thomas Monjalon,
	Shahaf Shuler, Olga Shern, Alex Rosenbaum

On Mon, Jan 08, 2018 at 02:37:15PM +0000, 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.

Firstly, I don't object this model. More precisely, I don't object for
introducing a port to control the VFs. I even like this idea a bit, for
at least it could get rid of some PMD specific APIs, say
rte_pmd_i40e_set_vf_mac_addr, etc.

However, I don't quite like this design, for a simple reason, it makes
things way more complex:

- new APIs are introduced.
- new virtual PMD is required
- broker concept


I was thinking below should work:

- Use the devargs for enabling the port (or VF) representor model.
  For example: -w 04:00.0,vf_ports=0-3

  The vf_ports is for telling the driver we are going to create VF
  representors for VF 0 to VF 3. It could be a port mask like what
  this patchset does.

- Then inside the driver (say, i40e)

  * allocate 1 DPDK ethdev port
  * allocate 4 DPDK ethdev port, one for each VF specified by
    the vf_ports option. And these are VF representors.
  * link the VF representors to the right VF port
    For example, for i40e, it should be (from patch 3):
        vf = &pf->vfs[representor->vport_id];
  * set the proper ethdev callbacks for the VF representors.

As you can see, none of above complexity is introduced.

Probably you might find something are missing:

- to identify the vf rep port for a specific VF.

  Which could be addressed by the new devargs syntax we are proposing:
  http://dpdk.org/ml/archives/dev/2017-December/084234.html

  For example, the right VF rep port could be identified by below devarg:
      bus=pci,id=04:00.0/class=eth,vf_id=0

- the ability of hotplug

  I think it could also be addressed by the new devargs syntax, also by
  re-using the rte_eth_dev_attach() function:

      rte_eth_dev_attach("bus=pci,id=04:00.0/class=eth,vf_id=4", &port_id);
  

Thoughts?

	--yliu
> 
> +-----------------------------+   +---------------+  +---------------+
> |        Control Plane        |   |   Data Plane  |  |   Data Plane  |
> |         Application         |   |   Application |  |   Application |
> +-----------------------------+   +---------------+  +---------------+
> |         eth dev api         |   |  eth dev api  |  |  eth dev api  |
> +-----------------------------+   +---------------+  +---------------+
> +-------+  +-------+  +-------+   +---------------+  +---------------+
> |  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
> |  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
> |       |  | PMD   |  | PMD   |                             |
> +---+--^+  +-------+  +-+-----+                             |
>     |  |                |  |                                |
>     |  +----------------+  |                                |
>     |                      |                                |
>     |                      |                                |
> +--------------------------------+                          |
> |   |  HW (logical view)   |     |                          |
> | --+------+ +-------+ +---+---+ |                          |
> | |   PF   | |  VF0  | |  VF1  | |                          |
> | |        | |       | |       +----------------------------+
> | +--------+ +-------+ +-------+ |
> | +----------------------------+ |
> | |        VEB                 | |
> | +----------------------------+ |
> | +--------+                     |
> | |  Port  |                     |
> | |   0    |                     |
> | +--------+                     |
> +--------------------------------+
> 
> The figure above shows a deployment where the PF is bound to a DPDK control
> plane application which uses representor ports to manage the configuration and
> monitoring of it's VF ports. Each virtual function is represented in the
> application by a representor port PMD which enables control of the corresponding
> VF through eth dev APIs on the representor PMD such as:
> 
> - void rte_eth_promiscuous_enable(uint8_t port_id);
> - void rte_eth_promiscuous_disable(uint8_t port_id);
> - void rte_eth_allmulticast_enable(uint8_t port_id);
> - void rte_eth_allmulticast_disable(uint8_t port_id);
> - int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
> 	uint32_t pool);
> - int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);
> 
> as well as monitoring through API's like
> 
> - void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
> - int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
> 
> The port representor infrastructure is enabled through a single common, device
> independent, virtual PMD whos context is initialized and enabled through a
> broker instance running within the context of the physical function device
> driver.
> 
> +-------------------------+       +-------------------------+
> |        rte_ethdev       |       |       rte_ethdev        |
> +-------------------------+       +-------------------------+
> |  Physical Function PMD  |       |  Port Reperesentor PMD  |
> |         +-------------+ |       | +---------+ +---------+ |
> |         | Representor | |       | | dev_data| | dev_ops | |
> |         |    Broker   | |       | +----+----+ +----+----+ |
> |         | +---------+ | |       +------|-----------|------+
> |         | | VF Port | | |              |           |
> |         | | Context +------------------+           |
> |         | +---------+ | |                          |
> |         | +---------+ | |                          |
> |         | | Handler +------------------------------+
> |         | |   Ops   | | |
> |         | +---------+ | |
> |         +-------------+ |
> +-------------------------+
> 
> Creation of representor ports can be achieved either through the --vdev EAL
> option or through the rte_vdev_init() API. Each port representor requires the
> BDF of it's parent PF and the Virtual Function ID of the port which the
> representor will support. During initialization of the representor PMD, it calls
> the broker API to register itself with the PF PMD and to get it's context
> configured which includes the setting up of it's context and ops function
> handlers.
> 
> As the port representor model is based around the paradigm of using standard
> port based APIs, it will allow future expansion of functionality without the
> need to add new APIs. For example it should be possible to support configuration
> of egress QoS parameters using existing TM APIs by extending the port
> representor PMD/broker infrastructure.
> 
> Changes in v2:
> * Rebased to DPDK 17.11
> 
> Changes in v3:
> * Removed RTE_ETH_DEV_REPRESENTOR_PORT define
> * Removed switch_domain from struct rte_eth_dev_info
>   (to be reintroduced seperately when required).
> * Port Representor PMD functionality merged into main library
> * Removed functions from .map file that are not for use by applications
> * Some minor bugfixes (uninitalised variables & NULL terminators)
> * Use of SPDX licence headers in new files
> * Seperate headers for PMD and application
> * SPDX-License-Identifier in new files
> * Added test-pmd representor add/del commands
> 
> Changes in v4:
> * Added documentation
> * Rebased to a12f22678915
> 
> 
> Remy Horton (5):
>   lib: add Port Representor library
>   eal: add Port Representor command-line option
>   drivers/net/i40e: add Port Representor functionality
>   drivers/net/ixgbe: add Port Representor functionality
>   app/test-pmd: add Port Representor commands
> 
>  MAINTAINERS                                        |  12 +-
>  app/test-pmd/cmdline.c                             |  88 ++++
>  config/common_base                                 |   5 +
>  doc/api/doxy-api-index.md                          |   3 +-
>  doc/api/doxy-api.conf                              |   1 +
>  doc/guides/prog_guide/index.rst                    |   1 +
>  doc/guides/prog_guide/representor_lib.rst          |  62 +++
>  doc/guides/rel_notes/release_18_02.rst             |   9 +
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  25 ++
>  drivers/net/i40e/Makefile                          |   1 +
>  drivers/net/i40e/i40e_ethdev.c                     |  16 +
>  drivers/net/i40e/i40e_ethdev.h                     |   1 +
>  drivers/net/i40e/i40e_prep_ops.c                   | 495 +++++++++++++++++++++
>  drivers/net/i40e/i40e_prep_ops.h                   |  15 +
>  drivers/net/i40e/rte_pmd_i40e.c                    |  47 ++
>  drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
>  drivers/net/ixgbe/Makefile                         |   1 +
>  drivers/net/ixgbe/ixgbe_ethdev.c                   |  22 +-
>  drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
>  drivers/net/ixgbe/ixgbe_prep_ops.c                 | 259 +++++++++++
>  drivers/net/ixgbe/ixgbe_prep_ops.h                 |  15 +
>  lib/Makefile                                       |   3 +
>  lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
>  lib/librte_eal/common/eal_common_options.c         |   1 +
>  lib/librte_eal/common/eal_internal_cfg.h           |   2 +
>  lib/librte_eal/common/eal_options.h                |   2 +
>  lib/librte_eal/common/include/rte_eal.h            |   8 +
>  lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
>  lib/librte_representor/Makefile                    |  26 ++
>  lib/librte_representor/rte_port_representor.c      | 326 ++++++++++++++
>  lib/librte_representor/rte_port_representor.h      |  60 +++
>  .../rte_port_representor_driver.h                  | 138 ++++++
>  .../rte_port_representor_version.map               |   8 +
>  mk/rte.app.mk                                      |   1 +
>  34 files changed, 1688 insertions(+), 3 deletions(-)
>  create mode 100644 doc/guides/prog_guide/representor_lib.rst
>  create mode 100644 drivers/net/i40e/i40e_prep_ops.c
>  create mode 100644 drivers/net/i40e/i40e_prep_ops.h
>  create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
>  create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h
>  create mode 100644 lib/librte_representor/Makefile
>  create mode 100644 lib/librte_representor/rte_port_representor.c
>  create mode 100644 lib/librte_representor/rte_port_representor.h
>  create mode 100644 lib/librte_representor/rte_port_representor_driver.h
>  create mode 100644 lib/librte_representor/rte_port_representor_version.map
> 
> -- 
> 2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-11  3:18     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Yuanhan Liu
@ 2018-01-11  8:37       ` Alex Rosenbaum
  2018-01-11  9:38       ` Remy Horton
  1 sibling, 0 replies; 75+ messages in thread
From: Alex Rosenbaum @ 2018-01-11  8:37 UTC (permalink / raw)
  To: Yuanhan Liu
  Cc: Remy Horton, DPDK, John McNamara, Wenzhuo Lu, Jingjing Wu,
	Thomas Monjalon, Shahaf Shuler, Olga Shern, Alex Rosenbaum

Declan,

In all previous series I explained my objection for using the broker
framework for holding the VF rep port.
You guys just waved it away (and sent a new series) instead of really
giving a clear reason why they are required.

I think Yuanhan's suggestion gets ride of the broker model in a clean way.
It exposes the VF rep's and keeps much similar to port model to allow
both control and second phase data path. The flow steering actions
suggestion match much nicer with this as well.

PS: me and Yuanhan did exchange ideas regarding this previously, so
it's not surprising I agree with his suggestion.

Alex


On Thu, Jan 11, 2018 at 5:18 AM, Yuanhan Liu <yliu@fridaylinux.org> wrote:
> On Mon, Jan 08, 2018 at 02:37:15PM +0000, 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.
>
> Firstly, I don't object this model. More precisely, I don't object for
> introducing a port to control the VFs. I even like this idea a bit, for
> at least it could get rid of some PMD specific APIs, say
> rte_pmd_i40e_set_vf_mac_addr, etc.
>
> However, I don't quite like this design, for a simple reason, it makes
> things way more complex:
>
> - new APIs are introduced.
> - new virtual PMD is required
> - broker concept
>
>
> I was thinking below should work:
>
> - Use the devargs for enabling the port (or VF) representor model.
>   For example: -w 04:00.0,vf_ports=0-3
>
>   The vf_ports is for telling the driver we are going to create VF
>   representors for VF 0 to VF 3. It could be a port mask like what
>   this patchset does.
>
> - Then inside the driver (say, i40e)
>
>   * allocate 1 DPDK ethdev port
>   * allocate 4 DPDK ethdev port, one for each VF specified by
>     the vf_ports option. And these are VF representors.
>   * link the VF representors to the right VF port
>     For example, for i40e, it should be (from patch 3):
>         vf = &pf->vfs[representor->vport_id];
>   * set the proper ethdev callbacks for the VF representors.
>
> As you can see, none of above complexity is introduced.
>
> Probably you might find something are missing:
>
> - to identify the vf rep port for a specific VF.
>
>   Which could be addressed by the new devargs syntax we are proposing:
>   http://dpdk.org/ml/archives/dev/2017-December/084234.html
>
>   For example, the right VF rep port could be identified by below devarg:
>       bus=pci,id=04:00.0/class=eth,vf_id=0
>
> - the ability of hotplug
>
>   I think it could also be addressed by the new devargs syntax, also by
>   re-using the rte_eth_dev_attach() function:
>
>       rte_eth_dev_attach("bus=pci,id=04:00.0/class=eth,vf_id=4", &port_id);
>
>
> Thoughts?
>
>         --yliu
>>
>> +-----------------------------+   +---------------+  +---------------+
>> |        Control Plane        |   |   Data Plane  |  |   Data Plane  |
>> |         Application         |   |   Application |  |   Application |
>> +-----------------------------+   +---------------+  +---------------+
>> |         eth dev api         |   |  eth dev api  |  |  eth dev api  |
>> +-----------------------------+   +---------------+  +---------------+
>> +-------+  +-------+  +-------+   +---------------+  +---------------+
>> |  PF0  |  | Port  |  | Port  |   |    VF0 PMD    |  |    VF0 PMD    |
>> |  PMD  <--+ Rep 0 |  | Rep 1 |   +---------------+  +------+--------+
>> |       |  | PMD   |  | PMD   |                             |
>> +---+--^+  +-------+  +-+-----+                             |
>>     |  |                |  |                                |
>>     |  +----------------+  |                                |
>>     |                      |                                |
>>     |                      |                                |
>> +--------------------------------+                          |
>> |   |  HW (logical view)   |     |                          |
>> | --+------+ +-------+ +---+---+ |                          |
>> | |   PF   | |  VF0  | |  VF1  | |                          |
>> | |        | |       | |       +----------------------------+
>> | +--------+ +-------+ +-------+ |
>> | +----------------------------+ |
>> | |        VEB                 | |
>> | +----------------------------+ |
>> | +--------+                     |
>> | |  Port  |                     |
>> | |   0    |                     |
>> | +--------+                     |
>> +--------------------------------+
>>
>> The figure above shows a deployment where the PF is bound to a DPDK control
>> plane application which uses representor ports to manage the configuration and
>> monitoring of it's VF ports. Each virtual function is represented in the
>> application by a representor port PMD which enables control of the corresponding
>> VF through eth dev APIs on the representor PMD such as:
>>
>> - void rte_eth_promiscuous_enable(uint8_t port_id);
>> - void rte_eth_promiscuous_disable(uint8_t port_id);
>> - void rte_eth_allmulticast_enable(uint8_t port_id);
>> - void rte_eth_allmulticast_disable(uint8_t port_id);
>> - int rte_eth_dev_mac_addr_add(uint8_t port, struct ether_addr *mac_addr,
>>       uint32_t pool);
>> - int rte_eth_dev_set_vlan_offload(uint8_t port_id, int offload_mask);
>>
>> as well as monitoring through API's like
>>
>> - void rte_eth_link_get(uint8_t port_id, struct rte_eth_link *link);
>> - int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
>>
>> The port representor infrastructure is enabled through a single common, device
>> independent, virtual PMD whos context is initialized and enabled through a
>> broker instance running within the context of the physical function device
>> driver.
>>
>> +-------------------------+       +-------------------------+
>> |        rte_ethdev       |       |       rte_ethdev        |
>> +-------------------------+       +-------------------------+
>> |  Physical Function PMD  |       |  Port Reperesentor PMD  |
>> |         +-------------+ |       | +---------+ +---------+ |
>> |         | Representor | |       | | dev_data| | dev_ops | |
>> |         |    Broker   | |       | +----+----+ +----+----+ |
>> |         | +---------+ | |       +------|-----------|------+
>> |         | | VF Port | | |              |           |
>> |         | | Context +------------------+           |
>> |         | +---------+ | |                          |
>> |         | +---------+ | |                          |
>> |         | | Handler +------------------------------+
>> |         | |   Ops   | | |
>> |         | +---------+ | |
>> |         +-------------+ |
>> +-------------------------+
>>
>> Creation of representor ports can be achieved either through the --vdev EAL
>> option or through the rte_vdev_init() API. Each port representor requires the
>> BDF of it's parent PF and the Virtual Function ID of the port which the
>> representor will support. During initialization of the representor PMD, it calls
>> the broker API to register itself with the PF PMD and to get it's context
>> configured which includes the setting up of it's context and ops function
>> handlers.
>>
>> As the port representor model is based around the paradigm of using standard
>> port based APIs, it will allow future expansion of functionality without the
>> need to add new APIs. For example it should be possible to support configuration
>> of egress QoS parameters using existing TM APIs by extending the port
>> representor PMD/broker infrastructure.
>>
>> Changes in v2:
>> * Rebased to DPDK 17.11
>>
>> Changes in v3:
>> * Removed RTE_ETH_DEV_REPRESENTOR_PORT define
>> * Removed switch_domain from struct rte_eth_dev_info
>>   (to be reintroduced seperately when required).
>> * Port Representor PMD functionality merged into main library
>> * Removed functions from .map file that are not for use by applications
>> * Some minor bugfixes (uninitalised variables & NULL terminators)
>> * Use of SPDX licence headers in new files
>> * Seperate headers for PMD and application
>> * SPDX-License-Identifier in new files
>> * Added test-pmd representor add/del commands
>>
>> Changes in v4:
>> * Added documentation
>> * Rebased to a12f22678915
>>
>>
>> Remy Horton (5):
>>   lib: add Port Representor library
>>   eal: add Port Representor command-line option
>>   drivers/net/i40e: add Port Representor functionality
>>   drivers/net/ixgbe: add Port Representor functionality
>>   app/test-pmd: add Port Representor commands
>>
>>  MAINTAINERS                                        |  12 +-
>>  app/test-pmd/cmdline.c                             |  88 ++++
>>  config/common_base                                 |   5 +
>>  doc/api/doxy-api-index.md                          |   3 +-
>>  doc/api/doxy-api.conf                              |   1 +
>>  doc/guides/prog_guide/index.rst                    |   1 +
>>  doc/guides/prog_guide/representor_lib.rst          |  62 +++
>>  doc/guides/rel_notes/release_18_02.rst             |   9 +
>>  doc/guides/testpmd_app_ug/testpmd_funcs.rst        |  25 ++
>>  drivers/net/i40e/Makefile                          |   1 +
>>  drivers/net/i40e/i40e_ethdev.c                     |  16 +
>>  drivers/net/i40e/i40e_ethdev.h                     |   1 +
>>  drivers/net/i40e/i40e_prep_ops.c                   | 495 +++++++++++++++++++++
>>  drivers/net/i40e/i40e_prep_ops.h                   |  15 +
>>  drivers/net/i40e/rte_pmd_i40e.c                    |  47 ++
>>  drivers/net/i40e/rte_pmd_i40e.h                    |  18 +
>>  drivers/net/ixgbe/Makefile                         |   1 +
>>  drivers/net/ixgbe/ixgbe_ethdev.c                   |  22 +-
>>  drivers/net/ixgbe/ixgbe_ethdev.h                   |   5 +
>>  drivers/net/ixgbe/ixgbe_prep_ops.c                 | 259 +++++++++++
>>  drivers/net/ixgbe/ixgbe_prep_ops.h                 |  15 +
>>  lib/Makefile                                       |   3 +
>>  lib/librte_eal/bsdapp/eal/eal.c                    |   6 +
>>  lib/librte_eal/common/eal_common_options.c         |   1 +
>>  lib/librte_eal/common/eal_internal_cfg.h           |   2 +
>>  lib/librte_eal/common/eal_options.h                |   2 +
>>  lib/librte_eal/common/include/rte_eal.h            |   8 +
>>  lib/librte_eal/linuxapp/eal/eal.c                  |   9 +
>>  lib/librte_representor/Makefile                    |  26 ++
>>  lib/librte_representor/rte_port_representor.c      | 326 ++++++++++++++
>>  lib/librte_representor/rte_port_representor.h      |  60 +++
>>  .../rte_port_representor_driver.h                  | 138 ++++++
>>  .../rte_port_representor_version.map               |   8 +
>>  mk/rte.app.mk                                      |   1 +
>>  34 files changed, 1688 insertions(+), 3 deletions(-)
>>  create mode 100644 doc/guides/prog_guide/representor_lib.rst
>>  create mode 100644 drivers/net/i40e/i40e_prep_ops.c
>>  create mode 100644 drivers/net/i40e/i40e_prep_ops.h
>>  create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.c
>>  create mode 100644 drivers/net/ixgbe/ixgbe_prep_ops.h
>>  create mode 100644 lib/librte_representor/Makefile
>>  create mode 100644 lib/librte_representor/rte_port_representor.c
>>  create mode 100644 lib/librte_representor/rte_port_representor.h
>>  create mode 100644 lib/librte_representor/rte_port_representor_driver.h
>>  create mode 100644 lib/librte_representor/rte_port_representor_version.map
>>
>> --
>> 2.9.5

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-11  3:18     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Yuanhan Liu
  2018-01-11  8:37       ` Alex Rosenbaum
@ 2018-01-11  9:38       ` Remy Horton
  1 sibling, 0 replies; 75+ messages in thread
From: Remy Horton @ 2018-01-11  9:38 UTC (permalink / raw)
  To: Yuanhan Liu
  Cc: dev, John McNamara, Wenzhuo Lu, Jingjing Wu, Thomas Monjalon,
	Shahaf Shuler, Olga Shern, Alex Rosenbaum


On 11/01/2018 03:18, Yuanhan Liu wrote:
[..]
> - Then inside the driver (say, i40e)
>
>   * allocate 1 DPDK ethdev port
>   * allocate 4 DPDK ethdev port, one for each VF specified by
>     the vf_ports option. And these are VF representors.
>   * link the VF representors to the right VF port
>     For example, for i40e, it should be (from patch 3):
>         vf = &pf->vfs[representor->vport_id];
>   * set the proper ethdev callbacks for the VF representors.
>
> As you can see, none of above complexity is introduced.

What springs to mind is whether this would end up delegating to the 
individual PMDs tasks that in the patchset are handled centrally in the 
library. Question is where the balance should be, and as an aside what 
should be the base-line requirements for a PMD to be "port representable".

..Remy

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-10 19:26         ` Thomas Monjalon
@ 2018-01-15 12:12           ` Doherty, Declan
  2018-01-15 16:09             ` Thomas Monjalon
  0 siblings, 1 reply; 75+ messages in thread
From: Doherty, Declan @ 2018-01-15 12:12 UTC (permalink / raw)
  To: Thomas Monjalon
  Cc: Remy Horton, Mohammad Abdul Awal, dev, John McNamara, Wenzhuo Lu,
	Jingjing Wu, Alejandro Lucero, vincent.jardin

On 10/01/2018 7:26 PM, Thomas Monjalon wrote:
> 10/01/2018 14:46, Doherty, Declan:
>> On 09/01/2018 11:22 PM, Thomas Monjalon wrote:
>>> Hi,
>>>
>>> 08/01/2018 15:37, Remy Horton:
>>>> 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.
>>>
>>> Extending control plane ability of DPDK has been discussed
>>> multiple times.
>>
>> It has, and I have yet to see a really strong reason as to why we would
>> not support control plane functions within DPDK, many of which are
>> already support today implicitly anyway through our ethdev APIs.
>>
>>> The current agreed policy is:
>>> "
>>> The primary goal of DPDK is to provide a userspace dataplane.
>>> Managing VFs from a PF driver is a control plane feature and developers
>>> should generally rely on the Linux Kernel for that.
>>> "
>>> http://dpdk.org/doc/guides/contributing/design.html#pf-and-vf-considerations
>>>
>>
>> My understanding is that this particular entry was based around the
>> discussion on the divergence of functionality between the Linux kernel
>> PF driver and the DPDK PF driver. I also don't really think the above
>> statement is valid as a blanket statement for the project as it makes
>> the assumption that DPDK is only deployed on Linux hosts, what about
>> FreeBSD? or in the future Windows?
> 
> Yes, we must agree on removing this scope limitation while working
> on a generic VF representor.
> 
>> A number of presentations at both Userspace in Dublin and the Summit
>> in San Jose discussed the support of control plane functionality by
>> DPDK and there wasn't any strong arguments or opposition against using
>> DPDK for control plane functions that I saw.
>>
>> In any case this patchset is not introducing any new control plane APIs
>> that don't already exist within DPDK today, it only enables the creation
>> of a new type of virtual PMDs which are linked to the same base
>> infrastructure and which can be used to represent VFs in a control plane
>> application as we have implemented in this patch set.
>>
>>> If we relax this policy, I think the representor solution should be
>>> a real port, not only "for the purposes of control and monitoring".
>>> It has been asked several times as replies to this series,
>>> but it is kindly ignored, saying it will be thought later.
>>>
>>
>> I think we have stated in multiple discussions, especially during the
>> userspace presentation back in September that this solution supports
>> data path on the representors PMDs, and we have used the
>> infrastructure proposed here to do exactly what you are asking. As the
>> representor infrastructure doesn't preclude the support of a data
>> path, we have used it as it is presented here to implement a data path
>> for exception path packets for a prototype vswitch offload implementation.
>>
>>
>>> I don't see a general agreement on this series so far.
>>>
>>
>> I think the main issue of contention is that there is a
>> misunderstanding that this implementation only supports control plane
>> management and monitoring, but that is not the case and it can be used
>> for full data path representors, with limited or no control plane
>> functionality if required, at the end of the day the only limitations
>> are based on what is implemented by the backend base driver were the
>> broker is running for the representor ports.
> 
> The misunderstanding may originates from what you describe (even in v5):
> "ports for the purposes of control and monitoring"
> 
noted, but that is the scope of what we demostrate in the patchset, but 
we'll update the introduction to reflect the fact that they can be used 
to also support data path functions, such as exception path traffic for 
hw switch.

> I think everybody agree to have VF representors in DPDK.
> But there are few things which are not generic enough,
> and not easy to use.
> I hoped the discussion started at Dublin would continue
> on the mailing list but I realize the joint effort with other vendors
> did not happen.
> I will elaborate quickly below and more detailed in later review.
> 
> 1/ In order to keep track of the relations between PF, VF and
> representor - which are all ethdev - you create a struct outside
> of ethdev. I think it should be managed inside ethdev API.

Initially we had implemented the representor functionality within the 
context of the ethdev library but ran into a number of scenarios where 
this didn't work well as it makes the assumption that the base device 
that the representors are attached to is always an ethdev, we ran into 
cases were the PF isn't necessarily an ethdev, for example in some 
smartNICs the PF would be better represented by a switchdev, or it is 
possible that the device hosting the representor broker could just 
provide a conduit to a kernel driver.


> As suggested by others, we could also think whether a switchdev API
> is interesting or not.
> 

Indeed if a switchdev is something that is required by the community it 
would make sense that the representor infrastructure was initialized 
within the switchdev and not an ethdev. The advantage of keeping the 
representor infrastructure independent is that it gives the flexibility 
for representors to be supported independently of device type they are 
attached to.

> 2/ You create a new library for ethdev device management.
> It is the responsibility of the bus to scan and probe devices.
> In Intel case, the representor has no real bus so it must rely on
> the vdev bus. Note that the new custom scan hook may help.

This isn't the case in latest versions of the patchset, the bus the 
representors are dependent on is that of the base device, so for the 
i40e it's the PF PCI device.

> In Mellanox case, the representor already exists in Linux, and is based
> on PCI bus.
> Then, as any other port, it must be managed with whitelist or blacklist.
> 

I think the suggestion by Yuanhan of using the device whitelist command 
option makes sense as a option from the commandline, but it would 
require the newly propose implementation which allows specification of 
both the bus and device as not all devices are PCI, which have multiple 
host ports using SR-IOV, but there are cases when an dynamic 
creation/destruction of ports may also need to be supported, which is 
what the representor APIs support.


> 2-bis/ Minor comments about this lib:
> 	- it is not convenient to ask user or app to enable it

I have no problem removing this EAL option.

> 	- it is not using dynamic logging

We will address this in the next revision

> 
> 3/ You are using PCI address + index to identify the representor.
> It is a no-go. We have made effort to abstract buses.
> As an idea, the identification of a representor could use the new
> proposed flexible device syntax.
> 

We are currently using net_representor_%bus%_%device_id%_%vport_id% to 
identify each representor device but I have no issue changing to either 
the current convention which would be net_representor_%unique_id% or if 
I understand the proposal in the RFC "ether: standardize getting the 
port by name" we would be using something like,

we should be looking at something along the lines of 
net_%bus%_%device_id%_%port_id% which is pretty close to what we are 
using now.

In terms of that RFC I'm not clear on if the proposal is just to affect 
the API for getting a port by name, or actually the name name assigned 
to the device itself.


> 4/ Such new API must be experimental.
> 

We will address this in the next revision


> I propose to better think the representor API inside ethdev
> with a good multi-vendor collaboration,
> and submit a deprecation notice for 18.05 integration.
> 

I would really like to see this included as experimental in 18.02 
release, if it is agreed by the community that we need to re-integate 
the representor concept into librte_ethdev during for 18.05 we will 
support that work.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors
  2018-01-15 12:12           ` Doherty, Declan
@ 2018-01-15 16:09             ` Thomas Monjalon
  0 siblings, 0 replies; 75+ messages in thread
From: Thomas Monjalon @ 2018-01-15 16:09 UTC (permalink / raw)
  To: Doherty, Declan
  Cc: Remy Horton, Mohammad Abdul Awal, dev, John McNamara, Wenzhuo Lu,
	Jingjing Wu, Alejandro Lucero, vincent.jardin, yuanhanl, alexr

15/01/2018 13:12, Doherty, Declan:
> On 10/01/2018 7:26 PM, Thomas Monjalon wrote:
> > 10/01/2018 14:46, Doherty, Declan:
> >> On 09/01/2018 11:22 PM, Thomas Monjalon wrote:
> >>> Hi,
> >>>
> >>> 08/01/2018 15:37, Remy Horton:
> >>>> 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.
> >>>
> >>> Extending control plane ability of DPDK has been discussed
> >>> multiple times.
> >>
> >> It has, and I have yet to see a really strong reason as to why we would
> >> not support control plane functions within DPDK, many of which are
> >> already support today implicitly anyway through our ethdev APIs.
> >>
> >>> The current agreed policy is:
> >>> "
> >>> The primary goal of DPDK is to provide a userspace dataplane.
> >>> Managing VFs from a PF driver is a control plane feature and developers
> >>> should generally rely on the Linux Kernel for that.
> >>> "
> >>> http://dpdk.org/doc/guides/contributing/design.html#pf-and-vf-considerations
> >>>
> >>
> >> My understanding is that this particular entry was based around the
> >> discussion on the divergence of functionality between the Linux kernel
> >> PF driver and the DPDK PF driver. I also don't really think the above
> >> statement is valid as a blanket statement for the project as it makes
> >> the assumption that DPDK is only deployed on Linux hosts, what about
> >> FreeBSD? or in the future Windows?
> > 
> > Yes, we must agree on removing this scope limitation while working
> > on a generic VF representor.
> > 
> >> A number of presentations at both Userspace in Dublin and the Summit
> >> in San Jose discussed the support of control plane functionality by
> >> DPDK and there wasn't any strong arguments or opposition against using
> >> DPDK for control plane functions that I saw.
> >>
> >> In any case this patchset is not introducing any new control plane APIs
> >> that don't already exist within DPDK today, it only enables the creation
> >> of a new type of virtual PMDs which are linked to the same base
> >> infrastructure and which can be used to represent VFs in a control plane
> >> application as we have implemented in this patch set.
> >>
> >>> If we relax this policy, I think the representor solution should be
> >>> a real port, not only "for the purposes of control and monitoring".
> >>> It has been asked several times as replies to this series,
> >>> but it is kindly ignored, saying it will be thought later.
> >>>
> >>
> >> I think we have stated in multiple discussions, especially during the
> >> userspace presentation back in September that this solution supports
> >> data path on the representors PMDs, and we have used the
> >> infrastructure proposed here to do exactly what you are asking. As the
> >> representor infrastructure doesn't preclude the support of a data
> >> path, we have used it as it is presented here to implement a data path
> >> for exception path packets for a prototype vswitch offload implementation.
> >>
> >>
> >>> I don't see a general agreement on this series so far.
> >>>
> >>
> >> I think the main issue of contention is that there is a
> >> misunderstanding that this implementation only supports control plane
> >> management and monitoring, but that is not the case and it can be used
> >> for full data path representors, with limited or no control plane
> >> functionality if required, at the end of the day the only limitations
> >> are based on what is implemented by the backend base driver were the
> >> broker is running for the representor ports.
> > 
> > The misunderstanding may originates from what you describe (even in v5):
> > "ports for the purposes of control and monitoring"
> > 
> noted, but that is the scope of what we demostrate in the patchset, but 
> we'll update the introduction to reflect the fact that they can be used 
> to also support data path functions, such as exception path traffic for 
> hw switch.
> 
> > I think everybody agree to have VF representors in DPDK.
> > But there are few things which are not generic enough,
> > and not easy to use.
> > I hoped the discussion started at Dublin would continue
> > on the mailing list but I realize the joint effort with other vendors
> > did not happen.
> > I will elaborate quickly below and more detailed in later review.
> > 
> > 1/ In order to keep track of the relations between PF, VF and
> > representor - which are all ethdev - you create a struct outside
> > of ethdev. I think it should be managed inside ethdev API.
> 
> Initially we had implemented the representor functionality within the 
> context of the ethdev library but ran into a number of scenarios where 
> this didn't work well as it makes the assumption that the base device 
> that the representors are attached to is always an ethdev, we ran into 
> cases were the PF isn't necessarily an ethdev, for example in some 
> smartNICs the PF would be better represented by a switchdev, or it is 
> possible that the device hosting the representor broker could just 
> provide a conduit to a kernel driver.

The base device may be something else than an ethdev PF,
so it may be represented as a rte_device.
But the VF and representor are still ethdev.
I still think the relationship should be described in ethdev.

> > As suggested by others, we could also think whether a switchdev API
> > is interesting or not.
> 
> Indeed if a switchdev is something that is required by the community it 
> would make sense that the representor infrastructure was initialized 
> within the switchdev and not an ethdev. The advantage of keeping the 
> representor infrastructure independent is that it gives the flexibility 
> for representors to be supported independently of device type they are 
> attached to.

switchdev is just another device class.
We must abstract the base device as a basic EAL rte_device for now.

> > 2/ You create a new library for ethdev device management.
> > It is the responsibility of the bus to scan and probe devices.
> > In Intel case, the representor has no real bus so it must rely on
> > the vdev bus. Note that the new custom scan hook may help.
> 
> This isn't the case in latest versions of the patchset, the bus the 
> representors are dependent on is that of the base device, so for the 
> i40e it's the PF PCI device.

I'm suggesting to use vdev as bus of i40e representor,
because there is no PCI identifier for them, right?

> > In Mellanox case, the representor already exists in Linux, and is based
> > on PCI bus.
> > Then, as any other port, it must be managed with whitelist or blacklist.
> 
> I think the suggestion by Yuanhan of using the device whitelist command 
> option makes sense as a option from the commandline, but it would 
> require the newly propose implementation which allows specification of 
> both the bus and device as not all devices are PCI, which have multiple 
> host ports using SR-IOV, but there are cases when an dynamic 
> creation/destruction of ports may also need to be supported, which is 
> what the representor APIs support.

The full proposed syntax of device identification is:
	http://dpdk.org/ml/archives/dev/2017-December/084572.html
With this generic syntax, we can describe port representors and request
their initialization via whitelisting.

[...]
> > 3/ You are using PCI address + index to identify the representor.
> > It is a no-go. We have made effort to abstract buses.
> > As an idea, the identification of a representor could use the new
> > proposed flexible device syntax.
> 
> We are currently using net_representor_%bus%_%device_id%_%vport_id% to 
> identify each representor device but I have no issue changing to either 
> the current convention which would be net_representor_%unique_id% or if 
> I understand the proposal in the RFC "ether: standardize getting the 
> port by name" we would be using something like,
> we should be looking at something along the lines of 
> net_%bus%_%device_id%_%port_id% which is pretty close to what we are 
> using now.

It is introducing yet another syntax.
It would be better to align every device identification usages
on a common and standard syntax.
Then the syntax parsing will be done in bus and libs (e.g. ethdev)
with some helper functions which can be re-used for every usages.
The latest version of representors is using direct PCI parsing instead
of relying on some bus or ethdev helpers.

> In terms of that RFC I'm not clear on if the proposal is just to affect 
> the API for getting a port by name, or actually the name name assigned 
> to the device itself.

It is not about the name. It is a proposal of syntax to describe a
resource of a hardware device, or a virtual device.
The most obvious usage is to replace -w/-b and --vdev.
It can also be used in OVS or any other DPDK configuration.

> > 4/ Such new API must be experimental.
> 
> We will address this in the next revision
> 
> > I propose to better think the representor API inside ethdev
> > with a good multi-vendor collaboration,
> > and submit a deprecation notice for 18.05 integration.
> 
> I would really like to see this included as experimental in 18.02 
> release, if it is agreed by the community that we need to re-integate 
> the representor concept into librte_ethdev during for 18.05 we will 
> support that work.

I don't see the benefit of introducing a lib and a syntax which would
be replaced in the next release.

^ permalink raw reply	[flat|nested] 75+ messages in thread

* Re: [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library
  2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
@ 2018-01-30  9:23         ` Andrew Rybchenko
  0 siblings, 0 replies; 75+ messages in thread
From: Andrew Rybchenko @ 2018-01-30  9:23 UTC (permalink / raw)
  To: Remy Horton, dev; +Cc: John McNamara, Declan Doherty, Mohammad Abdul Awal

On 01/10/2018 06:54 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>
> ---
>   MAINTAINERS                                        |   9 +-
>   config/common_base                                 |   5 +
>   doc/api/doxy-api-index.md                          |   1 +
>   doc/api/doxy-api.conf                              |   1 +
>   doc/guides/prog_guide/index.rst                    |   1 +
>   doc/guides/prog_guide/representor_lib.rst          |  62 ++++
>   doc/guides/rel_notes/release_18_02.rst             |  10 +
>   lib/Makefile                                       |   3 +
>   lib/librte_eal/common/eal_common_log.c             |   1 +
>   lib/librte_eal/common/include/rte_log.h            |   1 +
>   lib/librte_representor/Makefile                    |  26 ++
>   lib/librte_representor/rte_port_representor.c      | 345 +++++++++++++++++++++
>   lib/librte_representor/rte_port_representor.h      |  60 ++++
>   .../rte_port_representor_driver.h                  | 140 +++++++++
>   .../rte_port_representor_version.map               |   8 +
>   mk/rte.app.mk                                      |   1 +
>   16 files changed, 673 insertions(+), 1 deletion(-)
>   create mode 100644 doc/guides/prog_guide/representor_lib.rst
>   create mode 100644 lib/librte_representor/Makefile
>   create mode 100644 lib/librte_representor/rte_port_representor.c
>   create mode 100644 lib/librte_representor/rte_port_representor.h
>   create mode 100644 lib/librte_representor/rte_port_representor_driver.h
>   create mode 100644 lib/librte_representor/rte_port_representor_version.map

It look like it deserves an entry in the doc/guides/nics/features.

Also right now it is bound to rte_eth_dev inside, but does not bound to
ethdev outside (API, naming).  May be it is really good since it could be
useful to other cases of VFs (not networking).

Ideally it should use dynamic logging from the very beginning.

Also there is a work to standardize device identification in current
release cycle. I think it would be good if the first argument of
rte_representor_register/unregister() follow it (right now it is
something like pci_0000:01:00.1). May be it is not a problem to
change it in the next release cycle if the API is EXPERIMENTAL.

Wouldn't it be easier for user if register/unregister gets VFs
device string on input (not PF string plus VF number).
It is just a question and I'd like to know your thoughts on it.

<...>

> diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
> new file mode 100644
> index 0000000..b26600c
> --- /dev/null
> +++ b/lib/librte_representor/rte_port_representor_version.map
> @@ -0,0 +1,8 @@
> +DPDK_18.02 {
> +	global:
> +
> +	rte_representor_port_register;
> +	rte_representor_port_unregister;
> +
> +	local: *;
> +};

As I understand it should be EXPERIMENTAL (with __rte_experimental and
EXPERIMENTAL marks in the doxygen documentation as well).

<...>

Acked-by: Andrew Rybchenko <arybchenko@solarflare.com>

^ permalink raw reply	[flat|nested] 75+ messages in thread

end of thread, other threads:[~2018-01-30  9:23 UTC | newest]

Thread overview: 75+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-17 14:42 [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs Mohammad Abdul Awal
2017-11-17 23:03   ` Ferruh Yigit
2017-12-08 14:57     ` Mohammad Abdul Awal
2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 3/6] eal: added --enable-representor command line argument in EAL to load representor broker infrastructure Mohammad Abdul Awal
2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 4/6] net/representor: Implement port representor PMD Mohammad Abdul Awal
2017-11-20  7:46   ` Ferruh Yigit
2017-12-08 15:02     ` Remy Horton
2017-12-08 16:56       ` Mohammad Abdul Awal
2017-12-11 10:08         ` Remy Horton
2017-12-11 15:11           ` Mohammad Abdul Awal
2017-12-11 15:29             ` Remy Horton
2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 5/6] net/i40e: Enable port representor PMD and broker for fortville PMD driver Mohammad Abdul Awal
2017-11-20  7:48   ` Ferruh Yigit
2017-11-17 14:42 ` [dpdk-dev] [PATCH v2 6/6] net/ixgbe: Enable port representor PMD and broker for ixgbe " Mohammad Abdul Awal
2017-11-20 19:57 ` [dpdk-dev] [PATCH v2 1/6] ethdev: added switch_domain and representor port flag Ferruh Yigit
2017-12-08 15:33   ` Mohammad Abdul Awal
2017-12-11 13:45     ` Alex Rosenbaum
2017-12-11 18:00       ` Mohammad Abdul Awal
2017-12-22 14:41 ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
2017-12-22 14:41   ` [dpdk-dev] [DPDK 1/5] lib: add Port Representor library Remy Horton
2017-12-22 14:41   ` [dpdk-dev] [DPDK 2/5] eal: add Port Representor command-line option Remy Horton
2017-12-22 14:41   ` [dpdk-dev] [DPDK 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
2017-12-22 14:41   ` [dpdk-dev] [DPDK 4/5] drivers/net/ixgbe: " Remy Horton
2017-12-22 14:41   ` [dpdk-dev] [DPDK 5/5] app/test-pmd: add Port Representor commands Remy Horton
2017-12-22 15:09   ` [dpdk-dev] [DPDK 0/5] lib: add Port Representors Remy Horton
2017-12-22 16:37   ` Neil Horman
2018-01-03 12:14     ` Mohammad Abdul Awal
2017-12-22 14:52 ` [dpdk-dev] [PATCH v3 " Remy Horton
2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 1/5] lib: add Port Representor library Remy Horton
2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 2/5] eal: add Port Representor command-line option Remy Horton
2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 4/5] drivers/net/ixgbe: " Remy Horton
2017-12-22 14:52   ` [dpdk-dev] [PATCH v3 5/5] app/test-pmd: add Port Representor commands Remy Horton
2017-12-26 13:54   ` [dpdk-dev] [PATCH v3 0/5] lib: add Port Representors Neil Horman
2018-01-03 12:12     ` Mohammad Abdul Awal
2018-01-08 14:37   ` [dpdk-dev] [PATCH v4 " Remy Horton
2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 1/5] lib: add Port Representor library Remy Horton
2018-01-09 22:06       ` Ferruh Yigit
2018-01-10 11:40         ` Remy Horton
2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 2/5] eal: add Port Representor command-line option Remy Horton
2018-01-09 22:07       ` Ferruh Yigit
2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
2018-01-09 22:09       ` Ferruh Yigit
2018-01-10  7:56       ` Xing, Beilei
2018-01-10 10:11         ` Mohammad Abdul Awal
2018-01-10 12:37           ` Xing, Beilei
2018-01-10 14:04             ` Mohammad Abdul Awal
2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 4/5] drivers/net/ixgbe: " Remy Horton
2018-01-08 14:37     ` [dpdk-dev] [PATCH v4 5/5] app/test-pmd: add Port Representor commands Remy Horton
2018-01-09 22:10       ` Ferruh Yigit
2018-01-10  7:22         ` Remy Horton
2018-01-09 22:01     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Ferruh Yigit
2018-01-10 14:17       ` Mohammad Abdul Awal
2018-01-09 23:22     ` Thomas Monjalon
2018-01-10 13:46       ` Doherty, Declan
2018-01-10 19:26         ` Thomas Monjalon
2018-01-15 12:12           ` Doherty, Declan
2018-01-15 16:09             ` Thomas Monjalon
2018-01-10 15:54     ` [dpdk-dev] [PATCH v5 " Remy Horton
2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
2018-01-30  9:23         ` Andrew Rybchenko
2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 2/5] eal: add Port Representor command-line option Remy Horton
2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 4/5] drivers/net/ixgbe: " Remy Horton
2018-01-10 15:54       ` [dpdk-dev] [PATCH v5 5/5] app/test-pmd: add Port Representor commands Remy Horton
2018-01-10 17:49       ` [dpdk-dev] [PATCH v5 0/5] lib: add Port Representors Remy Horton
2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 1/5] lib: add Port Representor library Remy Horton
2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 2/5] eal: add Port Representor command-line option Remy Horton
2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 3/5] drivers/net/i40e: add Port Representor functionality Remy Horton
2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 4/5] drivers/net/ixgbe: " Remy Horton
2018-01-10 17:49         ` [dpdk-dev] [PATCH v5 5/5] app/test-pmd: add Port Representor commands Remy Horton
2018-01-11  3:18     ` [dpdk-dev] [PATCH v4 0/5] lib: add Port Representors Yuanhan Liu
2018-01-11  8:37       ` Alex Rosenbaum
2018-01-11  9:38       ` Remy Horton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).