DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH] ivshmem: remove integration in dpdk
@ 2016-07-29 12:28 David Marchand
  2016-08-04 12:50 ` Panu Matilainen
  2016-08-18 14:08 ` Burakov, Anatoly
  0 siblings, 2 replies; 4+ messages in thread
From: David Marchand @ 2016-07-29 12:28 UTC (permalink / raw)
  To: dev; +Cc: thomas.monjalon, anatoly.burakov

Following discussions on the mailing list [1] and since nobody stood up to
implement the necessary cleanups, here is the ivshmem integration removal.

There is not much to say about this patch, a lot of code is being removed.
The default configuration file for packet_ordering example is replaced with
the "native" x86 file.
The only tricky part is in eal_memory with the memseg index stuff.

More cleanups can be done after this but will come in subsequent patchsets.

[1]: http://dpdk.org/ml/archives/dev/2016-June/040844.html

Signed-off-by: David Marchand <david.marchand@6wind.com>
---
 MAINTAINERS                                  |   8 -
 app/test/Makefile                            |   1 -
 app/test/autotest_data.py                    |   6 -
 app/test/test.c                              |   3 -
 app/test/test.h                              |   1 -
 app/test/test_ivshmem.c                      | 433 ------------
 config/defconfig_arm64-armv8a-linuxapp-gcc   |   1 -
 config/defconfig_x86_64-ivshmem-linuxapp-gcc |  49 --
 config/defconfig_x86_64-ivshmem-linuxapp-icc |  49 --
 doc/api/doxy-api-index.md                    |   1 -
 doc/api/doxy-api.conf                        |   1 -
 doc/api/examples.dox                         |   2 -
 doc/guides/linux_gsg/build_dpdk.rst          |   2 +-
 doc/guides/linux_gsg/quick_start.rst         |  14 +-
 doc/guides/prog_guide/img/ivshmem.png        | Bin 44920 -> 0 bytes
 doc/guides/prog_guide/index.rst              |   1 -
 doc/guides/prog_guide/ivshmem_lib.rst        | 160 -----
 doc/guides/prog_guide/source_org.rst         |   1 -
 doc/guides/rel_notes/deprecation.rst         |   3 -
 doc/guides/rel_notes/release_16_11.rst       |   3 +
 examples/Makefile                            |   1 -
 examples/l2fwd-ivshmem/Makefile              |  43 --
 examples/l2fwd-ivshmem/guest/Makefile        |  50 --
 examples/l2fwd-ivshmem/guest/guest.c         | 452 -------------
 examples/l2fwd-ivshmem/host/Makefile         |  50 --
 examples/l2fwd-ivshmem/host/host.c           | 895 -------------------------
 examples/l2fwd-ivshmem/include/common.h      | 111 ----
 examples/packet_ordering/Makefile            |   2 +-
 lib/Makefile                                 |   1 -
 lib/librte_eal/common/eal_common_memzone.c   |  12 -
 lib/librte_eal/common/eal_private.h          |  22 -
 lib/librte_eal/common/include/rte_memory.h   |   3 -
 lib/librte_eal/common/include/rte_memzone.h  |   7 +-
 lib/librte_eal/common/malloc_heap.c          |   8 -
 lib/librte_eal/linuxapp/eal/Makefile         |   9 -
 lib/librte_eal/linuxapp/eal/eal.c            |  10 -
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c    | 954 ---------------------------
 lib/librte_eal/linuxapp/eal/eal_memory.c     |  30 +-
 lib/librte_ivshmem/Makefile                  |  54 --
 lib/librte_ivshmem/rte_ivshmem.c             | 919 --------------------------
 lib/librte_ivshmem/rte_ivshmem.h             | 165 -----
 lib/librte_ivshmem/rte_ivshmem_version.map   |  12 -
 mk/rte.app.mk                                |   1 -
 43 files changed, 13 insertions(+), 4537 deletions(-)
 delete mode 100644 app/test/test_ivshmem.c
 delete mode 100644 config/defconfig_x86_64-ivshmem-linuxapp-gcc
 delete mode 100644 config/defconfig_x86_64-ivshmem-linuxapp-icc
 delete mode 100644 doc/guides/prog_guide/img/ivshmem.png
 delete mode 100644 doc/guides/prog_guide/ivshmem_lib.rst
 delete mode 100644 examples/l2fwd-ivshmem/Makefile
 delete mode 100644 examples/l2fwd-ivshmem/guest/Makefile
 delete mode 100644 examples/l2fwd-ivshmem/guest/guest.c
 delete mode 100644 examples/l2fwd-ivshmem/host/Makefile
 delete mode 100644 examples/l2fwd-ivshmem/host/host.c
 delete mode 100644 examples/l2fwd-ivshmem/include/common.h
 delete mode 100644 lib/librte_eal/linuxapp/eal/eal_ivshmem.c
 delete mode 100644 lib/librte_ivshmem/Makefile
 delete mode 100644 lib/librte_ivshmem/rte_ivshmem.c
 delete mode 100644 lib/librte_ivshmem/rte_ivshmem.h
 delete mode 100644 lib/librte_ivshmem/rte_ivshmem_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 6536c6b..5e3d825 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -546,14 +546,6 @@ F: app/test/test_cmdline*
 F: examples/cmdline/
 F: doc/guides/sample_app_ug/cmd_line.rst
 
-Qemu IVSHMEM
-M: Anatoly Burakov <anatoly.burakov@intel.com>
-F: lib/librte_ivshmem/
-F: lib/librte_eal/linuxapp/eal/eal_ivshmem.c
-F: doc/guides/prog_guide/ivshmem_lib.rst
-F: app/test/test_ivshmem.c
-F: examples/l2fwd-ivshmem/
-
 Key/Value parsing
 M: Olivier Matz <olivier.matz@6wind.com>
 F: lib/librte_kvargs/
diff --git a/app/test/Makefile b/app/test/Makefile
index 49ea195..611d77a 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -167,7 +167,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_KNI) += test_kni.c
 SRCS-$(CONFIG_RTE_LIBRTE_POWER) += test_power.c test_power_acpi_cpufreq.c
 SRCS-$(CONFIG_RTE_LIBRTE_POWER) += test_power_kvm_vm.c
 SRCS-y += test_common.c
-SRCS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += test_ivshmem.c
 
 SRCS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += test_distributor.c
 SRCS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += test_distributor_perf.c
diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
index defd46e..9e8fd94 100644
--- a/app/test/autotest_data.py
+++ b/app/test/autotest_data.py
@@ -174,12 +174,6 @@ parallel_test_group_list = [
 			"Report" :  None,
 		},
 		{
-		 "Name" :	"IVSHMEM autotest",
-		 "Command" : 	"ivshmem_autotest",
-		 "Func" :	default_autotest,
-		 "Report" :	None,
-		},
-		{
 		 "Name" :	"Memcpy autotest",
 		 "Command" : 	"memcpy_autotest",
 		 "Func" :	default_autotest,
diff --git a/app/test/test.c b/app/test/test.c
index ccad0e3..cd0e784 100644
--- a/app/test/test.c
+++ b/app/test/test.c
@@ -95,9 +95,6 @@ do_recursive_call(void)
 			{ "test_memory_flags", no_action },
 			{ "test_file_prefix", no_action },
 			{ "test_no_huge_flag", no_action },
-#ifdef RTE_LIBRTE_IVSHMEM
-			{ "test_ivshmem", test_ivshmem },
-#endif
 	};
 
 	if (recursive_call == NULL)
diff --git a/app/test/test.h b/app/test/test.h
index 467b9c0..b250c84 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -235,7 +235,6 @@ int test_pci_run;
 
 int test_mp_secondary(void);
 
-int test_ivshmem(void);
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
 int test_set_rxtx_anchor(cmdline_fixed_string_t type);
 int test_set_rxtx_sc(cmdline_fixed_string_t type);
diff --git a/app/test/test_ivshmem.c b/app/test/test_ivshmem.c
deleted file mode 100644
index ae9fd6c..0000000
--- a/app/test/test_ivshmem.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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 <fcntl.h>
-#include <limits.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-#include <stdio.h>
-
-#include <cmdline_parse.h>
-
-#include "test.h"
-
-#include <rte_common.h>
-#include <rte_ivshmem.h>
-#include <rte_string_fns.h>
-#include "process.h"
-
-#define DUPLICATE_METADATA "duplicate"
-#define METADATA_NAME "metadata"
-#define NONEXISTENT_METADATA "nonexistent"
-#define FIRST_TEST 'a'
-
-#define launch_proc(ARGV) process_dup(ARGV, \
-		sizeof(ARGV)/(sizeof(ARGV[0])), "test_ivshmem")
-
-#define ASSERT(cond,msg) do {						\
-		if (!(cond)) {								\
-			printf("**** TEST %s() failed: %s\n",	\
-				__func__, msg);						\
-			return -1;								\
-		}											\
-} while(0)
-
-static char*
-get_current_prefix(char * prefix, int size)
-{
-	char path[PATH_MAX] = {0};
-	char buf[PATH_MAX] = {0};
-
-	/* get file for config (fd is always 3) */
-	snprintf(path, sizeof(path), "/proc/self/fd/%d", 3);
-
-	/* return NULL on error */
-	if (readlink(path, buf, sizeof(buf)) == -1)
-		return NULL;
-
-	/* get the basename */
-	snprintf(buf, sizeof(buf), "%s", basename(buf));
-
-	/* copy string all the way from second char up to start of _config */
-	snprintf(prefix, size, "%.*s",
-			(int)(strnlen(buf, sizeof(buf)) - sizeof("_config")),
-			&buf[1]);
-
-	return prefix;
-}
-
-static struct rte_ivshmem_metadata*
-mmap_metadata(const char *name)
-{
-	int fd;
-	char pathname[PATH_MAX];
-	struct rte_ivshmem_metadata *metadata;
-
-	snprintf(pathname, sizeof(pathname),
-			"/var/run/.dpdk_ivshmem_metadata_%s", name);
-
-	fd = open(pathname, O_RDWR, 0660);
-	if (fd < 0)
-		return NULL;
-
-	metadata = (struct rte_ivshmem_metadata*) mmap(NULL,
-			sizeof(struct rte_ivshmem_metadata), PROT_READ | PROT_WRITE,
-			MAP_SHARED, fd, 0);
-
-	if (metadata == MAP_FAILED)
-		return NULL;
-
-	close(fd);
-
-	return metadata;
-}
-
-static int
-create_duplicate(void)
-{
-	/* create a metadata that another process will then try to overwrite */
-	ASSERT (rte_ivshmem_metadata_create(DUPLICATE_METADATA) == 0,
-			"Creating metadata failed");
-	return 0;
-}
-
-static int
-test_ivshmem_create_lots_of_memzones(void)
-{
-	int i;
-	char name[IVSHMEM_NAME_LEN];
-	const struct rte_memzone *mz;
-
-	ASSERT(rte_ivshmem_metadata_create(METADATA_NAME) == 0,
-			"Failed to create metadata");
-
-	for (i = 0; i < RTE_LIBRTE_IVSHMEM_MAX_ENTRIES; i++) {
-		snprintf(name, sizeof(name), "mz_%i", i);
-
-		mz = rte_memzone_reserve(name, RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY, 0);
-		ASSERT(mz != NULL, "Failed to reserve memzone");
-
-		ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) == 0,
-				"Failed to add memzone");
-	}
-	mz = rte_memzone_reserve("one too many", RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY, 0);
-	ASSERT(mz != NULL, "Failed to reserve memzone");
-
-	ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) < 0,
-		"Metadata should have been full");
-
-	return 0;
-}
-
-static int
-test_ivshmem_create_duplicate_memzone(void)
-{
-	const struct rte_memzone *mz;
-
-	ASSERT(rte_ivshmem_metadata_create(METADATA_NAME) == 0,
-			"Failed to create metadata");
-
-	mz = rte_memzone_reserve("mz", RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY, 0);
-	ASSERT(mz != NULL, "Failed to reserve memzone");
-
-	ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) == 0,
-			"Failed to add memzone");
-
-	ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) < 0,
-			"Added the same memzone twice");
-
-	return 0;
-}
-
-static int
-test_ivshmem_api_test(void)
-{
-	const struct rte_memzone * mz;
-	struct rte_mempool * mp;
-	struct rte_ring * r;
-	char buf[BUFSIZ];
-
-	memset(buf, 0, sizeof(buf));
-
-	r = rte_ring_create("ring", 1, SOCKET_ID_ANY, 0);
-	mp = rte_mempool_create("mempool", 1, 1, 1, 1, NULL, NULL, NULL, NULL,
-			SOCKET_ID_ANY, 0);
-	mz = rte_memzone_reserve("memzone", 64, SOCKET_ID_ANY, 0);
-
-	ASSERT(r != NULL, "Failed to create ring");
-	ASSERT(mp != NULL, "Failed to create mempool");
-	ASSERT(mz != NULL, "Failed to reserve memzone");
-
-	/* try to create NULL metadata */
-	ASSERT(rte_ivshmem_metadata_create(NULL) < 0,
-			"Created metadata with NULL name");
-
-	/* create valid metadata to do tests on */
-	ASSERT(rte_ivshmem_metadata_create(METADATA_NAME) == 0,
-			"Failed to create metadata");
-
-	/* test adding memzone */
-	ASSERT(rte_ivshmem_metadata_add_memzone(NULL, NULL) < 0,
-			"Added NULL memzone to NULL metadata");
-	ASSERT(rte_ivshmem_metadata_add_memzone(NULL, METADATA_NAME) < 0,
-			"Added NULL memzone");
-	ASSERT(rte_ivshmem_metadata_add_memzone(mz, NULL) < 0,
-			"Added memzone to NULL metadata");
-	ASSERT(rte_ivshmem_metadata_add_memzone(mz, NONEXISTENT_METADATA) < 0,
-			"Added memzone to nonexistent metadata");
-
-	/* test adding ring */
-	ASSERT(rte_ivshmem_metadata_add_ring(NULL, NULL) < 0,
-			"Added NULL ring to NULL metadata");
-	ASSERT(rte_ivshmem_metadata_add_ring(NULL, METADATA_NAME) < 0,
-			"Added NULL ring");
-	ASSERT(rte_ivshmem_metadata_add_ring(r, NULL) < 0,
-			"Added ring to NULL metadata");
-	ASSERT(rte_ivshmem_metadata_add_ring(r, NONEXISTENT_METADATA) < 0,
-			"Added ring to nonexistent metadata");
-
-	/* test adding mempool */
-	ASSERT(rte_ivshmem_metadata_add_mempool(NULL, NULL) < 0,
-			"Added NULL mempool to NULL metadata");
-	ASSERT(rte_ivshmem_metadata_add_mempool(NULL, METADATA_NAME) < 0,
-			"Added NULL mempool");
-	ASSERT(rte_ivshmem_metadata_add_mempool(mp, NULL) < 0,
-			"Added mempool to NULL metadata");
-	ASSERT(rte_ivshmem_metadata_add_mempool(mp, NONEXISTENT_METADATA) < 0,
-			"Added mempool to nonexistent metadata");
-
-	/* test creating command line */
-	ASSERT(rte_ivshmem_metadata_cmdline_generate(NULL, sizeof(buf), METADATA_NAME) < 0,
-			"Written command line into NULL buffer");
-	ASSERT(strnlen(buf, sizeof(buf)) == 0, "Buffer is not empty");
-
-	ASSERT(rte_ivshmem_metadata_cmdline_generate(buf, 0, METADATA_NAME) < 0,
-			"Written command line into small buffer");
-	ASSERT(strnlen(buf, sizeof(buf)) == 0, "Buffer is not empty");
-
-	ASSERT(rte_ivshmem_metadata_cmdline_generate(buf, sizeof(buf), NULL) < 0,
-			"Written command line for NULL metadata");
-	ASSERT(strnlen(buf, sizeof(buf)) == 0, "Buffer is not empty");
-
-	ASSERT(rte_ivshmem_metadata_cmdline_generate(buf, sizeof(buf),
-			NONEXISTENT_METADATA) < 0,
-			"Writen command line for nonexistent metadata");
-	ASSERT(strnlen(buf, sizeof(buf)) == 0, "Buffer is not empty");
-
-	/* add stuff to config */
-	ASSERT(rte_ivshmem_metadata_add_memzone(mz, METADATA_NAME) == 0,
-			"Failed to add memzone to valid config");
-	ASSERT(rte_ivshmem_metadata_add_ring(r, METADATA_NAME) == 0,
-			"Failed to add ring to valid config");
-	ASSERT(rte_ivshmem_metadata_add_mempool(mp, METADATA_NAME) == 0,
-			"Failed to add mempool to valid config");
-
-	/* create config */
-	ASSERT(rte_ivshmem_metadata_cmdline_generate(buf, sizeof(buf),
-			METADATA_NAME) == 0, "Failed to write command-line");
-
-	/* check if something was written */
-	ASSERT(strnlen(buf, sizeof(buf)) != 0, "Buffer is empty");
-
-	/* make sure we don't segfault */
-	rte_ivshmem_metadata_dump(stdout, NULL);
-
-	/* dump our metadata */
-	rte_ivshmem_metadata_dump(stdout, METADATA_NAME);
-
-	return 0;
-}
-
-static int
-test_ivshmem_create_duplicate_metadata(void)
-{
-	ASSERT(rte_ivshmem_metadata_create(DUPLICATE_METADATA) < 0,
-			"Creating duplicate metadata should have failed");
-
-	return 0;
-}
-
-static int
-test_ivshmem_create_metadata_config(void)
-{
-	struct rte_ivshmem_metadata *metadata;
-
-	rte_ivshmem_metadata_create(METADATA_NAME);
-
-	metadata = mmap_metadata(METADATA_NAME);
-
-	ASSERT(metadata != MAP_FAILED, "Metadata mmaping failed");
-
-	ASSERT(metadata->magic_number == IVSHMEM_MAGIC,
-			"Magic number is not that magic");
-
-	ASSERT(strncmp(metadata->name, METADATA_NAME, sizeof(metadata->name)) == 0,
-			"Name has not been set up");
-
-	ASSERT(metadata->entry[0].offset == 0, "Offest is not initialized");
-	ASSERT(metadata->entry[0].mz.addr == 0, "mz.addr is not initialized");
-	ASSERT(metadata->entry[0].mz.len == 0, "mz.len is not initialized");
-
-	return 0;
-}
-
-static int
-test_ivshmem_create_multiple_metadata_configs(void)
-{
-	int i;
-	char name[IVSHMEM_NAME_LEN];
-	struct rte_ivshmem_metadata *metadata;
-
-	for (i = 0; i < RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES / 2; i++) {
-		snprintf(name, sizeof(name), "test_%d", i);
-		rte_ivshmem_metadata_create(name);
-		metadata = mmap_metadata(name);
-
-		ASSERT(metadata->magic_number == IVSHMEM_MAGIC,
-				"Magic number is not that magic");
-
-		ASSERT(strncmp(metadata->name, name, sizeof(metadata->name)) == 0,
-				"Name has not been set up");
-	}
-
-	return 0;
-}
-
-static int
-test_ivshmem_create_too_many_metadata_configs(void)
-{
-	int i;
-	char name[IVSHMEM_NAME_LEN];
-
-	for (i = 0; i < RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES; i++) {
-		snprintf(name, sizeof(name), "test_%d", i);
-		ASSERT(rte_ivshmem_metadata_create(name) == 0,
-				"Create config file failed");
-	}
-
-	ASSERT(rte_ivshmem_metadata_create(name) < 0,
-			"Create config file didn't fail");
-
-	return 0;
-}
-
-enum rte_ivshmem_tests {
-	_test_ivshmem_api_test = 0,
-	_test_ivshmem_create_metadata_config,
-	_test_ivshmem_create_multiple_metadata_configs,
-	_test_ivshmem_create_too_many_metadata_configs,
-	_test_ivshmem_create_duplicate_metadata,
-	_test_ivshmem_create_lots_of_memzones,
-	_test_ivshmem_create_duplicate_memzone,
-	_last_test,
-};
-
-#define RTE_IVSHMEM_TEST_ID "RTE_IVSHMEM_TEST_ID"
-
-static int
-launch_all_tests_on_secondary_processes(void)
-{
-	int ret = 0;
-	char id;
-	char testid;
-	char tmp[PATH_MAX] = {0};
-	char prefix[PATH_MAX] = {0};
-
-	get_current_prefix(tmp, sizeof(tmp));
-
-	snprintf(prefix, sizeof(prefix), "--file-prefix=%s", tmp);
-
-	const char *argv[] = { prgname, "-c", "1", "-n", "3",
-			"--proc-type=secondary", prefix };
-
-	for (id = 0; id < _last_test; id++) {
-		testid = (char)(FIRST_TEST + id);
-		setenv(RTE_IVSHMEM_TEST_ID, &testid, 1);
-		if (launch_proc(argv) != 0)
-			return -1;
-	}
-	return ret;
-}
-
-int
-test_ivshmem(void)
-{
-	int testid;
-
-	/* We want to have a clean execution for every test without exposing
-	 * private global data structures in rte_ivshmem so we launch each test
-	 * on a different secondary process. */
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
-
-		/* first, create metadata */
-		ASSERT(create_duplicate() == 0, "Creating metadata failed");
-
-		return launch_all_tests_on_secondary_processes();
-	}
-
-	testid = *(getenv(RTE_IVSHMEM_TEST_ID)) - FIRST_TEST;
-
-	printf("Secondary process running test %d \n", testid);
-
-	switch (testid) {
-	case _test_ivshmem_api_test:
-		return test_ivshmem_api_test();
-
-	case _test_ivshmem_create_metadata_config:
-		return test_ivshmem_create_metadata_config();
-
-	case _test_ivshmem_create_multiple_metadata_configs:
-		return test_ivshmem_create_multiple_metadata_configs();
-
-	case _test_ivshmem_create_too_many_metadata_configs:
-		return test_ivshmem_create_too_many_metadata_configs();
-
-	case _test_ivshmem_create_duplicate_metadata:
-		return test_ivshmem_create_duplicate_metadata();
-
-	case _test_ivshmem_create_lots_of_memzones:
-		return test_ivshmem_create_lots_of_memzones();
-
-	case _test_ivshmem_create_duplicate_memzone:
-		return test_ivshmem_create_duplicate_memzone();
-
-	default:
-		break;
-	}
-
-	return -1;
-}
-
-REGISTER_TEST_COMMAND(ivshmem_autotest, test_ivshmem);
diff --git a/config/defconfig_arm64-armv8a-linuxapp-gcc b/config/defconfig_arm64-armv8a-linuxapp-gcc
index 1a17126..73f4733 100644
--- a/config/defconfig_arm64-armv8a-linuxapp-gcc
+++ b/config/defconfig_arm64-armv8a-linuxapp-gcc
@@ -44,7 +44,6 @@ CONFIG_RTE_TOOLCHAIN_GCC=y
 
 CONFIG_RTE_EAL_IGB_UIO=n
 
