[dpdk-dev] [RFC 3/5] Implement port representor PMD

Mohammad Abdul Awal mohammad.abdul.awal at intel.com
Thu Sep 7 10:35:37 CEST 2017


Signed-off-by: Mohammad Abdul Awal <mohammad.abdul.awal at intel.com>
Signed-off-by: Remy Horton <remy.horton at intel.com>
Signed-off-by: Declan Doherty <declan.doherty at intel.com>
---
 config/common_base                                 |   5 +
 drivers/net/Makefile                               |   2 +
 drivers/net/representor/Makefile                   |  51 ++
 drivers/net/representor/rte_eth_representor.c      | 973 +++++++++++++++++++++
 .../representor/rte_pmd_representor_version.map    |   4 +
 lib/librte_ether/rte_ethdev_vdev.h                 |  37 +-
 mk/rte.app.mk                                      |   1 +
 7 files changed, 1070 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/representor/Makefile
 create mode 100644 drivers/net/representor/rte_eth_representor.c
 create mode 100644 drivers/net/representor/rte_pmd_representor_version.map

diff --git a/config/common_base b/config/common_base
index 5e97a08..d7ba871 100644
--- a/config/common_base
+++ b/config/common_base
@@ -750,3 +750,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y
 # Compile the eventdev application
 #
 CONFIG_RTE_APP_EVENTDEV=y
+
+#
+# Compile representor PMD
+#
+CONFIG_RTE_LIBRTE_PMD_REPRESENTOR=y
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index d33c959..1b76a42 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -83,6 +83,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_PCAP) += pcap
 DEPDIRS-pcap = $(core-libs)
 DIRS-$(CONFIG_RTE_LIBRTE_QEDE_PMD) += qede
 DEPDIRS-qede = $(core-libs)
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_REPRESENTOR) += representor
+DEPDIRS-representor = $(core-libs)
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_RING) += ring
 DEPDIRS-ring = $(core-libs)
 DIRS-$(CONFIG_RTE_LIBRTE_SFC_EFX_PMD) += sfc
