On 18.01.16 11:59, Maxim Uvarov wrote:
On 01/15/2016 15:57, Stuart Haslam wrote:
On Mon, Dec 21, 2015 at 01:56:11PM +0300, Maxim Uvarov wrote:
2 example ipc pktio applications create ipc pktio to each other and do
packet transfer, validation magic numbers and packets sequence counters
inside it.

It looks like there's a race somewhere as I get occasional failures:

#2  0x00000000004138b9 in odp_override_abort () at odp_weak.c:40
#3  0x0000000000407431 in _ipc_map_remote_pool (
     name=name@entry=0x7fad1cb48020 <error: Cannot access memory at address 
0x7fad1cb48020>,
     size=1310720) at pktio/ipc.c:265
#4  0x000000000040845c in _ipc_slave_start (pktio_entry=0x7fad1ca68240) at 
pktio/ipc.c:359
#5  ipc_start (pktio_entry=0x7fad1ca68240) at pktio/ipc.c:670
#6  0x0000000000405930 in odp_pktio_start (id=0x1414, id@entry=0x1) at 
odp_packet_io.c:309
#7  0x00000000004026c1 in ipc_second_process () at pktio_ipc2.c:66
#8  main (argc=<optimised out>, argv=<optimised out>) at pktio_ipc2.c:184


Did you run make check? Maybe some files from previous wrong clean up were in 
shm?
I tested make check bunch of time and did not see any fails. Will try again.

Maxim.

Signed-off-by: Maxim Uvarov <maxim.uva...@linaro.org>
---
  platform/linux-generic/m4/configure.m4             |   1 +
  platform/linux-generic/test/Makefile.am            |   3 +-
  platform/linux-generic/test/pktio_ipc/.gitignore   |   2 +
  platform/linux-generic/test/pktio_ipc/Makefile.am  |  20 ++
  platform/linux-generic/test/pktio_ipc/ipc_common.c | 138 +++++++++
  platform/linux-generic/test/pktio_ipc/ipc_common.h |  87 ++++++
  platform/linux-generic/test/pktio_ipc/pktio_ipc1.c | 310 +++++++++++++++++++++
  platform/linux-generic/test/pktio_ipc/pktio_ipc2.c | 185 ++++++++++++
  .../linux-generic/test/pktio_ipc/pktio_ipc_run     |  68 +++++
  9 files changed, 813 insertions(+), 1 deletion(-)
  create mode 100644 platform/linux-generic/test/pktio_ipc/.gitignore
  create mode 100644 platform/linux-generic/test/pktio_ipc/Makefile.am
  create mode 100644 platform/linux-generic/test/pktio_ipc/ipc_common.c
  create mode 100644 platform/linux-generic/test/pktio_ipc/ipc_common.h
  create mode 100644 platform/linux-generic/test/pktio_ipc/pktio_ipc1.c
  create mode 100644 platform/linux-generic/test/pktio_ipc/pktio_ipc2.c
  create mode 100755 platform/linux-generic/test/pktio_ipc/pktio_ipc_run

diff --git a/platform/linux-generic/m4/configure.m4 
b/platform/linux-generic/m4/configure.m4
index 6bb159f..46aaf40 100644
--- a/platform/linux-generic/m4/configure.m4
+++ b/platform/linux-generic/m4/configure.m4
@@ -24,4 +24,5 @@ m4_include([platform/linux-generic/m4/odp_pcap.m4])
  AC_CONFIG_FILES([platform/linux-generic/Makefile
           platform/linux-generic/test/Makefile
           platform/linux-generic/test/pktio/Makefile
+         platform/linux-generic/test/pktio_ipc/Makefile
           platform/linux-generic/test/ring/Makefile])
diff --git a/platform/linux-generic/test/Makefile.am 
b/platform/linux-generic/test/Makefile.am
index f81eeb8..6a05a54 100644
--- a/platform/linux-generic/test/Makefile.am
+++ b/platform/linux-generic/test/Makefile.am
@@ -1,11 +1,12 @@
  include $(top_srcdir)/test/Makefile.inc
  TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/validation
-ODP_MODULES = pktio ring
+ODP_MODULES = pktio pktio_ipc ring
  if test_vald
  TESTS = pktio/pktio_run \
      pktio/pktio_run_tap \
+    pktio_ipc/pktio_ipc_run \
      ring/ringtest$(EXEEXT) \
      ${top_builddir}/test/validation/buffer/buffer_main$(EXEEXT) \
      