-CONFIG_RTE_LIBRTE_IVSHMEM=n
 CONFIG_RTE_LIBRTE_FM10K_PMD=n
 CONFIG_RTE_LIBRTE_I40E_PMD=n
 
diff --git a/config/defconfig_x86_64-ivshmem-linuxapp-gcc b/config/defconfig_x86_64-ivshmem-linuxapp-gcc
deleted file mode 100644
index 41ac5c3..0000000
--- a/config/defconfig_x86_64-ivshmem-linuxapp-gcc
+++ /dev/null
@@ -1,49 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 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.
-#
-
-#
-# use default config
-#
-
-#include "defconfig_x86_64-native-linuxapp-gcc"
-
-#
-# Compile IVSHMEM library
-#
-CONFIG_RTE_LIBRTE_IVSHMEM=y
-CONFIG_RTE_LIBRTE_IVSHMEM_DEBUG=n
-CONFIG_RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS=4
-CONFIG_RTE_LIBRTE_IVSHMEM_MAX_ENTRIES=128
-CONFIG_RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES=32
-
-# Set EAL to single file segments
-CONFIG_RTE_EAL_SINGLE_FILE_SEGMENTS=y
\ No newline at end of file
diff --git a/config/defconfig_x86_64-ivshmem-linuxapp-icc b/config/defconfig_x86_64-ivshmem-linuxapp-icc
deleted file mode 100644
index 77fec93..0000000
--- a/config/defconfig_x86_64-ivshmem-linuxapp-icc
+++ /dev/null
@@ -1,49 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 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.
-#
-
-#
-# use default config
-#
-
-#include "defconfig_x86_64-native-linuxapp-icc"
-
-#
-# Compile IVSHMEM library
-#
-CONFIG_RTE_LIBRTE_IVSHMEM=y
-CONFIG_RTE_LIBRTE_IVSHMEM_DEBUG=n
-CONFIG_RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS=4
-CONFIG_RTE_LIBRTE_IVSHMEM_MAX_ENTRIES=128
-CONFIG_RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES=32
-
-# Set EAL to single file segments
-CONFIG_RTE_EAL_SINGLE_FILE_SEGMENTS=y
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 2284a53..6675f96 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -108,7 +108,6 @@ There are many libraries, so their headers may be grouped by topics:
   [reorder]            (@ref rte_reorder.h),
   [tailq]              (@ref rte_tailq.h),
   [bitmap]             (@ref rte_bitmap.h),
-  [ivshmem]            (@ref rte_ivshmem.h)
 
 - **packet framework**:
   * [port]             (@ref rte_port.h):
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index af5d6dd..9dc7ae5 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -43,7 +43,6 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_ether \
                           lib/librte_hash \
                           lib/librte_ip_frag \
-                          lib/librte_ivshmem \
                           lib/librte_jobstats \
                           lib/librte_kni \
                           lib/librte_kvargs \
diff --git a/doc/api/examples.dox b/doc/api/examples.dox
index 200af0b..1626852 100644
--- a/doc/api/examples.dox
+++ b/doc/api/examples.dox
@@ -40,8 +40,6 @@
 @example ipv4_multicast/main.c
 @example kni/main.c
 @example l2fwd-crypto/main.c
-@example l2fwd-ivshmem/guest/guest.c
-@example l2fwd-ivshmem/host/host.c
 @example l2fwd-jobstats/main.c
 @example l2fwd-keepalive/main.c
 @example l2fwd/main.c
diff --git a/doc/guides/linux_gsg/build_dpdk.rst b/doc/guides/linux_gsg/build_dpdk.rst
index f8007b3..474598a 100644
--- a/doc/guides/linux_gsg/build_dpdk.rst
+++ b/doc/guides/linux_gsg/build_dpdk.rst
@@ -75,7 +75,7 @@ where:
 
 * ``ARCH`` can be:  ``i686``, ``x86_64``, ``ppc_64``
 
-* ``MACHINE`` can be:  ``native``, ``ivshmem``, ``power8``
+* ``MACHINE`` can be:  ``native``, ``power8``
 
 * ``EXECENV`` can be:  ``linuxapp``,  ``bsdapp``
 
diff --git a/doc/guides/linux_gsg/quick_start.rst b/doc/guides/linux_gsg/quick_start.rst
index 8789b58..6e858c2 100644
--- a/doc/guides/linux_gsg/quick_start.rst
+++ b/doc/guides/linux_gsg/quick_start.rst
@@ -126,19 +126,15 @@ Some options in the script prompt the user for further data before proceeding.
 
     [3] ppc_64-power8-linuxapp-gcc
 
-    [4] x86_64-ivshmem-linuxapp-gcc
+    [4] x86_64-native-bsdapp-clang
 
-    [5] x86_64-ivshmem-linuxapp-icc
+    [5] x86_64-native-bsdapp-gcc
 
-    [6] x86_64-native-bsdapp-clang
+    [6] x86_64-native-linuxapp-clang
 
-    [7] x86_64-native-bsdapp-gcc
+    [7] x86_64-native-linuxapp-gcc
 
-    [8] x86_64-native-linuxapp-clang
-
-    [9] x86_64-native-linuxapp-gcc
-
-    [10] x86_64-native-linuxapp-icc
+    [8] x86_64-native-linuxapp-icc
 
     ------------------------------------------------------------------------
 
