DPDK patches and discussions
 help / color / mirror / Atom feed
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] [PATCH 2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs
Date: Wed,  1 Nov 2017 15:46:23 +0000	[thread overview]
Message-ID: <1509551187-25726-2-git-send-email-mohammad.abdul.awal@intel.com> (raw)
In-Reply-To: <1509551187-25726-1-git-send-email-mohammad.abdul.awal@intel.com>

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 82ee754..06e9d43 100644
--- a/config/common_base
+++ b/config/common_base
@@ -814,3 +814,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 047121d..0778589 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

  reply	other threads:[~2017-11-01 15:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-01 15:46 [dpdk-dev] [PATCH 1/6] ethdev: added switch_domain and representor port flag Mohammad Abdul Awal
2017-11-01 15:46 ` Mohammad Abdul Awal [this message]
2017-11-01 15:46 ` [dpdk-dev] [PATCH 3/6] eal: added --enable-representor command line argument in EAL to load representor broker infrastructure Mohammad Abdul Awal
2017-11-01 15:46 ` [dpdk-dev] [PATCH 4/6] net/representor: Implement port representor PMD Mohammad Abdul Awal
2017-11-01 15:46 ` [dpdk-dev] [PATCH 5/6] net/i40e: Enable port representor PMD and broker for fortville PMD driver Mohammad Abdul Awal
2017-11-01 15:46 ` [dpdk-dev] [PATCH 6/6] net/ixgbe: Enable port representor PMD and broker for ixgbe " 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=1509551187-25726-2-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).