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/
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
"Func" : default_autotest,
"Report" : None,
},
- {
- "Name" : "IVSHMEM autotest",
- "Command" : "ivshmem_autotest",
- "Func" : default_autotest,
- "Report" : None,
- },
{
"Name" : "Memcpy autotest",
"Command" : "memcpy_autotest",
{ "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)
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);
+++ /dev/null
-/*-
- * 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);
CONFIG_RTE_EAL_IGB_UIO=n
-CONFIG_RTE_LIBRTE_IVSHMEM=n
CONFIG_RTE_LIBRTE_FM10K_PMD=n
CONFIG_RTE_LIBRTE_I40E_PMD=n
+++ /dev/null
-# 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
+++ /dev/null
-# 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
[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):
lib/librte_ether \
lib/librte_hash \
lib/librte_ip_frag \
- lib/librte_ivshmem \
lib/librte_jobstats \
lib/librte_kni \
lib/librte_kvargs \
@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
* ``ARCH`` can be: ``i686``, ``x86_64``, ``ppc_64``
-* ``MACHINE`` can be: ``native``, ``ivshmem``, ``power8``
+* ``MACHINE`` can be: ``native``, ``power8``
* ``EXECENV`` can be: ``linuxapp``, ``bsdapp``
[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
------------------------------------------------------------------------
mbuf_lib
poll_mode_drv
cryptodev_lib
- ivshmem_lib
link_bonding_poll_mode_drv_lib
timer_lib
hash_lib
+++ /dev/null
-.. 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).
+-- 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
and will be removed in 17.02.
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.
* The log history is removed.
+* 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
-----------
+ librte_eal.so.3
librte_hash.so.2
librte_ip_frag.so.1
- librte_ivshmem.so.1
librte_jobstats.so.1
librte_kni.so.2
librte_kvargs.so.1
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
+++ /dev/null
-# 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
+++ /dev/null
-# 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
+++ /dev/null
-/*-
- * 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 = ð->d_addr.addr_bytes[0];
- *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)portid << 40);
-
- /* src addr */
- ether_addr_copy(&ctrl->vm_ports[portid].dst->ethaddr,
- ð->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;
-}
+++ /dev/null
-# 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
+++ /dev/null
-/*-
- * 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;
-}
+++ /dev/null
-/*-
- * 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_ */
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
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
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) {
*/
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;
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. */
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 */
/**
* 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);
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);
}
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
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
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");
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");
+++ /dev/null
-/*-
- * 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
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;
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.
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
+++ /dev/null
-# 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
+++ /dev/null
-/*-
- * 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);
-}
+++ /dev/null
-/*-
- * 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_ */
+++ /dev/null
-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: *;
-};
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