diff --git a/doc/guides/prog_guide/img/ivshmem.png b/doc/guides/prog_guide/img/ivshmem.png
deleted file mode 100644
index 2b34a2cfdf3d65025c1f942f5cc1f2a1ef05892c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 44920
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
J)d1t*{{tHm(mwzI

diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index 07a4d35..e5a50a8 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -43,7 +43,6 @@ Programmer's Guide
     mbuf_lib
     poll_mode_drv
     cryptodev_lib
-    ivshmem_lib
     link_bonding_poll_mode_drv_lib
     timer_lib
     hash_lib
diff --git a/doc/guides/prog_guide/ivshmem_lib.rst b/doc/guides/prog_guide/ivshmem_lib.rst
deleted file mode 100644
index b8a32e4..0000000
--- a/doc/guides/prog_guide/ivshmem_lib.rst
+++ /dev/null
@@ -1,160 +0,0 @@
-..  BSD LICENSE
-    Copyright(c) 2010-2014 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.
-
-IVSHMEM Library
-===============
-
-The DPDK IVSHMEM library facilitates fast zero-copy data sharing among virtual machines
-(host-to-guest or guest-to-guest) by means of QEMU's IVSHMEM mechanism.
-
-The library works by providing a command line for QEMU to map several hugepages into a single IVSHMEM device.
-For the guest to know what is inside any given IVSHMEM device
-(and to distinguish between DPDK and non-DPDK IVSHMEM devices),
-a metadata file is also mapped into the IVSHMEM segment.
-No work needs to be done by the guest application to map IVSHMEM devices into memory;
-they are automatically recognized by the DPDK Environment Abstraction Layer (EAL).
-
-A typical DPDK IVSHMEM use case looks like the following.
-
-
-.. figure:: img/ivshmem.*
-
-   Typical Ivshmem use case
-
-
-The same could work with several virtual machines, providing host-to-VM or VM-to-VM communication.
-The maximum number of metadata files is 32 (by default) and each metadata file can contain different (or even the same) hugepages.
-The only constraint is that each VM has to have access to the memory it is sharing with other entities (be it host or another VM).
-For example, if the user wants to share the same memzone across two VMs, each VM must have that memzone in its metadata file.
-
-IVHSHMEM Library API Overview
------------------------------
-
-The following is a simple guide to using the IVSHMEM Library API:
-
-*   Call rte_ivshmem_metadata_create() to create a new metadata file.
-    The metadata name is used to distinguish between multiple metadata files.
-
-*   Populate each metadata file with DPDK data structures.
-    This can be done using the following API calls:
-
-    *   rte_ivhshmem_metadata_add_memzone() to add rte_memzone to metadata file
-
-    *   rte_ivshmem_metadata_add_ring() to add rte_ring to metadata file
-
-    *   rte_ivshmem_metadata_add_mempool() to add rte_mempool to metadata file
-
-*   Finally, call rte_ivshmem_metadata_cmdline_generate() to generate the command line for QEMU.
-    Multiple metadata files (and thus multiple command lines) can be supplied to a single VM.
-
-.. note::
-
-    Only data structures fully residing in DPDK hugepage memory work correctly.
-    Supported data structures created by malloc(), mmap()
-    or otherwise using non-DPDK memory cause undefined behavior and even a segmentation fault.
-    Specifically, because the memzone field in an rte_ring refers to a memzone structure residing in local memory,
-    accessing the memzone field in a shared rte_ring will cause an immediate segmentation fault.
-
-IVSHMEM Environment Configuration
----------------------------------
-
-The steps needed to successfully run IVSHMEM applications are the following:
-
-*   Compile a special version of QEMU from sources.
-
-    The source code can be found on the QEMU website (currently, version 1.4.x is supported, but version 1.5.x is known to work also),
-    however, the source code will need to be patched to support using regular files as the IVSHMEM memory backend.
-    The patch is not included in the DPDK package,
-    but is available on the `Intel®DPDK-vswitch project webpage <https://01.org/packet-processing/intel%C2%AE-ovdk>`_
-    (either separately or in a DPDK vSwitch package).
-
-*   Enable IVSHMEM library in the DPDK build configuration.
-
-    In the default configuration, IVSHMEM library is not compiled. To compile the IVSHMEM library,
-    one has to either use one of the provided IVSHMEM targets
-    (for example, x86_64-ivshmem-linuxapp-gcc),
-    or set CONFIG_RTE_LIBRTE_IVSHMEM to "y" in the build configuration.
-
-*   Set up hugepage memory on the virtual machine.
-
-    The guest applications run as regular DPDK (primary) processes and thus need their own hugepage memory set up inside the VM.
-    The process is identical to the one described in the *DPDK Getting Started Guide*.
-
-Best Practices for Writing IVSHMEM Applications
------------------------------------------------
-
-When considering the use of IVSHMEM for sharing memory, security implications need to be carefully evaluated.
-IVSHMEM is not suitable for untrusted guests, as IVSHMEM is essentially a window into the host process memory.
-This also has implications for the multiple VM scenarios.
-While the IVSHMEM library tries to share as little memory as possible,
-it is quite probable that data designated for one VM might also be present in an IVSMHMEM device designated for another VM.
-Consequently, any shared memory corruption will affect both host and all VMs sharing that particular memory.
-
-IVSHMEM applications essentially behave like multi-process applications,
-so it is important to implement access serialization to data and thread safety.
-DPDK ring structures are already thread-safe, however,
-any custom data structures that the user might need would have to be thread-safe also.
-
-Similar to regular DPDK multi-process applications,
-it is not recommended to use function pointers as functions might have different memory addresses in different processes.
-
-It is best to avoid freeing the rte_mbuf structure on a different machine from where it was allocated,
-that is, if the mbuf was allocated on the host, the host should free it.
-Consequently, any packet transmission and reception should also happen on the same machine (whether virtual or physical).
-Failing to do so may lead to data corruption in the mempool cache.
-
-Despite the IVSHMEM mechanism being zero-copy and having good performance,
-it is still desirable to do processing in batches and follow other procedures described in
-:ref:`Performance Optimization <Performance_Optimization>`.
-
-Best Practices for Running IVSHMEM Applications
------------------------------------------------
-
-For performance reasons,
-it is best to pin host processes and QEMU processes to different cores so that they do not interfere with each other.
-If NUMA support is enabled, it is also desirable to keep host process' hugepage memory and QEMU process on the same NUMA node.
-
-For the best performance across all NUMA nodes, each QEMU core should be pinned to host CPU core on the appropriate NUMA node.
-QEMU's virtual NUMA nodes should also be set up to correspond to physical NUMA nodes.
-More on how to set up DPDK and QEMU NUMA support can be found in *DPDK Getting Started Guide* and
-`QEMU documentation <http://qemu.weilnetz.de/qemu-doc.html>`_ respectively.
-A script called cpu_layout.py is provided with the DPDK package (in the tools directory)
-that can be used to identify which CPU cores correspond to which NUMA node.
-
-The QEMU IVSHMEM command line creation should be considered the last step before starting the virtual machine.
-Currently, there is no hot plug support for QEMU IVSHMEM devices,
-so one cannot add additional memory to an IVSHMEM device once it has been created.
-Therefore, the correct sequence to run an IVSHMEM application is to run host application first,
-obtain the command lines for each IVSHMEM device and then run all QEMU instances with guest applications afterwards.
-
-It is important to note that once QEMU is started, it holds on to the hugepages it uses for IVSHMEM devices.
-As a result, if the user wishes to shut down or restart the IVSHMEM host application,
-it is not enough to simply shut the application down.
-The virtual machine must also be shut down (if not, it will hold onto outdated host data).
diff --git a/doc/guides/prog_guide/source_org.rst b/doc/guides/prog_guide/source_org.rst
index 0c06d47..d9c140f 100644
--- a/doc/guides/prog_guide/source_org.rst
+++ b/doc/guides/prog_guide/source_org.rst
@@ -70,7 +70,6 @@ The lib directory contains::
     +-- librte_ether        # Generic interface to poll mode driver
     +-- librte_hash         # Hash library
     +-- librte_ip_frag      # IP fragmentation library
-    +-- librte_ivshmem      # QEMU IVSHMEM library
     +-- librte_kni          # Kernel NIC interface
     +-- librte_kvargs       # Argument parsing library
     +-- librte_lpm          # Longest prefix match library
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index d2dc4a9..be03262 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -54,9 +54,6 @@ Deprecation Notices
   will be removed in 16.11.
   It is replaced by rte_mempool_generic_get/put functions.
 
-* The ``rte_ivshmem`` feature (including library and EAL code) will be removed
-  in 16.11 because it has some design issues which are not planned to be fixed.
-
 * The vhost-cuse will be removed in 16.11. Since v2.1, a large majority of
   development effort has gone to vhost-user, such as multiple-queue, live
   migration, reconnect etc. Therefore, vhost-user should be used instead.
diff --git a/doc/guides/rel_notes/release_16_11.rst b/doc/guides/rel_notes/release_16_11.rst
index a6e3307..f7a2ceb 100644
--- a/doc/guides/rel_notes/release_16_11.rst
+++ b/doc/guides/rel_notes/release_16_11.rst
@@ -94,6 +94,9 @@ API Changes
 
    This section is a comment. Make sure to start the actual text at the margin.
 
+* The ``rte_ivshmem`` feature (including library and EAL code) has been removed
+  in 16.11 because it had some design issues which were not planned to be fixed.
+
 
 ABI Changes
 -----------
diff --git a/examples/Makefile b/examples/Makefile
index 18b41b9..d49c7f2 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -61,7 +61,6 @@ ifneq ($(PQOS_INSTALL_PATH),)
 DIRS-y += l2fwd-cat
 endif
 DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += l2fwd-crypto
-DIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += l2fwd-ivshmem
 DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += l2fwd-jobstats
 DIRS-y += l2fwd-keepalive
 DIRS-y += l2fwd-keepalive/ka-agent
diff --git a/examples/l2fwd-ivshmem/Makefile b/examples/l2fwd-ivshmem/Makefile
deleted file mode 100644
index 5f1d172..0000000
--- a/examples/l2fwd-ivshmem/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 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.
-
-ifeq ($(RTE_SDK),)
-$(error "Please define RTE_SDK environment variable")
-endif
-
-# Default target, can be overriden by command line or environment
-RTE_TARGET ?= x86_64-ivshmem-linuxapp-gcc
-
-include $(RTE_SDK)/mk/rte.vars.mk
-
-DIRS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += host guest
-
-include $(RTE_SDK)/mk/rte.extsubdir.mk
diff --git a/examples/l2fwd-ivshmem/guest/Makefile b/examples/l2fwd-ivshmem/guest/Makefile
deleted file mode 100644
index 3ca73b4..0000000
--- a/examples/l2fwd-ivshmem/guest/Makefile
+++ /dev/null
@@ -1,50 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 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.
-
-ifeq ($(RTE_SDK),)
-$(error "Please define RTE_SDK environment variable")
-endif
-
-# Default target, can be overriden by command line or environment
-RTE_TARGET ?= x86_64-ivshmem-linuxapp-gcc
-
-include $(RTE_SDK)/mk/rte.vars.mk
-
-# binary name
-APP = guest
-
-# all source are stored in SRCS-y
-SRCS-y := guest.c
-
-CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
-
-include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/examples/l2fwd-ivshmem/guest/guest.c b/examples/l2fwd-ivshmem/guest/guest.c
deleted file mode 100644
index 7c49521..0000000
--- a/examples/l2fwd-ivshmem/guest/guest.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/queue.h>
-#include <sys/file.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-
-#include <rte_common.h>
-#include <rte_eal_memconfig.h>
-#include <rte_log.h>
-#include <rte_memory.h>
-#include <rte_memcpy.h>
-#include <rte_memzone.h>
-#include <rte_eal.h>
-#include <rte_per_lcore.h>
-#include <rte_launch.h>
-#include <rte_atomic.h>
-#include <rte_cycles.h>
-#include <rte_prefetch.h>
-#include <rte_lcore.h>
-#include <rte_per_lcore.h>
-#include <rte_branch_prediction.h>
-#include <rte_interrupts.h>
-#include <rte_pci.h>
-#include <rte_random.h>
-#include <rte_debug.h>
-#include <rte_ether.h>
-#include <rte_ethdev.h>
-#include <rte_ring.h>
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-#include <rte_ivshmem.h>
-
-#include "../include/common.h"
-
-#define MAX_RX_QUEUE_PER_LCORE 16
-#define MAX_TX_QUEUE_PER_PORT 16
-struct lcore_queue_conf {
-	unsigned n_rx_port;
-	unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];
-	struct mbuf_table rx_mbufs[RTE_MAX_ETHPORTS];
-	struct vm_port_param * port_param[MAX_RX_QUEUE_PER_LCORE];
-} __rte_cache_aligned;
-static struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
-
-/* Print out statistics on packets dropped */
-static void
-print_stats(void)
-{
-	uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;
-	unsigned portid;
-
-	total_packets_dropped = 0;
-	total_packets_tx = 0;
-	total_packets_rx = 0;
-
-	const char clr[] = { 27, '[', '2', 'J', '\0' };
-	const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' };
-
-		/* Clear screen and move to top left */
-	printf("%s%s", clr, topLeft);
-
-	printf("\nPort statistics ====================================");
-
-	for (portid = 0; portid < ctrl->nb_ports; portid++) {
-		/* skip ports that are not enabled */
-		printf("\nStatistics for port %u ------------------------------"
-			   "\nPackets sent: %24"PRIu64
-			   "\nPackets received: %20"PRIu64
-			   "\nPackets dropped: %21"PRIu64,
-			   portid,
-			   ctrl->vm_ports[portid].stats.tx,
-			   ctrl->vm_ports[portid].stats.rx,
-			   ctrl->vm_ports[portid].stats.dropped);
-
-		total_packets_dropped += ctrl->vm_ports[portid].stats.dropped;
-		total_packets_tx += ctrl->vm_ports[portid].stats.tx;
-		total_packets_rx += ctrl->vm_ports[portid].stats.rx;
-	}
-	printf("\nAggregate statistics ==============================="
-		   "\nTotal packets sent: %18"PRIu64
-		   "\nTotal packets received: %14"PRIu64
-		   "\nTotal packets dropped: %15"PRIu64,
-		   total_packets_tx,
-		   total_packets_rx,
-		   total_packets_dropped);
-	printf("\n====================================================\n");
-}
-
-/* display usage */
-static void
-l2fwd_ivshmem_usage(const char *prgname)
-{
-	printf("%s [EAL options] -- [-q NQ -T PERIOD]\n"
-		   "  -q NQ: number of queue (=ports) per lcore (default is 1)\n"
-		   "  -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n",
-	       prgname);
-}
-
-static unsigned int
-l2fwd_ivshmem_parse_nqueue(const char *q_arg)
-{
-	char *end = NULL;
-	unsigned long n;
-
-	/* parse hexadecimal string */
-	n = strtoul(q_arg, &end, 10);
-	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
-		return 0;
-	if (n == 0)
-		return 0;
-	if (n >= MAX_RX_QUEUE_PER_LCORE)
-		return 0;
-
-	return n;
-}
-
-static int
-l2fwd_ivshmem_parse_timer_period(const char *q_arg)
-{
-	char *end = NULL;
-	int n;
-
-	/* parse number string */
-	n = strtol(q_arg, &end, 10);
-	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
-		return -1;
-	if (n >= MAX_TIMER_PERIOD)
-		return -1;
-
-	return n;
-}
-
-/* Parse the argument given in the command line of the application */
-static int
-l2fwd_ivshmem_parse_args(int argc, char **argv)
-{
-	int opt, ret;
-	char **argvopt;
-	int option_index;
-	char *prgname = argv[0];
-	static struct option lgopts[] = {
-		{NULL, 0, 0, 0}
-	};
-
-	argvopt = argv;
-
-	while ((opt = getopt_long(argc, argvopt, "q:p:T:",
-				  lgopts, &option_index)) != EOF) {
-
-		switch (opt) {
-
-		/* nqueue */
-		case 'q':
-			l2fwd_ivshmem_rx_queue_per_lcore = l2fwd_ivshmem_parse_nqueue(optarg);
-			if (l2fwd_ivshmem_rx_queue_per_lcore == 0) {
-				printf("invalid queue number\n");
-				l2fwd_ivshmem_usage(prgname);
-				return -1;
-			}
-			break;
-
-		/* timer period */
-		case 'T':
-			timer_period = l2fwd_ivshmem_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND;
-			if (timer_period < 0) {
-				printf("invalid timer period\n");
-				l2fwd_ivshmem_usage(prgname);
-				return -1;
-			}
-			break;
-
-		/* long options */
-		case 0:
-			l2fwd_ivshmem_usage(prgname);
-			return -1;
-
-		default:
-			l2fwd_ivshmem_usage(prgname);
-			return -1;
-		}
-	}
-
-	if (optind >= 0)
-		argv[optind-1] = prgname;
-
-	ret = optind-1;
-	optind = 0; /* reset getopt lib */
-	return ret;
-}
-
-/*
- * this loop is getting packets from RX rings of each port, and puts them
- * into TX rings of destination ports.
- */
-static void
-fwd_loop(void)
-{
-
-	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
-	struct rte_mbuf **m_table;
-	struct rte_mbuf *m;
-	struct rte_ring *rx, *tx;
-	unsigned lcore_id, len;
-	uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;
-	unsigned i, j, portid, nb_rx;
-	struct lcore_queue_conf *qconf;
-	struct ether_hdr *eth;
-	void *tmp;
-
-	prev_tsc = 0;
-	timer_tsc = 0;
-
-	lcore_id = rte_lcore_id();
-	qconf = &lcore_queue_conf[lcore_id];
-
-	if (qconf->n_rx_port == 0) {
-		RTE_LOG(INFO, L2FWD_IVSHMEM, "lcore %u has nothing to do\n", lcore_id);
-		return;
-	}
-
-	RTE_LOG(INFO, L2FWD_IVSHMEM, "entering main loop on lcore %u\n", lcore_id);
-
-	for (i = 0; i < qconf->n_rx_port; i++) {
-		portid = qconf->rx_port_list[i];
-		RTE_LOG(INFO, L2FWD_IVSHMEM, " -- lcoreid=%u portid=%u\n", lcore_id,
-			portid);
-	}
-
-	while (ctrl->state == STATE_FWD) {
-		cur_tsc = rte_rdtsc();
-
-		diff_tsc = cur_tsc - prev_tsc;
-
-		/*
-		 * Read packet from RX queues and send it to TX queues
-		 */
-		for (i = 0; i < qconf->n_rx_port; i++) {
-
-			portid = qconf->rx_port_list[i];
-
-			len = qconf->rx_mbufs[portid].len;
-
-			rx = ctrl->vm_ports[portid].rx_ring;
-			tx = ctrl->vm_ports[portid].dst->tx_ring;
-
-			m_table = qconf->rx_mbufs[portid].m_table;
-
-			/* if we have something in the queue, try and transmit it down */
-			if (len != 0) {
-
-				/* if we succeed in sending the packets down, mark queue as free */
-				if (rte_ring_enqueue_bulk(tx, (void**) m_table, len) == 0) {
-					ctrl->vm_ports[portid].stats.tx += len;
-					qconf->rx_mbufs[portid].len = 0;
-					len = 0;
-				}
-			}
-
-			nb_rx = rte_ring_count(rx);
-
-			nb_rx = RTE_MIN(nb_rx, (unsigned) MAX_PKT_BURST);
-
-			if (nb_rx == 0)
-				continue;
-
-			/* if we can get packets into the m_table */
-			if (nb_rx < (RTE_DIM(qconf->rx_mbufs[portid].m_table) - len)) {
-
-				/* this situation cannot exist, so if we fail to dequeue, that
-				 * means something went horribly wrong, hence the failure. */
-				if (rte_ring_dequeue_bulk(rx, (void**) pkts_burst, nb_rx) < 0) {
-					ctrl->state = STATE_FAIL;
-					return;
-				}
-
-				ctrl->vm_ports[portid].stats.rx += nb_rx;
-
-				/* put packets into the queue */
-				for (j = 0; j < nb_rx; j++) {
-					m = pkts_burst[j];
-
-					rte_prefetch0(rte_pktmbuf_mtod(m, void *));
-
-					m_table[len + j] = m;
-
-					eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
-
-					/* 02:00:00:00:00:xx */
-					tmp = &eth->d_addr.addr_bytes[0];
-					*((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)portid << 40);
-
-					/* src addr */
-					ether_addr_copy(&ctrl->vm_ports[portid].dst->ethaddr,
-							&eth->s_addr);
-				}
-				qconf->rx_mbufs[portid].len += nb_rx;
-
-			}
-
-		}
-
-		/* if timer is enabled */
-		if (timer_period > 0) {
-
-			/* advance the timer */
-			timer_tsc += diff_tsc;
-
-			/* if timer has reached its timeout */
-			if (unlikely(timer_tsc >= (uint64_t) timer_period)) {
-
-				/* do this only on master core */
-				if (lcore_id == rte_get_master_lcore()) {
-					print_stats();
-					/* reset the timer */
-					timer_tsc = 0;
-				}
-			}
-		}
-
-		prev_tsc = cur_tsc;
-	}
-}
-
-static int
-l2fwd_ivshmem_launch_one_lcore(__attribute__((unused)) void *dummy)
-{
-	fwd_loop();
-	return 0;
-}
-
-int
-main(int argc, char **argv)
-{
-	struct lcore_queue_conf *qconf;
-	const struct rte_memzone * mz;
-	int ret;
-	uint8_t portid;
-	unsigned rx_lcore_id, lcore_id;
-
-	/* init EAL */
-	ret = rte_eal_init(argc, argv);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
-	argc -= ret;
-	argv += ret;
-
-	/* parse application arguments (after the EAL ones) */
-	ret = l2fwd_ivshmem_parse_args(argc, argv);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Invalid l2fwd-ivshmem arguments\n");
-
-	/* find control structure */
-	mz = rte_memzone_lookup(CTRL_MZ_NAME);
-	if (mz == NULL)
-		rte_exit(EXIT_FAILURE, "Cannot find control memzone\n");
-
-	ctrl = (struct ivshmem_ctrl*) mz->addr;
-
-	/* lock the ctrl so that we don't have conflicts with anything else */
-	rte_spinlock_lock(&ctrl->lock);
-
-	if (ctrl->state == STATE_FWD)
-		rte_exit(EXIT_FAILURE, "Forwarding already started!\n");
-
-	rx_lcore_id = 0;
-	qconf = NULL;
-
-	/* Initialize the port/queue configuration of each logical core */
-	for (portid = 0; portid < ctrl->nb_ports; portid++) {
-
-		/* get the lcore_id for this port */
-		while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
-			   lcore_queue_conf[rx_lcore_id].n_rx_port ==
-			   l2fwd_ivshmem_rx_queue_per_lcore) {
-			rx_lcore_id++;
-			if (rx_lcore_id >= RTE_MAX_LCORE)
-				rte_exit(EXIT_FAILURE, "Not enough cores\n");
-		}
-
-		if (qconf != &lcore_queue_conf[rx_lcore_id])
-			/* Assigned a new logical core in the loop above. */
-			qconf = &lcore_queue_conf[rx_lcore_id];
-
-		qconf->rx_port_list[qconf->n_rx_port] = portid;
-		qconf->port_param[qconf->n_rx_port] = &ctrl->vm_ports[portid];
-		qconf->n_rx_port++;
-
-		printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid);
-	}
-
-	sigsetup();
-
-	/* indicate that we are ready to forward */
-	ctrl->state = STATE_FWD;
-
-	/* unlock */
-	rte_spinlock_unlock(&ctrl->lock);
-
-	/* launch per-lcore init on every lcore */
-	rte_eal_mp_remote_launch(l2fwd_ivshmem_launch_one_lcore, NULL, CALL_MASTER);
-	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
-		if (rte_eal_wait_lcore(lcore_id) < 0)
-			return -1;
-	}
-
-	return 0;
-}
diff --git a/examples/l2fwd-ivshmem/host/Makefile b/examples/l2fwd-ivshmem/host/Makefile
deleted file mode 100644
index f91419e..0000000
--- a/examples/l2fwd-ivshmem/host/Makefile
+++ /dev/null
@@ -1,50 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 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.
-
-ifeq ($(RTE_SDK),)
-$(error "Please define RTE_SDK environment variable")
-endif
-
-# Default target, can be overriden by command line or environment
-RTE_TARGET ?= x86_64-ivshmem-linuxapp-gcc
-
-include $(RTE_SDK)/mk/rte.vars.mk
-
-# binary name
-APP = host
-
-# all source are stored in SRCS-y
-SRCS-y := host.c
-
-CFLAGS += -O3
-CFLAGS += $(WERROR_FLAGS)
-
-include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/examples/l2fwd-ivshmem/host/host.c b/examples/l2fwd-ivshmem/host/host.c
deleted file mode 100644
index da7b00d..0000000
--- a/examples/l2fwd-ivshmem/host/host.c
+++ /dev/null
@@ -1,895 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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 <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <inttypes.h>
-#include <getopt.h>
-#include <signal.h>
-
-#include <rte_eal.h>
-#include <rte_cycles.h>
-#include <rte_eal_memconfig.h>
-#include <rte_debug.h>
-#include <rte_ether.h>
-#include <rte_ethdev.h>
-#include <rte_string_fns.h>
-#include <rte_ivshmem.h>
-#include <rte_ring.h>
-#include <rte_mempool.h>
-#include <rte_mbuf.h>
-
-#include "../include/common.h"
-
-/*
- * Configurable number of RX/TX ring descriptors
- */
-#define RTE_TEST_RX_DESC_DEFAULT 128
-#define RTE_TEST_TX_DESC_DEFAULT 512
-static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
-static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
-
-#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
-
-/* mask of enabled ports */
-static uint32_t l2fwd_ivshmem_enabled_port_mask = 0;
-
-static struct ether_addr l2fwd_ivshmem_ports_eth_addr[RTE_MAX_ETHPORTS];
-
-#define NB_MBUF   8192
-
-#define MAX_RX_QUEUE_PER_LCORE 16
-#define MAX_TX_QUEUE_PER_PORT 16
-struct lcore_queue_conf {
-	unsigned n_rx_port;
-	unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];
-	struct vm_port_param * port_param[MAX_RX_QUEUE_PER_LCORE];
-	struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];
-	struct mbuf_table rx_mbufs[RTE_MAX_ETHPORTS];
-} __rte_cache_aligned;
-static struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
-
-static const struct rte_eth_conf port_conf = {
-	.rxmode = {
-		.split_hdr_size = 0,
-		.header_split   = 0, /**< Header Split disabled */
-		.hw_ip_checksum = 0, /**< IP checksum offload disabled */
-		.hw_vlan_filter = 0, /**< VLAN filtering disabled */
-		.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
-		.hw_strip_crc   = 0, /**< CRC stripped by hardware */
-	},
-	.txmode = {
-		.mq_mode = ETH_MQ_TX_NONE,
-	},
-};
-
-#define METADATA_NAME "l2fwd_ivshmem"
-#define CMDLINE_OPT_FWD_CONF "fwd-conf"
-
-#define QEMU_CMD_FMT "/tmp/ivshmem_qemu_cmdline_%s"
-
-struct port_statistics port_statistics[RTE_MAX_ETHPORTS];
-
-struct rte_mempool * l2fwd_ivshmem_pktmbuf_pool = NULL;
-
-/* Print out statistics on packets dropped */
-static void
-print_stats(void)
-{
-	uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;
-	uint64_t total_vm_packets_dropped = 0;
-	uint64_t total_vm_packets_tx, total_vm_packets_rx;
-	unsigned portid;
-
-	total_packets_dropped = 0;
-	total_packets_tx = 0;
-	total_packets_rx = 0;
-	total_vm_packets_tx = 0;
-	total_vm_packets_rx = 0;
-
-	const char clr[] = { 27, '[', '2', 'J', '\0' };
-	const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' };
-
-		/* Clear screen and move to top left */
-	printf("%s%s", clr, topLeft);
-
-	printf("\nPort statistics ====================================");
-
-	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
-		/* skip disabled ports */
-		if ((l2fwd_ivshmem_enabled_port_mask & (1 << portid)) == 0)
-			continue;
-		printf("\nStatistics for port %u ------------------------------"
-			   "\nPackets sent: %24"PRIu64
-			   "\nPackets received: %20"PRIu64
-			   "\nPackets dropped: %21"PRIu64,
-			   portid,
-			   port_statistics[portid].tx,
-			   port_statistics[portid].rx,
-			   port_statistics[portid].dropped);
-
-		total_packets_dropped += port_statistics[portid].dropped;
-		total_packets_tx += port_statistics[portid].tx;
-		total_packets_rx += port_statistics[portid].rx;
-	}
-
-	printf("\nVM statistics ======================================");
-	for (portid = 0; portid < ctrl->nb_ports; portid++) {
-		printf("\nStatistics for port %u ------------------------------"
-			   "\nPackets sent: %24"PRIu64
-			   "\nPackets received: %20"PRIu64,
-			   portid,
-			   ctrl->vm_ports[portid].stats.tx,
-			   ctrl->vm_ports[portid].stats.rx);
-
-		total_vm_packets_dropped += ctrl->vm_ports[portid].stats.dropped;
-		total_vm_packets_tx += ctrl->vm_ports[portid].stats.tx;
-		total_vm_packets_rx += ctrl->vm_ports[portid].stats.rx;
-	}
-	printf("\nAggregate statistics ==============================="
-			   "\nTotal packets sent: %18"PRIu64
-			   "\nTotal packets received: %14"PRIu64
-			   "\nTotal packets dropped: %15"PRIu64
-			   "\nTotal VM packets sent: %15"PRIu64
-			   "\nTotal VM packets received: %11"PRIu64,
-			   total_packets_tx,
-			   total_packets_rx,
-			   total_packets_dropped,
-			   total_vm_packets_tx,
-			   total_vm_packets_rx);
-	printf("\n====================================================\n");
-}
-
-static int
-print_to_file(const char *cmdline, const char *config_name)
-{
-	FILE *file;
-	char path[PATH_MAX];
-
-	snprintf(path, sizeof(path), QEMU_CMD_FMT, config_name);
-	file = fopen(path, "w");
-	if (file == NULL) {
-		RTE_LOG(ERR, L2FWD_IVSHMEM, "Could not open '%s' \n", path);
-		return -1;
-	}
-
-	RTE_LOG(DEBUG, L2FWD_IVSHMEM, "QEMU command line for config '%s': %s \n",
-			config_name, cmdline);
-
-	fprintf(file, "%s\n", cmdline);
-	fclose(file);
-	return 0;
-}
-
-static int
-generate_ivshmem_cmdline(const char *config_name)
-{
-	char cmdline[PATH_MAX];
-	if (rte_ivshmem_metadata_cmdline_generate(cmdline, sizeof(cmdline),
-			config_name) < 0)
-		return -1;
-
-	if (print_to_file(cmdline, config_name) < 0)
-		return -1;
-
-	rte_ivshmem_metadata_dump(stdout, config_name);
-	return 0;
-}
-
-/* display usage */
-static void
-l2fwd_ivshmem_usage(const char *prgname)
-{
-	printf("%s [EAL options] -- -p PORTMASK [-q NQ -T PERIOD]\n"
-		   "  -p PORTMASK: hexadecimal bitmask of ports to configure\n"
-		   "  -q NQ: number of queue (=ports) per lcore (default is 1)\n"
-		   "  -T PERIOD: statistics will be refreshed each PERIOD seconds "
-		       "(0 to disable, 10 default, 86400 maximum)\n",
-	       prgname);
-}
-
-static unsigned int
-l2fwd_ivshmem_parse_nqueue(const char *q_arg)
-{
-	char *end = NULL;
-	unsigned long n;
-
-	/* parse hexadecimal string */
-	n = strtoul(q_arg, &end, 10);
-	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
-		return 0;
-	if (n == 0)
-		return 0;
-	if (n >= MAX_RX_QUEUE_PER_LCORE)
-		return 0;
-
-	return n;
-}
-
-static int
-l2fwd_ivshmem_parse_portmask(const char *portmask)
-{
-	char *end = NULL;
-	unsigned long pm;
-
-	/* parse hexadecimal string */
-	pm = strtoul(portmask, &end, 16);
-	if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
-		return -1;
-
-	if (pm == 0)
-		return -1;
-
-	return pm;
-}
-
-static int
-l2fwd_ivshmem_parse_timer_period(const char *q_arg)
-{
-	char *end = NULL;
-	int n;
-
-	/* parse number string */
-	n = strtol(q_arg, &end, 10);
-	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
-		return -1;
-	if (n >= MAX_TIMER_PERIOD)
-		return -1;
-
-	return n;
-}
-
-/* Parse the argument given in the command line of the application */
-static int
-l2fwd_ivshmem_parse_args(int argc, char **argv)
-{
-	int opt, ret;
-	char **argvopt;
-	int option_index;
-	char *prgname = argv[0];
-	static struct option lgopts[] = {
-			{CMDLINE_OPT_FWD_CONF, 1, 0, 0},
-		{NULL, 0, 0, 0}
-	};
-
-	argvopt = argv;
-
-	while ((opt = getopt_long(argc, argvopt, "q:p:T:",
-				  lgopts, &option_index)) != EOF) {
-
-		switch (opt) {
-		/* portmask */
-		case 'p':
-			l2fwd_ivshmem_enabled_port_mask = l2fwd_ivshmem_parse_portmask(optarg);
-			if (l2fwd_ivshmem_enabled_port_mask == 0) {
-				printf("invalid portmask\n");
-				l2fwd_ivshmem_usage(prgname);
-				return -1;
-			}
-			break;
-
-		/* nqueue */
-		case 'q':
-			l2fwd_ivshmem_rx_queue_per_lcore = l2fwd_ivshmem_parse_nqueue(optarg);
-			if (l2fwd_ivshmem_rx_queue_per_lcore == 0) {
-				printf("invalid queue number\n");
-				l2fwd_ivshmem_usage(prgname);
-				return -1;
-			}
-			break;
-
-		/* timer period */
-		case 'T':
-			timer_period = l2fwd_ivshmem_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND;
-			if (timer_period < 0) {
-				printf("invalid timer period\n");
-				l2fwd_ivshmem_usage(prgname);
-				return -1;
-			}
-			break;
-
-		/* long options */
-		case 0:
-			l2fwd_ivshmem_usage(prgname);
-			return -1;
-
-		default:
-			l2fwd_ivshmem_usage(prgname);
-			return -1;
-		}
-	}
-
-	if (optind >= 0)
-		argv[optind-1] = prgname;
-
-	ret = optind-1;
-	optind = 0; /* reset getopt lib */
-	return ret;
-}
-
-/* Check the link status of all ports in up to 9s, and print them finally */
-static void
-check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
-{
-#define CHECK_INTERVAL 100 /* 100ms */
-#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
-	uint8_t portid, count, all_ports_up, print_flag = 0;
-	struct rte_eth_link link;
-
-	printf("\nChecking link status");
-	fflush(stdout);
-	for (count = 0; count <= MAX_CHECK_TIME; count++) {
-		all_ports_up = 1;
-		for (portid = 0; portid < port_num; portid++) {
-			if ((port_mask & (1 << portid)) == 0)
-				continue;
-			memset(&link, 0, sizeof(link));
-			rte_eth_link_get_nowait(portid, &link);
-			/* print link status if flag set */
-			if (print_flag == 1) {
-				if (link.link_status)
-					printf("Port %d Link Up - speed %u "
-						"Mbps - %s\n", (uint8_t)portid,
-						(unsigned)link.link_speed,
-				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
-				else
-					printf("Port %d Link Down\n",
-						(uint8_t)portid);
-				continue;
-			}
-			/* clear all_ports_up flag if any link down */
-			if (link.link_status == ETH_LINK_DOWN) {
-				all_ports_up = 0;
-				break;
-			}
-		}
-		/* after finally printing all link status, get out */
-		if (print_flag == 1)
-			break;
-
-		if (all_ports_up == 0) {
-			printf(".");
-			fflush(stdout);
-			rte_delay_ms(CHECK_INTERVAL);
-		}
-
-		/* set the print_flag if all ports up or timeout */
-		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
-			print_flag = 1;
-			printf("done\n");
-		}
-	}
-}
-
-/* Send the burst of packets on an output interface */
-static int
-l2fwd_ivshmem_send_burst(struct lcore_queue_conf *qconf, unsigned n, uint8_t port)
-{
-	struct rte_mbuf **m_table;
-	unsigned ret;
-	unsigned queueid =0;
-
-	m_table = (struct rte_mbuf **)qconf->tx_mbufs[port].m_table;
-
-	ret = rte_eth_tx_burst(port, (uint16_t) queueid, m_table, (uint16_t) n);
-	port_statistics[port].tx += ret;
-	if (unlikely(ret < n)) {
-		port_statistics[port].dropped += (n - ret);
-		do {
-			rte_pktmbuf_free(m_table[ret]);
-		} while (++ret < n);
-	}
-
-	return 0;
-}
-
-/* Enqueue packets for TX and prepare them to be sent on the network */
-static int
-l2fwd_ivshmem_send_packet(struct rte_mbuf *m, uint8_t port)
-{
-	unsigned lcore_id, len;
-	struct lcore_queue_conf *qconf;
-
-	lcore_id = rte_lcore_id();
-
-	qconf = &lcore_queue_conf[lcore_id];
-	len = qconf->tx_mbufs[port].len;
-	qconf->tx_mbufs[port].m_table[len] = m;
-	len++;
-
-	/* enough pkts to be sent */
-	if (unlikely(len == MAX_PKT_BURST)) {
-		l2fwd_ivshmem_send_burst(qconf, MAX_PKT_BURST, port);
-		len = 0;
-	}
-
-	qconf->tx_mbufs[port].len = len;
-	return 0;
-}
-
-static int
-l2fwd_ivshmem_receive_burst(struct lcore_queue_conf *qconf, unsigned portid,
-		unsigned vm_port)
-{
-	struct rte_mbuf ** m;
-	struct rte_ring * rx;
-	unsigned len, pkt_idx;
-
-	m = qconf->rx_mbufs[portid].m_table;
-	len = qconf->rx_mbufs[portid].len;
-	rx = qconf->port_param[vm_port]->rx_ring;
-
-	/* if enqueueing failed, ring is probably full, so drop the packets */
-	if (rte_ring_enqueue_bulk(rx, (void**) m, len) < 0) {
-		port_statistics[portid].dropped += len;
-
-		pkt_idx = 0;
-		do {
-			rte_pktmbuf_free(m[pkt_idx]);
-		} while (++pkt_idx < len);
-	}
-	else
-		/* increment rx stats by however many packets we managed to receive */
-		port_statistics[portid].rx += len;
-
-	return 0;
-}
-
-/* Enqueue packets for RX and prepare them to be sent to VM */
-static int
-l2fwd_ivshmem_receive_packets(struct rte_mbuf ** m, unsigned n, unsigned portid,
-		unsigned vm_port)
-{
-	unsigned lcore_id, len, pkt_idx;
-	struct lcore_queue_conf *qconf;
-
-	lcore_id = rte_lcore_id();
-
-	qconf = &lcore_queue_conf[lcore_id];
-
-	len = qconf->rx_mbufs[portid].len;
-	pkt_idx = 0;
-
-	/* enqueue packets */
-	while (pkt_idx < n && len < MAX_PKT_BURST * 2) {
-		qconf->rx_mbufs[portid].m_table[len++] = m[pkt_idx++];
-	}
-
-	/* increment queue len by however many packets we managed to receive */
-	qconf->rx_mbufs[portid].len += pkt_idx;
-
-	/* drop the unreceived packets */
-	if (unlikely(pkt_idx < n)) {
-		port_statistics[portid].dropped += n - pkt_idx;
-		do {
-			rte_pktmbuf_free(m[pkt_idx]);
-		} while (++pkt_idx < n);
-	}
-
-	/* drain the queue halfway through the maximum capacity */
-	if (unlikely(qconf->rx_mbufs[portid].len >= MAX_PKT_BURST))
-		l2fwd_ivshmem_receive_burst(qconf, portid, vm_port);
-
-	return 0;
-}
-
-/* loop for host forwarding mode.
- * the data flow is as follows:
- *  1) get packets from TX queue and send it out from a given port
- *  2) RX packets from given port and enqueue them on RX ring
- *  3) dequeue packets from TX ring and put them on TX queue for a given port
- */
-static void
-fwd_loop(void)
-{
-	struct rte_mbuf *pkts_burst[MAX_PKT_BURST * 2];
-	struct rte_mbuf *m;
-	unsigned lcore_id;
-	uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;
-	unsigned i, j, portid, nb_rx;
-	struct lcore_queue_conf *qconf;
-	struct rte_ring *tx;
-	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US;
-
-	prev_tsc = 0;
-	timer_tsc = 0;
-
-	lcore_id = rte_lcore_id();
-	qconf = &lcore_queue_conf[lcore_id];
-
-	if (qconf->n_rx_port == 0) {
-		RTE_LOG(INFO, L2FWD_IVSHMEM, "lcore %u has nothing to do\n", lcore_id);
-		return;
-	}
-
-	RTE_LOG(INFO, L2FWD_IVSHMEM, "entering main loop on lcore %u\n", lcore_id);
-
-	for (i = 0; i < qconf->n_rx_port; i++) {
-
-		portid = qconf->rx_port_list[i];
-		RTE_LOG(INFO, L2FWD_IVSHMEM, " -- lcoreid=%u portid=%u\n", lcore_id,
-			portid);
-	}
-
-	while (ctrl->state == STATE_FWD) {
-
-		cur_tsc = rte_rdtsc();
-
-		/*
-		 * Burst queue drain
-		 */
-		diff_tsc = cur_tsc - prev_tsc;
-		if (unlikely(diff_tsc > drain_tsc)) {
-
-			/*
-			 * TX
-			 */
-			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
-				if (qconf->tx_mbufs[portid].len == 0)
-					continue;
-				l2fwd_ivshmem_send_burst(qconf,
-						 qconf->tx_mbufs[portid].len,
-						 (uint8_t) portid);
-				qconf->tx_mbufs[portid].len = 0;
-			}
-
-			/*
-			 * RX
-			 */
-			for (i = 0; i < qconf->n_rx_port; i++) {
-				portid = qconf->rx_port_list[i];
-				if (qconf->rx_mbufs[portid].len == 0)
-					continue;
-				l2fwd_ivshmem_receive_burst(qconf, portid, i);
-				qconf->rx_mbufs[portid].len = 0;
-			}
-
-			/* if timer is enabled */
-			if (timer_period > 0) {
-
-				/* advance the timer */
-				timer_tsc += diff_tsc;
-
-				/* if timer has reached its timeout */
-				if (unlikely(timer_tsc >= (uint64_t) timer_period)) {
-
-					/* do this only on master core */
-					if (lcore_id == rte_get_master_lcore()) {
-						print_stats();
-						/* reset the timer */
-						timer_tsc = 0;
-					}
-				}
-			}
-
-			prev_tsc = cur_tsc;
-		}
-
-		/*
-		 * packet RX and forwarding
-		 */
-		for (i = 0; i < qconf->n_rx_port; i++) {
-
-			/* RX packets from port and put them on RX ring */
-			portid = qconf->rx_port_list[i];
-			nb_rx = rte_eth_rx_burst((uint8_t) portid, 0,
-						 pkts_burst, MAX_PKT_BURST);
-
-			if (nb_rx != 0)
-				l2fwd_ivshmem_receive_packets(pkts_burst, nb_rx, portid, i);
-
-			/* dequeue packets from TX ring and send them to TX queue */
-			tx = qconf->port_param[i]->tx_ring;
-
-			nb_rx = rte_ring_count(tx);
-
-			nb_rx = RTE_MIN(nb_rx, (unsigned) MAX_PKT_BURST);
-
-			if (nb_rx == 0)
-				continue;
-
-			/* should not happen */
-			if (unlikely(rte_ring_dequeue_bulk(tx, (void**) pkts_burst, nb_rx) < 0)) {
-				ctrl->state = STATE_FAIL;
-				return;
-			}
-
-			for (j = 0; j < nb_rx; j++) {
-				m = pkts_burst[j];
-				l2fwd_ivshmem_send_packet(m, portid);
-			}
-		}
-	}
-}
-
-static int
-l2fwd_ivshmem_launch_one_lcore(__attribute__((unused)) void *dummy)
-{
-	fwd_loop();
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	char name[RTE_RING_NAMESIZE];
-	struct rte_ring *r;
-	struct lcore_queue_conf *qconf;
-	struct rte_eth_dev_info dev_info;
-	uint8_t portid, port_nr;
-	uint8_t nb_ports, nb_ports_available;
-	uint8_t nb_ports_in_mask;
-	int ret;
-	unsigned lcore_id, rx_lcore_id;
-
-	/* init EAL */
-	ret = rte_eal_init(argc, argv);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
-	argc -= ret;
-	argv += ret;
-
-	/* parse application arguments (after the EAL ones) */
-	ret = l2fwd_ivshmem_parse_args(argc, argv);
-	if (ret < 0)
-		rte_exit(EXIT_FAILURE, "Invalid l2fwd-ivshmem arguments\n");
-
-	/* create a shared mbuf pool */
-	l2fwd_ivshmem_pktmbuf_pool =
-		rte_pktmbuf_pool_create(MBUF_MP_NAME, NB_MBUF, 32,
-			0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
-	if (l2fwd_ivshmem_pktmbuf_pool == NULL)
-		rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
-
-	nb_ports = rte_eth_dev_count();
-	if (nb_ports == 0)
-		rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
-
-	/*
-	 * reserve memzone to communicate with VMs - we cannot use rte_malloc here
-	 * because while it is technically possible, it is a very bad idea to share
-	 * the heap between two primary processes.
-	 */
-	ctrl_mz = rte_memzone_reserve(CTRL_MZ_NAME, sizeof(struct ivshmem_ctrl),
-			SOCKET_ID_ANY, 0);
-	if (ctrl_mz == NULL)
-		rte_exit(EXIT_FAILURE, "Cannot reserve control memzone\n");
-	ctrl = (struct ivshmem_ctrl*) ctrl_mz->addr;
-
-	memset(ctrl, 0, sizeof(struct ivshmem_ctrl));
-
-	/*
-	 * Each port is assigned an output port.
-	 */
-	nb_ports_in_mask = 0;
-	for (portid = 0; portid < nb_ports; portid++) {
-		/* skip ports that are not enabled */
-		if ((l2fwd_ivshmem_enabled_port_mask & (1 << portid)) == 0)
-			continue;
-		if (portid % 2) {
-			ctrl->vm_ports[nb_ports_in_mask].dst = &ctrl->vm_ports[nb_ports_in_mask-1];
-			ctrl->vm_ports[nb_ports_in_mask-1].dst = &ctrl->vm_ports[nb_ports_in_mask];
-		}
-
-		nb_ports_in_mask++;
-
-		rte_eth_dev_info_get(portid, &dev_info);
-	}
-	if (nb_ports_in_mask % 2) {
-		printf("Notice: odd number of ports in portmask.\n");
-		ctrl->vm_ports[nb_ports_in_mask-1].dst =
-				&ctrl->vm_ports[nb_ports_in_mask-1];
-	}
-
-	rx_lcore_id = 0;
-	qconf = NULL;
-
-	printf("Initializing ports configuration...\n");
-
-	nb_ports_available = nb_ports;
-
-	/* Initialise each port */
-	for (portid = 0; portid < nb_ports; portid++) {
-
-		/* skip ports that are not enabled */
-		if ((l2fwd_ivshmem_enabled_port_mask & (1 << portid)) == 0) {
-			printf("Skipping disabled port %u\n", (unsigned) portid);
-			nb_ports_available--;
-			continue;
-		}
-
-		/* init port */
-		printf("Initializing port %u... ", (unsigned) portid);
-		fflush(stdout);
-		ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n",
-				  ret, (unsigned) portid);
-
-		rte_eth_macaddr_get(portid,&l2fwd_ivshmem_ports_eth_addr[portid]);
-
-		/* init one RX queue */
-		fflush(stdout);
-		ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
-						 rte_eth_dev_socket_id(portid),
-						 NULL,
-						 l2fwd_ivshmem_pktmbuf_pool);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n",
-				  ret, (unsigned) portid);
-
-		/* init one TX queue on each port */
-		fflush(stdout);
-		ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
-				rte_eth_dev_socket_id(portid),
-				NULL);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n",
-				ret, (unsigned) portid);
-
-		/* Start device */
-		ret = rte_eth_dev_start(portid);
-		if (ret < 0)
-			rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n",
-				  ret, (unsigned) portid);
-
-		printf("done: \n");
-
-		rte_eth_promiscuous_enable(portid);
-
-		printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
-				(unsigned) portid,
-				l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[0],
-				l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[1],
-				l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[2],
-				l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[3],
-				l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[4],
-				l2fwd_ivshmem_ports_eth_addr[portid].addr_bytes[5]);
-
-		/* initialize port stats */
-		memset(&port_statistics, 0, sizeof(port_statistics));
-	}
-
-	if (!nb_ports_available) {
-		rte_exit(EXIT_FAILURE,
-			"All available ports are disabled. Please set portmask.\n");
-	}
-	port_nr = 0;
-
-	/* Initialize the port/queue configuration of each logical core */
-	for (portid = 0; portid < nb_ports; portid++) {
-		if ((l2fwd_ivshmem_enabled_port_mask & (1 << portid)) == 0)
-			continue;
-
-		/* get the lcore_id for this port */
-		while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
-			   lcore_queue_conf[rx_lcore_id].n_rx_port ==
-					   l2fwd_ivshmem_rx_queue_per_lcore) {
-			rx_lcore_id++;
-			if (rx_lcore_id >= RTE_MAX_LCORE)
-				rte_exit(EXIT_FAILURE, "Not enough cores\n");
-		}
-
-		if (qconf != &lcore_queue_conf[rx_lcore_id])
-			/* Assigned a new logical core in the loop above. */
-			qconf = &lcore_queue_conf[rx_lcore_id];
-
-
-		rte_eth_macaddr_get(portid, &ctrl->vm_ports[port_nr].ethaddr);
-
-		qconf->rx_port_list[qconf->n_rx_port] = portid;
-		qconf->port_param[qconf->n_rx_port] = &ctrl->vm_ports[port_nr];
-		qconf->n_rx_port++;
-		port_nr++;
-		printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid);
-	}
-
-	check_all_ports_link_status(nb_ports_available, l2fwd_ivshmem_enabled_port_mask);
-
-	/* create rings for each VM port (several ports can be on the same VM).
-	 * note that we store the pointers in ctrl - that way, they are the same
-	 * and valid across all VMs because ctrl is also in DPDK memory */
-	for (portid = 0; portid < nb_ports_available; portid++) {
-
-		/* RX ring. SP/SC because it's only used by host and a single VM */
-		snprintf(name, sizeof(name), "%s%i", RX_RING_PREFIX, portid);
-		r = rte_ring_create(name, NB_MBUF,
-				SOCKET_ID_ANY, RING_F_SP_ENQ | RING_F_SC_DEQ);
-		if (r == NULL)
-			rte_exit(EXIT_FAILURE, "Cannot create ring %s\n", name);
-
-		ctrl->vm_ports[portid].rx_ring = r;
-
-		/* TX ring. SP/SC because it's only used by host and a single VM */
-		snprintf(name, sizeof(name), "%s%i", TX_RING_PREFIX, portid);
-		r = rte_ring_create(name, NB_MBUF,
-				SOCKET_ID_ANY, RING_F_SP_ENQ | RING_F_SC_DEQ);
-		if (r == NULL)
-			rte_exit(EXIT_FAILURE, "Cannot create ring %s\n", name);
-
-		ctrl->vm_ports[portid].tx_ring = r;
-	}
-
-	/* create metadata, output cmdline */
-	if (rte_ivshmem_metadata_create(METADATA_NAME) < 0)
-		rte_exit(EXIT_FAILURE, "Cannot create IVSHMEM metadata\n");
-
-	if (rte_ivshmem_metadata_add_memzone(ctrl_mz, METADATA_NAME))
-		rte_exit(EXIT_FAILURE, "Cannot add memzone to IVSHMEM metadata\n");
-
-	if (rte_ivshmem_metadata_add_mempool(l2fwd_ivshmem_pktmbuf_pool, METADATA_NAME))
-		rte_exit(EXIT_FAILURE, "Cannot add mbuf mempool to IVSHMEM metadata\n");
-
-	for (portid = 0; portid < nb_ports_available; portid++) {
-		if (rte_ivshmem_metadata_add_ring(ctrl->vm_ports[portid].rx_ring,
-				METADATA_NAME) < 0)
-			rte_exit(EXIT_FAILURE, "Cannot add ring %s to IVSHMEM metadata\n",
-					ctrl->vm_ports[portid].rx_ring->name);
-		if (rte_ivshmem_metadata_add_ring(ctrl->vm_ports[portid].tx_ring,
-				METADATA_NAME) < 0)
-			rte_exit(EXIT_FAILURE, "Cannot add ring %s to IVSHMEM metadata\n",
-					ctrl->vm_ports[portid].tx_ring->name);
-	}
-	generate_ivshmem_cmdline(METADATA_NAME);
-
-	ctrl->nb_ports = nb_ports_available;
-
-	printf("Waiting for VM to initialize...\n");
-
-	/* wait for VM to initialize */
-	while (ctrl->state != STATE_FWD) {
-		if (ctrl->state == STATE_FAIL)
-			rte_exit(EXIT_FAILURE, "VM reported failure\n");
-
-		sleep(1);
-	}
-
-	printf("Done!\n");
-
-	sigsetup();
-
-	/* launch per-lcore init on every lcore */
-	rte_eal_mp_remote_launch(l2fwd_ivshmem_launch_one_lcore, NULL, CALL_MASTER);
-	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
-		if (rte_eal_wait_lcore(lcore_id) < 0)
-			return -1;
-	}
-
-	if (ctrl->state == STATE_FAIL)
-		rte_exit(EXIT_FAILURE, "VM reported failure\n");
-
-	return 0;
-}
diff --git a/examples/l2fwd-ivshmem/include/common.h b/examples/l2fwd-ivshmem/include/common.h
deleted file mode 100644
index 8564d32..0000000
--- a/examples/l2fwd-ivshmem/include/common.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _IVSHMEM_COMMON_H_
-#define _IVSHMEM_COMMON_H_
-
-#define RTE_LOGTYPE_L2FWD_IVSHMEM RTE_LOGTYPE_USER1
-
-#define CTRL_MZ_NAME "CTRL_MEMZONE"
-#define MBUF_MP_NAME "MBUF_MEMPOOL"
-#define RX_RING_PREFIX "RX_"
-#define TX_RING_PREFIX "TX_"
-
-/* A tsc-based timer responsible for triggering statistics printout */
-#define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */
-#define MAX_TIMER_PERIOD 86400 /* 1 day max */
-static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */
-
-#define DIM(x)\
-	(sizeof(x)/sizeof(x)[0])
-
-#define MAX_PKT_BURST 32
-
-const struct rte_memzone * ctrl_mz;
-
-enum l2fwd_state {
-	STATE_NONE = 0,
-	STATE_FWD,
-	STATE_EXIT,
-	STATE_FAIL
-};
-
-/* Per-port statistics struct */
-struct port_statistics {
-	uint64_t tx;
-	uint64_t rx;
-	uint64_t dropped;
-} __rte_cache_aligned;
-
-struct mbuf_table {
-	unsigned len;
-	struct rte_mbuf *m_table[MAX_PKT_BURST * 2]; /**< allow up to two bursts */
-};
-
-struct vm_port_param {
-	struct rte_ring * rx_ring;         /**< receiving ring for current port */
-	struct rte_ring * tx_ring;         /**< transmitting ring for current port */
-	struct vm_port_param * dst;        /**< current port's destination port */
-	volatile struct port_statistics stats;      /**< statistics for current port */
-	struct ether_addr ethaddr;         /**< Ethernet address of the port */
-};
-
-/* control structure, to synchronize host and VM */
-struct ivshmem_ctrl {
-	rte_spinlock_t lock;
-	uint8_t nb_ports;                /**< total nr of ports */
-	volatile enum l2fwd_state state; /**< report state */
-	struct vm_port_param vm_ports[RTE_MAX_ETHPORTS];
-};
-
-struct ivshmem_ctrl * ctrl;
-
-static unsigned int l2fwd_ivshmem_rx_queue_per_lcore = 1;
-
-static void sighandler(int __rte_unused s)
-{
-	ctrl->state = STATE_EXIT;
-}
-
-static void sigsetup(void)
-{
-	   struct sigaction sigIntHandler;
-
-	   sigIntHandler.sa_handler = sighandler;
-	   sigemptyset(&sigIntHandler.sa_mask);
-	   sigIntHandler.sa_flags = 0;
-
-	   sigaction(SIGINT, &sigIntHandler, NULL);
-}
-
-#endif /* _IVSHMEM_COMMON_H_ */
diff --git a/examples/packet_ordering/Makefile b/examples/packet_ordering/Makefile
index 9e080a3..de066c4 100644
--- a/examples/packet_ordering/Makefile
+++ b/examples/packet_ordering/Makefile
@@ -34,7 +34,7 @@ $(error "Please define RTE_SDK environment variable")
 endif
 
 # Default target, can be overridden by command line or environment