diff --git a/drivers/net/representor/Makefile b/drivers/net/representor/Makefile
new file mode 100644
index 0000000..18b23f4
--- /dev/null
+++ b/drivers/net/representor/Makefile
@@ -0,0 +1,51 @@
+#   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)
+
+EXPORT_MAP := rte_pmd_representor_version.map
+
+LIBABIVER := 1
+
+#
+# all source are stored in SRCS-y
+#
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_REPRESENTOR) += rte_eth_representor.c
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/representor/rte_eth_representor.c b/drivers/net/representor/rte_eth_representor.c
new file mode 100644
index 0000000..cec532d
--- /dev/null
+++ b/drivers/net/representor/rte_eth_representor.c
@@ -0,0 +1,973 @@
+/*-
+ *   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_vdev.h>
+#include <rte_kvargs.h>
+#include <rte_port_representor.h>
+#include <rte_flow_driver.h>
+
+#define PORT_REP_MAX_VFS 64
+
+static struct ether_addr list_eth_addrs[PORT_REP_MAX_VFS];
+
+struct port_rep_parameters {
+	uint32_t mask;
+	uint64_t vf_mask;
+	uint8_t parent;
+};
+
+struct port_rep_internals {
+	uint8_t port_id;
+	struct port_rep_parameters params;
+	struct rte_port_representor *port_rep;
+};
+
+static struct port_rep_parameters vdev_params;
+
+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;
+}
+
+/****************************************************************************
+ * PMD operation callbacks
+ ****************************************************************************/
+
+static void
+port_rep_info(struct rte_eth_dev *dev,
+		struct rte_eth_dev_info *dev_info)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev || !dev_info)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep) {
+		RTE_LOG(ERR, PMD, "Representor PMD is NULL\n");
+		return;
+	}
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker) {
+		RTE_LOG(ERR, PMD, "Representor Broker is NULL\n");
+		return;
+	}
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->dev_infos_get);
+	repr_broker->rep_ops->dev_infos_get(repr_broker, internals->port_rep,
+		dev_info);
+}
+
+static int
+port_rep_start(struct rte_eth_dev *dev)
+{
+	if (!dev)
+		return -EINVAL;
+
+	dev->data->dev_link.link_status = ETH_LINK_UP;
+	return 0;
+}
+
+static void
+port_rep_stop(struct rte_eth_dev *dev)
+{
+	if (!dev)
+		return;
+
+	dev->data->dev_link.link_status = ETH_LINK_DOWN;
+}
+
+static int
+port_rep_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+		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)
+{
+	if (!dev || !mb_pool)
+		return -EINVAL;
+
+	if (rx_queue_id >= dev->data->nb_rx_queues)
+		return -ENODEV;
+
+	dev->data->rx_queues[rx_queue_id] = (void *)0xdeadbeef;
+
+	return 0;
+}
+
+static int
+port_rep_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+		uint16_t nb_tx_desc __rte_unused,
+		unsigned int socket_id __rte_unused,
+		const struct rte_eth_txconf *tx_conf __rte_unused)
+{
+	if (!dev)
+		return -EINVAL;
+
+	if (tx_queue_id >= dev->data->nb_tx_queues)
+		return -ENODEV;
+
+	dev->data->tx_queues[tx_queue_id] = (void *)0xdeadbeef;
+
+	return 0;
+}
+
+static void
+port_rep_queue_release(__rte_unused void *q)
+{
+}
+
+static int
+port_rep_link_update(struct rte_eth_dev *dev, int wait_to_complete)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return -EINVAL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return -ENODEV;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return -ENODEV;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->link_update, -ENOTSUP);
+
+	return repr_broker->rep_ops->link_update(repr_broker,
+		internals->port_rep, wait_to_complete);
+}
+
+static void
+port_rep_promiscuous_enable(struct rte_eth_dev *dev)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->promiscuous_enable);
+	repr_broker->rep_ops->promiscuous_enable(
+		repr_broker, internals->port_rep);
+}
+
+static void
+port_rep_promiscuous_disable(struct rte_eth_dev *dev)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->promiscuous_disable);
+	repr_broker->rep_ops->promiscuous_disable(
+		repr_broker, internals->port_rep);
+}
+
+static void
+port_rep_allmulticast_enable(struct rte_eth_dev *dev)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->allmulticast_enable);
+	repr_broker->rep_ops->allmulticast_enable(
+		repr_broker, internals->port_rep);
+}
+
+static void
+port_rep_allmulticast_disable(struct rte_eth_dev *dev)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->allmulticast_disable);
+	repr_broker->rep_ops->allmulticast_disable(
+		repr_broker, internals->port_rep);
+}
+
+static void
+port_rep_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->mac_addr_remove);
+	repr_broker->rep_ops->mac_addr_remove(
+		repr_broker, internals->port_rep, index);
+}
+
+static int
+port_rep_mac_addr_add(__rte_unused struct rte_eth_dev *dev,
+	struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return -EINVAL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return -ENODEV;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return -ENODEV;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->mac_addr_add, -ENOTSUP);
+
+	return repr_broker->rep_ops->mac_addr_add(repr_broker,
+		internals->port_rep, mac_addr, index, vmdq);
+}
+
+static void
+port_rep_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev || !mac_addr)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->mac_addr_set);
+	repr_broker->rep_ops->mac_addr_set(repr_broker, internals->port_rep,
+		mac_addr);
+}
+
+static int
+port_rep_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id,  int on)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return -EINVAL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return -ENODEV;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return -ENODEV;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->vlan_filter_set,
+		-ENOTSUP);
+	return repr_broker->rep_ops->vlan_filter_set(repr_broker,
+		internals->port_rep, vlan_id, on);
+}
+
+static int
+port_rep_vlan_tpid_set(struct rte_eth_dev *dev, enum rte_vlan_type type,
+	uint16_t tpid)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return -EINVAL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return -ENODEV;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return -ENODEV;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->vlan_tpid_set, -ENOTSUP);
+
+	return repr_broker->rep_ops->vlan_tpid_set(repr_broker,
+		internals->port_rep, type, tpid);
+}
+
+static void
+port_rep_vlan_strip_queue_set(struct rte_eth_dev *dev,
+	__rte_unused uint16_t rx_queue_id, int on)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->vlan_strip_queue_set);
+	repr_broker->rep_ops->vlan_strip_queue_set(repr_broker,
+		internals->port_rep, on);
+}
+
+static void
+port_rep_vlan_offload_set(struct rte_eth_dev *dev, int mask)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->vlan_offload_set);
+	repr_broker->rep_ops->vlan_offload_set(repr_broker,
+		internals->port_rep, mask);
+}
+
+static int
+port_rep_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t vlan_id,
+	__rte_unused int on)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return -EINVAL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return -ENODEV;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return -ENODEV;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->vlan_pvid_set, -ENOTSUP);
+
+	return repr_broker->rep_ops->vlan_pvid_set(repr_broker,
+		internals->port_rep, vlan_id);
+}
+
+static void
+port_rep_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->stats_get);
+	repr_broker->rep_ops->stats_get(repr_broker,
+		internals->port_rep, stats);
+}
+
+static void
+port_rep_stats_reset(struct rte_eth_dev *dev)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return;
+
+	RTE_FUNC_PTR_OR_RET(*repr_broker->rep_ops->stats_reset);
+	repr_broker->rep_ops->stats_reset(repr_broker,
+		internals->port_rep);
+}
+
+static int
+port_rep_flow_validate(struct rte_eth_dev *dev,
+	const struct rte_flow_attr *attr, const struct rte_flow_item pattern[],
+	const struct rte_flow_action actions[], struct rte_flow_error *error)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return -EINVAL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return -ENODEV;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return -ENODEV;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->flow_validate, -EINVAL);
+	return repr_broker->rep_ops->flow_validate(repr_broker,
+		internals->port_rep, attr, pattern, actions, error);
+}
+
+static struct rte_flow *
+port_rep_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
+	const struct rte_flow_item pattern[],
+	const struct rte_flow_action actions[], struct rte_flow_error *error)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return NULL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return NULL;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return NULL;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->flow_validate, NULL);
+	return repr_broker->rep_ops->flow_create(repr_broker,
+		internals->port_rep, attr, pattern, actions, error);
+}
+
+static int
+port_rep_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
+	struct rte_flow_error *error)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return -EINVAL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return -ENODEV;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return -ENODEV;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->flow_validate, -EINVAL);
+	return repr_broker->rep_ops->flow_destroy(repr_broker,
+		internals->port_rep, flow, error);
+}
+
+static int
+port_rep_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
+{
+	struct port_rep_internals *internals;
+	struct rte_port_representor_broker *repr_broker;
+
+	if (!dev)
+		return -EINVAL;
+
+	internals = dev->data->dev_private;
+	if (!internals->port_rep)
+		return -ENODEV;
+	repr_broker = internals->port_rep->pdev->rep_broker;
+	if (!repr_broker)
+		return -ENODEV;
+
+	RTE_FUNC_PTR_OR_ERR_RET(*repr_broker->rep_ops->flow_validate, -EINVAL);
+	return repr_broker->rep_ops->flow_flush(repr_broker,
+		internals->port_rep, error);
+}
+
+static const struct rte_flow_ops port_rep_flow_ops = {
+	.validate = port_rep_flow_validate,
+	.create = port_rep_flow_create,
+	.destroy = port_rep_flow_destroy,
+	.flush = port_rep_flow_flush,
+};
+
+static int
+port_rep_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,
+	enum rte_filter_op filter_op, void *arg)
+{
+	int ret = 0;
+
+	if (!dev)
+		return -EINVAL;
+
+	switch (filter_type) {
+	case RTE_ETH_FILTER_GENERIC:
+		if (filter_op != RTE_ETH_FILTER_GET)
+			return -EINVAL;
+		*(const void **)arg = &port_rep_flow_ops;
+		break;
+	default:
+		RTE_LOG(WARNING, PMD, "Filter type (%d) not supported",
+			filter_type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/* Stub function to make eth_dev happy */
+static int
+port_rep_configure(__rte_unused struct rte_eth_dev *dev)
+{
+	return 0;
+}
+
+/* Stub function to make eth_dev happy */
+static uint16_t
+port_rep_rx(__rte_unused void *q, __rte_unused struct rte_mbuf **bufs,
+	__rte_unused uint16_t nb_bufs)
+{
+	return 0;
+}
+
+/* Stub function to make eth_dev happy */
+static uint16_t
+port_rep_tx(__rte_unused void *q, __rte_unused struct rte_mbuf **bufs,
+	__rte_unused uint16_t nb_bufs)
+{
+	return 0;
+}
+
+static const struct eth_dev_ops port_rep_ops = {
+	.dev_start = port_rep_start,
+	.dev_stop = port_rep_stop,
+	.dev_configure = port_rep_configure,
+	.dev_infos_get = port_rep_info,
+	.rx_queue_setup = port_rep_rx_queue_setup,
+	.tx_queue_setup = port_rep_tx_queue_setup,
+	.rx_queue_release = port_rep_queue_release,
+	.tx_queue_release = port_rep_queue_release,
+
+	.link_update = port_rep_link_update,
+
+	.promiscuous_enable = port_rep_promiscuous_enable,
+	.promiscuous_disable = port_rep_promiscuous_disable,
+	.allmulticast_enable = port_rep_allmulticast_enable,
+	.allmulticast_disable = port_rep_allmulticast_disable,
+
+	.mac_addr_remove = port_rep_mac_addr_remove,
+	.mac_addr_add = port_rep_mac_addr_add,
+	.mac_addr_set = port_rep_mac_addr_set,
+
+	.vlan_filter_set = port_rep_vlan_filter_set,
+	.vlan_tpid_set = port_rep_vlan_tpid_set,
+	.vlan_strip_queue_set = port_rep_vlan_strip_queue_set,
+	.vlan_offload_set = port_rep_vlan_offload_set,
+	.vlan_pvid_set = port_rep_vlan_pvid_set,
+
+	.stats_get = port_rep_stats_get,
+	.stats_reset = port_rep_stats_reset,
+
+	.filter_ctrl = port_rep_filter_ctrl,
+};
+
+/****************************************************************************
+ * Startup & parameter handling
+ ****************************************************************************/
+
+static void port_rep_default_params(struct port_rep_parameters *params)
+{
+	params->parent = -1;
+	params->vf_mask = 0UL;
+}
+
+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;
+
+	/* only added this check to accept uint values as we do not have
+	 * B:D:F to uint mapping function
+	 */
+	if (!strchr(value, ':')) {
+		params->parent = strtoul(value, NULL, 0);
+	} else {
+		ret = rte_eth_dev_get_port_by_pci_addr_str(value,
+			&params->parent);
+		if (ret != 0)
+			RTE_LOG(ERR, PMD,
+				"'pfid=%s' does not give a valid device name\n",
+				value);
+	}
+
+	return ret;
+}
+
+static int
+port_rep_kvargs_vf_index(__rte_unused const char *key,
+	const char *value, void *ptr)
+{
+	struct port_rep_parameters *params = ptr;
+	int ret;
+
+	ret = range_to_mask(value, &params->vf_mask);
+	if (ret != 0)
+		RTE_LOG(ERR, PMD, "'vf_index=%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", "vf_index", NULL
+};
+
+static port_rep_arg_func_t port_rep_kvargs_callbacks[] = {
+	&port_rep_kvargs_parent,
+	&port_rep_kvargs_vf_index,
+	NULL
+};
+
+static int
+port_rep_create(struct rte_vdev_device *dev,
+	struct port_rep_parameters *params)
+{
+	const unsigned nb_rx_queues = 1;
+	const unsigned nb_tx_queues = 1;
+	struct rte_eth_dev_data *data = NULL;
+	struct port_rep_internals *internals = NULL;
+	struct rte_eth_dev *eth_dev = NULL;
+	struct rte_port_representor *rep = NULL;
+	uint64_t vf_mask;
+	uint16_t idx_vf;
+
+	char name_buffer[RTE_ETH_NAME_MAX_LEN];
+
+	if (dev->device.numa_node == SOCKET_ID_ANY)
+		dev->device.numa_node = rte_socket_id();
+
+	RTE_LOG(INFO, PMD, "Creating representor ethdev on numa socket %u\n",
+		dev->device.numa_node);
+
+	memset(&list_eth_addrs, 0, sizeof(list_eth_addrs));
+
+	vf_mask = 1;
+	idx_vf = 0;
+	while (vf_mask <= params->vf_mask) {
+		if (params->vf_mask & vf_mask) {
+			/* now do all data allocation - for eth_dev structure,
+			 * dummy pci driver and internal (private) data
+			 */
+			data = rte_zmalloc_socket(rte_vdev_device_name(dev),
+				sizeof(*data), 0, dev->device.numa_node);
+			if (!data)
+				return -ENOMEM;
+
+			snprintf(name_buffer, RTE_ETH_NAME_MAX_LEN,
+				"%s.%i", rte_vdev_device_name(dev), idx_vf);
+
+			eth_dev = rte_eth_vdev_allocate_2(dev,
+				sizeof(*internals), name_buffer);
+			if (!eth_dev) {
+				rte_free(data);
+				return -ENOMEM;
+			}
+			/* create hook for port representor in broker */
+			rep = NULL;
+			if (rte_representor_enabled()) {
+				rep = rte_representor_initialize(
+					params->parent, idx_vf, eth_dev);
+				if (!rep) {
+					rte_free(data);
+					return -ENOMEM;
+				}
+			}
+			/* now put it all together
+			 * - store queue data in internals,
+			 * - store numa_node info in ethdev data
+			 * - point eth_dev_data to internals
+			 * - and point eth_dev structure to new eth_dev_data
+			 *   structure
+			 */
+			/* NOTE: we'll replace the data element, of originally
+			 * allocated eth_dev so the nulls are local per-process
+			 */
+
+			internals = eth_dev->data->dev_private;
+
+			rte_memcpy(&internals->params, params,
+				sizeof(struct port_rep_parameters));
+			internals->port_id = eth_dev->data->port_id;
+			internals->port_rep = rep;
+
+			rte_memcpy(data, eth_dev->data, sizeof(*data));
+			data->nb_rx_queues = (uint16_t)nb_rx_queues;
+			data->nb_tx_queues = (uint16_t)nb_tx_queues;
+
+			/* Link state. */
+			data->dev_link.link_speed = ETH_SPEED_NUM_10G;
+			data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+			data->dev_link.link_status = ETH_LINK_DOWN;
+			data->dev_link.link_autoneg = ETH_LINK_SPEED_AUTONEG;
+
+			/* MAC address. Same caveats as link state. */
+			data->mac_addrs = &list_eth_addrs[idx_vf];
+
+			eth_dev->data = data;
+			eth_dev->dev_ops = &port_rep_ops;
+
+			data->dev_flags = RTE_ETH_DEV_DETACHABLE;
+
+			/* finally assign rx and tx ops */
+			eth_dev->rx_pkt_burst = port_rep_rx;
+			eth_dev->tx_pkt_burst = port_rep_tx;
+		}
+		/* Keep bitmask and bit index in sync */
+		vf_mask = vf_mask << 1;
+		idx_vf++;
+	}
+
+	return 0;
+}
+
+static int
+port_rep_probe(struct rte_vdev_device *dev)
+{
+	const char *name;
+	const char *args;
+	struct rte_kvargs *kvlist = NULL;
+	int ret;
+	int idx_table;
+
+	if (!dev)
+		return -EINVAL;
+
+	port_rep_default_params(&vdev_params);
+
+	name = rte_vdev_device_name(dev);
+	args = rte_vdev_device_args(dev);
+	RTE_LOG(INFO, PMD, "Initializing port_representor pmd for %s\n", name);
+	if (args) {
+		kvlist = rte_kvargs_parse(args, port_rep_kvargs_codes);
+		if (!kvlist)
+			return -1;
+
+		idx_table = 0;
+		while (port_rep_kvargs_codes[idx_table] != NULL) {
+			ret = rte_kvargs_process(kvlist,
+				port_rep_kvargs_codes[idx_table],
+				port_rep_kvargs_callbacks[idx_table],
+				&vdev_params);
+			if (ret != 0) {
+				RTE_LOG(ERR, PMD, "port_representor pmd "
+					"parameter error\n");
+				rte_kvargs_free(kvlist);
+				return -1;
+			}
+			idx_table++;
+		}
+	}
+	RTE_LOG(INFO, PMD, "Configure port_representor pmd with args=\"%s\"\n",
+		args);
+
+	ret = port_rep_create(dev, &vdev_params);
+
+	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;
+	uint64_t vf_mask;
+	uint16_t cnt_vf;
+	char name_buffer[RTE_ETH_NAME_MAX_LEN];
+
+	if (!dev)
+		return -EINVAL;
+
+	RTE_LOG(INFO, PMD, "Closing representor port on numa socket %u\n",
+			rte_socket_id());
+
+	vf_mask = 1;
+	cnt_vf = 0;
+	while (vf_mask <= vdev_params.vf_mask) {
+		if (vdev_params.vf_mask & vf_mask) {
+			snprintf(name_buffer, RTE_ETH_NAME_MAX_LEN, "%s.%i",
+				rte_vdev_device_name(dev), cnt_vf);
+
+			/* Find and deallocate the ethdev entry */
+			eth_dev = rte_eth_dev_allocated(
+					rte_vdev_device_name(dev));
+			if (!eth_dev)
+				return -1;
+
+			rte_free(eth_dev->data->dev_private);
+			rte_free(eth_dev->data);
+			rte_eth_dev_release_port(eth_dev);
+		}
+
+		cnt_vf++;
+		vf_mask = vf_mask << 1;
+	}
+
+	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=<pci addr>:vf_index=<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/lib/librte_ether/rte_ethdev_vdev.h b/lib/librte_ether/rte_ethdev_vdev.h
index 4d2c3e2..7aaaca3 100644
--- a/lib/librte_ether/rte_ethdev_vdev.h
+++ b/lib/librte_ether/rte_ethdev_vdev.h
@@ -49,18 +49,29 @@
  * @param private_data_size
  *	Size of private data structure
  *
+ * @param override_name
+ *	Given name for the vdev instead of default one
+ *
  * @return
  *	A pointer to a rte_eth_dev or NULL if allocation failed.
  */
 static inline struct rte_eth_dev *
-rte_eth_vdev_allocate(struct rte_vdev_device *dev, size_t private_data_size)
+rte_eth_vdev_allocate_2(struct rte_vdev_device *dev, size_t private_data_size,
+	const char *override_name)
 {
 	struct rte_eth_dev *eth_dev;
-	const char *name = rte_vdev_device_name(dev);
+	const char *name;
+
+	if (override_name)
+		name = override_name;
+	else
+		name = rte_vdev_device_name(dev);
 
 	eth_dev = rte_eth_dev_allocate(name);
-	if (!eth_dev)
+	if (!eth_dev) {
+		printf("FAILED!\n");
 		return NULL;
+	}
 
 	if (private_data_size) {
 		eth_dev->data->dev_private = rte_zmalloc_socket(name,
@@ -80,4 +91,24 @@ rte_eth_vdev_allocate(struct rte_vdev_device *dev, size_t private_data_size)
 	return eth_dev;
 }
 
+/**
+ * @internal
+ * Allocates a new ethdev slot for an ethernet device and returns the pointer
+ * to that slot for the driver to use.
+ *
+ * @param dev
+ *	Pointer to virtual device
+ *
+ * @param private_data_size
+ *	Size of private data structure
+ *
+ * @return
+ *	A pointer to a rte_eth_dev or NULL if allocation failed.
+ */
+static inline struct rte_eth_dev *
+rte_eth_vdev_allocate(struct rte_vdev_device *dev, size_t private_data_size)
+{
+	return rte_eth_vdev_allocate_2(dev, private_data_size, NULL);
+}
+
 #endif /* _RTE_ETHDEV_VDEV_H_ */
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index c25fdd9..3dbbe3a 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -132,6 +132,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += -lrte_pmd_mlx4 -libverbs
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += -lrte_pmd_mlx5 -libverbs
 _LDLIBS-$(CONFIG_RTE_LIBRTE_NFP_PMD)        += -lrte_pmd_nfp
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NULL)       += -lrte_pmd_null
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_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



More information about the dev mailing list