aboutsummaryrefslogtreecommitdiff
path: root/test/linux-generic/pktio_ipc
diff options
context:
space:
mode:
authorChristophe Milard <christophe.milard@linaro.org>2016-07-13 21:50:42 +0200
committerMaxim Uvarov <maxim.uvarov@linaro.org>2016-07-21 16:02:50 +0300
commit79534012879ca74a68256ca40922b3fef7983611 (patch)
tree986c402d6138d81f93fe050bad4f507591f1f561 /test/linux-generic/pktio_ipc
parentefa6bc89a4e7a5823a3c8c27fcdc9573d7ac5694 (diff)
test: restructuring platform-specific tests to allow other interface
test/platform/<platform_name>/* moves to: test/<platform_name>/validation/api/ Two reasons: *test/platform/<platform_name>/ now moves to test/<platform_name>, hence at the same level than "common_plat" clearly separating between platform agnostic and platform specific parts. *Also, under test/<platform_name>, the test group "validation" and interface "api" are created, hence allowing for other tests type to have platform specifics (for instance running perf test from platform side to set proper pktios), and allowing other interfaces to be tested under validation. Signed-off-by: Christophe Milard <christophe.milard@linaro.org> Reviewed-by: Bill Fischofer <bill.fischofer@linaro.org> Reviewed-and-tested-by: Yi He <yi.he@linaro.org> Reviewed-by: Mike Holmes <mike.holmes@linaro.org> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
Diffstat (limited to 'test/linux-generic/pktio_ipc')
-rw-r--r--test/linux-generic/pktio_ipc/.gitignore2
-rw-r--r--test/linux-generic/pktio_ipc/Makefile.am20
-rw-r--r--test/linux-generic/pktio_ipc/ipc_common.c162
-rw-r--r--test/linux-generic/pktio_ipc/ipc_common.h91
-rw-r--r--test/linux-generic/pktio_ipc/pktio_ipc1.c329
-rw-r--r--test/linux-generic/pktio_ipc/pktio_ipc2.c197
-rwxr-xr-xtest/linux-generic/pktio_ipc/pktio_ipc_run.sh72
7 files changed, 873 insertions, 0 deletions
diff --git a/test/linux-generic/pktio_ipc/.gitignore b/test/linux-generic/pktio_ipc/.gitignore
new file mode 100644
index 000000000..49ee4fd29
--- /dev/null
+++ b/test/linux-generic/pktio_ipc/.gitignore
@@ -0,0 +1,2 @@
+pktio_ipc1
+pktio_ipc2
diff --git a/test/linux-generic/pktio_ipc/Makefile.am b/test/linux-generic/pktio_ipc/Makefile.am
new file mode 100644
index 000000000..8858bd2f5
--- /dev/null
+++ b/test/linux-generic/pktio_ipc/Makefile.am
@@ -0,0 +1,20 @@
+include $(top_srcdir)/test/Makefile.inc
+TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/validation
+
+test_PROGRAMS = pktio_ipc1\
+ pktio_ipc2
+
+pktio_ipc1_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example
+pktio_ipc1_LDFLAGS = $(AM_LDFLAGS) -static
+pktio_ipc2_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example
+pktio_ipc2_LDFLAGS = $(AM_LDFLAGS) -static
+
+noinst_HEADERS = $(top_srcdir)/test/test_debug.h
+
+dist_pktio_ipc1_SOURCES = pktio_ipc1.c ipc_common.c
+dist_pktio_ipc2_SOURCES = pktio_ipc2.c ipc_common.c
+
+EXTRA_DIST = ipc_common.h
+
+dist_check_SCRIPTS = pktio_ipc_run.sh
+test_SCRIPTS = $(dist_check_SCRIPTS)
diff --git a/test/linux-generic/pktio_ipc/ipc_common.c b/test/linux-generic/pktio_ipc/ipc_common.c
new file mode 100644
index 000000000..2ee326e28
--- /dev/null
+++ b/test/linux-generic/pktio_ipc/ipc_common.c
@@ -0,0 +1,162 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "ipc_common.h"
+
+/** Run time in seconds */
+int run_time_sec;
+int ipc_name_space;
+
+int ipc_odp_packet_sendall(odp_pktio_t pktio,
+ odp_packet_t pkt_tbl[], int num)
+{
+ int ret;
+ int sent = 0;
+ odp_time_t start_time;
+ odp_time_t end_time;
+ odp_time_t wait;
+ odp_pktout_queue_t pktout;
+
+ start_time = odp_time_local();
+ wait = odp_time_local_from_ns(ODP_TIME_SEC_IN_NS);
+ end_time = odp_time_sum(start_time, wait);
+
+ if (odp_pktout_queue(pktio, &pktout, 1) != 1) {
+ EXAMPLE_ERR("no output queue\n");
+ return -1;
+ }
+
+ while (sent != num) {
+ ret = odp_pktout_send(pktout, &pkt_tbl[sent], num - sent);
+ if (ret < 0)
+ return -1;
+
+ sent += ret;
+
+ if (odp_time_cmp(end_time, odp_time_local()) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+odp_pktio_t create_pktio(odp_pool_t pool)
+{
+ odp_pktio_param_t pktio_param;
+ odp_pktio_t ipc_pktio;
+
+ odp_pktio_param_init(&pktio_param);
+
+ printf("pid: %d, create IPC pktio\n", getpid());
+ ipc_pktio = odp_pktio_open("ipc_pktio", pool, &pktio_param);
+ if (ipc_pktio == ODP_PKTIO_INVALID)
+ EXAMPLE_ABORT("Error: ipc pktio create failed.\n");
+
+ if (odp_pktin_queue_config(ipc_pktio, NULL)) {
+ EXAMPLE_ERR("Input queue config failed\n");
+ return ODP_PKTIO_INVALID;
+ }
+
+ if (odp_pktout_queue_config(ipc_pktio, NULL)) {
+ EXAMPLE_ERR("Output queue config failed\n");
+ return ODP_PKTIO_INVALID;
+ }
+
+ return ipc_pktio;
+}
+
+/**
+ * Parse and store the command line arguments
+ *
+ * @param argc argument count
+ * @param argv[] argument vector
+ * @param appl_args Store application arguments here
+ */
+void parse_args(int argc, char *argv[])
+{
+ int opt;
+ int long_index;
+ static struct option longopts[] = {
+ {"time", required_argument, NULL, 't'},
+ {"ns", required_argument, NULL, 'n'}, /* ipc name space */
+ {"help", no_argument, NULL, 'h'}, /* return 'h' */
+ {NULL, 0, NULL, 0}
+ };
+
+ run_time_sec = 0; /* loop forever if time to run is 0 */
+ ipc_name_space = 0;
+
+ while (1) {
+ opt = getopt_long(argc, argv, "+t:n:h",
+ longopts, &long_index);
+
+ if (opt == -1)
+ break; /* No more options */
+
+ switch (opt) {
+ case 't':
+ run_time_sec = atoi(optarg);
+ break;
+ case 'n':
+ ipc_name_space = atoi(optarg);
+ break;
+ case 'h':
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ optind = 1; /* reset 'extern optind' from the getopt lib */
+
+ if (!ipc_name_space) {
+ usage(argv[0]);
+ exit(1);
+ }
+}
+
+/**
+ * Print system and application info
+ */
+void print_info(char *progname)
+{
+ printf("\n"
+ "ODP system info\n"
+ "---------------\n"
+ "ODP API version: %s\n"
+ "CPU model: %s\n"
+ "\n",
+ odp_version_api_str(), odp_cpu_model_str());
+
+ printf("Running ODP appl: \"%s\"\n"
+ "-----------------\n"
+ "Using IF: %s\n",
+ progname, pktio_name);
+ printf("\n\n");
+ fflush(NULL);
+}
+
+/**
+ * Prinf usage information
+ */
+void usage(char *progname)
+{
+ printf("\n"
+ "Usage: %s OPTIONS\n"
+ " E.g. -n ipc_name_space %s -t seconds\n"
+ "\n"
+ "OpenDataPlane odp-linux ipc test application.\n"
+ "\n"
+ "Mandatory OPTIONS:\n"
+ " -n, --ns IPC name space ID /dev/shm/odp-<ns>-objname.\n"
+ "Optional OPTIONS\n"
+ " -h, --help Display help and exit.\n"
+ " -t, --time Time to run in seconds.\n"
+ "\n", NO_PATH(progname), NO_PATH(progname)
+ );
+}
diff --git a/test/linux-generic/pktio_ipc/ipc_common.h b/test/linux-generic/pktio_ipc/ipc_common.h
new file mode 100644
index 000000000..a6b7c581b
--- /dev/null
+++ b/test/linux-generic/pktio_ipc/ipc_common.h
@@ -0,0 +1,91 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#define _POSIX_C_SOURCE 200809L
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+#include <example_debug.h>
+
+#include <odp.h>
+#include <odp/helper/linux.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+#include <odp/helper/udp.h>
+
+/** @def SHM_PKT_POOL_SIZE
+ * @brief Size of the shared memory block
+ */
+#define SHM_PKT_POOL_SIZE 8192
+
+/** @def SHM_PKT_POOL_BUF_SIZE
+ * @brief Buffer size of the packet pool buffer
+ */
+#define SHM_PKT_POOL_BUF_SIZE 1856
+
+/** @def MAX_PKT_BURST
+ * @brief Maximum number of packet bursts
+ */
+#define MAX_PKT_BURST 16
+
+/** Get rid of path in filename - only for unix-type paths using '/' */
+#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
+ strrchr((file_name), '/') + 1 : (file_name))
+
+#define TEST_SEQ_MAGIC 0x92749451
+#define TEST_SEQ_MAGIC_2 0x81638340
+
+#define TEST_ALLOC_MAGIC 0x1234adcd
+
+/** magic number and sequence at start of packet payload */
+typedef struct ODP_PACKED {
+ odp_u32be_t magic;
+ odp_u32be_t seq;
+} pkt_head_t;
+
+/** magic number at end of packet payload */
+typedef struct ODP_PACKED {
+ odp_u32be_t magic;
+} pkt_tail_t;
+
+/** Application argument */
+char *pktio_name;
+
+/** Run time in seconds */
+int run_time_sec;
+
+/** IPC name space id /dev/shm/odp-nsid-objname */
+int ipc_name_space;
+
+/* helper funcs */
+void parse_args(int argc, char *argv[]);
+void print_info(char *progname);
+void usage(char *progname);
+
+/**
+ * Create a ipc pktio handle.
+ *
+ * @param pool Pool to associate with device for packet RX/TX
+ *
+ * @return The handle of the created pktio object.
+ * @retval ODP_PKTIO_INVALID if the create fails.
+ */
+odp_pktio_t create_pktio(odp_pool_t pool);
+
+/** Spin and send all packet from table
+ *
+ * @param pktio pktio device
+ * @param pkt_tbl packets table
+ * @param num number of packets
+ */
+int ipc_odp_packet_sendall(odp_pktio_t pktio,
+ odp_packet_t pkt_tbl[], int num);
diff --git a/test/linux-generic/pktio_ipc/pktio_ipc1.c b/test/linux-generic/pktio_ipc/pktio_ipc1.c
new file mode 100644
index 000000000..a4eed8832
--- /dev/null
+++ b/test/linux-generic/pktio_ipc/pktio_ipc1.c
@@ -0,0 +1,329 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "ipc_common.h"
+
+/**
+ * @file
+ * @example pktio_ipc1.c ODP IPC example application.
+ * This application works in pair with pktio_ipc2 application.
+ * It opens ipc pktio, allocates packets, sets magic number and
+ * sends packets to ipc pktio. Then app reads packets and checks
+ * that magic number was properly updated and there is no packet
+ * loss (i.e. sequesce counter continiusly incrementing.)
+ */
+
+/**
+ * Packet IO loopback worker thread using bursts from/to IO resources
+ *
+ * @param arg thread arguments of type 'thread_args_t *'
+ */
+static int pktio_run_loop(odp_pool_t pool)
+{
+ int thr;
+ int pkts;
+ odp_pktio_t ipc_pktio;
+ odp_packet_t pkt_tbl[MAX_PKT_BURST];
+ uint64_t cnt = 0; /* increasing counter on each send packet */
+ uint64_t cnt_recv = 0; /* increasing counter to validate
+ cnt on receive */
+ uint64_t stat_pkts = 0;
+ uint64_t stat_pkts_alloc = 0;
+ uint64_t stat_pkts_prev = 0;
+ uint64_t stat_errors = 0;
+ odp_time_t start_cycle;
+ odp_time_t current_cycle;
+ odp_time_t cycle;
+ odp_time_t diff;
+ odp_time_t wait;
+ int ret;
+ odp_pktin_queue_t pktin;
+
+ thr = odp_thread_id();
+
+ ipc_pktio = odp_pktio_lookup("ipc_pktio");
+ if (ipc_pktio == ODP_PKTIO_INVALID) {
+ EXAMPLE_ERR(" [%02i] Error: lookup of pktio %s failed\n",
+ thr, "ipc_pktio");
+ return -2;
+ }
+ printf(" [%02i] looked up ipc_pktio:%02" PRIu64 ", burst mode\n",
+ thr, odp_pktio_to_u64(ipc_pktio));
+
+ wait = odp_time_local_from_ns(run_time_sec * ODP_TIME_SEC_IN_NS);
+ start_cycle = odp_time_local();
+ current_cycle = start_cycle;
+
+ if (odp_pktin_queue(ipc_pktio, &pktin, 1) != 1) {
+ EXAMPLE_ERR("no input queue\n");
+ return -1;
+ }
+
+ /* start ipc pktio, i.e. wait until other process connects */
+ for (;;) {
+ if (run_time_sec) {
+ cycle = odp_time_local();
+ diff = odp_time_diff(cycle, start_cycle);
+ if (odp_time_cmp(wait, diff) < 0) {
+ printf("timeout exit, run_time_sec %d\n",
+ run_time_sec);
+ goto exit;
+ }
+ }
+
+ ret = odp_pktio_start(ipc_pktio);
+ if (!ret)
+ break;
+ }
+
+ /* packets loop */
+ for (;;) {
+ int i;
+
+ /* 1. exit loop if time specified */
+ if (run_time_sec) {
+ cycle = odp_time_local();
+ diff = odp_time_diff(cycle, start_cycle);
+ if (odp_time_cmp(wait, diff) < 0) {
+ EXAMPLE_DBG("exit after %d seconds\n",
+ run_time_sec);
+ break;
+ }
+ }
+
+ /* 2. Receive packets back from ipc_pktio, validate magic
+ * number sequence counter and free that packet
+ */
+ while (1) {
+ pkts = odp_pktin_recv(pktin, pkt_tbl, MAX_PKT_BURST);
+ if (pkts <= 0)
+ break;
+
+ for (i = 0; i < pkts; i++) {
+ odp_packet_t pkt = pkt_tbl[i];
+ pkt_head_t head;
+ pkt_tail_t tail;
+ size_t off;
+
+ off = odp_packet_l4_offset(pkt);
+ if (off == ODP_PACKET_OFFSET_INVALID)
+ EXAMPLE_ABORT("invalid l4 offset\n");
+
+ off += ODPH_UDPHDR_LEN;
+ ret = odp_packet_copy_to_mem(pkt, off,
+ sizeof(head),
+ &head);
+ if (ret) {
+ stat_errors++;
+ odp_packet_free(pkt);
+ EXAMPLE_DBG("error\n");
+ continue;
+ }
+
+ if (head.magic == TEST_ALLOC_MAGIC) {
+ stat_pkts_alloc++;
+ odp_packet_free(pkt);
+ continue;
+ }
+
+ if (head.magic != TEST_SEQ_MAGIC_2) {
+ stat_errors++;
+ odp_packet_free(pkt);
+ EXAMPLE_DBG("error\n");
+ continue;
+ }
+
+ off = odp_packet_len(pkt) - sizeof(pkt_tail_t);
+ ret = odp_packet_copy_to_mem(pkt, off,
+ sizeof(tail),
+ &tail);
+ if (ret) {
+ stat_errors++;
+ odp_packet_free(pkt);
+ continue;
+ }
+
+ if (tail.magic != TEST_SEQ_MAGIC) {
+ stat_errors++;
+ odp_packet_free(pkt);
+ continue;
+ }
+
+ cnt_recv++;
+
+ if (head.seq != cnt_recv) {
+ stat_errors++;
+ odp_packet_free(pkt);
+ EXAMPLE_DBG("head.seq %d - "
+ "cnt_recv %" PRIu64 ""
+ " = %" PRIu64 "\n",
+ head.seq, cnt_recv,
+ head.seq - cnt_recv);
+ cnt_recv = head.seq;
+ continue;
+ }
+
+ stat_pkts++;
+ odp_packet_free(pkt);
+ }
+ }
+
+ /* 3. emulate that pkts packets were received */
+ odp_random_data((uint8_t *)&pkts, sizeof(pkts), 0);
+ pkts = ((pkts & 0xffff) % MAX_PKT_BURST) + 1;
+
+ for (i = 0; i < pkts; i++) {
+ odp_packet_t pkt;
+
+ pkt = odp_packet_alloc(pool, SHM_PKT_POOL_BUF_SIZE);
+ if (pkt == ODP_PACKET_INVALID)
+ break;
+
+ odp_packet_l4_offset_set(pkt, 30);
+ pkt_tbl[i] = pkt;
+ }
+
+ /* exit if no packets allocated */
+ if (i == 0) {
+ EXAMPLE_DBG("unable to alloc packet pkts %d/%d\n",
+ i, pkts);
+ break;
+ }
+
+ pkts = i;
+
+ /* 4. Copy counter and magic numbers to that packets */
+ for (i = 0; i < pkts; i++) {
+ pkt_head_t head;
+ pkt_tail_t tail;
+ size_t off;
+ odp_packet_t pkt = pkt_tbl[i];
+
+ off = odp_packet_l4_offset(pkt);
+ if (off == ODP_PACKET_OFFSET_INVALID)
+ EXAMPLE_ABORT("packet L4 offset not set");
+
+ head.magic = TEST_SEQ_MAGIC;
+ head.seq = cnt++;
+
+ off += ODPH_UDPHDR_LEN;
+ ret = odp_packet_copy_from_mem(pkt, off, sizeof(head),
+ &head);
+ if (ret)
+ EXAMPLE_ABORT("unable to copy in head data");
+
+ tail.magic = TEST_SEQ_MAGIC;
+ off = odp_packet_len(pkt) - sizeof(pkt_tail_t);
+ ret = odp_packet_copy_from_mem(pkt, off, sizeof(tail),
+ &tail);
+ if (ret)
+ EXAMPLE_ABORT("unable to copy in tail data");
+ }
+
+ /* 5. Send packets to ipc_pktio */
+ ret = ipc_odp_packet_sendall(ipc_pktio, pkt_tbl, pkts);
+ if (ret < 0) {
+ EXAMPLE_DBG("unable to sending to ipc pktio\n");
+ break;
+ }
+
+ cycle = odp_time_local();
+ diff = odp_time_diff(cycle, current_cycle);
+ if (odp_time_cmp(odp_time_local_from_ns(ODP_TIME_SEC_IN_NS),
+ diff) < 0) {
+ current_cycle = cycle;
+ printf("\rpkts: %" PRIu64 ", alloc %" PRIu64 ","
+ " errors %" PRIu64 ", pps %" PRIu64 ".",
+ stat_pkts, stat_pkts_alloc, stat_errors,
+ (stat_pkts + stat_pkts_alloc - stat_pkts_prev));
+ fflush(stdout);
+ stat_pkts_prev = stat_pkts + stat_pkts_alloc;
+ }
+ }
+
+ /* cleanup and exit */
+ ret = odp_pktio_stop(ipc_pktio);
+ if (ret) {
+ EXAMPLE_DBG("odp_pktio_stop error %d\n", ret);
+ return -1;
+ }
+
+exit:
+ ret = odp_pktio_close(ipc_pktio);
+ if (ret) {
+ EXAMPLE_DBG("odp_pktio_close error %d\n", ret);
+ return -1;
+ }
+
+ ret = odp_pool_destroy(pool);
+ if (ret) {
+ EXAMPLE_DBG("pool_destroy error %d\n", ret);
+ /* Remote process can end with reference to our local pool.
+ * Usully it unmaps it clenealy but some time there are some
+ * pending packets in the pool in case of remote process was
+ * trapped or did not call odp_pktio_close() correctly and
+ * release buffers and free buffer from shared rings.
+ * return -1;
+ */
+ }
+
+ return (stat_errors > 10 || stat_pkts < 1000) ? -1 : 0;
+}
+
+/**
+ * ODP packet example main function
+ */
+int main(int argc, char *argv[])
+{
+ odp_pool_t pool;
+ odp_pool_param_t params;
+ odp_instance_t instance;
+ odp_platform_init_t plat_idata;
+ int ret;
+
+ /* Parse and store the application arguments */
+ parse_args(argc, argv);
+
+ memset(&plat_idata, 0, sizeof(odp_platform_init_t));
+ plat_idata.ipc_ns = ipc_name_space;
+
+ /* Init ODP before calling anything else */
+ if (odp_init_global(&instance, NULL, &plat_idata)) {
+ EXAMPLE_ERR("Error: ODP global init failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Init this thread */
+ if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
+ EXAMPLE_ERR("Error: ODP local init failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Print both system and application information */
+ print_info(NO_PATH(argv[0]));
+
+ /* Create packet pool */
+ memset(&params, 0, sizeof(params));
+ params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
+ params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
+ params.pkt.num = SHM_PKT_POOL_SIZE;
+ params.type = ODP_POOL_PACKET;
+
+ pool = odp_pool_create("packet_pool1", &params);
+ if (pool == ODP_POOL_INVALID) {
+ EXAMPLE_ERR("Error: packet pool create failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ odp_pool_print(pool);
+
+ create_pktio(pool);
+
+ ret = pktio_run_loop(pool);
+
+ EXAMPLE_DBG("return %d\n", ret);
+ return ret;
+}
diff --git a/test/linux-generic/pktio_ipc/pktio_ipc2.c b/test/linux-generic/pktio_ipc/pktio_ipc2.c
new file mode 100644
index 000000000..c0c6ff543
--- /dev/null
+++ b/test/linux-generic/pktio_ipc/pktio_ipc2.c
@@ -0,0 +1,197 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * @example pktio_ipc2.c ODP IPC example application.
+ * This application works in pair with pktio_ipc1 application.
+ * It opens ipc pktio, reads packets and updates magic number.
+ * Also it allocates some packets from internal pool and sends
+ * to ipc pktio.
+ */
+
+#include "ipc_common.h"
+
+static int ipc_second_process(void)
+{
+ odp_pktio_t ipc_pktio;
+ odp_pool_param_t params;
+ odp_pool_t pool;
+ odp_packet_t pkt_tbl[MAX_PKT_BURST];
+ odp_packet_t alloc_pkt;
+ int pkts;
+ int ret;
+ int i;
+ odp_time_t start_cycle;
+ odp_time_t cycle;
+ odp_time_t diff;
+ odp_time_t wait;
+ uint64_t stat_pkts = 0;
+ odp_pktin_queue_t pktin;
+
+ /* Create packet pool */
+ memset(&params, 0, sizeof(params));
+ params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
+ params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
+ params.pkt.num = SHM_PKT_POOL_SIZE;
+ params.type = ODP_POOL_PACKET;
+
+ pool = odp_pool_create("packet_pool2", &params);
+ if (pool == ODP_POOL_INVALID) {
+ EXAMPLE_ERR("Error: packet pool create failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ ipc_pktio = create_pktio(pool);
+
+ wait = odp_time_local_from_ns(run_time_sec * ODP_TIME_SEC_IN_NS);
+ start_cycle = odp_time_local();
+
+ if (odp_pktin_queue(ipc_pktio, &pktin, 1) != 1) {
+ EXAMPLE_ERR("no input queue\n");
+ return -1;
+ }
+
+ /* start ipc pktio, i.e. wait until other process connects */
+ for (;;) {
+ /* 1. exit loop if time specified */
+ if (run_time_sec) {
+ cycle = odp_time_local();
+ diff = odp_time_diff(cycle, start_cycle);
+ if (odp_time_cmp(wait, diff) < 0) {
+ printf("timeout exit, run_time_sec %d\n",
+ run_time_sec);
+ goto exit;
+ }
+ }
+
+ ret = odp_pktio_start(ipc_pktio);
+ if (!ret)
+ break;
+ }
+
+ for (;;) {
+ /* exit loop if time specified */
+ if (run_time_sec) {
+ cycle = odp_time_local();
+ diff = odp_time_diff(cycle, start_cycle);
+ if (odp_time_cmp(wait, diff) < 0) {
+ EXAMPLE_DBG("exit after %d seconds\n",
+ run_time_sec);
+ break;
+ }
+ }
+
+ /* recv some packets and change MAGIC to MAGIC_2 */
+ pkts = odp_pktin_recv(pktin, pkt_tbl, MAX_PKT_BURST);
+ if (pkts <= 0)
+ continue;
+
+ for (i = 0; i < pkts; i++) {
+ odp_packet_t pkt = pkt_tbl[i];
+ pkt_head_t head;
+ size_t off;
+
+ off = odp_packet_l4_offset(pkt);
+ if (off == ODP_PACKET_OFFSET_INVALID)
+ EXAMPLE_ABORT("invalid l4 offset\n");
+
+ off += ODPH_UDPHDR_LEN;
+ ret = odp_packet_copy_to_mem(pkt, off, sizeof(head),
+ &head);
+ if (ret)
+ EXAMPLE_ABORT("unable copy out head data");
+
+ if (head.magic != TEST_SEQ_MAGIC)
+ EXAMPLE_ABORT("Wrong head magic!");
+
+ /* Modify magic number in packet */
+ head.magic = TEST_SEQ_MAGIC_2;
+ ret = odp_packet_copy_from_mem(pkt, off, sizeof(head),
+ &head);
+ if (ret)
+ EXAMPLE_ABORT("unable to copy in head data");
+ }
+
+ /* send all packets back */
+ ret = ipc_odp_packet_sendall(ipc_pktio, pkt_tbl, pkts);
+ if (ret < 0)
+ EXAMPLE_ABORT("can not send packets\n");
+ stat_pkts += pkts;
+
+ /* alloc packet from local pool, set magic to ALLOC_MAGIC,
+ * and send it.*/
+ alloc_pkt = odp_packet_alloc(pool, SHM_PKT_POOL_BUF_SIZE);
+ if (alloc_pkt != ODP_PACKET_INVALID) {
+ pkt_head_t head;
+ size_t off;
+
+ odp_packet_l4_offset_set(alloc_pkt, 30);
+
+ head.magic = TEST_ALLOC_MAGIC;
+
+ off = odp_packet_l4_offset(alloc_pkt);
+ off += ODPH_UDPHDR_LEN;
+ ret = odp_packet_copy_from_mem(alloc_pkt, off,
+ sizeof(head),
+ &head);
+ if (ret)
+ EXAMPLE_ABORT("unable to copy in head data");
+
+ pkt_tbl[0] = alloc_pkt;
+ ret = ipc_odp_packet_sendall(ipc_pktio, pkt_tbl, 1);
+ if (ret < 0)
+ EXAMPLE_ABORT("can not send packets\n");
+ stat_pkts += 1;
+ }
+ }
+
+ /* cleanup and exit */
+ ret = odp_pktio_stop(ipc_pktio);
+ if (ret) {
+ EXAMPLE_DBG("odp_pktio_stop error %d\n", ret);
+ return -1;
+ }
+
+exit:
+ ret = odp_pktio_close(ipc_pktio);
+ if (ret) {
+ EXAMPLE_DBG("odp_pktio_close error %d\n", ret);
+ return -1;
+ }
+
+ ret = odp_pool_destroy(pool);
+ if (ret)
+ EXAMPLE_DBG("pool_destroy error %d\n", ret);
+
+ return stat_pkts > 1000 ? 0 : -1;
+}
+
+int main(int argc, char *argv[])
+{
+ odp_instance_t instance;
+ odp_platform_init_t plat_idata;
+
+ /* Parse and store the application arguments */
+ parse_args(argc, argv);
+
+ memset(&plat_idata, 0, sizeof(odp_platform_init_t));
+ plat_idata.ipc_ns = ipc_name_space;
+
+ if (odp_init_global(&instance, NULL, &plat_idata)) {
+ EXAMPLE_ERR("Error: ODP global init failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Init this thread */
+ if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
+ EXAMPLE_ERR("Error: ODP local init failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ return ipc_second_process();
+}
diff --git a/test/linux-generic/pktio_ipc/pktio_ipc_run.sh b/test/linux-generic/pktio_ipc/pktio_ipc_run.sh
new file mode 100755
index 000000000..112800273
--- /dev/null
+++ b/test/linux-generic/pktio_ipc/pktio_ipc_run.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# Copyright (c) 2015, Linaro Limited
+# All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# directories where test binary can be found:
+# -in the validation dir when running make check (intree or out of tree)
+# -in the script directory, when running after 'make install', or
+# -in the validation when running standalone (./pktio_ipc_run) intree.
+# -in the current directory.
+# running stand alone out of tree requires setting PATH
+PATH=./pktio_ipc:$PATH
+PATH=$(dirname $0):$PATH
+PATH=$(dirname $0)/../../../../platform/linux-generic/test/pktio_ipc:$PATH
+PATH=.:$PATH
+
+run()
+{
+ local ret=0
+ IPC_NS=$$
+
+ #if test was interrupted with CTRL+c than files
+ #might remain in shm. Needed cleanely delete them.
+ rm -rf /dev/shm/odp-${IPC_NS}* 2>&1 > /dev/null
+
+ echo "==== run pktio_ipc1 then pktio_ipc2 ===="
+ pktio_ipc1${EXEEXT} -n ${IPC_NS} -t 30 &
+ IPC_PID=$!
+
+ pktio_ipc2${EXEEXT} -n ${IPC_NS} -t 10
+ ret=$?
+ # pktio_ipc1 should do clean up and exit just
+ # after pktio_ipc2 exited. If it does not happen
+ # kill him in test.
+ sleep 1
+ kill ${IPC_PID} 2>&1 > /dev/null
+ if [ $? -eq 0 ]; then
+ rm -rf /dev/shm/odp-${IPC_NS}* 2>&1 > /dev/null
+ fi
+
+ if [ $ret -ne 0 ]; then
+ echo "!!!First stage FAILED $ret!!!"
+ exit $ret
+ else
+ echo "First stage PASSED"
+ fi
+
+ echo "==== run pktio_ipc2 then pktio_ipc1 ===="
+ pktio_ipc2${EXEEXT} -n ${IPC_NS} -t 10 &
+ IPC_PID=$!
+
+ pktio_ipc1${EXEEXT} -n ${IPC_NS} -t 20
+ ret=$?
+ (kill ${IPC_PID} 2>&1 > /dev/null) > /dev/null || true
+
+ if [ $ret -ne 0 ]; then
+ echo "!!! FAILED !!!"
+ exit $ret
+ else
+ echo "Second stage PASSED"
+ fi
+
+ echo "!!!PASSED!!!"
+ exit 0
+}
+
+case "$1" in
+ *) run ;;
+esac