-RTE_TARGET ?= x86_64-ivshmem-linuxapp-gcc
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
 
 include $(RTE_SDK)/mk/rte.vars.mk
 
diff --git a/lib/Makefile b/lib/Makefile
index ca7c02f..990f23a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -61,7 +61,6 @@ DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
-DIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += librte_ivshmem
 endif
 
 include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/lib/librte_eal/common/eal_common_memzone.c b/lib/librte_eal/common/eal_common_memzone.c
index 1bd0a33..64f4e0a 100644
--- a/lib/librte_eal/common/eal_common_memzone.c
+++ b/lib/librte_eal/common/eal_common_memzone.c
@@ -337,19 +337,7 @@ rte_memzone_free(const struct rte_memzone *mz)
 	idx = ((uintptr_t)mz - (uintptr_t)mcfg->memzone);
 	idx = idx / sizeof(struct rte_memzone);
 
-#ifdef RTE_LIBRTE_IVSHMEM
-	/*
-	 * If ioremap_addr is set, it's an IVSHMEM memzone and we cannot
-	 * free it.
-	 */
-	if (mcfg->memzone[idx].ioremap_addr != 0) {
-		rte_rwlock_write_unlock(&mcfg->mlock);
-		return -EINVAL;
-	}
-#endif
-
 	addr = mcfg->memzone[idx].addr;
