[dpdk-dev,v2,2/6] lib/representor: port representor library to manage broker infrastructure and representor PMDs

Message ID 1510929733-7225-2-git-send-email-mohammad.abdul.awal@intel.com
State Superseded, archived
Delegated to: Ferruh Yigit
Headers show

Checks

Context Check Description
ci/Intel-compilation fail Compilation issues
ci/checkpatch warning coding style issues

Commit Message

Mohammad Abdul Awal Nov. 17, 2017, 2:42 p.m.
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

Comments

Ferruh Yigit Nov. 17, 2017, 11:03 p.m. | #1
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: *;
> +};
Mohammad Abdul Awal Dec. 8, 2017, 2:57 p.m. | #2
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: *;
>> +};

Patch

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