From: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
To: dev@dpdk.org
Cc: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>,
Remy Horton <remy.horton@intel.com>,
Declan Doherty <declan.doherty@intel.com>
Subject: [dpdk-dev] [RFC 3/5] Implement port representor PMD
Date: Thu, 7 Sep 2017 09:35:37 +0100 [thread overview]
Message-ID: <1504773339-21022-4-git-send-email-mohammad.abdul.awal@intel.com> (raw)
In-Reply-To: <1504773339-21022-1-git-send-email-mohammad.abdul.awal@intel.com>
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 +
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,
+ ¶ms->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, ¶ms->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
next prev parent reply other threads:[~2017-09-07 8:36 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-07 8:35 [dpdk-dev] [RFC 0/5] Port Representor for control and monitoring of VF devices Mohammad Abdul Awal
2017-09-07 8:35 ` [dpdk-dev] [RFC 1/5] Implemented port representor broker infrastructure, created BDF to port function Mohammad Abdul Awal
2017-09-07 8:35 ` [dpdk-dev] [RFC 2/5] added --enable-representor command line argument in EAL to load representor broker infrastructure Mohammad Abdul Awal
2017-09-07 8:35 ` Mohammad Abdul Awal [this message]
2017-09-07 8:35 ` [dpdk-dev] [RFC 4/5] Enable port representor PMD and broker for fortville PMD driver Mohammad Abdul Awal
2017-09-07 8:35 ` [dpdk-dev] [RFC 5/5] Enable port representor PMD and broker for ixgbe " Mohammad Abdul Awal
2017-09-07 10:01 ` [dpdk-dev] [RFC 0/5] Port Representor for control and monitoring of VF devices Alejandro Lucero
2017-09-07 13:13 ` Declan Doherty
2017-09-08 13:59 ` Alejandro Lucero
2017-12-21 14:51 ` Alex Rosenbaum
2017-12-22 14:31 ` Mohammad Abdul Awal
2017-12-22 22:33 ` Alex Rosenbaum
2017-12-27 9:40 ` Mohammad Abdul Awal
2017-12-27 15:50 ` Alex Rosenbaum
2018-01-02 15:19 ` Mohammad Abdul Awal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1504773339-21022-4-git-send-email-mohammad.abdul.awal@intel.com \
--to=mohammad.abdul.awal@intel.com \
--cc=declan.doherty@intel.com \
--cc=dev@dpdk.org \
--cc=remy.horton@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).