-
 	if (addr == NULL)
 		ret = -EINVAL;
 	else if (mcfg->memzone_cnt == 0) {
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 857dc3e..0bda493 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -126,28 +126,6 @@ int rte_eal_log_init(const char *id, int facility);
  */
 int rte_eal_pci_init(void);
 
-#ifdef RTE_LIBRTE_IVSHMEM
-/**
- * Init the memory from IVSHMEM devices
- *
- * This function is private to EAL.
- *
- * @return
- *  0 on success, negative on error
- */
-int rte_eal_ivshmem_init(void);
-
-/**
- * Init objects in IVSHMEM devices
- *
- * This function is private to EAL.
- *
- * @return
- *  0 on success, negative on error
- */
-int rte_eal_ivshmem_obj_init(void);
-#endif
-
 struct rte_pci_driver;
 struct rte_pci_device;
 
diff --git a/lib/librte_eal/common/include/rte_memory.h b/lib/librte_eal/common/include/rte_memory.h
index 0661109..d9e8c21 100644
--- a/lib/librte_eal/common/include/rte_memory.h
+++ b/lib/librte_eal/common/include/rte_memory.h
@@ -107,9 +107,6 @@ struct rte_memseg {
 		void *addr;         /**< Start virtual address. */
 		uint64_t addr_64;   /**< Makes sure addr is always 64 bits */
 	};
-#ifdef RTE_LIBRTE_IVSHMEM
-	phys_addr_t ioremap_addr; /**< Real physical address inside the VM */
-#endif
 	size_t len;               /**< Length of the segment. */
 	uint64_t hugepage_sz;       /**< The pagesize of underlying memory */
 	int32_t socket_id;          /**< NUMA socket ID. */
diff --git a/lib/librte_eal/common/include/rte_memzone.h b/lib/librte_eal/common/include/rte_memzone.h
index f69b5a8..dae98f5 100644
--- a/lib/librte_eal/common/include/rte_memzone.h
+++ b/lib/librte_eal/common/include/rte_memzone.h
@@ -82,9 +82,6 @@ struct rte_memzone {
 		void *addr;                   /**< Start virtual address. */
 		uint64_t addr_64;             /**< Makes sure addr is always 64-bits */
 	};
-#ifdef RTE_LIBRTE_IVSHMEM
-	phys_addr_t ioremap_addr;         /**< Real physical address inside the VM */
-#endif
 	size_t len;                       /**< Length of the memzone. */
 
 	uint64_t hugepage_sz;             /**< The page size of underlying memory */
@@ -256,12 +253,10 @@ const struct rte_memzone *rte_memzone_reserve_bounded(const char *name,
 /**
  * Free a memzone.
  *
- * Note: an IVSHMEM zone cannot be freed.
- *
  * @param mz
  *   A pointer to the memzone
  * @return
- *  -EINVAL - invalid parameter, IVSHMEM memzone.
+ *  -EINVAL - invalid parameter.
  *  0 - success
  */
 int rte_memzone_free(const struct rte_memzone *mz);
diff --git a/lib/librte_eal/common/malloc_heap.c b/lib/librte_eal/common/malloc_heap.c
index 763fa32..267a4c6 100644
--- a/lib/librte_eal/common/malloc_heap.c
+++ b/lib/librte_eal/common/malloc_heap.c
@@ -221,14 +221,6 @@ rte_eal_malloc_heap_init(void)
 	for (ms = &mcfg->memseg[0], ms_cnt = 0;
 			(ms_cnt < RTE_MAX_MEMSEG) && (ms->len > 0);
 			ms_cnt++, ms++) {
-#ifdef RTE_LIBRTE_IVSHMEM
-		/*
-		 * if segment has ioremap address set, it's an IVSHMEM segment and
-		 * it is not memory to allocate from.
-		 */
-		if (ms->ioremap_addr != 0)
-			continue;
-#endif
 		malloc_heap_add_memseg(&mcfg->malloc_heaps[ms->socket_id], ms);
 	}
 
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 182729c..0baa571 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -44,12 +44,6 @@ VPATH += $(RTE_SDK)/lib/librte_eal/common
 CFLAGS += -I$(SRCDIR)/include
 CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common
 CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include
-ifeq ($(CONFIG_RTE_LIBRTE_IVSHMEM),y)
-# workaround for circular dependency eal -> ivshmem -> ring/mempool -> eal
-CFLAGS += -I$(RTE_SDK)/lib/librte_ring
-CFLAGS += -I$(RTE_SDK)/lib/librte_mempool
-CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem
-endif
 CFLAGS += $(WERROR_FLAGS) -O3
 
 LDLIBS += -ldl
@@ -76,9 +70,6 @@ SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_lcore.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_timer.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_interrupts.c
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_alarm.c
-ifeq ($(CONFIG_RTE_LIBRTE_IVSHMEM),y)
-SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_ivshmem.c
-endif
 
 # from common dir
 SRCS-$(CONFIG_RTE_EXEC_ENV_LINUXAPP) += eal_common_lcore.c
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 3fb2188..d5b81a3 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -797,11 +797,6 @@ rte_eal_init(int argc, char **argv)
 		rte_panic("Cannot init VFIO\n");
 #endif
 
-#ifdef RTE_LIBRTE_IVSHMEM
-	if (rte_eal_ivshmem_init() < 0)
-		rte_panic("Cannot init IVSHMEM\n");
-#endif
-
 	if (rte_eal_memory_init() < 0)
 		rte_panic("Cannot init memory\n");
 
@@ -814,11 +809,6 @@ rte_eal_init(int argc, char **argv)
 	if (rte_eal_tailqs_init() < 0)
 		rte_panic("Cannot init tail queues for objects\n");
 
-#ifdef RTE_LIBRTE_IVSHMEM
-	if (rte_eal_ivshmem_obj_init() < 0)
-		rte_panic("Cannot init IVSHMEM objects\n");
-#endif
-
 	if (rte_eal_log_init(logid, internal_config.syslog_facility) < 0)
 		rte_panic("Cannot init logs\n");
 
diff --git a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
deleted file mode 100644
index 67b3caf..0000000
--- a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
+++ /dev/null
@@ -1,954 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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.
- */
-
-#ifdef RTE_LIBRTE_IVSHMEM /* hide it from coverage */
-
-#include <stdint.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <sys/file.h>
-#include <string.h>
-#include <sys/queue.h>
-
-#include <rte_log.h>
-#include <rte_pci.h>
-#include <rte_memory.h>
-#include <rte_eal.h>
-#include <rte_eal_memconfig.h>
-#include <rte_string_fns.h>
-#include <rte_errno.h>
-#include <rte_ring.h>
-#include <rte_malloc.h>
-#include <rte_common.h>
-#include <rte_ivshmem.h>
-
-#include "eal_internal_cfg.h"
-#include "eal_private.h"
-
-#define PCI_VENDOR_ID_IVSHMEM 0x1Af4
-#define PCI_DEVICE_ID_IVSHMEM 0x1110
-
-#define IVSHMEM_MAGIC 0x0BADC0DE
-
-#define IVSHMEM_RESOURCE_PATH "/sys/bus/pci/devices/%04x:%02x:%02x.%x/resource2"
-#define IVSHMEM_CONFIG_PATH "/var/run/.%s_ivshmem_config"
-
-#define PHYS 0x1
-#define VIRT 0x2
-#define IOREMAP 0x4
-#define FULL (PHYS|VIRT|IOREMAP)
-
-#define METADATA_SIZE_ALIGNED \
-	(RTE_ALIGN_CEIL(sizeof(struct rte_ivshmem_metadata),pagesz))
-
-#define CONTAINS(x,y)\
-	(((y).addr_64 >= (x).addr_64) && ((y).addr_64 < (x).addr_64 + (x).len))
-
-#define DIM(x) (sizeof(x)/sizeof(x[0]))
-
-struct ivshmem_pci_device {
-	char path[PATH_MAX];
-	phys_addr_t ioremap_addr;
-};
-
-/* data type to store in config */
-struct ivshmem_segment {
-	struct rte_ivshmem_metadata_entry entry;
-	uint64_t align;
-	char path[PATH_MAX];
-};
-struct ivshmem_shared_config {
-	struct ivshmem_segment segment[RTE_MAX_MEMSEG];
-	uint32_t segment_idx;
-	struct ivshmem_pci_device pci_devs[RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS];
-	uint32_t pci_devs_idx;
-};
-static struct ivshmem_shared_config * ivshmem_config;
-static int memseg_idx;
-static int pagesz;
-
-/* Tailq heads to add rings to */
-TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
-
-/*
- * Utility functions
- */
-
-static int
-is_ivshmem_device(struct rte_pci_device * dev)
-{
-	return dev->id.vendor_id == PCI_VENDOR_ID_IVSHMEM
-			&& dev->id.device_id == PCI_DEVICE_ID_IVSHMEM;
-}
-
-static void *
-map_metadata(int fd, uint64_t len)
-{
-	size_t metadata_len = sizeof(struct rte_ivshmem_metadata);
-	size_t aligned_len = METADATA_SIZE_ALIGNED;
-
-	return mmap(NULL, metadata_len, PROT_READ | PROT_WRITE,
-			MAP_SHARED, fd, len - aligned_len);
-}
-
-static void
-unmap_metadata(void * ptr)
-{
-	munmap(ptr, sizeof(struct rte_ivshmem_metadata));
-}
-
-static int
-has_ivshmem_metadata(int fd, uint64_t len)
-{
-	struct rte_ivshmem_metadata metadata;
-	void * ptr;
-
-	ptr = map_metadata(fd, len);
-
-	if (ptr == MAP_FAILED)
-		return -1;
-
-	metadata = *(struct rte_ivshmem_metadata*) (ptr);
-
-	unmap_metadata(ptr);
-
-	return metadata.magic_number == IVSHMEM_MAGIC;
-}
-
-static void
-remove_segment(struct ivshmem_segment * ms, int len, int idx)
-{
-	int i;
-
-	for (i = idx; i < len - 1; i++)
-		memcpy(&ms[i], &ms[i+1], sizeof(struct ivshmem_segment));
-	memset(&ms[len-1], 0, sizeof(struct ivshmem_segment));
-}
-
-static int
-overlap(const struct rte_memzone * mz1, const struct rte_memzone * mz2)
-{
-	uint64_t start1, end1, start2, end2;
-	uint64_t p_start1, p_end1, p_start2, p_end2;
-	uint64_t i_start1, i_end1, i_start2, i_end2;
-	int result = 0;
-
-	/* gather virtual addresses */
-	start1 = mz1->addr_64;
-	end1 = mz1->addr_64 + mz1->len;
-	start2 = mz2->addr_64;
-	end2 = mz2->addr_64 + mz2->len;
-
-	/* gather physical addresses */
-	p_start1 = mz1->phys_addr;
-	p_end1 = mz1->phys_addr + mz1->len;
-	p_start2 = mz2->phys_addr;
-	p_end2 = mz2->phys_addr + mz2->len;
-
-	/* gather ioremap addresses */
-	i_start1 = mz1->ioremap_addr;
-	i_end1 = mz1->ioremap_addr + mz1->len;
-	i_start2 = mz2->ioremap_addr;
-	i_end2 = mz2->ioremap_addr + mz2->len;
-
-	/* check for overlap in virtual addresses */
-	if (start1 >= start2 && start1 < end2)
-		result |= VIRT;
-	if (start2 >= start1 && start2 < end1)
-		result |= VIRT;
-
-	/* check for overlap in physical addresses */
-	if (p_start1 >= p_start2 && p_start1 < p_end2)
-		result |= PHYS;
-	if (p_start2 >= p_start1 && p_start2 < p_end1)
-		result |= PHYS;
-
-	/* check for overlap in ioremap addresses */
-	if (i_start1 >= i_start2 && i_start1 < i_end2)
-		result |= IOREMAP;
-	if (i_start2 >= i_start1 && i_start2 < i_end1)
-		result |= IOREMAP;
-
-	return result;
-}
-
-static int
-adjacent(const struct rte_memzone * mz1, const struct rte_memzone * mz2)
-{
-	uint64_t start1, end1, start2, end2;
-	uint64_t p_start1, p_end1, p_start2, p_end2;
-	uint64_t i_start1, i_end1, i_start2, i_end2;
-	int result = 0;
-
-	/* gather virtual addresses */
-	start1 = mz1->addr_64;
-	end1 = mz1->addr_64 + mz1->len;
-	start2 = mz2->addr_64;
-	end2 = mz2->addr_64 + mz2->len;
-
-	/* gather physical addresses */
-	p_start1 = mz1->phys_addr;
-	p_end1 = mz1->phys_addr + mz1->len;
-	p_start2 = mz2->phys_addr;
-	p_end2 = mz2->phys_addr + mz2->len;
-
-	/* gather ioremap addresses */
-	i_start1 = mz1->ioremap_addr;
-	i_end1 = mz1->ioremap_addr + mz1->len;
-	i_start2 = mz2->ioremap_addr;
-	i_end2 = mz2->ioremap_addr + mz2->len;
-
-	/* check if segments are virtually adjacent */
-	if (start1 == end2)
-		result |= VIRT;
-	if (start2 == end1)
-		result |= VIRT;
-
-	/* check if segments are physically adjacent */
-	if (p_start1 == p_end2)
-		result |= PHYS;
-	if (p_start2 == p_end1)
-		result |= PHYS;
-
-	/* check if segments are ioremap-adjacent */
-	if (i_start1 == i_end2)
-		result |= IOREMAP;
-	if (i_start2 == i_end1)
-		result |= IOREMAP;
-
-	return result;
-}
-
-static int
-has_adjacent_segments(struct ivshmem_segment * ms, int len)
-{
-	int i, j;
-
-	for (i = 0; i < len; i++)
-		for (j = i + 1; j < len; j++) {
-			/* we're only interested in fully adjacent segments; partially
-			 * adjacent segments can coexist.
-			 */
-			if (adjacent(&ms[i].entry.mz, &ms[j].entry.mz) == FULL)
-				return 1;
-		}
-	return 0;
-}
-
-static int
-has_overlapping_segments(struct ivshmem_segment * ms, int len)
-{
-	int i, j;
-
-	for (i = 0; i < len; i++)
-		for (j = i + 1; j < len; j++)
-			if (overlap(&ms[i].entry.mz, &ms[j].entry.mz))
-				return 1;
-	return 0;
-}
-
-static int
-seg_compare(const void * a, const void * b)
-{
-	const struct ivshmem_segment * s1 = (const struct ivshmem_segment*) a;
-	const struct ivshmem_segment * s2 = (const struct ivshmem_segment*) b;
-
-	/* move unallocated zones to the end */
-	if (s1->entry.mz.addr == NULL && s2->entry.mz.addr == NULL)
-		return 0;
-	if (s1->entry.mz.addr == 0)
-		return 1;
-	if (s2->entry.mz.addr == 0)
-		return -1;
-
-	return s1->entry.mz.phys_addr > s2->entry.mz.phys_addr;
-}
-
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-static void
-entry_dump(struct rte_ivshmem_metadata_entry *e)
-{
-	RTE_LOG(DEBUG, EAL, "\tvirt: %p-%p\n", e->mz.addr,
-			RTE_PTR_ADD(e->mz.addr, e->mz.len));
-	RTE_LOG(DEBUG, EAL, "\tphys: 0x%" PRIx64 "-0x%" PRIx64 "\n",
-			e->mz.phys_addr,
-			e->mz.phys_addr + e->mz.len);
-	RTE_LOG(DEBUG, EAL, "\tio: 0x%" PRIx64 "-0x%" PRIx64 "\n",
-			e->mz.ioremap_addr,
-			e->mz.ioremap_addr + e->mz.len);
-	RTE_LOG(DEBUG, EAL, "\tlen: 0x%" PRIx64 "\n", e->mz.len);
-	RTE_LOG(DEBUG, EAL, "\toff: 0x%" PRIx64 "\n", e->offset);
-}
-#endif
-
-
-
-/*
- * Actual useful code
- */
-
-/* read through metadata mapped from the IVSHMEM device */
-static int
-read_metadata(char * path, int path_len, int fd, uint64_t flen)
-{
-	struct rte_ivshmem_metadata metadata;
-	struct rte_ivshmem_metadata_entry * entry;
-	int idx, i;
-	void * ptr;
-
-	ptr = map_metadata(fd, flen);
-
-	if (ptr == MAP_FAILED)
-		return -1;
-
-	metadata = *(struct rte_ivshmem_metadata*) (ptr);
-
-	unmap_metadata(ptr);
-
-	RTE_LOG(DEBUG, EAL, "Parsing metadata for \"%s\"\n", metadata.name);
-
-	idx = ivshmem_config->segment_idx;
-
-	for (i = 0; i < RTE_LIBRTE_IVSHMEM_MAX_ENTRIES &&
-		idx <= RTE_MAX_MEMSEG; i++) {
-
-		if (idx == RTE_MAX_MEMSEG) {
-			RTE_LOG(ERR, EAL, "Not enough memory segments!\n");
-			return -1;
-		}
-
-		entry = &metadata.entry[i];
-
-		/* stop on uninitialized memzone */
-		if (entry->mz.len == 0)
-			break;
-
-		/* copy metadata entry */
-		memcpy(&ivshmem_config->segment[idx].entry, entry,
-				sizeof(struct rte_ivshmem_metadata_entry));
-
-		/* copy path */
-		snprintf(ivshmem_config->segment[idx].path, path_len, "%s", path);
-
-		idx++;
-	}
-	ivshmem_config->segment_idx = idx;
-
-	return 0;
-}
-
-/* check through each segment and look for adjacent or overlapping ones. */
-static int
-cleanup_segments(struct ivshmem_segment * ms, int tbl_len)
-{
-	struct ivshmem_segment * s, * tmp;
-	int i, j, concat, seg_adjacent, seg_overlapping;
-	uint64_t start1, start2, end1, end2, p_start1, p_start2, i_start1, i_start2;
-
-	qsort(ms, tbl_len, sizeof(struct ivshmem_segment),
-				seg_compare);
-
-	while (has_overlapping_segments(ms, tbl_len) ||
-			has_adjacent_segments(ms, tbl_len)) {
-
-		for (i = 0; i < tbl_len; i++) {
-			s = &ms[i];
-
-			concat = 0;
-
-			for (j = i + 1; j < tbl_len; j++) {
-				tmp = &ms[j];
-
-				/* check if this segment is overlapping with existing segment,
-				 * or is adjacent to existing segment */
-				seg_overlapping = overlap(&s->entry.mz, &tmp->entry.mz);
-				seg_adjacent = adjacent(&s->entry.mz, &tmp->entry.mz);
-
-				/* check if segments fully overlap or are fully adjacent */
-				if ((seg_adjacent == FULL) || (seg_overlapping == FULL)) {
-
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-					RTE_LOG(DEBUG, EAL, "Concatenating segments\n");
-					RTE_LOG(DEBUG, EAL, "Segment %i:\n", i);
-					entry_dump(&s->entry);
-					RTE_LOG(DEBUG, EAL, "Segment %i:\n", j);
-					entry_dump(&tmp->entry);
-#endif
-
-					start1 = s->entry.mz.addr_64;
-					start2 = tmp->entry.mz.addr_64;
-					p_start1 = s->entry.mz.phys_addr;
-					p_start2 = tmp->entry.mz.phys_addr;
-					i_start1 = s->entry.mz.ioremap_addr;
-					i_start2 = tmp->entry.mz.ioremap_addr;
-					end1 = s->entry.mz.addr_64 + s->entry.mz.len;
-					end2 = tmp->entry.mz.addr_64 + tmp->entry.mz.len;
-
-					/* settle for minimum start address and maximum length */
-					s->entry.mz.addr_64 = RTE_MIN(start1, start2);
-					s->entry.mz.phys_addr = RTE_MIN(p_start1, p_start2);
-					s->entry.mz.ioremap_addr = RTE_MIN(i_start1, i_start2);
-					s->entry.offset = RTE_MIN(s->entry.offset, tmp->entry.offset);
-					s->entry.mz.len = RTE_MAX(end1, end2) - s->entry.mz.addr_64;
-					concat = 1;
-
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-					RTE_LOG(DEBUG, EAL, "Resulting segment:\n");
-					entry_dump(&s->entry);
-
-#endif
-				}
-				/* if segments not fully overlap, we have an error condition.
-				 * adjacent segments can coexist.
-				 */
-				else if (seg_overlapping > 0) {
-					RTE_LOG(ERR, EAL, "Segments %i and %i overlap!\n", i, j);
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-					RTE_LOG(DEBUG, EAL, "Segment %i:\n", i);
-					entry_dump(&s->entry);
-					RTE_LOG(DEBUG, EAL, "Segment %i:\n", j);
-					entry_dump(&tmp->entry);
-#endif
-					return -1;
-				}
-				if (concat)
-					break;
-			}
-			/* if we concatenated, remove segment at j */
-			if (concat) {
-				remove_segment(ms, tbl_len, j);
-				tbl_len--;
-				break;
-			}
-		}
-	}
-
-	return tbl_len;
-}
-
-static int
-create_shared_config(void)
-{
-	char path[PATH_MAX];
-	int fd;
-
-	/* build ivshmem config file path */
-	snprintf(path, sizeof(path), IVSHMEM_CONFIG_PATH,
-			internal_config.hugefile_prefix);
-
-	fd = open(path, O_CREAT | O_RDWR, 0600);
-
-	if (fd < 0) {
-		RTE_LOG(ERR, EAL, "Could not open %s: %s\n", path, strerror(errno));
-		return -1;
-	}
-
-	/* try ex-locking first - if the file is locked, we have a problem */
-	if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
-		RTE_LOG(ERR, EAL, "Locking %s failed: %s\n", path, strerror(errno));
-		close(fd);
-		return -1;
-	}
-
-	if (ftruncate(fd, sizeof(struct ivshmem_shared_config)) < 0) {
-		RTE_LOG(ERR, EAL, "ftruncate failed: %s\n", strerror(errno));
-		return -1;
-	}
-
-	ivshmem_config = mmap(NULL, sizeof(struct ivshmem_shared_config),
-			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-
-	if (ivshmem_config == MAP_FAILED)
-		return -1;
-
-	memset(ivshmem_config, 0, sizeof(struct ivshmem_shared_config));
-
-	/* change the exclusive lock we got earlier to a shared lock */
-	if (flock(fd, LOCK_SH | LOCK_NB) == -1) {
-		RTE_LOG(ERR, EAL, "Locking %s failed: %s \n", path, strerror(errno));
-		return -1;
-	}
-
-	close(fd);
-
-	return 0;
-}
-
-/* open shared config file and, if present, map the config.
- * having no config file is not an error condition, as we later check if
- * ivshmem_config is NULL (if it is, that means nothing was mapped). */
-static int
-open_shared_config(void)
-{
-	char path[PATH_MAX];
-	int fd;
-
-	/* build ivshmem config file path */
-	snprintf(path, sizeof(path), IVSHMEM_CONFIG_PATH,
-			internal_config.hugefile_prefix);
-
-	fd = open(path, O_RDONLY);
-
-	/* if the file doesn't exist, just return success */
-	if (fd < 0 && errno == ENOENT)
-		return 0;
-	/* else we have an error condition */
-	else if (fd < 0) {
-		RTE_LOG(ERR, EAL, "Could not open %s: %s\n",
-				path, strerror(errno));
-		return -1;
-	}
-
-	/* try ex-locking first - if the lock *does* succeed, this means it's a
-	 * stray config file, so it should be deleted.
-	 */
-	if (flock(fd, LOCK_EX | LOCK_NB) != -1) {
-
-		/* if we can't remove the file, something is wrong */
-		if (unlink(path) < 0) {
-			RTE_LOG(ERR, EAL, "Could not remove %s: %s\n", path,
-					strerror(errno));
-			return -1;
-		}
-
-		/* release the lock */
-		flock(fd, LOCK_UN);
-		close(fd);
-
-		/* return success as having a stray config file is equivalent to not
-		 * having config file at all.
-		 */
-		return 0;
-	}
-
-	ivshmem_config = mmap(NULL, sizeof(struct ivshmem_shared_config),
-			PROT_READ, MAP_SHARED, fd, 0);
-
-	if (ivshmem_config == MAP_FAILED)
-		return -1;
-
-	/* place a shared lock on config file */
-	if (flock(fd, LOCK_SH | LOCK_NB) == -1) {
-		RTE_LOG(ERR, EAL, "Locking %s failed: %s \n", path, strerror(errno));
-		return -1;
-	}
-
-	close(fd);
-
-	return 0;
-}
-
-/*
- * This function does the following:
- *
- * 1) Builds a table of ivshmem_segments with proper offset alignment
- * 2) Cleans up that table so that we don't have any overlapping or adjacent
- *    memory segments
- * 3) Creates memsegs from this table and maps them into memory.
- */
-static inline int
-map_all_segments(void)
-{
-	struct ivshmem_segment ms_tbl[RTE_MAX_MEMSEG];
-	struct ivshmem_pci_device * pci_dev;
-	struct rte_mem_config * mcfg;
-	struct ivshmem_segment * seg;
-	int fd, fd_zero;
-	unsigned i, j;
-	struct rte_memzone mz;
-	struct rte_memseg ms;
-	void * base_addr;
-	uint64_t align, len;
-	phys_addr_t ioremap_addr;
-
-	ioremap_addr = 0;
-
-	memset(ms_tbl, 0, sizeof(ms_tbl));
-	memset(&mz, 0, sizeof(struct rte_memzone));
-	memset(&ms, 0, sizeof(struct rte_memseg));
-
-	/* first, build a table of memsegs to map, to avoid failed mmaps due to
-	 * overlaps
-	 */
-	for (i = 0; i < ivshmem_config->segment_idx && i <= RTE_MAX_MEMSEG; i++) {
-		if (i == RTE_MAX_MEMSEG) {
-			RTE_LOG(ERR, EAL, "Too many segments requested!\n");
-			return -1;
-		}
-
-		seg = &ivshmem_config->segment[i];
-
-		/* copy segment to table */
-		memcpy(&ms_tbl[i], seg, sizeof(struct ivshmem_segment));
-
-		/* find ioremap addr */
-		for (j = 0; j < DIM(ivshmem_config->pci_devs); j++) {
-			pci_dev = &ivshmem_config->pci_devs[j];
-			if (!strncmp(pci_dev->path, seg->path, sizeof(pci_dev->path))) {
-				ioremap_addr = pci_dev->ioremap_addr;
-				break;
-			}
-		}
-		if (ioremap_addr == 0) {
-			RTE_LOG(ERR, EAL, "Cannot find ioremap addr!\n");
-			return -1;
-		}
-
-		/* work out alignments */
-		align = seg->entry.mz.addr_64 -
-				RTE_ALIGN_FLOOR(seg->entry.mz.addr_64, 0x1000);
-		len = RTE_ALIGN_CEIL(seg->entry.mz.len + align, 0x1000);
-
-		/* save original alignments */
-		ms_tbl[i].align = align;
-
-		/* create a memory zone */
-		mz.addr_64 = seg->entry.mz.addr_64 - align;
-		mz.len = len;
-		mz.hugepage_sz = seg->entry.mz.hugepage_sz;
-		mz.phys_addr = seg->entry.mz.phys_addr - align;
-
-		/* find true physical address */
-		mz.ioremap_addr = ioremap_addr + seg->entry.offset - align;
-
-		ms_tbl[i].entry.offset = seg->entry.offset - align;
-
-		memcpy(&ms_tbl[i].entry.mz, &mz, sizeof(struct rte_memzone));
-	}
-
-	/* clean up the segments */
-	memseg_idx = cleanup_segments(ms_tbl, ivshmem_config->segment_idx);
-
-	if (memseg_idx < 0)
-		return -1;
-
-	mcfg = rte_eal_get_configuration()->mem_config;
-
-	fd_zero = open("/dev/zero", O_RDWR);
-
-	if (fd_zero < 0) {
-		RTE_LOG(ERR, EAL, "Cannot open /dev/zero: %s\n", strerror(errno));
-		return -1;
-	}
-
-	/* create memsegs and put them into DPDK memory */
-	for (i = 0; i < (unsigned) memseg_idx; i++) {
-
-		seg = &ms_tbl[i];
-
-		ms.addr_64 = seg->entry.mz.addr_64;
-		ms.hugepage_sz = seg->entry.mz.hugepage_sz;
-		ms.len = seg->entry.mz.len;
-		ms.nchannel = rte_memory_get_nchannel();
-		ms.nrank = rte_memory_get_nrank();
-		ms.phys_addr = seg->entry.mz.phys_addr;
-		ms.ioremap_addr = seg->entry.mz.ioremap_addr;
-		ms.socket_id = seg->entry.mz.socket_id;
-
-		base_addr = mmap(ms.addr, ms.len,
-				PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_zero, 0);
-
-		if (base_addr == MAP_FAILED || base_addr != ms.addr) {
-			RTE_LOG(ERR, EAL, "Cannot map /dev/zero!\n");
-			return -1;
-		}
-
-		fd = open(seg->path, O_RDWR);
-
-		if (fd < 0) {
-			RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", seg->path,
-					strerror(errno));
-			return -1;
-		}
-
-		munmap(ms.addr, ms.len);
-
-		base_addr = mmap(ms.addr, ms.len,
-				PROT_READ | PROT_WRITE, MAP_SHARED, fd,
-				seg->entry.offset);
-
-
-		if (base_addr == MAP_FAILED || base_addr != ms.addr) {
-			RTE_LOG(ERR, EAL, "Cannot map segment into memory: "
-					"expected %p got %p (%s)\n", ms.addr, base_addr,
-					strerror(errno));
-			return -1;
-		}
-
-		RTE_LOG(DEBUG, EAL, "Memory segment mapped: %p (len %" PRIx64 ") at "
-				"offset 0x%" PRIx64 "\n",
-				ms.addr, ms.len, seg->entry.offset);
-
-		/* put the pointers back into their real positions using original
-		 * alignment */
-		ms.addr_64 += seg->align;
-		ms.phys_addr += seg->align;
-		ms.ioremap_addr += seg->align;
-		ms.len -= seg->align;
-
-		/* at this point, the rest of DPDK memory is not initialized, so we
-		 * expect memsegs to be empty */
-		memcpy(&mcfg->memseg[i], &ms,
-				sizeof(struct rte_memseg));
-
-		close(fd);
-
-		RTE_LOG(DEBUG, EAL, "IVSHMEM segment found, size: 0x%lx\n",
-				ms.len);
-	}
-
-	return 0;
-}
-
-/* this happens at a later stage, after general EAL memory initialization */
-int
-rte_eal_ivshmem_obj_init(void)
-{
-	struct rte_ring_list* ring_list = NULL;
-	struct rte_mem_config * mcfg;
-	struct ivshmem_segment * seg;
-	struct rte_memzone * mz;
-	struct rte_ring * r;
-	struct rte_tailq_entry *te;
-	unsigned i, ms, idx;
-	uint64_t offset;
-
-	/* secondary process would not need any object discovery - it'll all
-	 * already be in shared config */
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY || ivshmem_config == NULL)
-		return 0;
-
-	/* check that we have an initialised ring tail queue */
-	ring_list = RTE_TAILQ_LOOKUP(RTE_TAILQ_RING_NAME, rte_ring_list);
-	if (ring_list == NULL) {
-		RTE_LOG(ERR, EAL, "No rte_ring tailq found!\n");
-		return -1;
-	}
-
-	mcfg = rte_eal_get_configuration()->mem_config;
-
-	/* create memzones */
-	for (i = 0; i < ivshmem_config->segment_idx && i <= RTE_MAX_MEMZONE; i++) {
-
-		seg = &ivshmem_config->segment[i];
-
-		/* add memzone */
-		if (mcfg->memzone_cnt == RTE_MAX_MEMZONE) {
-			RTE_LOG(ERR, EAL, "No more memory zones available!\n");
-			return -1;
-		}
-
-		idx = mcfg->memzone_cnt;
-
-		RTE_LOG(DEBUG, EAL, "Found memzone: '%s' at %p (len 0x%" PRIx64 ")\n",
-				seg->entry.mz.name, seg->entry.mz.addr, seg->entry.mz.len);
-
-		memcpy(&mcfg->memzone[idx], &seg->entry.mz,
-				sizeof(struct rte_memzone));
-
-		/* find ioremap address */
-		for (ms = 0; ms <= RTE_MAX_MEMSEG; ms++) {
-			if (ms == RTE_MAX_MEMSEG) {
-				RTE_LOG(ERR, EAL, "Physical address of segment not found!\n");
-				return -1;
-			}
-			if (CONTAINS(mcfg->memseg[ms], mcfg->memzone[idx])) {
-				offset = mcfg->memzone[idx].addr_64 -
-								mcfg->memseg[ms].addr_64;
-				mcfg->memzone[idx].ioremap_addr = mcfg->memseg[ms].ioremap_addr +
-						offset;
-				break;
-			}
-		}
-
-		mcfg->memzone_cnt++;
-	}
-
-	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
-
-	/* find rings */
-	for (i = 0; i < mcfg->memzone_cnt; i++) {
-		mz = &mcfg->memzone[i];
-
-		/* check if memzone has a ring prefix */
-		if (strncmp(mz->name, RTE_RING_MZ_PREFIX,
-				sizeof(RTE_RING_MZ_PREFIX) - 1) != 0)
-			continue;
-
-		r = (struct rte_ring*) (mz->addr_64);
-
-		te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
-		if (te == NULL) {
-			RTE_LOG(ERR, EAL, "Cannot allocate ring tailq entry!\n");
-			return -1;
-		}
-
-		te->data = (void *) r;
-
-		TAILQ_INSERT_TAIL(ring_list, te, next);
-
-		RTE_LOG(DEBUG, EAL, "Found ring: '%s' at %p\n", r->name, mz->addr);
-	}
-	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
-
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-	rte_memzone_dump(stdout);
-	rte_ring_list_dump(stdout);
-#endif
-
-	return 0;
-}
-
-/* initialize ivshmem structures */
-int rte_eal_ivshmem_init(void)
-{
-	struct rte_pci_device * dev;
-	struct rte_pci_resource * res;
-	int fd, ret;
-	char path[PATH_MAX];
-
-	/* initialize everything to 0 */
-	memset(path, 0, sizeof(path));
-	ivshmem_config = NULL;
-
-	pagesz = getpagesize();
-
-	RTE_LOG(DEBUG, EAL, "Searching for IVSHMEM devices...\n");
-
-	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
-
-		if (open_shared_config() < 0) {
-			RTE_LOG(ERR, EAL, "Could not open IVSHMEM config!\n");
-			return -1;
-		}
-	}
-	else {
-
-		TAILQ_FOREACH(dev, &pci_device_list, next) {
-
-			if (is_ivshmem_device(dev)) {
-
-				/* IVSHMEM memory is always on BAR2 */
-				res = &dev->mem_resource[2];
-
-				/* if we don't have a BAR2 */
-				if (res->len == 0)
-					continue;
-
-				/* construct pci device path */
-				snprintf(path, sizeof(path), IVSHMEM_RESOURCE_PATH,
-						dev->addr.domain, dev->addr.bus, dev->addr.devid,
-						dev->addr.function);
-
-				/* try to find memseg */
-				fd = open(path, O_RDWR);
-				if (fd < 0) {
-					RTE_LOG(ERR, EAL, "Could not open %s\n", path);
-					return -1;
-				}
-
-				/* check if it's a DPDK IVSHMEM device */
-				ret = has_ivshmem_metadata(fd, res->len);
-
-				/* is DPDK device */
-				if (ret == 1) {
-
-					/* config file creation is deferred until the first
-					 * DPDK device is found. then, it has to be created
-					 * only once. */
-					if (ivshmem_config == NULL &&
-							create_shared_config() < 0) {
-						RTE_LOG(ERR, EAL, "Could not create IVSHMEM config!\n");
-						close(fd);
-						return -1;
-					}
-
-					if (read_metadata(path, sizeof(path), fd, res->len) < 0) {
-						RTE_LOG(ERR, EAL, "Could not read metadata from"
-								" device %02x:%02x.%x!\n", dev->addr.bus,
-								dev->addr.devid, dev->addr.function);
-						close(fd);
-						return -1;
-					}
-
-					if (ivshmem_config->pci_devs_idx == RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS) {
-						RTE_LOG(WARNING, EAL,
-								"IVSHMEM PCI device limit exceeded. Increase "
-								"CONFIG_RTE_LIBRTE_IVSHMEM_MAX_PCI_DEVS  in "
-								"your config file.\n");
-						break;
-					}
-
-					RTE_LOG(INFO, EAL, "Found IVSHMEM device %02x:%02x.%x\n",
-							dev->addr.bus, dev->addr.devid, dev->addr.function);
-
-					ivshmem_config->pci_devs[ivshmem_config->pci_devs_idx].ioremap_addr = res->phys_addr;
-					snprintf(ivshmem_config->pci_devs[ivshmem_config->pci_devs_idx].path,
-							sizeof(ivshmem_config->pci_devs[ivshmem_config->pci_devs_idx].path),
-							"%s", path);
-
-					ivshmem_config->pci_devs_idx++;
-				}
-				/* failed to read */
-				else if (ret < 0) {
-					RTE_LOG(ERR, EAL, "Could not read IVSHMEM device: %s\n",
-							strerror(errno));
-					close(fd);
-					return -1;
-				}
-				/* not a DPDK device */
-				else
-					RTE_LOG(DEBUG, EAL, "Skipping non-DPDK IVSHMEM device\n");
-
-				/* close the BAR fd */
-				close(fd);
-			}
-		}
-	}
-
-	/* ivshmem_config is not NULL only if config was created and/or mapped */
-	if (ivshmem_config) {
-		if (map_all_segments() < 0) {
-			RTE_LOG(ERR, EAL, "Mapping IVSHMEM segments failed!\n");
-			return -1;
-		}
-	}
-	else {
-		RTE_LOG(DEBUG, EAL, "No IVSHMEM configuration found! \n");
-	}
-
-	return 0;
-}
-
-#endif
diff --git a/lib/librte_eal/linuxapp/eal/eal_memory.c b/lib/librte_eal/linuxapp/eal/eal_memory.c
index 41e0a92..992a1b1 100644
--- a/lib/librte_eal/linuxapp/eal/eal_memory.c
+++ b/lib/librte_eal/linuxapp/eal/eal_memory.c
@@ -1436,15 +1436,8 @@ rte_eal_hugepage_init(void)
 	free(tmp_hp);
 	tmp_hp = NULL;
 