${top_builddir}/test/validation/classification/classification_main$(EXEEXT) \
diff --git a/platform/linux-generic/test/pktio_ipc/.gitignore 
b/platform/linux-generic/test/pktio_ipc/.gitignore
new file mode 100644
index 0000000..49ee4fd
--- /dev/null
+++ b/platform/linux-generic/test/pktio_ipc/.gitignore
@@ -0,0 +1,2 @@
+pktio_ipc1
+pktio_ipc2
diff --git a/platform/linux-generic/test/pktio_ipc/Makefile.am 
b/platform/linux-generic/test/pktio_ipc/Makefile.am
new file mode 100644
index 0000000..bc224ae
--- /dev/null
+++ b/platform/linux-generic/test/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
+test_SCRIPTS = $(dist_check_SCRIPTS)
diff --git a/platform/linux-generic/test/pktio_ipc/ipc_common.c 
b/platform/linux-generic/test/pktio_ipc/ipc_common.c
new file mode 100644
index 0000000..33775b0
--- /dev/null
+++ b/platform/linux-generic/test/pktio_ipc/ipc_common.c
@@ -0,0 +1,138 @@
+/* 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_odp_packet_sendall(odp_pktio_t pktio,
+               odp_packet_t pkt_tbl[], int num)
+{
+    int ret;
+    int sent = 0;
+    uint64_t start_cycle;
+    uint64_t diff;
+    uint64_t wait;
+
+    wait = odp_time_local_from_ns(1 * ODP_TIME_SEC_IN_NS);
+    start_cycle = odp_time_local();
1. cycle word should be avoided here.
2. 1 * can be removed
3. here better to use the following approach:

start = odp_time_local();
wait = odp_time_local_from_ns(ODP_TIME_SEC_IN_NS);
end_time = odp_time_sum(start, wait);
while (sent != num) {
        ...
        if (odp_time_cmp(end, odp_time_local()) < 0)
                return -1;
}


+
+    while (sent != num) {
+        ret = odp_pktio_send(pktio, &pkt_tbl[sent], num - sent);
+        if (ret < 0)
+            return -1;
+
+        sent += ret;
+
+        diff = odp_time_diff(odp_time_local(), start_cycle);
+        if (odp_time_cmp(wait, diff) < 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;
+
+    memset(&pktio_param, 0, sizeof(pktio_param));
+    pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
+
+    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");
+    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'},
+        {"help", no_argument, NULL, 'h'},        /* return 'h' */
+        {NULL, 0, NULL, 0}
+    };
+
+    run_time_sec = 0; /* loop forever if time to run is 0 */
+
+    while (1) {
+        opt = getopt_long(argc, argv, "+t:h",
+                  longopts, &long_index);
+
+        if (opt == -1)
+            break;    /* No more options */
+
+        switch (opt) {
+        case 't':
+            run_time_sec = atoi(optarg);
+            break;
+        case 'h':
+            usage(argv[0]);
+            exit(EXIT_SUCCESS);
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    optind = 1;        /* reset 'extern optind' from the getopt lib */
+}
+
+/**
+ * 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"
+           "CPU freq (hz):   %" PRIu64 "\n"
+           "Cache line size: %i\n"
+           "CPU count:       %i\n"
+           "\n",
+           odp_version_api_str(), odp_sys_cpu_model_str(), odp_sys_cpu_hz(),
+           odp_sys_cache_line_size(), odp_cpu_count());
+
+    printf("Running ODP appl: \"%s\"\n"
+           "-----------------\n"
+           "Using IF:        %s\n",
+           progname, pktio_name);
pktio_name is null

+    printf("\n\n");
+    fflush(NULL);
+}
+
+/**
+ * Prinf usage information
+ */
+void usage(char *progname)
+{
+    printf("\n"
+           "Usage: %s OPTIONS\n"
+           "  E.g. %s -t seconds\n"
+           "\n"
+           "OpenDataPlane linux-generic ipc test application.\n"
+           "\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/platform/linux-generic/test/pktio_ipc/ipc_common.h 
b/platform/linux-generic/test/pktio_ipc/ipc_common.h
new file mode 100644
index 0000000..f802b28
--- /dev/null
+++ b/platform/linux-generic/test/pktio_ipc/ipc_common.h
@@ -0,0 +1,87 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#define _POSIX_C_SOURCE 200809L
+#include <stdlib.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      (512 * 2048)
+
+/** @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 {
+    uint32be_t magic;
+    uint32be_t seq;
+} pkt_head_t;
+
+/** magic number at end of packet payload */
+typedef struct ODP_PACKED {
+    uint32be_t magic;
+} pkt_tail_t;
+
+/** Application argument */
+char *pktio_name;
+
+/** Run time in seconds */
+int run_time_sec;
+
+/* 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/platform/linux-generic/test/pktio_ipc/pktio_ipc1.c 
b/platform/linux-generic/test/pktio_ipc/pktio_ipc1.c
new file mode 100644
index 0000000..355dd9f
--- /dev/null
+++ b/platform/linux-generic/test/pktio_ipc/pktio_ipc1.c
@@ -0,0 +1,310 @@
+/* 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;
+    uint64_t start_cycle;
+    uint64_t current_cycle;
+    uint64_t cycle;
+    uint64_t diff;
+    uint64_t wait;
+    int ret;
+
+    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;
the same here

+
+    /* 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;
So if odp_pktio_start() fails we just continue?

+    }
+
+    /* 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_pktio_recv(ipc_pktio, 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_copydata_out(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_copydata_out(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;
+                }
Why do each of the above error conditions not just cause the test to
fail immediately?

+
+                cnt_recv++;
I think this increment needs to move after the following condition, as I
always get one of these errors -

pktio_ipc1.c:160:pktio_run_loop():head.seq 0 - cnt_recv 1 = 18446744073709551615

+
+                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);
This seems to always happen at the end of the test run, presumably
because the other process has exited -

pkts:  15788357, alloc  1531442, errors 0, pps 1921744.
pktio_ipc2.c:78:ipc_second_process():exit after 10 seconds
pktio_ipc1.c:191:pktio_run_loop():unable to alloc packet pkts 0/11

Perhaps it's not really a problem, but the log entry makes it look like
a problem.

+            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_copydata_in(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_copydata_in(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("error sending to ipc pktio\n");
+
+        cycle = odp_time_local();
same here. and avoid cycle word...

+        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);
+        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;
+    int ret;
+
+    /* Parse and store the application arguments */
+    parse_args(argc, argv);
+
+    /* Init ODP before calling anything else */
+    if (odp_init_global(NULL, NULL)) {
+        EXAMPLE_ERR("Error: ODP global init failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Init this thread */
+    if (odp_init_local(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 / SHM_PKT_POOL_BUF_SIZE;
+    params.type        = ODP_POOL_PACKET;
+
+    pool = odp_pool_create("packet_pool", &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);
+
+    return ret;
+}
diff --git a/platform/linux-generic/test/pktio_ipc/pktio_ipc2.c 
b/platform/linux-generic/test/pktio_ipc/pktio_ipc2.c
new file mode 100644
index 0000000..562ffe4
--- /dev/null
+++ b/platform/linux-generic/test/pktio_ipc/pktio_ipc2.c
@@ -0,0 +1,185 @@
+/* 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;
+    uint64_t start_cycle;
+    uint64_t cycle;
+    uint64_t diff;
+    uint64_t wait;
+    uint64_t stat_pkts = 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 / SHM_PKT_POOL_BUF_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(ODP_TIME_SEC_IN_NS);
ODP_TIME_SEC_IN_NS * run_time_sec

+    start_cycle = odp_time_local();
same here.

+
+    /* 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();
same here.

+            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_pktio_recv(ipc_pktio, 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_copydata_out(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_copydata_in(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_copydata_in(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[])
+{
+    /* Parse and store the application arguments */
+    parse_args(argc, argv);
+
+    if (odp_init_global(NULL, NULL)) {
+        EXAMPLE_ERR("Error: ODP global init failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Init this thread */
+    if (odp_init_local(ODP_THREAD_CONTROL)) {
+        EXAMPLE_ERR("Error: ODP local init failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    return ipc_second_process();
+}
diff --git a/platform/linux-generic/test/pktio_ipc/pktio_ipc_run 
b/platform/linux-generic/test/pktio_ipc/pktio_ipc_run
new file mode 100755
index 0000000..1e41e8b
--- /dev/null
+++ b/platform/linux-generic/test/pktio_ipc/pktio_ipc_run
@@ -0,0 +1,68 @@
+#!/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
+
+    echo "==== run pktio_ipc1 then pktio_ipc2 ===="
+    pktio_ipc1${EXEEXT} -t 30 &
+    IPC_PID=$!
+
+    pktio_ipc2${EXEEXT} -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/ipc_pktio_* 2>&1 > /dev/null
+        rm -rf /dev/shm/packet_pool2 2>&1 > /dev/null
The fact that this is needed is still a problem.

+    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} -t 10 &
+    IPC_PID=$!
+
+    pktio_ipc1${EXEEXT} -t 20
+    ret=$?
+    kill ${IPC_PID} 2>&1 || 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
--
1.9.1


_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

--
Regards,
Ivan Khoronzhuk
_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to