-	/* find earliest free memseg - this is needed because in case of IVSHMEM,
-	 * segments might have already been initialized */
-	for (j = 0; j < RTE_MAX_MEMSEG; j++)
-		if (mcfg->memseg[j].addr == NULL) {
-			/* move to previous segment and exit loop */
-			j--;
-			break;
-		}
-
+	/* first memseg index shall be 0 after incrementing it below */
+	j = -1;
 	for (i = 0; i < nr_hugefiles; i++) {
 		new_memseg = 0;
 
@@ -1597,15 +1590,6 @@ rte_eal_hugepage_attach(void)
 		if (mcfg->memseg[s].len == 0)
 			break;
 
-#ifdef RTE_LIBRTE_IVSHMEM
-		/*
-		 * if segment has ioremap address set, it's an IVSHMEM segment and
-		 * doesn't need mapping as it was already mapped earlier
-		 */
-		if (mcfg->memseg[s].ioremap_addr != 0)
-			continue;
-#endif
-
 		/*
 		 * fdzero is mmapped to get a contiguous block of virtual
 		 * addresses of the appropriate memseg size.
@@ -1644,16 +1628,6 @@ rte_eal_hugepage_attach(void)
 		void *addr, *base_addr;
 		uintptr_t offset = 0;
 		size_t mapping_size;
-#ifdef RTE_LIBRTE_IVSHMEM
-		/*
-		 * if segment has ioremap address set, it's an IVSHMEM segment and
-		 * doesn't need mapping as it was already mapped earlier
-		 */
-		if (mcfg->memseg[s].ioremap_addr != 0) {
-			s++;
-			continue;
-		}
-#endif
 		/*
 		 * free previously mapped memory so we can map the
 		 * hugepages into the space
diff --git a/lib/librte_ivshmem/Makefile b/lib/librte_ivshmem/Makefile
deleted file mode 100644
index c099438..0000000
--- a/lib/librte_ivshmem/Makefile
+++ /dev/null
@@ -1,54 +0,0 @@
-#   BSD LICENSE
-#
-#   Copyright(c) 2010-2014 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_ivshmem.a
-
-CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
-
-EXPORT_MAP := rte_ivshmem_version.map
-
-LIBABIVER := 1
-
-# all source are stored in SRCS-y
-SRCS-$(CONFIG_RTE_LIBRTE_IVSHMEM) := rte_ivshmem.c
-
-# install includes
-SYMLINK-$(CONFIG_RTE_LIBRTE_IVSHMEM)-include := rte_ivshmem.h
-
-# this lib needs EAL, ring and mempool
-DEPDIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += lib/librte_eal
-DEPDIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += lib/librte_ring
-DEPDIRS-$(CONFIG_RTE_LIBRTE_IVSHMEM) += lib/librte_mempool
-
-include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ivshmem/rte_ivshmem.c b/lib/librte_ivshmem/rte_ivshmem.c
deleted file mode 100644
index c26edb6..0000000
--- a/lib/librte_ivshmem/rte_ivshmem.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 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 <fcntl.h>
-#include <limits.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <rte_eal_memconfig.h>
-#include <rte_memory.h>
-#include <rte_ivshmem.h>
-#include <rte_string_fns.h>
-#include <rte_common.h>
-#include <rte_log.h>
-#include <rte_debug.h>
-#include <rte_spinlock.h>
-#include <rte_common.h>
-#include <rte_malloc.h>
-
-#include "rte_ivshmem.h"
-
-#define IVSHMEM_CONFIG_FILE_FMT "/var/run/.dpdk_ivshmem_metadata_%s"
-#define IVSHMEM_QEMU_CMD_LINE_HEADER_FMT "-device ivshmem,size=%" PRIu64 "M,shm=fd%s"
-#define IVSHMEM_QEMU_CMD_FD_FMT ":%s:0x%" PRIx64 ":0x%" PRIx64
-#define IVSHMEM_QEMU_CMDLINE_BUFSIZE 1024
-#define IVSHMEM_MAX_PAGES (1 << 12)
-#define adjacent(x,y) (((x).phys_addr+(x).len)==(y).phys_addr)
-#define METADATA_SIZE_ALIGNED \
-	(RTE_ALIGN_CEIL(sizeof(struct rte_ivshmem_metadata),pagesz))
-
-#define GET_PAGEMAP_ADDR(in,addr,dlm,err)    \
-{                                      \
-	char *end;                         \
-	errno = 0;                         \
-	addr = strtoull((in), &end, 16);   \
-	if (errno != 0 || *end != (dlm)) { \
-		RTE_LOG(ERR, EAL, err);        \
-		goto error;                    \
-	}                                  \
-	(in) = end + 1;                    \
-}
-
-static int pagesz;
-
-struct memseg_cache_entry {
-	char filepath[PATH_MAX];
-	uint64_t offset;
-	uint64_t len;
-};
-
-struct ivshmem_config {
-	struct rte_ivshmem_metadata * metadata;
-	struct memseg_cache_entry memseg_cache[IVSHMEM_MAX_PAGES];
-		/**< account for multiple files per segment case */
-	struct flock lock;
-	rte_spinlock_t sl;
-};
-
-static struct ivshmem_config
-ivshmem_global_config[RTE_LIBRTE_IVSHMEM_MAX_METADATA_FILES];
-
-static rte_spinlock_t global_cfg_sl;
-
-static struct ivshmem_config *
-get_config_by_name(const char * name)
-{
-	struct rte_ivshmem_metadata * config;
-	unsigned i;
-
-	for (i = 0; i < RTE_DIM(ivshmem_global_config); i++) {
-		config = ivshmem_global_config[i].metadata;
-		if (config == NULL)
-			return NULL;
-		if (strncmp(name, config->name, IVSHMEM_NAME_LEN) == 0)
-			return &ivshmem_global_config[i];
-	}
-
-	return NULL;
-}
-
-static int
-overlap(const struct rte_memzone * s1, const struct rte_memzone * s2)
-{
-	uint64_t start1, end1, start2, end2;
-
-	start1 = s1->addr_64;
-	end1 = s1->addr_64 + s1->len;
-	start2 = s2->addr_64;
-	end2 = s2->addr_64 + s2->len;
-
-	if (start1 >= start2 && start1 < end2)
-		return 1;
-	if (start2 >= start1 && start2 < end1)
-		return 1;
-
-	return 0;
-}
-
-static struct rte_memzone *
-get_memzone_by_addr(const void * addr)
-{
-	struct rte_memzone * tmp, * mz;
-	struct rte_mem_config * mcfg;
-	int i;
-
-	mcfg = rte_eal_get_configuration()->mem_config;
-	mz = NULL;
-
-	/* find memzone for the ring */
-	for (i = 0; i < RTE_MAX_MEMZONE; i++) {
-		tmp = &mcfg->memzone[i];
-
-		if (tmp->addr_64 == (uint64_t) addr) {
-			mz = tmp;
-			break;
-		}
-	}
-
-	return mz;
-}
-
-static int
-entry_compare(const void * a, const void * b)
-{
-	const struct rte_ivshmem_metadata_entry * e1 =
-			(const struct rte_ivshmem_metadata_entry*) a;
-	const struct rte_ivshmem_metadata_entry * e2 =
-			(const struct rte_ivshmem_metadata_entry*) b;
-
-	/* move unallocated zones to the end */
-	if (e1->mz.addr == NULL && e2->mz.addr == NULL)
-		return 0;
-	if (e1->mz.addr == 0)
-		return 1;
-	if (e2->mz.addr == 0)
-		return -1;
-
-	return e1->mz.phys_addr > e2->mz.phys_addr;
-}
-
-/* fills hugepage cache entry for a given start virt_addr */
-static int
-get_hugefile_by_virt_addr(uint64_t virt_addr, struct memseg_cache_entry * e)
-{
-	uint64_t start_addr, end_addr;
-	char *start,*path_end;
-	char buf[PATH_MAX*2];
-	FILE *f;
-
-	start = NULL;
-	path_end = NULL;
-	start_addr = 0;
-
-	memset(e->filepath, 0, sizeof(e->filepath));
-
-	/* open /proc/self/maps */
-	f = fopen("/proc/self/maps", "r");
-	if (f == NULL) {
-		RTE_LOG(ERR, EAL, "cannot open /proc/self/maps!\n");
-		return -1;
-	}
-
-	/* parse maps */
-	while (fgets(buf, sizeof(buf), f) != NULL) {
-
-		/* get endptr to end of start addr */
-		start = buf;
-
-		GET_PAGEMAP_ADDR(start,start_addr,'-',
-				"Cannot find start address in maps!\n");
-
-		/* if start address is bigger than our address, skip */
-		if (start_addr > virt_addr)
-			continue;
-
-		GET_PAGEMAP_ADDR(start,end_addr,' ',
-				"Cannot find end address in maps!\n");
-
-		/* if end address is less than our address, skip */
-		if (end_addr <= virt_addr)
-			continue;
-
-		/* find where the path starts */
-		start = strstr(start, "/");
-
-		if (start == NULL)
-			continue;
-
-		/* at this point, we know that this is our map.
-		 * now let's find the file */
-		path_end = strstr(start, "\n");
-		break;
-	}
-
-	if (path_end == NULL) {
-		RTE_LOG(ERR, EAL, "Hugefile path not found!\n");
-		goto error;
-	}
-
-	/* calculate offset and copy the file path */
-	snprintf(e->filepath, RTE_PTR_DIFF(path_end, start) + 1, "%s", start);
-
-	e->offset = virt_addr - start_addr;
-
-	fclose(f);
-
-	return 0;
-error:
-	fclose(f);
-	return -1;
-}
-
-/*
- * This is a complex function. What it does is the following:
- *  1. Goes through metadata and gets list of hugepages involved
- *  2. Sorts the hugepages by size (1G first)
- *  3. Goes through metadata again and writes correct offsets
- *  4. Goes through pages and finds out their filenames, offsets etc.
- */
-static int
-build_config(struct rte_ivshmem_metadata * metadata)
-{
-	struct rte_ivshmem_metadata_entry * e_local;
-	struct memseg_cache_entry * ms_local;
-	struct rte_memseg pages[IVSHMEM_MAX_PAGES];
-	struct rte_ivshmem_metadata_entry *entry;
-	struct memseg_cache_entry * c_entry, * prev_entry;
-	struct ivshmem_config * config;
-	unsigned i, j, mz_iter, ms_iter;
-	uint64_t biggest_len;
-	int biggest_idx;
-
-	/* return error if we try to use an unknown config file */
-	config = get_config_by_name(metadata->name);
-	if (config == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", metadata->name);
-		goto fail_e;
-	}
-
-	memset(pages, 0, sizeof(pages));
-
-	e_local = malloc(sizeof(config->metadata->entry));
-	if (e_local == NULL)
-		goto fail_e;
-	ms_local = malloc(sizeof(config->memseg_cache));
-	if (ms_local == NULL)
-		goto fail_ms;
-
-
-	/* make local copies before doing anything */
-	memcpy(e_local, config->metadata->entry, sizeof(config->metadata->entry));
-	memcpy(ms_local, config->memseg_cache, sizeof(config->memseg_cache));
-
-	qsort(e_local, RTE_DIM(config->metadata->entry), sizeof(struct rte_ivshmem_metadata_entry),
-			entry_compare);
-
-	/* first pass - collect all huge pages */
-	for (mz_iter = 0; mz_iter < RTE_DIM(config->metadata->entry); mz_iter++) {
-
-		entry = &e_local[mz_iter];
-
-		uint64_t start_addr = RTE_ALIGN_FLOOR(entry->mz.addr_64,
-				entry->mz.hugepage_sz);
-		uint64_t offset = entry->mz.addr_64 - start_addr;
-		uint64_t len = RTE_ALIGN_CEIL(entry->mz.len + offset,
-				entry->mz.hugepage_sz);
-
-		if (entry->mz.addr_64 == 0 || start_addr == 0 || len == 0)
-			continue;
-
-		int start_page;
-
-		/* find first unused page - mz are phys_addr sorted so we don't have to
-		 * look out for holes */
-		for (i = 0; i < RTE_DIM(pages); i++) {
-
-			/* skip if we already have this page */
-			if (pages[i].addr_64 == start_addr) {
-				start_addr += entry->mz.hugepage_sz;
-				len -= entry->mz.hugepage_sz;
-				continue;
-			}
-			/* we found a new page */
-			else if (pages[i].addr_64 == 0) {
-				start_page = i;
-				break;
-			}
-		}
-		if (i == RTE_DIM(pages)) {
-			RTE_LOG(ERR, EAL, "Cannot find unused page!\n");
-			goto fail;
-		}
-
-		/* populate however many pages the memzone has */
-		for (i = start_page; i < RTE_DIM(pages) && len != 0; i++) {
-
-			pages[i].addr_64 = start_addr;
-			pages[i].len = entry->mz.hugepage_sz;
-			start_addr += entry->mz.hugepage_sz;
-			len -= entry->mz.hugepage_sz;
-		}
-		/* if there's still length left */
-		if (len != 0) {
-			RTE_LOG(ERR, EAL, "Not enough space for pages!\n");
-			goto fail;
-		}
-	}
-
-	/* second pass - sort pages by size */
-	for (i = 0; i < RTE_DIM(pages); i++) {
-
-		if (pages[i].addr == NULL)
-			break;
-
-		biggest_len = 0;
-		biggest_idx = -1;
-
-		/*
-		 * browse all entries starting at 'i', and find the
-		 * entry with the smallest addr
-		 */
-		for (j=i; j< RTE_DIM(pages); j++) {
-			if (pages[j].addr == NULL)
-					break;
-			if (biggest_len == 0 ||
-				pages[j].len > biggest_len) {
-				biggest_len = pages[j].len;
-				biggest_idx = j;
-			}
-		}
-
-		/* should not happen */
-		if (biggest_idx == -1) {
-			RTE_LOG(ERR, EAL, "Error sorting by size!\n");
-			goto fail;
-		}
-		if (i != (unsigned) biggest_idx) {
-			struct rte_memseg tmp;
-
-			memcpy(&tmp, &pages[biggest_idx], sizeof(struct rte_memseg));
-
-			/* we don't want to break contiguousness, so instead of just
-			 * swapping segments, we move all the preceding segments to the
-			 * right and then put the old segment @ biggest_idx in place of
-			 * segment @ i */
-			for (j = biggest_idx - 1; j >= i; j--) {
-				memcpy(&pages[j+1], &pages[j], sizeof(struct rte_memseg));
-				memset(&pages[j], 0, sizeof(struct rte_memseg));
-				if (j == 0)
-					break;
-			}
-
-			/* put old biggest segment to its new place */
-			memcpy(&pages[i], &tmp, sizeof(struct rte_memseg));
-		}
-	}
-
-	/* third pass - write correct offsets */
-	for (mz_iter = 0; mz_iter < RTE_DIM(config->metadata->entry); mz_iter++) {
-
-		uint64_t offset = 0;
-
-		entry = &e_local[mz_iter];
-
-		if (entry->mz.addr_64 == 0)
-			break;
-
-		/* find page for current memzone */
-		for (i = 0; i < RTE_DIM(pages); i++) {
-			/* we found our page */
-			if (entry->mz.addr_64 >= pages[i].addr_64 &&
-					entry->mz.addr_64 < pages[i].addr_64 + pages[i].len) {
-				entry->offset = (entry->mz.addr_64 - pages[i].addr_64) +
-						offset;
-				break;
-			}
-			offset += pages[i].len;
-		}
-		if (i == RTE_DIM(pages)) {
-			RTE_LOG(ERR, EAL, "Page not found!\n");
-			goto fail;
-		}
-	}
-
-	ms_iter = 0;
-	prev_entry = NULL;
-
-	/* fourth pass - create proper memseg cache */
-	for (i = 0; i < RTE_DIM(pages) &&
-			ms_iter <= RTE_DIM(config->memseg_cache); i++) {
-		if (pages[i].addr_64 == 0)
-			break;
-
-
-		if (ms_iter == RTE_DIM(pages)) {
-			RTE_LOG(ERR, EAL, "The universe has collapsed!\n");
-			goto fail;
-		}
-
-		c_entry = &ms_local[ms_iter];
-		c_entry->len = pages[i].len;
-
-		if (get_hugefile_by_virt_addr(pages[i].addr_64, c_entry) < 0)
-			goto fail;
-
-		/* if previous entry has the same filename and is contiguous,
-		 * clear current entry and increase previous entry's length
-		 */
-		if (prev_entry != NULL &&
-				strncmp(c_entry->filepath, prev_entry->filepath,
-				sizeof(c_entry->filepath)) == 0 &&
-				prev_entry->offset + prev_entry->len == c_entry->offset) {
-			prev_entry->len += pages[i].len;
-			memset(c_entry, 0, sizeof(struct memseg_cache_entry));
-		}
-		else {
-			prev_entry = c_entry;
-			ms_iter++;
-		}
-	}
-
-	/* update current configuration with new valid data */
-	memcpy(config->metadata->entry, e_local, sizeof(config->metadata->entry));
-	memcpy(config->memseg_cache, ms_local, sizeof(config->memseg_cache));
-
-	free(ms_local);
-	free(e_local);
-
-	return 0;
-fail:
-	free(ms_local);
-fail_ms:
-	free(e_local);
-fail_e:
-	return -1;
-}
-
-static int
-add_memzone_to_metadata(const struct rte_memzone * mz,
-		struct ivshmem_config * config)
-{
-	struct rte_ivshmem_metadata_entry * entry;
-	unsigned i, idx;
-	struct rte_mem_config *mcfg;
-
-	if (mz->len == 0) {
-		RTE_LOG(ERR, EAL, "Trying to add an empty memzone\n");
-		return -1;
-	}
-
-	rte_spinlock_lock(&config->sl);
-
-	mcfg = rte_eal_get_configuration()->mem_config;
-
-	/* it prevents the memzone being freed while we add it to the metadata */
-	rte_rwlock_write_lock(&mcfg->mlock);
-
-	/* find free slot in this config */
-	for (i = 0; i < RTE_DIM(config->metadata->entry); i++) {
-		entry = &config->metadata->entry[i];
-
-		if (&entry->mz.addr_64 != 0 && overlap(mz, &entry->mz)) {
-			RTE_LOG(ERR, EAL, "Overlapping memzones!\n");
-			goto fail;
-		}
-
-		/* if addr is zero, the memzone is probably free */
-		if (entry->mz.addr_64 == 0) {
-			RTE_LOG(DEBUG, EAL, "Adding memzone '%s' at %p to metadata %s\n",
-					mz->name, mz->addr, config->metadata->name);
-			memcpy(&entry->mz, mz, sizeof(struct rte_memzone));
-
-			/* run config file parser */
-			if (build_config(config->metadata) < 0)
-				goto fail;
-
-			break;
-		}
-	}
-
-	/* if we reached the maximum, that means we have no place in config */
-	if (i == RTE_DIM(config->metadata->entry)) {
-		RTE_LOG(ERR, EAL, "No space left in IVSHMEM metadata %s!\n",
-				config->metadata->name);
-		goto fail;
-	}
-
-	idx = ((uintptr_t)mz - (uintptr_t)mcfg->memzone);
-	idx = idx / sizeof(struct rte_memzone);
-
-	/* mark the memzone not freeable */
-	mcfg->memzone[idx].ioremap_addr = mz->phys_addr;
-
-	rte_rwlock_write_unlock(&mcfg->mlock);
-	rte_spinlock_unlock(&config->sl);
-	return 0;
-fail:
-	rte_rwlock_write_unlock(&mcfg->mlock);
-	rte_spinlock_unlock(&config->sl);
-	return -1;
-}
-
-static int
-add_ring_to_metadata(const struct rte_ring * r,
-		struct ivshmem_config * config)
-{
-	struct rte_memzone * mz;
-
-	mz = get_memzone_by_addr(r);
-
-	if (!mz) {
-		RTE_LOG(ERR, EAL, "Cannot find memzone for ring!\n");
-		return -1;
-	}
-
-	return add_memzone_to_metadata(mz, config);
-}
-
-static int
-add_mempool_memzone_to_metadata(const void *addr,
-		struct ivshmem_config *config)
-{
-	struct rte_memzone *mz;
-
-	mz = get_memzone_by_addr(addr);
-
-	if (!mz) {
-		RTE_LOG(ERR, EAL, "Cannot find memzone for mempool!\n");
-		return -1;
-	}
-
-	return add_memzone_to_metadata(mz, config);
-}
-
-static int
-add_mempool_to_metadata(const struct rte_mempool *mp,
-		struct ivshmem_config *config)
-{
-	struct rte_mempool_memhdr *memhdr;
-	int ret;
-
-	ret = add_mempool_memzone_to_metadata(mp, config);
-	if (ret < 0)
-		return -1;
-
-	STAILQ_FOREACH(memhdr, &mp->mem_list, next) {
-		ret = add_mempool_memzone_to_metadata(memhdr->addr, config);
-		if (ret < 0)
-			return -1;
-	}
-
-	/* mempool consists of memzone and ring */
-	return add_ring_to_metadata(mp->pool_data, config);
-}
-
-int
-rte_ivshmem_metadata_add_ring(const struct rte_ring * r, const char * name)
-{
-	struct ivshmem_config * config;
-
-	if (name == NULL || r == NULL)
-		return -1;
-
-	config = get_config_by_name(name);
-
-	if (config == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name);
-		return -1;
-	}
-
-	return add_ring_to_metadata(r, config);
-}
-
-int
-rte_ivshmem_metadata_add_memzone(const struct rte_memzone * mz, const char * name)
-{
-	struct ivshmem_config * config;
-
-	if (name == NULL || mz == NULL)
-		return -1;
-
-	config = get_config_by_name(name);
-
-	if (config == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name);
-		return -1;
-	}
-
-	return add_memzone_to_metadata(mz, config);
-}
-
-int
-rte_ivshmem_metadata_add_mempool(const struct rte_mempool * mp, const char * name)
-{
-	struct ivshmem_config * config;
-
-	if (name == NULL || mp == NULL)
-		return -1;
-
-	config = get_config_by_name(name);
-
-	if (config == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name);
-		return -1;
-	}
-
-	return add_mempool_to_metadata(mp, config);
-}
-
-static inline void
-ivshmem_config_path(char *buffer, size_t bufflen, const char *name)
-{
-	snprintf(buffer, bufflen, IVSHMEM_CONFIG_FILE_FMT, name);
-}
-
-
-
-static inline
-void *ivshmem_metadata_create(const char *name, size_t size,
-		struct flock *lock)
-{
-	int retval, fd;
-	void *metadata_addr;
-	char pathname[PATH_MAX];
-
-	ivshmem_config_path(pathname, sizeof(pathname), name);
-
-	fd = open(pathname, O_RDWR | O_CREAT, 0660);
-	if (fd < 0) {
-		RTE_LOG(ERR, EAL, "Cannot open '%s'\n", pathname);
-		return NULL;
-	}
-
-	size = METADATA_SIZE_ALIGNED;
-
-	retval = fcntl(fd, F_SETLK, lock);
-	if (retval < 0){
-		close(fd);
-		RTE_LOG(ERR, EAL, "Cannot create lock on '%s'. Is another "
-				"process using it?\n", pathname);
-		return NULL;
-	}
-
-	retval = ftruncate(fd, size);
-	if (retval < 0){
-		close(fd);
-		RTE_LOG(ERR, EAL, "Cannot resize '%s'\n", pathname);
-		return NULL;
-	}
-
-	metadata_addr = mmap(NULL, size,
-				PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-
-	if (metadata_addr == MAP_FAILED){
-		RTE_LOG(ERR, EAL, "Cannot mmap memory for '%s'\n", pathname);
-
-		/* we don't care if we can't unlock */
-		fcntl(fd, F_UNLCK, lock);
-		close(fd);
-
-		return NULL;
-	}
-
-	return metadata_addr;
-}
-
-int rte_ivshmem_metadata_create(const char *name)
-{
-	struct ivshmem_config * ivshmem_config;
-	unsigned index;
-
-	if (pagesz == 0)
-		pagesz = getpagesize();
-
-	if (name == NULL)
-		return -1;
-
-	rte_spinlock_lock(&global_cfg_sl);
-
-	for (index = 0; index < RTE_DIM(ivshmem_global_config); index++) {
-		if (ivshmem_global_config[index].metadata == NULL) {
-			ivshmem_config = &ivshmem_global_config[index];
-			break;
-		}
-	}
-
-	if (index == RTE_DIM(ivshmem_global_config)) {
-		RTE_LOG(ERR, EAL, "Cannot create more ivshmem config files. "
-		"Maximum has been reached\n");
-		rte_spinlock_unlock(&global_cfg_sl);
-		return -1;
-	}
-
-	ivshmem_config->lock.l_type = F_WRLCK;
-	ivshmem_config->lock.l_whence = SEEK_SET;
-
-	ivshmem_config->lock.l_start = 0;
-	ivshmem_config->lock.l_len = METADATA_SIZE_ALIGNED;
-
-	ivshmem_global_config[index].metadata = ((struct rte_ivshmem_metadata *)
-			ivshmem_metadata_create(
-					name,
-					sizeof(struct rte_ivshmem_metadata),
-					&ivshmem_config->lock));
-
-	if (ivshmem_global_config[index].metadata == NULL) {
-		rte_spinlock_unlock(&global_cfg_sl);
-		return -1;
-	}
-
-	/* Metadata setup */
-	memset(ivshmem_config->metadata, 0, sizeof(struct rte_ivshmem_metadata));
-	ivshmem_config->metadata->magic_number = IVSHMEM_MAGIC;
-	snprintf(ivshmem_config->metadata->name,
-			sizeof(ivshmem_config->metadata->name), "%s", name);
-
-	rte_spinlock_unlock(&global_cfg_sl);
-
-	return 0;
-}
-
-int
-rte_ivshmem_metadata_cmdline_generate(char *buffer, unsigned size, const char *name)
-{
-	const struct memseg_cache_entry * ms_cache, *entry;
-	struct ivshmem_config * config;
-	char cmdline[IVSHMEM_QEMU_CMDLINE_BUFSIZE], *cmdline_ptr;
-	char cfg_file_path[PATH_MAX];
-	unsigned remaining_len, tmplen, iter;
-	uint64_t shared_mem_size, zero_size, total_size;
-
-	if (buffer == NULL || name == NULL)
-		return -1;
-
-	config = get_config_by_name(name);
-
-	if (config == NULL) {
-		RTE_LOG(ERR, EAL, "Config %s not found!\n", name);
-		return -1;
-	}
-
-	rte_spinlock_lock(&config->sl);
-
-	/* prepare metadata file path */
-	snprintf(cfg_file_path, sizeof(cfg_file_path), IVSHMEM_CONFIG_FILE_FMT,
-			config->metadata->name);
-
-	ms_cache = config->memseg_cache;
-
-	cmdline_ptr = cmdline;
-	remaining_len = sizeof(cmdline);
-
-	shared_mem_size = 0;
-	iter = 0;
-
-	while ((ms_cache[iter].len != 0) && (iter < RTE_DIM(config->metadata->entry))) {
-
-		entry = &ms_cache[iter];
-
-		/* Offset and sizes within the current pathname */
-		tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
-				entry->filepath, entry->offset, entry->len);
-
-		shared_mem_size += entry->len;
-
-		cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
-		remaining_len -= tmplen;
-
-		if (remaining_len == 0) {
-			RTE_LOG(ERR, EAL, "Command line too long!\n");
-			rte_spinlock_unlock(&config->sl);
-			return -1;
-		}
-
-		iter++;
-	}
-
-	total_size = rte_align64pow2(shared_mem_size + METADATA_SIZE_ALIGNED);
-	zero_size = total_size - shared_mem_size - METADATA_SIZE_ALIGNED;
-
-	/* add /dev/zero to command-line to fill the space */
-	tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
-			"/dev/zero",
-			(uint64_t)0x0,
-			zero_size);
-
-	cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
-	remaining_len -= tmplen;
-
-	if (remaining_len == 0) {
-		RTE_LOG(ERR, EAL, "Command line too long!\n");
-		rte_spinlock_unlock(&config->sl);
-		return -1;
-	}
-
-	/* add metadata file to the end of command-line */
-	tmplen = snprintf(cmdline_ptr, remaining_len, IVSHMEM_QEMU_CMD_FD_FMT,
-			cfg_file_path,
-			(uint64_t)0x0,
-			METADATA_SIZE_ALIGNED);
-
-	cmdline_ptr = RTE_PTR_ADD(cmdline_ptr, tmplen);
-	remaining_len -= tmplen;
-
-	if (remaining_len == 0) {
-		RTE_LOG(ERR, EAL, "Command line too long!\n");
-		rte_spinlock_unlock(&config->sl);
-		return -1;
-	}
-
-	/* if current length of the command line is bigger than the buffer supplied
-	 * by the user, or if command-line is bigger than what IVSHMEM accepts */
-	if ((sizeof(cmdline) - remaining_len) > size) {
-		RTE_LOG(ERR, EAL, "Buffer is too short!\n");
-		rte_spinlock_unlock(&config->sl);
-		return -1;
-	}
-	/* complete the command-line */
-	snprintf(buffer, size,
-			IVSHMEM_QEMU_CMD_LINE_HEADER_FMT,
-			total_size >> 20,
-			cmdline);
-
-	rte_spinlock_unlock(&config->sl);
-
-	return 0;
-}
-
-void
-rte_ivshmem_metadata_dump(FILE *f, const char *name)
-{
-	unsigned i = 0;
-	struct ivshmem_config * config;
-	struct rte_ivshmem_metadata_entry *entry;
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-	uint64_t addr;
-	uint64_t end, hugepage_sz;
-	struct memseg_cache_entry e;
-#endif
-
-	if (name == NULL)
-		return;
-
-	/* return error if we try to use an unknown config file */
-	config = get_config_by_name(name);
-	if (config == NULL) {
-		RTE_LOG(ERR, EAL, "Cannot find IVSHMEM config %s!\n", name);
-		return;
-	}
-
-	rte_spinlock_lock(&config->sl);
-
-	entry = &config->metadata->entry[0];
-
-	while (entry->mz.addr != NULL && i < RTE_DIM(config->metadata->entry)) {
-
-		fprintf(f, "Entry %u: name:<%-20s>, phys:0x%-15lx, len:0x%-15lx, "
-			"virt:%-15p, off:0x%-15lx\n",
-			i,
-			entry->mz.name,
-			entry->mz.phys_addr,
-			entry->mz.len,
-			entry->mz.addr,
-			entry->offset);
-		i++;
-
-#ifdef RTE_LIBRTE_IVSHMEM_DEBUG
-		fprintf(f, "\tHugepage files:\n");
-
-		hugepage_sz = entry->mz.hugepage_sz;
-		addr = RTE_ALIGN_FLOOR(entry->mz.addr_64, hugepage_sz);
-		end = addr + RTE_ALIGN_CEIL(entry->mz.len + (entry->mz.addr_64 - addr),
-				hugepage_sz);
-
-		for (; addr < end; addr += hugepage_sz) {
-			memset(&e, 0, sizeof(e));
-
-			get_hugefile_by_virt_addr(addr, &e);
-
-			fprintf(f, "\t0x%"PRIx64 "-0x%" PRIx64 " offset: 0x%" PRIx64 " %s\n",
-					addr, addr + hugepage_sz, e.offset, e.filepath);
-		}
-#endif
-		entry++;
-	}
-
-	rte_spinlock_unlock(&config->sl);
-}
diff --git a/lib/librte_ivshmem/rte_ivshmem.h b/lib/librte_ivshmem/rte_ivshmem.h
deleted file mode 100644
index a5d36d6..0000000
--- a/lib/librte_ivshmem/rte_ivshmem.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef RTE_IVSHMEM_H_
-#define RTE_IVSHMEM_H_
-
-#include <rte_memzone.h>
-#include <rte_mempool.h>
-
-/**
- * @file
- *
- * The RTE IVSHMEM interface provides functions to create metadata files
- * describing memory segments to be shared via QEMU IVSHMEM.
- */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define IVSHMEM_MAGIC 0x0BADC0DE
-#define IVSHMEM_NAME_LEN 32
-
-/**
- * Structure that holds IVSHMEM shared metadata entry.
- */
-struct rte_ivshmem_metadata_entry {
-	struct rte_memzone mz;	/**< shared memzone */
-	uint64_t offset;	/**< offset of memzone within IVSHMEM device */
-};
-
-/**
- * Structure that holds IVSHMEM metadata.
- */
-struct rte_ivshmem_metadata {
-	int magic_number;				/**< magic number */
-	char name[IVSHMEM_NAME_LEN];	/**< name of the metadata file */
-	struct rte_ivshmem_metadata_entry entry[RTE_LIBRTE_IVSHMEM_MAX_ENTRIES];
-			/**< metadata entries */
-};
-
-/**
- * Creates metadata file with a given name
- *
- * @param name
- *  Name of metadata file to be created
- *
- * @return
- *  - On success, zero
- *  - On failure, a negative value
- */
-int rte_ivshmem_metadata_create(const char * name);
-
-/**
- * Adds memzone to a specific metadata file
- *
- * @param mz
- *  Memzone to be added
- * @param md_name
- *  Name of metadata file for the memzone to be added to
- *
- * @return
- *  - On success, zero
- *  - On failure, a negative value
- */
-int rte_ivshmem_metadata_add_memzone(const struct rte_memzone * mz,
-		const char * md_name);
-
-/**
- * Adds a ring descriptor to a specific metadata file
- *
- * @param r
- *  Ring descriptor to be added
- * @param md_name
- *  Name of metadata file for the ring to be added to
- *
- * @return
- *  - On success, zero
- *  - On failure, a negative value
- */
-int rte_ivshmem_metadata_add_ring(const struct rte_ring * r,
-		const char * md_name);
-
-/**
- * Adds a mempool to a specific metadata file
- *
- * @param mp
- *  Mempool to be added
- * @param md_name
- *  Name of metadata file for the mempool to be added to
- *
- * @return
- *  - On success, zero
- *  - On failure, a negative value
- */
-int rte_ivshmem_metadata_add_mempool(const struct rte_mempool * mp,
-		const char * md_name);
-
-
-/**
- * Generates the QEMU command-line for IVSHMEM device for a given metadata file.
- * This function is to be called after all the objects were added.
- *
- * @param buffer
- *  Buffer to be filled with the command line arguments.
- * @param size
- *  Size of the buffer.
- * @param name
- *  Name of metadata file to generate QEMU command-line parameters for
- *
- * @return
- *  - On success, zero
- *  - On failure, a negative value
- */
-int rte_ivshmem_metadata_cmdline_generate(char *buffer, unsigned size,
-		const char *name);
-
-
-/**
- * Dump all metadata entries from a given metadata file to the console.
- *
- * @param f
- *   A pointer to a file for output
- * @name
- *  Name of the metadata file to be dumped to console.
- */
-void rte_ivshmem_metadata_dump(FILE *f, const char *name);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* RTE_IVSHMEM_H_ */
diff --git a/lib/librte_ivshmem/rte_ivshmem_version.map b/lib/librte_ivshmem/rte_ivshmem_version.map
deleted file mode 100644
index 5a393dd..0000000
--- a/lib/librte_ivshmem/rte_ivshmem_version.map
+++ /dev/null
@@ -1,12 +0,0 @@
-DPDK_2.0 {
-	global:
-
-	rte_ivshmem_metadata_add_mempool;
-	rte_ivshmem_metadata_add_memzone;
-	rte_ivshmem_metadata_add_ring;
-	rte_ivshmem_metadata_cmdline_generate;
-	rte_ivshmem_metadata_create;
-	rte_ivshmem_metadata_dump;
-
-	local: *;
-};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index eb28e11..1a0095b 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -62,7 +62,6 @@ _LDLIBS-y += -L$(RTE_SDK_BIN)/lib
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 _LDLIBS-$(CONFIG_RTE_LIBRTE_KNI)            += -lrte_kni
-_LDLIBS-$(CONFIG_RTE_LIBRTE_IVSHMEM)        += -lrte_ivshmem
 endif
 
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PIPELINE)       += -lrte_pipeline
-- 
1.9.1

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

end of thread, other threads:[~2016-08-23 10:46 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-29 12:28 [dpdk-dev] [PATCH] ivshmem: remove integration in dpdk David Marchand
2016-08-04 12:50 ` Panu Matilainen
2016-08-18 14:08 ` Burakov, Anatoly
2016-08-23 10:24   ` Thomas Monjalon

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).