aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Kiss <zoltan.kiss@linaro.org>2015-11-03 15:26:06 +0000
committerZoltan Kiss <zoltan.kiss@linaro.org>2015-11-03 15:53:59 +0000
commitf8c6fcc8e510f1ba7c0c258e13a994dc5836933e (patch)
tree84d252edd371f2e4fb0c10225daf8ec9dcd833b3
parentd8bceaec15a1ca37cd23d420b1f285c94e5736fc (diff)
parentfdcd79c00c5c493106a532e29f680cf89c188d05 (diff)
Merge branch 'master' of https://git.linaro.org/lng/odp to 1.4.0.0
Merging commits from mainline odp.git master branch, up until fdcd79c0 "test: l2fwd: separate rx and tx drop counters" Conflicts: configure.ac test/validation/Makefile.am Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org>
-rw-r--r--.checkpatch.conf2
-rw-r--r--DEPENDENCIES84
-rw-r--r--configure.ac16
-rw-r--r--debian/changelog107
-rw-r--r--debian/control2
-rw-r--r--doc/doxygen.cfg1
-rw-r--r--doc/doxygenlayout.xml193
-rw-r--r--doc/implementers-guide/implementers-guide.adoc108
-rw-r--r--example/classifier/odp_classifier.c140
-rw-r--r--example/generator/odp_generator.c25
-rw-r--r--example/ipsec/odp_ipsec.c89
-rw-r--r--example/packet/odp_pktio.c10
-rw-r--r--example/timer/odp_timer_test.c24
-rw-r--r--helper/include/odp/helper/tcp.h1
-rw-r--r--helper/test/odp_process.c2
-rw-r--r--helper/test/odp_thread.c2
-rw-r--r--include/odp/api/classification.h81
-rw-r--r--include/odp/api/config.h77
-rw-r--r--include/odp/api/cpu.h52
-rw-r--r--include/odp/api/cpumask.h10
-rw-r--r--include/odp/api/init.h17
-rw-r--r--include/odp/api/packet.h37
-rw-r--r--include/odp/api/packet_flags.h18
-rw-r--r--include/odp/api/packet_io.h62
-rw-r--r--include/odp/api/queue.h13
-rw-r--r--include/odp/api/schedule.h62
-rw-r--r--include/odp/api/schedule_types.h2
-rw-r--r--include/odp/api/thread.h14
-rw-r--r--include/odp/api/version.h2
-rw-r--r--m4/ax_valgrind_check.m42
-rw-r--r--platform/linux-generic/Makefile.am17
-rw-r--r--platform/linux-generic/arch/linux/odp_cpu_cycles.c (renamed from platform/linux-generic/arch/linux/odp_time_cycles.c)18
-rw-r--r--platform/linux-generic/arch/mips64/odp_cpu_cycles.c (renamed from platform/linux-generic/arch/mips64/odp_time_cycles.c)14
-rw-r--r--platform/linux-generic/arch/x86/odp_cpu_cycles.c (renamed from platform/linux-generic/arch/x86/odp_time_cycles.c)14
-rw-r--r--platform/linux-generic/include/odp/config.h176
-rw-r--r--platform/linux-generic/include/odp/debug.h8
-rw-r--r--platform/linux-generic/include/odp/plat/cpumask_types.h7
-rw-r--r--platform/linux-generic/include/odp/plat/schedule_types.h6
-rw-r--r--platform/linux-generic/include/odp_buffer_internal.h5
-rw-r--r--platform/linux-generic/include/odp_classification_datamodel.h3
-rw-r--r--platform/linux-generic/include/odp_classification_inlines.h21
-rw-r--r--platform/linux-generic/include/odp_config_internal.h29
-rw-r--r--platform/linux-generic/include/odp_cpu_internal.h29
-rw-r--r--platform/linux-generic/include/odp_internal.h1
-rw-r--r--platform/linux-generic/include/odp_packet_internal.h64
-rw-r--r--platform/linux-generic/include/odp_packet_io_internal.h47
-rw-r--r--platform/linux-generic/include/odp_packet_netmap.h25
-rw-r--r--platform/linux-generic/include/odp_packet_socket.h5
-rw-r--r--platform/linux-generic/include/odp_pool_internal.h13
-rw-r--r--platform/linux-generic/include/odp_queue_internal.h25
-rw-r--r--platform/linux-generic/m4/configure.m42
-rw-r--r--platform/linux-generic/m4/odp_netmap.m447
-rw-r--r--platform/linux-generic/m4/odp_pcap.m415
-rw-r--r--platform/linux-generic/odp_classification.c84
-rw-r--r--platform/linux-generic/odp_cpu.c14
-rw-r--r--platform/linux-generic/odp_cpumask_task.c4
-rw-r--r--platform/linux-generic/odp_init.c5
-rw-r--r--platform/linux-generic/odp_packet.c237
-rw-r--r--platform/linux-generic/odp_packet_flags.c39
-rw-r--r--platform/linux-generic/odp_packet_io.c155
-rw-r--r--platform/linux-generic/odp_pool.c28
-rw-r--r--platform/linux-generic/odp_queue.c70
-rw-r--r--platform/linux-generic/odp_schedule.c18
-rw-r--r--platform/linux-generic/odp_thread.c14
-rw-r--r--platform/linux-generic/odp_thrmask.c4
-rw-r--r--platform/linux-generic/odp_time.c12
-rw-r--r--platform/linux-generic/pktio/io_ops.c6
-rw-r--r--platform/linux-generic/pktio/loop.c10
-rw-r--r--platform/linux-generic/pktio/netmap.c324
-rw-r--r--platform/linux-generic/pktio/pcap.c381
-rw-r--r--platform/linux-generic/pktio/socket.c76
-rw-r--r--platform/linux-generic/pktio/socket_mmap.c135
-rw-r--r--platform/linux-generic/test/Makefile.am5
-rw-r--r--platform/linux-generic/test/pktio/Makefile.am4
-rw-r--r--platform/linux-generic/test/pktio/pktio_env8
-rwxr-xr-xplatform/linux-generic/test/pktio/pktio_run_pcap33
-rwxr-xr-xscripts/checkpatch.pl8
-rwxr-xr-xscripts/git_hash.sh4
-rw-r--r--test/api_test/odp_common.c2
-rw-r--r--test/performance/odp_atomic.c2
-rw-r--r--test/performance/odp_l2fwd.c472
-rw-r--r--test/performance/odp_pktio_perf.c63
-rw-r--r--test/performance/odp_scheduling.c149
-rw-r--r--test/validation/Makefile.am1
-rw-r--r--test/validation/README55
-rw-r--r--test/validation/buffer/Makefile.am6
-rw-r--r--test/validation/buffer/buffer.c27
-rw-r--r--test/validation/buffer/buffer.h6
-rw-r--r--test/validation/classification/Makefile.am8
-rw-r--r--test/validation/classification/classification.c16
-rw-r--r--test/validation/classification/classification.h52
-rw-r--r--test/validation/classification/odp_classification_basic.c45
-rw-r--r--test/validation/classification/odp_classification_common.c285
-rw-r--r--test/validation/classification/odp_classification_test_pmr.c543
-rw-r--r--test/validation/classification/odp_classification_tests.c416
-rw-r--r--test/validation/classification/odp_classification_testsuites.h24
-rw-r--r--test/validation/common/odp_cunit_common.c236
-rw-r--r--test/validation/common/odp_cunit_common.h50
-rw-r--r--test/validation/config/.gitignore1
-rw-r--r--test/validation/config/Makefile.am10
-rw-r--r--test/validation/config/config.c62
-rw-r--r--test/validation/config/config.h28
-rw-r--r--test/validation/config/config_main.c11
-rw-r--r--test/validation/cpumask/Makefile.am8
-rw-r--r--test/validation/cpumask/cpumask.c61
-rw-r--r--test/validation/cpumask/cpumask.h6
-rw-r--r--test/validation/crypto/Makefile.am6
-rw-r--r--test/validation/crypto/crypto.c22
-rw-r--r--test/validation/crypto/crypto.h6
-rw-r--r--test/validation/crypto/odp_crypto_test_inp.c14
-rw-r--r--test/validation/crypto/odp_crypto_test_inp.h4
-rw-r--r--test/validation/errno/Makefile.am6
-rw-r--r--test/validation/errno/errno.c19
-rw-r--r--test/validation/errno/errno.h6
-rw-r--r--test/validation/init/Makefile.am10
-rw-r--r--test/validation/init/init.c68
-rw-r--r--test/validation/init/init.h14
-rw-r--r--test/validation/packet/Makefile.am6
-rw-r--r--test/validation/packet/packet.c94
-rw-r--r--test/validation/packet/packet.h6
-rw-r--r--test/validation/pktio/Makefile.am6
-rw-r--r--test/validation/pktio/pktio.c403
-rw-r--r--test/validation/pktio/pktio.h8
-rw-r--r--test/validation/pool/Makefile.am6
-rw-r--r--test/validation/pool/pool.c23
-rw-r--r--test/validation/pool/pool.h6
-rw-r--r--test/validation/queue/Makefile.am6
-rw-r--r--test/validation/queue/queue.c20
-rw-r--r--test/validation/queue/queue.h6
-rw-r--r--test/validation/random/Makefile.am6
-rw-r--r--test/validation/random/random.c19
-rw-r--r--test/validation/random/random.h6
-rw-r--r--test/validation/scheduler/Makefile.am6
-rw-r--r--test/validation/scheduler/scheduler.c146
-rw-r--r--test/validation/scheduler/scheduler.h6
-rw-r--r--test/validation/shmem/Makefile.am6
-rw-r--r--test/validation/shmem/shmem.c19
-rw-r--r--test/validation/shmem/shmem.h6
-rw-r--r--test/validation/synchronizers/Makefile.am6
-rw-r--r--test/validation/synchronizers/synchronizers.c100
-rw-r--r--test/validation/synchronizers/synchronizers.h16
-rw-r--r--test/validation/system/Makefile.am6
-rw-r--r--test/validation/system/system.c31
-rw-r--r--test/validation/system/system.h6
-rw-r--r--test/validation/thread/Makefile.am10
-rw-r--r--test/validation/thread/thread.c57
-rw-r--r--test/validation/thread/thread.h6
-rw-r--r--test/validation/time/Makefile.am6
-rw-r--r--test/validation/time/time.c23
-rw-r--r--test/validation/time/time.h6
-rw-r--r--test/validation/timer/Makefile.am6
-rw-r--r--test/validation/timer/timer.c25
-rw-r--r--test/validation/timer/timer.h6
153 files changed, 5581 insertions, 1883 deletions
diff --git a/.checkpatch.conf b/.checkpatch.conf
index fbbb14656..69af10135 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -1,6 +1,8 @@
--no-tree
--strict
+--ignore=SPLIT_STRING
--ignore=NEW_TYPEDEFS
--ignore=DEPRECATED_VARIABLE
+--ignore=COMPARISON_TO_NULL
--codespell
--codespellfile=/usr/share/codespell/dictionary.txt
diff --git a/DEPENDENCIES b/DEPENDENCIES
index 852beeb4a..51951d798 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -16,11 +16,11 @@ Prerequisites for building the OpenDataPlane (ODP) API
On CentOS/RedHat/Fedora systems:
$ sudo yum install automake autoconf libtool libtoolize
-3. required libraries
+3. Required libraries
Libraries currently required to link: openssl
-3.1 native compile
+3.1 OpenSSL native compile
For native compilation, simply load the necessary libraries using the appropriate
tool set.
@@ -31,7 +31,7 @@ Prerequisites for building the OpenDataPlane (ODP) API
On CentOS/RedHat/Fedora systems:
$ sudo yum install openssl-devel
-3.2 cross compilation
+3.2 OpenSSL cross compilation
Cross compilation requires cross compiling the individual libraries. In order for
a cross compiled executable to run on a target system, one must build the same
@@ -76,6 +76,84 @@ Prerequisites for building the OpenDataPlane (ODP) API
--with-openssl-path=/home/user/src/install-openssl-aarch64
$ make
+3.3 Netmap (optional)
+
+ Netmap accelerated ODP packet I/O.
+
+3.3.1 Building netmap kernel modules
+
+ ODP works (at least) with the latest release version of netmap, which is
+ currently at API version 11.1.
+
+ # Checkout netmap code
+ $ git clone https://github.com/luigirizzo/netmap.git
+ $ cd netmap
+ $ git checkout v11.1
+
+ This is enough to build ODP. If you don't want to build netmap kernel
+ modules you can jump to section 3.3.2.
+
+ Netmap consists of a core kernel module (netmap.ko), optional modified
+ device drivers and user space API headers to access the netmap
+ functionality. It is recommended to build both the core module and modified
+ device drivers for optimal performance.
+
+ Netmap builds as an out-of-tree kernel module, you need matching kernel
+ sources to compile it. General build instructions can be found in the packet
+ README: https://github.com/luigirizzo/netmap/blob/master/LINUX/README.
+
+ If you are running Ubuntu/Debian with the stock kernel and you want to
+ compile both netmap.ko and modified drivers, these steps will guide you
+ through it.
+
+ # Download kernel headers
+ $ sudo apt-get install linux-headers-$(uname -r)
+
+ # Download kernel source matching to the headers
+ $ sudo apt-get install linux-source
+ # or
+ $ apt-get source linux-image-$(uname -r)
+
+ The source archive will be placed in /usr/src/linux-source-<kernel-version>
+ (or in the current directory if using apt-get source). You will need to
+ locate it and extract it to a convenient place.
+
+ # Compile netmap
+ $ cd <netmap_dir>/LINUX
+ $ ./configure --kernel-sources=<path_to_kernel_src>
+ $ make
+
+3.3.2 Building ODP
+
+ $ cd <odp_dir>
+ $ ./bootstrap
+ $ ./configure --with-netmap-path=<netmap_dir>
+ $ make
+
+3.3.3 Inserting netmap kernel modules
+
+ In order to use netmap I/O you need to insert at least the core netmap
+ kernel module.
+
+ $ cd <netmap_dir>/LINUX
+ $ sudo insmod netmap.ko
+
+ To insert the optional modified drivers you first need to remove the
+ original drivers, if loaded (and if not linked into the kernel). For
+ example, if using ixgbe:
+
+ $ cd <netmap_path>/LINUX
+ $ sudo rmmod ixgbe
+ $ sudo insmod ixgbe/ixgbe.ko
+
+ To restore the original drivers you should be able to use modprobe.
+
+3.3.4 Running ODP with netmap I/O
+
+ ODP applications will use netmap for packet I/O by default as long as the
+ netmap kernel module is loaded. If socket I/O is desired instead, it can be
+ activated by setting the environment variable ODP_PKTIO_DISABLE_NETMAP.
+
4.0 Packages needed to build API tests
Cunit test framework version 2.1-3 is required
diff --git a/configure.ac b/configure.ac
index 7386d6537..3610bc6fa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,16 @@ AC_SUBST([with_platform])
AC_SUBST([platform_with_platform], ["platform/${with_platform}"])
AC_SUBST([platform_with_platform_test], ["platform/${with_platform}/test"])
+##########################################################################
+# Prepare default values for platform specific optional features
+##########################################################################
+netmap_support=no
+
+##########################################################################
+# Set conditionals as computed within platform specific files
+##########################################################################
+AM_CONDITIONAL([netmap_support], [test x$netmap_support = xyes ])
+
AC_ARG_WITH([sdk-install-path],
AC_HELP_STRING([--with-sdk-install-path=DIR path to external libs and headers],
[(or in the default path if not specified).]),
@@ -89,6 +99,9 @@ AC_SUBST(SDK_INSTALL_PATH)
AM_CONDITIONAL([SDK_INSTALL_PATH_], [test "x${SDK_INSTALL_PATH_}" = "x1"])
+##########################################################################
+# Run platform specific checks and settings
+##########################################################################
if test "${with_platform}" == "linux-generic";
then
m4_include([./platform/linux-generic/m4/configure.m4])
@@ -273,6 +286,8 @@ ODP_CFLAGS="$ODP_CFLAGS -Wmissing-declarations -Wold-style-definition -Wpointer-
ODP_CFLAGS="$ODP_CFLAGS -Wcast-align -Wnested-externs -Wcast-qual -Wformat-nonliteral"
ODP_CFLAGS="$ODP_CFLAGS -Wformat-security -Wundef -Wwrite-strings"
ODP_CFLAGS="$ODP_CFLAGS -std=gnu99"
+# Extra flags for example to suppress certain warning types
+ODP_CFLAGS="$ODP_CFLAGS $ODP_CFLAGS_EXTRA"
##########################################################################
# Default include setup
@@ -300,6 +315,7 @@ AC_CONFIG_FILES([Makefile
test/validation/Makefile
test/validation/buffer/Makefile
test/validation/classification/Makefile
+ test/validation/config/Makefile
test/validation/cpumask/Makefile
test/validation/common/Makefile
test/validation/crypto/Makefile
diff --git a/debian/changelog b/debian/changelog
index 57ae1dca4..d446cc800 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,110 @@
+opendataplane (1.4.0.0-1) unstable; urgency=low
+ * API:
+ - ** Classification **
+ - odp_cos_set_queue() renamed to odp_cos_queue_set()
+ - int odp_cos_set_drop renamed to odp_cos_drop_set()
+ - new: odp_queue_t odp_cos_queue(odp_cos_t cos_id)
+ - new: odp_drop_e odp_cos_drop(odp_cos_t cos_id)
+ - ODP_PMR_CUSTOM_FRAME support in classification
+ - odp_pmr_create() arguments passing change to use struct
+ - odp_pmr_match_set_create() added id argument
+ - ** Config **
+ - new: odp_config_...() API introduced instead of ODP_CONFIG_ defines
+ - ** Cpu, Threads and Scheduler **
+ - new: uint64_t odp_cpu_cycles(void)
+ - new: uint64_t odp_cpu_cycles_diff(uint64_t c1, uint64_t c2);
+ - new: uint64_t odp_cpu_cycles_max(void);
+ - new: uint64_t odp_cpu_cycles_resolution(void);
+ - odp_cpumask_def_worker() renamed to odp_cpumask_default_worker()
+ - odp_cpumask_def_control() renamed to odp_cpumask_default_control()
+ - odp init extended with num worker and control threads
+ - new: int odp_queue_lock_count(odp_queue_t queue);
+ - refine api doc for scheduler and schedule orderd locks
+ - argument of odp_schedule_order_lock() and odp_schedule_order_unlock changed to unsigned
+ - new: int odp_thread_count_max(void)
+ - ** Packet **
+ - new: uint32_t odp_packet_flow_hash(odp_packet_t pkt)
+ - new: void odp_packet_flow_hash_set(odp_packet_t pkt, uint32_t flow_hash)
+ - new: int odp_packet_has_flow_hash(odp_packet_t pkt);
+ - new: void odp_packet_has_flow_hash_clr(odp_packet_t pkt);
+ - ** Pktio **
+ - pktio can be configuread as receive or transmit only
+ - pktio: refined api doc for start() and stop()
+ - new: void odp_pktio_param_init(odp_pktio_param_t *param)
+ * ODP docs:
+ - implementers-guide: update names of test module libraries
+ - implementers-guide: update section on skipping tests
+ * Test framework
+ - update README files
+ - renaming module libs
+ - add odp_cunit_update() to modify registered tests
+ - add ability to mark tests inactive
+ * Validation
+ - ** Classification **
+ - Add fix for classification tests
+ - remove redundant pool lookup function
+ - remove redundant sequence number check
+ - use tcp data offset field to calculate data offset
+ - move destroy_inq() to common file
+ - add odp_pktio_param_init() API
+ - added additional suite to test individual PMRs
+ - use a structure instead of many args for odp_pmr_create
+ - Add init calls for queue parameters
+ - syntax correction for CU_ASSERT
+ - Add init calls for pool parameters
+ - queue and drop policy API name change
+ - Queue parameter init calls
+ - ** Cpu, Threads and Scheduler **
+ - rename odp_cpumask_def to _default
+ - schedule: revise definition of ordered locks
+ - schedule: remove odp_schedule_order_lock_init() API
+ - schedule: don't check schedule time on 0
+ - synchronizers: support a single worker
+ - init: fix test when debug-print is disabled
+ - ** Packet **
+ - packet: test flow hash
+ - packet: test now handles pool that do not support segmentation
+ - ** Pktio **
+ - pktio: don't call APIs with an invalid pktio handle
+ - ** Config **
+ - config: removed ODP_CONFIG_MAX_THREADS
+ - config: add CUnit tests for config APIs
+ * Performance
+ - l2fwd: add missing braces
+ - l2fwd: add option to disable filling eth addresses
+ - l2fwd: add support for using odd number of ports
+ - l2fwd: fix crash when accuracy is set to 0
+ - l2fwd: add option to select scheduler queue type
+ - l2fwd: add option to change destination eth addresses
+ - l2fwd: obey -t in queue mode
+ - l2fwd: fill correct source ethernet address
+ - sched: update scheduling test to use cycle counts
+ - odp_pktio_perf: fix potential overflow for burst_gap
+ - odp_pktio_perf: fix potential overflow for send_duration
+ * general:
+ - classification: implement ODP_PMR_CUSTOM_FRAME matching
+ - classification: queue and drop policy API name change
+ - cpu: created arch dependent cpu_cycles files
+ - cpu: fix cycle lost while cycle counter overflow
+ - cpu: implementation for cycle count API
+ - cpu: rename time_cycles to cpu_cycles
+ - pktio: implemented pcap pktio
+ - pktio: implemented netmap pktio
+ - pktio: close all pktio when term is called
+ - pktio: enable classifier only when needed
+ - pktio: factor state management into packet_io
+ - pktio: fill in L2 parse results by default
+ - pktio: implement odp_pktio_param_init() API
+ - packet: implement flow hash support
+ - schedule: fix odp_schdule_wait_time
+ - queue: change lock_index from uint32_t to unsigned to match API
+ - queue: direct internal enqueues to target queue
+ - queue: fix pktout_enqueue() logic
+ - queue: remove obsolete prototypes
+ - use cycles_diff for time API also
+
+ -- Maxim Uvarov <maxim.uvarov@linaro.org> Fri, 30 Oct 2015 13:55:07 +0300
+
opendataplane (1.3.0.0-1) unstable; urgency=low
* API:
- codespell: correct spelling
diff --git a/debian/control b/debian/control
index 21d8d4424..ad3c13f62 100644
--- a/debian/control
+++ b/debian/control
@@ -1,7 +1,7 @@
Source: opendataplane
Priority: optional
Maintainer: Anders Roxell <anders.roxell@linaro.org>
-Build-Depends: debhelper (>= 9), autotools-dev
+Build-Depends: debhelper (>= 9), autotools-dev, libssl-dev
Standards-Version: 3.9.6
Section: libs
Homepage: http://www.opendataplane.org/
diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg
index f28ec244e..909f0ce47 100644
--- a/doc/doxygen.cfg
+++ b/doc/doxygen.cfg
@@ -33,6 +33,7 @@ EXAMPLE_PATTERNS = *.c
EXAMPLE_RECURSIVE = YES
IMAGE_PATH = $(SRCDIR)/doc/images
HTML_EXTRA_STYLESHEET = $(SRCDIR)/doc/odpdoxygen.css
+LAYOUT_FILE = $(SRCDIR)/doc/doxygenlayout.xml
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
diff --git a/doc/doxygenlayout.xml b/doc/doxygenlayout.xml
new file mode 100644
index 000000000..90e189a44
--- /dev/null
+++ b/doc/doxygenlayout.xml
@@ -0,0 +1,193 @@
+<doxygenlayout version="1.0">
+ <!-- Navigation index tabs for HTML output -->
+ <navindex>
+ <tab type="mainpage" visible="yes" title=""/>
+ <tab type="pages" visible="yes" title="" intro=""/>
+ <tab type="modules" visible="yes" title="" intro=""/>
+ <tab type="namespaces" visible="yes" title="">
+ <tab type="namespacelist" visible="yes" title="" intro=""/>
+ <tab type="namespacemembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="classes" visible="yes" title="">
+ <tab type="classlist" visible="yes" title="" intro=""/>
+ <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
+ <tab type="hierarchy" visible="yes" title="" intro=""/>
+ <tab type="classmembers" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="files" visible="yes" title="">
+ <tab type="filelist" visible="yes" title="" intro=""/>
+ <tab type="globals" visible="yes" title="" intro=""/>
+ </tab>
+ <tab type="examples" visible="yes" title="" intro=""/>
+ </navindex>
+
+ <!-- Layout definition for a class page -->
+ <class>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <inheritancegraph visible="$CLASS_GRAPH"/>
+ <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+ <memberdecl>
+ <nestedclasses visible="yes" title=""/>
+ <publictypes title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <publicslots title=""/>
+ <signals title=""/>
+ <publicmethods title=""/>
+ <publicstaticmethods title=""/>
+ <publicattributes title=""/>
+ <publicstaticattributes title=""/>
+ <protectedtypes title=""/>
+ <protectedslots title=""/>
+ <protectedmethods title=""/>
+ <protectedstaticmethods title=""/>
+ <protectedattributes title=""/>
+ <protectedstaticattributes title=""/>
+ <packagetypes title=""/>
+ <packagemethods title=""/>
+ <packagestaticmethods title=""/>
+ <packageattributes title=""/>
+ <packagestaticattributes title=""/>
+ <properties title=""/>
+ <events title=""/>
+ <privatetypes title=""/>
+ <privateslots title=""/>
+ <privatemethods title=""/>
+ <privatestaticmethods title=""/>
+ <privateattributes title=""/>
+ <privatestaticattributes title=""/>
+ <friends title=""/>
+ <related title="" subtitle=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <services title=""/>
+ <interfaces title=""/>
+ <constructors title=""/>
+ <functions title=""/>
+ <related title=""/>
+ <variables title=""/>
+ <properties title=""/>
+ <events title=""/>
+ </memberdef>
+ <allmemberslink visible="yes"/>
+ <usedfiles visible="$SHOW_USED_FILES"/>
+ <authorsection visible="yes"/>
+ </class>
+
+ <!-- Layout definition for a namespace page -->
+ <namespace>
+ <briefdescription visible="yes"/>
+ <memberdecl>
+ <nestednamespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </namespace>
+
+ <!-- Layout definition for a file page -->
+ <file>
+ <briefdescription visible="yes"/>
+ <includes visible="$SHOW_INCLUDE_FILES"/>
+ <includegraph visible="$INCLUDE_GRAPH"/>
+ <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+ <sourcelink visible="yes"/>
+ <memberdecl>
+ <classes visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <constantgroups visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ <memberdef>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ </memberdef>
+ <authorsection/>
+ </file>
+
+ <!-- Layout definition for a group page -->
+ <group>
+ <briefdescription visible="no"/>
+ <detaileddescription visible="yes" title="API Description"/>
+ <groupgraph visible="$GROUP_GRAPHS"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title=""/>
+ <dirs visible="yes" title=""/>
+ <files visible="yes" title=""/>
+ <namespaces visible="yes" title=""/>
+ <classes visible="yes" title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses title=""/>
+ <defines title=""/>
+ <typedefs title=""/>
+ <enums title=""/>
+ <enumvalues title=""/>
+ <functions title=""/>
+ <variables title=""/>
+ <signals title=""/>
+ <publicslots title=""/>
+ <protectedslots title=""/>
+ <privateslots title=""/>
+ <events title=""/>
+ <properties title=""/>
+ <friends title=""/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+
+ <!-- Layout definition for a directory page -->
+ <directory>
+ <briefdescription visible="yes"/>
+ <directorygraph visible="yes"/>
+ <memberdecl>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ </memberdecl>
+ <detaileddescription title=""/>
+ </directory>
+</doxygenlayout>
diff --git a/doc/implementers-guide/implementers-guide.adoc b/doc/implementers-guide/implementers-guide.adoc
index 32dbfea39..0033ba31c 100644
--- a/doc/implementers-guide/implementers-guide.adoc
+++ b/doc/implementers-guide/implementers-guide.adoc
@@ -1,4 +1,4 @@
-OpenDataPlane (ODP) Implementers-Guide
+OpenDataPlane (ODP) Implementers Guide
=======================================
:toc:
@@ -70,14 +70,14 @@ This grouping defines tests that are expected to be executable and succeed on an
They are written in plain C code, and may only use functions defined in the standard libC library (besides the ODP functions being tested, of course).
No other languages (like scripting) are allowed as their usage would make assumptions on the platform capability.
-This area is located at: '<ODP_ROOT>/test/validation/'
+This area is located at: 'test/validation/'
The ODP API itself is ordered by module, where each module groups the set of ODP API functions related to the same "topic".
Examples of modules includes "classification" (API functions dealing with ingres packets classification), time (functions dealing with time, excluding timers which have their own module), timer,...
The complete module list can be seen at: http://docs.opendataplane.org/linux-generic-doxygen-html/modules.html[ODP Modules] +
-Within the platform agnostic area, the tests are also grouped by modules, matching the ODP API modules: '<ODP_ROOT>/test/validation/' mainly contains a list of directories matching each module name (as defined by the doxygen "@defgroup" or "@ingroup" statement present in each API ".h" file).
+Within the platform agnostic area, the tests are also grouped by modules, matching the ODP API modules: 'test/validation/' mainly contains a list of directories matching each module name (as defined by the doxygen "@defgroup" or "@ingroup" statement present in each API ".h" file).
-Within each of these directories, a library (called "lib<module>.la") and its associated ".h" file (called "<module>.h") defines all the test functions for this module as well as few other functions to initialize, terminate, and group the tests.
+Within each of these directories, a library (called "libtest<module>.la") and its associated ".h" file (called "<module>.h") defines all the test functions for this module as well as few other functions to initialize, terminate, and group the tests.
An executable called "<module>_main*", is also built. It is permissible to generate more than one executable to cover the functionality in the test library for the module.
These executable(s) shall call all the tests for this module. +
See <<anchor-1, Module test and naming convention>> for more details.
@@ -87,38 +87,36 @@ The obvious illustration of this is for module "init" whose functions are requir
There is a "Makefile.am" located at the top of the platform agnostic area. Its role is limited to the construction of the different test libraries and the "<module>_main*" executables. No tests are run from this area when "make check" is performed.
-A convenience library '.../test/validation/libodptests.la' (and its associated .h file, '.../test/validation/odptest.h') regrouping all tests symbols of all modules may be built in the future. (The superlib)
-
-C_UNIT
+CUnit
^^^^^^
-Within a given test executable C_UNIT is used to run the different tests. The usage of C_UNIT implies the following structure:
+Within a given test executable CUnit is used to run the different tests. The usage of CUnit implies the following structure:
* Tests are simple C functions.
-* Tests are grouped in arrays called test suites. Each test suite can be associated with a suite initialization/termination function(s), called by C_UNIT before and after the whole suite is ran.
-* An array of test suites (and associated init/term functions) defines the test registry ran by the test executable.
+* Tests are grouped in arrays called test suites. Each test suite can be associated with a suite initialization/termination function(s), called by CUnit before and after the whole suite is run.
+* An array of test suites (and associated init/term functions) defines the test registry run by the test executable.
-Moreover, two extra functions can be used to initialize/terminate the test executable (these are not part of C_UNIT). +
-A test executable return success (0) if every tests of each suite succeed.
+Moreover, two extra functions can be used to initialize/terminate the test executable (these are not part of CUnit). +
+A test executable return success (0) if every test of each suite succeed.
-More details about http://cunit.sourceforge.net/doc/index.html[C_Unit users guide]
+More details about http://cunit.sourceforge.net/doc/index.html[CUnit users guide]
[[anchor-1]]
Module test and naming convention
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-* Tests, i.e. C functions which are used in CUNIT test suites are named:
+* Tests, i.e. C functions which are used in CUnit test suites are named:
*<Module>_test_+++*+++* +
where the suffix idendify the test.
-* Test arrays, i.e. arrays of CU_TestInfo, listing the test functions belonging to a suite, are called:
+* Test arrays, i.e. arrays of odp_testinfo_t, listing the test functions belonging to a suite, are called:
*<Module>_suite+++[_*]+++* +
where the possible suffix can be used if many suites are declared.
-* CUNIT suite init and termination functions are called:
+* CUnit suite init and termination functions are called:
*<Module>+++_suite[_*]_init()+++* and *<Module>+++_suite[_*]_term()+++* respectively. +
where the possible extra middle pattern can be used if many suites are declared.
-* Suite arrays, i.e. arrays of CU_SuiteInfo used in executables (C_UNIT registry) are called:
+* Suite arrays, i.e. arrays of odp_suiteinfo_t used in executables (CUnit registry) are called:
*<Module>+++_suites[_*]+++* +
where the possible suffix identifies the executable using it, if many.
@@ -130,18 +128,18 @@ Module test and naming convention
*<Module>_init*
*<Module>_term*
-All the above symbols are part of the generated lib<Module>.la libraries. The generated main executable(s) (named <module>_+++main[_*]+++, where the optional suffix is used to distinguish the executables belonging to the same module, if many) simply call(s) the related <Module>_main+++[_*]+++ from the library.
+All the above symbols are part of the generated libtest<Module>.la libraries. The generated main executable(s) (named <module>_+++main[_*]+++, where the optional suffix is used to distinguish the executables belonging to the same module, if many) simply call(s) the related <Module>_main+++[_*]+++ from the library.
Platform specific
~~~~~~~~~~~~~~~~~
-These tests are located under '<ODP_ROOT>/platform/<platform>/test'. There is one such area for each platform implementing ODP.
+These tests are located under 'platform/<platform>/test'. There is one such area for each platform implementing ODP.
This location will be referred as <PLATFORM_SPECIFIC> in the rest of this document.
The normal case
^^^^^^^^^^^^^^^
-If the considered platform needs nothing specific to be tested this directory will contain a single "Makefile.am".
-This "Makefile.am" then only lists the executables to be run on "make check" (in the automake TEST variable): when the platform has nothing specific to it, this just list the "<module>_main+++[_*]+++" executables, picked from the platform agnostic area.
-For the linux-generic platform, most tested modules fall into this category: currently, the '<ODP_ROOT>/platform/linux-generic/test/Makefile.am' looks as follows:
+If the considered platform needs no platform specific tests, this directory simply needs to contain a single Makefile.am listing each of the executables (named <module>_main) built from the platform agnostic area. The executables are listed in the automake TEST variable and will therefore be run on "make check".
+
+For the linux-generic platform, most tested modules fall into this category: currently, the 'platform/linux-generic/test/Makefile.am' looks as follows:
[source,am]
----
@@ -179,13 +177,11 @@ endif
With the exception for module pktio, all other modules testing just involves calling the platform agnostic <module>_main executables (in test/validation).
-When no platform specific testing is required, the '<PLATFORM_SPECIFIC>/Makefile.am' is used to list the tests executables to be run only, as these tests are actually built from the platform agnostic side by the 'test/validation/Makefile.am' (and subdirectories). '<PLATFORM_SPECIFIC>/Makefile.am' is involved in building only when platform specific tests exists, as discussed below.
-
Using other languages
^^^^^^^^^^^^^^^^^^^^^
-The pktio module, above, is actually tested using a bash script. This script is needed to set up the interfaces used by the tests. The pktio_run script actually eventually calls the platform agnostic 'test/validation/pktio/pktio_main' after setting up the interfaces needed by the tests.
-Notice that the path to the script is '<PLATFORM_SPECIFIC>/pktio/pktio_run', i.e. it is private to this platform. Any languages supported by the tested platform can be used there, as it will not impact other platforms.
-The platform "private" executables (such as this script), of course, must also return one of the return code expected by the automake test harness (0 for success, 77 for inconclusive, other values for errors).
+The pktio module, above, is actually tested using a bash script. This script is needed to set up the interfaces used by the tests. The pktio_run script eventually calls the platform agnostic 'test/validation/pktio/pktio_main' after setting up the interfaces needed by the tests.
+Notice that the path to the script, 'pktio/pktio_run', is pointing to a file within the <PLATFORM_SPECIFIC> tree so is private to this platform. Any languages supported by the tested platform can be used there, as it will not impact other platforms.
+The platform "private" executables (such as this script), of course, must also return one of the return code expected by the automake test harness (0 for success, 77 for skipped, other values for errors).
Defining test wrappers
^^^^^^^^^^^^^^^^^^^^^^
@@ -232,14 +228,56 @@ Defining platform specific tests
Sometimes, it may be necessary to call platform specific system calls to check some functionality: For instance, testing odp_cpumask_* could involve checking the underlying system CPU mask. On linux, such a test would require using the CPU_ISSET macro, which is linux specific. Such a test would be written in '<PLATFORM_SPECIFIC>/cpumask/...' The contents of this directory would be very similar to the contents of the platform agnostic side cpu_mask tests (including a Makefile.am...), but platform specific test would be written there.
'<PLATFORM_SPECIFIC>/Makefile.am' would then trigger the building of the platform specific tests (by listing their module name in SUBDIRS and therefore calling the appropriate Makefile.am) and then it would call both the platform agnostic executable(s) and the platform specific test executable.
-Skipping tests during development
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-During ODP development, it may be useful to skip some test. This can be achieved by creating a new test executable (still on the platform side), picking up the required tests from the platform agnostic lib<module>.la.
+Marking tests as inactive
+^^^^^^^^^^^^^^^^^^^^^^^^^
+The general policy is that a full run of the validation suite (a "make check") must pass at all times. However a particular platform may have one or more test cases that are known to be unimplemented either during development or permanently, so to avoid these test cases being reported as failures it's useful to be able to skip them. This can be achieved by creating a new test executable (still on the platform side), giving the platform specific initialisation code the opportunity to modify the registered tests in order to mark unwanted tests as inactive while leaving the remaining tests active. It's important that the unwanted tests are still registered with the test framework to allow the fact that they're not being tested to be recorded.
+
+The odp_cunit_update() function is intended for this purpose, it is used to modify the properties of previously registered tests, for example to mark them as inactive. Inactive tests are registered with the test framework but aren't executed and will be recorded as inactive in test reports.
+
+In 'test/validation/foo/foo.c', define all tests for the 'foo' module:
+
+[source,c]
+------------------
+odp_testinfo_t foo_tests[] = {
+ ODP_TEST_INFO(foo_test_a),
+ ODP_TEST_INFO(foo_test_b),
+ ODP_TEST_INFO_NULL
+};
+
+odp_suiteinfo_t foo_suites[] = {
+ {"Foo", foo_suite_init, foo_suite_term, foo_tests},
+ ODP_SUITE_INFO_NULL
+};
+------------------
+
+In 'platform/<platform>/test/foo/foo_main.c', register all the tests defined in the 'foo' module, then mark a single specific test case as inactive:
+
+[source,c]
+------------------
+static odp_testinfo_t foo_tests_updates[] = {
+ ODP_TEST_INFO_INACTIVE(foo_test_b),
+ ODP_TEST_INFO_NULL
+};
+
+static odp_suiteinfo_t foo_suites_updates[] = {
+ {"Foo", foo_suite_init, foo_suite_term, foo_tests_updates},
+ ODP_SUITE_INFO_NULL
+};
+
+int foo_main(void)
+{
+ int ret = odp_cunit_register(foo_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_update(foo_suites_updates);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
-The top Makefile would then call only the platform specific executable, hence skipping the tests which have been omitted.
+ return ret;
+}
+------------------
-TIP: You probably want to copy the platform-agnostic module main function and prune it from the undesired tests when writing your own platform specific main, for a given module.
+So 'foo_test_a' will be executed and 'foo_test_b' is inactive.
-Permanently skipping test
-^^^^^^^^^^^^^^^^^^^^^^^^^^
-If a platform wants to permanently skip a test (i.e. a part of the ODP API is and will not be supported on that platform), it is recommended to use the function odp_cunit_TBD() to removed the tests or suite from the list of tests. This gives a chance to the test environment to trace this removal.
+It's expected that early in the development cycle of a new implementation the inactive list will be quite long, but it should shrink over time as more parts of the API are implemented.
diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c
index 685f335f2..ba7f4379a 100644
--- a/example/classifier/odp_classifier.c
+++ b/example/classifier/odp_classifier.c
@@ -53,11 +53,12 @@ typedef struct {
odp_pmr_t pmr; /**< Associated pmr handle */
odp_atomic_u64_t packet_count; /**< count of received packets */
char queue_name[ODP_QUEUE_NAME_LEN]; /**< queue name */
- int val_sz; /**< size of the pmr term */
struct {
odp_pmr_term_e term; /**< odp pmr term value */
- uint32_t val; /**< pmr term value */
- uint32_t mask; /**< pmr term mask */
+ uint64_t val; /**< pmr term value */
+ uint64_t mask; /**< pmr term mask */
+ uint32_t val_sz; /**< size of the pmr term */
+ uint32_t offset; /**< pmr term offset */
} rule;
char value[DISPLAY_STRING_LEN]; /**< Display string for value */
char mask[DISPLAY_STRING_LEN]; /**< Display string for mask */
@@ -86,7 +87,8 @@ static void print_info(char *progname, appl_args_t *appl_args);
static void usage(char *progname);
static void configure_cos_queue(odp_pktio_t pktio, appl_args_t *args);
static void configure_default_queue(odp_pktio_t pktio, appl_args_t *args);
-static int convert_str_to_pmr_enum(char *token, odp_pmr_term_e *term);
+static int convert_str_to_pmr_enum(char *token, odp_pmr_term_e *term,
+ uint32_t *offset);
static int parse_pmr_policy(appl_args_t *appl_args, char *argv[], char *optarg);
static inline
@@ -151,12 +153,13 @@ void print_cls_statistics(appl_args_t *args)
}
static inline
-int parse_ipv4_addr(const char *ipaddress, uint32_t *addr)
+int parse_ipv4_addr(const char *ipaddress, uint64_t *addr)
{
- int b[4];
+ uint32_t b[4];
int converted;
- converted = sscanf(ipaddress, "%d.%d.%d.%d",
+ converted = sscanf(ipaddress, "%" SCNx32 ".%" SCNx32
+ ".%" SCNx32 ".%" SCNx32,
&b[3], &b[2], &b[1], &b[0]);
if (4 != converted)
return -1;
@@ -170,16 +173,42 @@ int parse_ipv4_addr(const char *ipaddress, uint32_t *addr)
}
static inline
-int parse_ipv4_mask(const char *str, uint32_t *mask)
+int parse_mask(const char *str, uint64_t *mask)
{
- uint32_t b;
+ uint64_t b;
int ret;
- ret = sscanf(str, "%" SCNx32, &b);
+ ret = sscanf(str, "%" SCNx64, &b);
*mask = b;
return ret != 1;
}
+static
+int parse_value(const char *str, uint64_t *val, uint32_t *val_sz)
+{
+ size_t len;
+ size_t i;
+ int converted;
+ union {
+ uint64_t u64;
+ uint8_t u8[8];
+ } buf = {.u64 = 0};
+
+ len = strlen(str);
+ if (len > 2 * sizeof(buf))
+ return -1;
+
+ for (i = 0; i < len; i += 2) {
+ converted = sscanf(&str[i], "%2" SCNx8, &buf.u8[i / 2]);
+ if (1 != converted)
+ return -1;
+ }
+
+ *val = buf.u64;
+ *val_sz = len / 2;
+ return 0;
+}
+
/**
* Create a pktio handle, optionally associating a default input queue.
*
@@ -198,7 +227,7 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool)
int ret;
odp_pktio_param_t pktio_param;
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
/* Open a packet IO instance */
@@ -317,26 +346,35 @@ static void configure_default_queue(odp_pktio_t pktio, appl_args_t *args)
odp_queue_param_t qparam;
odp_cos_t cos_default;
char cos_name[ODP_COS_NAME_LEN];
- char queue_name[ODP_QUEUE_NAME_LEN];
+ const char *queue_name = "DefaultQueue";
odp_queue_t queue_default;
global_statistics *stats = args->stats;
- sprintf(cos_name, "Default%s", args->if_name);
+
+ snprintf(cos_name, sizeof(cos_name), "Default%s", args->if_name);
cos_default = odp_cos_create(cos_name);
odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
- sprintf(queue_name, "%s", "DefaultQueue");
queue_default = odp_queue_create(queue_name,
- ODP_QUEUE_TYPE_SCHED, &qparam);
+ ODP_QUEUE_TYPE_SCHED, &qparam);
+
+ if (0 > odp_cos_queue_set(cos_default, queue_default)) {
+ EXAMPLE_ERR("odp_cos_queue_set failed");
+ exit(EXIT_FAILURE);
+ }
- odp_cos_set_queue(cos_default, queue_default);
- odp_pktio_default_cos_set(pktio, cos_default);
+ if (0 > odp_pktio_default_cos_set(pktio, cos_default)) {
+ EXAMPLE_ERR("odp_pktio_default_cos_set failed");
+ exit(EXIT_FAILURE);
+ }
stats[args->policy_count].cos = cos_default;
/* add default queue to global stats */
stats[args->policy_count].queue = queue_default;
- strcpy(stats[args->policy_count].queue_name, "DefaultQueue");
+ snprintf(stats[args->policy_count].queue_name,
+ sizeof(stats[args->policy_count].queue_name),
+ "%s", queue_name);
odp_atomic_init_u64(&stats[args->policy_count].packet_count, 0);
args->policy_count++;
}
@@ -351,23 +389,37 @@ static void configure_cos_queue(odp_pktio_t pktio, appl_args_t *args)
for (i = 0; i < args->policy_count; i++) {
stats = &args->stats[i];
- sprintf(cos_name, "CoS%s", stats->queue_name);
+ snprintf(cos_name, sizeof(cos_name), "CoS%s",
+ stats->queue_name);
stats->cos = odp_cos_create(cos_name);
- stats->pmr = odp_pmr_create(stats->rule.term,
- &stats->rule.val,
- &stats->rule.mask,
- stats->val_sz);
+ const odp_pmr_match_t match = {
+ .term = stats->rule.term,
+ .val = &stats->rule.val,
+ .mask = &stats->rule.mask,
+ .val_sz = stats->rule.val_sz,
+ .offset = stats->rule.offset
+ };
+
+ stats->pmr = odp_pmr_create(&match);
qparam.sched.prio = i % odp_schedule_num_prio();
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
- sprintf(queue_name, "%s%d", args->stats[i].queue_name, i);
+ snprintf(queue_name, sizeof(queue_name), "%s%d",
+ args->stats[i].queue_name, i);
stats->queue = odp_queue_create(queue_name,
ODP_QUEUE_TYPE_SCHED,
&qparam);
- odp_cos_set_queue(stats->cos, stats->queue);
- odp_pktio_pmr_cos(stats->pmr, pktio, stats->cos);
+ if (0 > odp_cos_queue_set(stats->cos, stats->queue)) {
+ EXAMPLE_ERR("odp_cos_queue_set failed");
+ exit(EXIT_FAILURE);
+ }
+
+ if (0 > odp_pktio_pmr_cos(stats->pmr, pktio, stats->cos)) {
+ EXAMPLE_ERR("odp_pktio_pmr_cos failed");
+ exit(EXIT_FAILURE);
+ }
odp_atomic_init_u64(&stats->packet_count, 0);
}
@@ -431,7 +483,7 @@ int main(int argc, char *argv[])
num_workers = args->cpu_count;
/* Get default worker cpumask */
- num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
+ num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
printf("num worker threads: %i\n", num_workers);
@@ -567,7 +619,8 @@ static void swap_pkt_addrs(odp_packet_t pkt_tbl[], unsigned len)
}
}
-static int convert_str_to_pmr_enum(char *token, odp_pmr_term_e *term)
+static int convert_str_to_pmr_enum(char *token, odp_pmr_term_e *term,
+ uint32_t *offset)
{
if (NULL == token)
return -1;
@@ -575,6 +628,13 @@ static int convert_str_to_pmr_enum(char *token, odp_pmr_term_e *term)
if (0 == strcasecmp(token, "ODP_PMR_SIP_ADDR")) {
*term = ODP_PMR_SIP_ADDR;
return 0;
+ } else {
+ errno = 0;
+ *offset = strtoul(token, NULL, 0);
+ if (errno)
+ return -1;
+ *term = ODP_PMR_CUSTOM_FRAME;
+ return 0;
}
return -1;
}
@@ -588,6 +648,7 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *argv[], char *optarg)
odp_pmr_term_e term;
global_statistics *stats;
char *pmr_str;
+ uint32_t offset;
policy_count = appl_args->policy_count;
stats = appl_args->stats;
@@ -605,7 +666,7 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *argv[], char *optarg)
/* PMR TERM */
token = strtok(pmr_str, ":");
- if (convert_str_to_pmr_enum(token, &term)) {
+ if (convert_str_to_pmr_enum(token, &term, &offset)) {
EXAMPLE_ERR("Invalid ODP_PMR_TERM string\n");
exit(EXIT_FAILURE);
}
@@ -621,8 +682,21 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *argv[], char *optarg)
token = strtok(NULL, ":");
strncpy(stats[policy_count].mask, token,
DISPLAY_STRING_LEN - 1);
- parse_ipv4_mask(token, &stats[policy_count].rule.mask);
- stats[policy_count].val_sz = 4;
+ parse_mask(token, &stats[policy_count].rule.mask);
+ stats[policy_count].rule.val_sz = 4;
+ stats[policy_count].rule.offset = 0;
+ break;
+ case ODP_PMR_CUSTOM_FRAME:
+ token = strtok(NULL, ":");
+ strncpy(stats[policy_count].value, token,
+ DISPLAY_STRING_LEN - 1);
+ parse_value(token, &stats[policy_count].rule.val,
+ &stats[policy_count].rule.val_sz);
+ token = strtok(NULL, ":");
+ strncpy(stats[policy_count].mask, token,
+ DISPLAY_STRING_LEN - 1);
+ parse_mask(token, &stats[policy_count].rule.mask);
+ stats[policy_count].rule.offset = offset;
break;
default:
usage(argv[0]);
@@ -776,10 +850,12 @@ static void usage(char *progname)
"\n"
"Mandatory OPTIONS:\n"
" -i, --interface Eth interface\n"
- " -p, --policy <odp_pmr_term_e>:<value>:<mask bits>:<queue name>\n"
+ " -p, --policy [<odp_pmr_term_e>|<offset>]:<value>:<mask bits>:<queue name>\n"
"\n"
"<odp_pmr_term_e> Packet Matching Rule defined with odp_pmr_term_e "
"for the policy\n"
+ "<offset> Absolute offset in bytes from frame start to define a "
+ "ODP_PMR_CUSTOM_FRAME Packet Matching Rule for the policy\n"
"\n"
"<value> PMR value to be matched.\n"
"\n"
diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
index f7aed7608..68f38e624 100644
--- a/example/generator/odp_generator.c
+++ b/example/generator/odp_generator.c
@@ -68,6 +68,7 @@ static struct {
odp_atomic_u64_t ip; /**< ip packets */
odp_atomic_u64_t udp; /**< udp packets */
odp_atomic_u64_t icmp; /**< icmp packets */
+ odp_atomic_u64_t cnt; /**< sent packets*/
} counters;
/** * Thread specific arguments
@@ -241,7 +242,7 @@ static odp_packet_t pack_udp_pkt(odp_pool_t pool)
udp->dst_port = 0;
udp->length = odp_cpu_to_be_16(args->appl.payload + ODPH_UDPHDR_LEN);
udp->chksum = 0;
- udp->chksum = odph_ipv4_udp_chksum(pkt);
+ udp->chksum = odp_cpu_to_be_16(odph_ipv4_udp_chksum(pkt));
return pkt;
}
@@ -330,7 +331,7 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool)
odp_queue_t inq_def;
odp_pktio_param_t pktio_param;
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
/* Open a packet IO instance */
@@ -407,6 +408,11 @@ static void *gen_send_thread(void *arg)
for (;;) {
int err;
+ if (args->appl.number != -1 &&
+ odp_atomic_fetch_add_u64(&counters.cnt, 1) >=
+ (unsigned int)args->appl.number)
+ break;
+
if (args->appl.mode == APPL_MODE_UDP)
pkt = pack_udp_pkt(thr_args->pool);
else if (args->appl.mode == APPL_MODE_PING)
@@ -438,11 +444,6 @@ static void *gen_send_thread(void *arg)
thr_args->tmo_ev);
}
- if (args->appl.number != -1 &&
- odp_atomic_load_u64(&counters.seq)
- >= (unsigned int)args->appl.number) {
- break;
- }
}
/* receive number of reply pks until timeout */
@@ -597,7 +598,7 @@ static void print_global_stats(int num_workers)
while (odp_thrmask_worker(&thrd_mask) == num_workers) {
if (args->appl.number != -1 &&
- odp_atomic_load_u64(&counters.seq) >=
+ odp_atomic_load_u64(&counters.cnt) >=
(unsigned int)args->appl.number) {
break;
}
@@ -669,6 +670,7 @@ int main(int argc, char *argv[])
odp_atomic_init_u64(&counters.ip, 0);
odp_atomic_init_u64(&counters.udp, 0);
odp_atomic_init_u64(&counters.icmp, 0);
+ odp_atomic_init_u64(&counters.cnt, 0);
/* Reserve memory for args from shared mem */
shm = odp_shm_reserve("shm_args", sizeof(args_t),
@@ -692,7 +694,7 @@ int main(int argc, char *argv[])
if (args->appl.cpu_count)
num_workers = args->appl.cpu_count;
- num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
+ num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
if (args->appl.mask) {
odp_cpumask_from_str(&cpumask, args->appl.mask);
num_workers = odp_cpumask_count(&cpumask);
@@ -918,7 +920,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
case 'c':
appl_args->mask = optarg;
odp_cpumask_from_str(&cpumask_args, args->appl.mask);
- num_workers = odp_cpumask_def_worker(&cpumask, 0);
+ num_workers = odp_cpumask_default_worker(&cpumask, 0);
odp_cpumask_and(&cpumask_and, &cpumask_args, &cpumask);
if (odp_cpumask_count(&cpumask_and) <
odp_cpumask_count(&cpumask_args)) {
@@ -1114,7 +1116,8 @@ static void usage(char *progname)
"\n"
"Optional OPTIONS\n"
" -h, --help Display help and exit.\n"
- " environment variables: ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
+ " environment variables: ODP_PKTIO_DISABLE_NETMAP\n"
+ " ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
" ODP_PKTIO_DISABLE_SOCKET_MMSG\n"
" can be used to advanced pkt I/O selection for linux-generic\n"
" -p, --packetsize payload length of the packets\n"
diff --git a/example/ipsec/odp_ipsec.c b/example/ipsec/odp_ipsec.c
index 96effe28a..2aaae1dde 100644
--- a/example/ipsec/odp_ipsec.c
+++ b/example/ipsec/odp_ipsec.c
@@ -221,8 +221,7 @@ void free_pkt_ctx(pkt_ctx_t *ctx)
*/
typedef odp_queue_t (*queue_create_func_t)
(const char *, odp_queue_type_t, odp_queue_param_t *);
-typedef odp_event_t (*schedule_func_t)
- (odp_queue_t *, uint64_t);
+typedef odp_event_t (*schedule_func_t) (odp_queue_t *);
static queue_create_func_t queue_create;
static schedule_func_t schedule;
@@ -259,49 +258,33 @@ odp_queue_t polled_odp_queue_create(const char *name,
return my_queue;
}
+static inline
+odp_event_t odp_schedule_cb(odp_queue_t *from)
+{
+ return odp_schedule(from, ODP_SCHED_WAIT);
+}
+
/**
* odp_schedule replacement to poll queues versus using ODP scheduler
*/
static
-odp_event_t polled_odp_schedule(odp_queue_t *from, uint64_t wait)
+odp_event_t polled_odp_schedule_cb(odp_queue_t *from)
{
- uint64_t start_cycle;
- uint64_t cycle;
- uint64_t diff;
-
- start_cycle = 0;
+ int idx = 0;
while (1) {
- int idx;
+ if (idx >= num_polled_queues)
+ idx = 0;
- for (idx = 0; idx < num_polled_queues; idx++) {
- odp_queue_t queue = poll_queues[idx];
- odp_event_t buf;
+ odp_queue_t queue = poll_queues[idx++];
+ odp_event_t buf;
- buf = odp_queue_deq(queue);
+ buf = odp_queue_deq(queue);
- if (ODP_EVENT_INVALID != buf) {
- *from = queue;
- return buf;
- }
+ if (ODP_EVENT_INVALID != buf) {
+ *from = queue;
+ return buf;
}
-
- if (ODP_SCHED_WAIT == wait)
- continue;
-
- if (ODP_SCHED_NO_WAIT == wait)
- break;
-
- if (0 == start_cycle) {
- start_cycle = odp_time_cycles();
- continue;
- }
-
- cycle = odp_time_cycles();
- diff = odp_time_diff_cycles(start_cycle, cycle);
-
- if (wait < diff)
- break;
}
*from = ODP_QUEUE_INVALID;
@@ -513,13 +496,12 @@ void initialize_intf(char *intf)
char src_mac_str[MAX_STRING];
odp_pktio_param_t pktio_param;
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
-#ifdef IPSEC_POLL_QUEUES
- pktio_param.in_mode = ODP_PKTIN_MODE_POLL;
-#else
- pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
-#endif
+ if (getenv("ODP_IPSEC_USE_POLL_QUEUES"))
+ pktio_param.in_mode = ODP_PKTIN_MODE_POLL;
+ else
+ pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
/*
* Open a packet IO instance for thread and get default output queue
@@ -870,6 +852,7 @@ pkt_disposition_e do_ipsec_out_classify(odp_packet_t pkt,
if (entry->mode == IPSEC_SA_MODE_TUNNEL) {
hdr_len += sizeof(odph_ipv4hdr_t);
ip_data = (uint8_t *)ip;
+ ip_data_len += sizeof(odph_ipv4hdr_t);
}
/* Compute ah and esp, determine length of headers, move the data */
if (entry->ah.alg) {
@@ -897,17 +880,10 @@ pkt_disposition_e do_ipsec_out_classify(odp_packet_t pkt,
uint32_t encrypt_len;
odph_esptrl_t *esp_t;
- if (entry->mode == IPSEC_SA_MODE_TUNNEL) {
- encrypt_len = ESP_ENCODE_LEN(ip->tot_len +
- sizeof(*esp_t),
- entry->esp.block_len);
- trl_len = encrypt_len - ip->tot_len;
- } else {
- encrypt_len = ESP_ENCODE_LEN(ip_data_len +
- sizeof(*esp_t),
- entry->esp.block_len);
- trl_len = encrypt_len - ip_data_len;
- }
+ encrypt_len = ESP_ENCODE_LEN(ip_data_len +
+ sizeof(*esp_t),
+ entry->esp.block_len);
+ trl_len = encrypt_len - ip_data_len;
esp->spi = odp_cpu_to_be_32(entry->esp.spi);
memcpy(esp + 1, entry->state.iv, entry->esp.iv_len);
@@ -1095,7 +1071,7 @@ void *pktio_thread(void *arg EXAMPLE_UNUSED)
odp_crypto_op_result_t result;
/* Use schedule to get event from any input queue */
- ev = schedule(&dispatchq, ODP_SCHED_WAIT);
+ ev = schedule(&dispatchq);
/* Determine new work versus completion or sequence number */
if (ODP_EVENT_PACKET == odp_event_type(ev)) {
@@ -1246,12 +1222,12 @@ main(int argc, char *argv[])
/* create by default scheduled queues */
queue_create = odp_queue_create;
- schedule = odp_schedule;
+ schedule = odp_schedule_cb;
/* check for using poll queues */
if (getenv("ODP_IPSEC_USE_POLL_QUEUES")) {
queue_create = polled_odp_queue_create;
- schedule = polled_odp_schedule;
+ schedule = polled_odp_schedule_cb;
}
/* Init ODP before calling anything else */
@@ -1296,7 +1272,7 @@ main(int argc, char *argv[])
num_workers = args->appl.cpu_count;
/* Get default worker cpumask */
- num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
+ num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
printf("num worker threads: %i\n", num_workers);
@@ -1594,7 +1570,8 @@ static void usage(char *progname)
"Optional OPTIONS\n"
" -c, --count <number> CPU count.\n"
" -h, --help Display help and exit.\n"
- " environment variables: ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
+ " environment variables: ODP_PKTIO_DISABLE_NETMAP\n"
+ " ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
" ODP_PKTIO_DISABLE_SOCKET_MMSG\n"
" can be used to advanced pkt I/O selection for linux-generic\n"
" ODP_IPSEC_USE_POLL_QUEUES\n"
diff --git a/example/packet/odp_pktio.c b/example/packet/odp_pktio.c
index df53ea2d9..239c1b038 100644
--- a/example/packet/odp_pktio.c
+++ b/example/packet/odp_pktio.c
@@ -118,7 +118,7 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool, int mode)
int ret;
odp_pktio_param_t pktio_param;
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
switch (mode) {
case APPL_MODE_PKT_BURST:
@@ -146,6 +146,9 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool, int mode)
switch (mode) {
case APPL_MODE_PKT_BURST:
/* no further setup needed for burst mode */
+ ret = odp_pktio_start(pktio);
+ if (ret != 0)
+ EXAMPLE_ABORT("Error: unable to start %s\n", dev);
return pktio;
case APPL_MODE_PKT_QUEUE:
inq_def = odp_queue_create(inq_name,
@@ -386,7 +389,7 @@ int main(int argc, char *argv[])
num_workers = args->appl.cpu_count;
/* Get default worker cpumask */
- num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
+ num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
printf("num worker threads: %i\n", num_workers);
@@ -697,7 +700,8 @@ static void usage(char *progname)
" 1: Receive and send via queues.\n"
" 2: Receive via scheduler, send via queues.\n"
" -h, --help Display help and exit.\n"
- " environment variables: ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
+ " environment variables: ODP_PKTIO_DISABLE_NETMAP\n"
+ " ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
" ODP_PKTIO_DISABLE_SOCKET_MMSG\n"
" can be used to advanced pkt I/O selection for linux-generic\n"
"\n", NO_PATH(progname), NO_PATH(progname)
diff --git a/example/timer/odp_timer_test.c b/example/timer/odp_timer_test.c
index 49630b053..94619e481 100644
--- a/example/timer/odp_timer_test.c
+++ b/example/timer/odp_timer_test.c
@@ -322,7 +322,7 @@ int main(int argc, char *argv[])
odph_linux_pthread_t thread_tbl[MAX_WORKERS];
int num_workers;
odp_queue_t queue;
- uint64_t cycles, ns;
+ uint64_t tick, ns;
odp_queue_param_t param;
odp_pool_param_t params;
odp_timer_pool_param_t tparams;
@@ -381,7 +381,7 @@ int main(int argc, char *argv[])
num_workers = gbls->args.cpu_count;
/* Get default worker cpumask */
- num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
+ num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
printf("num worker threads: %i\n", num_workers);
@@ -447,21 +447,21 @@ int main(int argc, char *argv[])
}
printf("CPU freq %"PRIu64" Hz\n", odp_sys_cpu_hz());
- printf("Cycles vs nanoseconds:\n");
+ printf("Timer ticks vs nanoseconds:\n");
ns = 0;
- cycles = odp_time_ns_to_cycles(ns);
+ tick = odp_timer_ns_to_tick(gbls->tp, ns);
- printf(" %12"PRIu64" ns -> %12"PRIu64" cycles\n", ns, cycles);
- printf(" %12"PRIu64" cycles -> %12"PRIu64" ns\n", cycles,
- odp_time_cycles_to_ns(cycles));
+ printf(" %12" PRIu64 " ns -> %12" PRIu64 " ticks\n", ns, tick);
+ printf(" %12" PRIu64 " ticks -> %12" PRIu64 " ns\n", tick,
+ odp_timer_tick_to_ns(gbls->tp, tick));
for (ns = 1; ns <= 100*ODP_TIME_SEC; ns *= 10) {
- cycles = odp_time_ns_to_cycles(ns);
+ tick = odp_timer_ns_to_tick(gbls->tp, ns);
- printf(" %12"PRIu64" ns -> %12"PRIu64" cycles\n", ns,
- cycles);
- printf(" %12"PRIu64" cycles -> %12"PRIu64" ns\n", cycles,
- odp_time_cycles_to_ns(cycles));
+ printf(" %12" PRIu64 " ns -> %12" PRIu64 " ticks\n", ns,
+ tick);
+ printf(" %12" PRIu64 " ticks -> %12" PRIu64 " ns\n", tick,
+ odp_timer_tick_to_ns(gbls->tp, tick));
}
printf("\n");
diff --git a/helper/include/odp/helper/tcp.h b/helper/include/odp/helper/tcp.h
index defe4221b..42f0cbe1f 100644
--- a/helper/include/odp/helper/tcp.h
+++ b/helper/include/odp/helper/tcp.h
@@ -26,6 +26,7 @@ extern "C" {
* @{
*/
+#define ODPH_TCPHDR_LEN 20 /**< Min length of TCP header (no options) */
/** TCP header */
typedef struct ODP_PACKED {
diff --git a/helper/test/odp_process.c b/helper/test/odp_process.c
index d3a594353..cb9b328bc 100644
--- a/helper/test/odp_process.c
+++ b/helper/test/odp_process.c
@@ -39,7 +39,7 @@ int main(int argc TEST_UNUSED, char *argv[] TEST_UNUSED)
}
/* discover how many processes this system can support */
- num_workers = odp_cpumask_def_worker(&cpu_mask, NUMBER_WORKERS);
+ num_workers = odp_cpumask_default_worker(&cpu_mask, NUMBER_WORKERS);
if (num_workers < NUMBER_WORKERS) {
printf("System can only support %d processes and not the %d requested\n",
num_workers, NUMBER_WORKERS);
diff --git a/helper/test/odp_thread.c b/helper/test/odp_thread.c
index 1de30ab67..592f85624 100644
--- a/helper/test/odp_thread.c
+++ b/helper/test/odp_thread.c
@@ -40,7 +40,7 @@ int main(int argc TEST_UNUSED, char *argv[] TEST_UNUSED)
}
/* discover how many threads this system can support */
- num_workers = odp_cpumask_def_worker(&cpu_mask, NUMBER_WORKERS);
+ num_workers = odp_cpumask_default_worker(&cpu_mask, NUMBER_WORKERS);
if (num_workers < NUMBER_WORKERS) {
printf("System can only support %d threads and not the %d requested\n",
num_workers, NUMBER_WORKERS);
diff --git a/include/odp/api/classification.h b/include/odp/api/classification.h
index f597b2627..380d91b15 100644
--- a/include/odp/api/classification.h
+++ b/include/odp/api/classification.h
@@ -120,7 +120,19 @@ int odp_cos_destroy(odp_cos_t cos_id);
* @retval 0 on success
* @retval <0 on failure
*/
-int odp_cos_set_queue(odp_cos_t cos_id, odp_queue_t queue_id);
+int odp_cos_queue_set(odp_cos_t cos_id, odp_queue_t queue_id);
+
+/**
+* Get the queue associated with the specific class-of-service
+*
+* @param[in] cos_id class-of-service instance.
+*
+* @retval queue_handle Queue handle associated with the
+* given class-of-service
+*
+* @retval ODP_QUEUE_INVALID on failure
+*/
+odp_queue_t odp_cos_queue(odp_cos_t cos_id);
/**
* Assign packet drop policy for specific class-of-service
@@ -133,7 +145,17 @@ int odp_cos_set_queue(odp_cos_t cos_id, odp_queue_t queue_id);
*
* @note Optional.
*/
-int odp_cos_set_drop(odp_cos_t cos_id, odp_drop_e drop_policy);
+int odp_cos_drop_set(odp_cos_t cos_id, odp_drop_e drop_policy);
+
+/**
+* Get the drop policy configured for a specific class-of-service instance.
+*
+* @param[in] cos_id class-of-service instance.
+*
+* @retval Drop policy configured with the given
+* class-of-service
+*/
+odp_drop_e odp_cos_drop(odp_cos_t cos_id);
/**
* Request to override per-port class of service
@@ -215,29 +237,38 @@ typedef enum odp_pmr_term {
ODP_PMR_IPSEC_SPI, /**< IPsec session identifier(*val=uint32_t)*/
ODP_PMR_LD_VNI, /**< NVGRE/VXLAN network identifier
(*val=uint32_t)*/
+ ODP_PMR_CUSTOM_FRAME, /**< Custom match rule, offset from start of
+ frame. The match is defined by the offset, the
+ expected value, and its size. They must be
+ applied before any other PMR.
+ (*val=uint8_t[val_sz])*/
/** Inner header may repeat above values with this offset */
ODP_PMR_INNER_HDR_OFF = 32
} odp_pmr_term_e;
/**
+ * Following structure is used to define a packet matching rule
+ */
+typedef struct odp_pmr_match_t {
+ odp_pmr_term_e term; /**< PMR term value to be matched */
+ const void *val; /**< Value to be matched */
+ const void *mask; /**< Masked set of bits to be matched */
+ uint32_t val_sz; /**< Size of the term value */
+ uint32_t offset; /**< User-defined offset in packet
+ Used if term == ODP_PMR_CUSTOM_FRAME only,
+ ignored otherwise */
+} odp_pmr_match_t;
+
+/**
* Create a packet match rule with mask and value
*
- * @param[in] term One of the enumerated values supported
- * @param[in] val Value to match against the packet header
- * in native byte order.
- * @param[in] mask Mask to indicate which bits of the header
- * should be matched ('1') and
- * which should be ignored ('0')
- * @param[in] val_sz Size of the val and mask arguments,
- * that must match the value size requirement of the
- * specific term.
+ * @param[in] match packet matching rule definition
*
* @return Handle of the matching rule
* @retval ODP_PMR_INVAL on failure
*/
-odp_pmr_t odp_pmr_create(odp_pmr_term_e term, const void *val,
- const void *mask, uint32_t val_sz);
+odp_pmr_t odp_pmr_create(const odp_pmr_match_t *match);
/**
* Invalidate a packet match rule and vacate its resources
@@ -290,27 +321,17 @@ unsigned long long odp_pmr_terms_cap(void);
unsigned odp_pmr_terms_avail(void);
/**
- * Following structure is used to define composite packet matching rules
- * in the form of an array of individual match rules.
- * The underlying platform may not support all or any specific combination
- * of value match rules, and the application should take care
- * of inspecting the return value when installing such rules, and perform
- * appropriate fallback action.
- */
-typedef struct odp_pmr_match_t {
- odp_pmr_term_e term; /**< PMR term value to be matched */
- const void *val; /**< Value to be matched */
- const void *mask; /**< Masked set of bits to be matched */
- unsigned int val_sz; /**< Size of the term value */
-} odp_pmr_match_t;
-
-/**
* @typedef odp_pmr_set_t
* An opaque handle to a composite packet match rule-set
*/
/**
- * Create a composite packet match rule
+ * Create a composite packet match rule in the form of an array of individual
+ * match rules.
+ * The underlying platform may not support all or any specific combination
+ * of value match rules, and the application should take care
+ * of inspecting the return value when installing such rules, and perform
+ * appropriate fallback action.
*
* @param[in] num_terms Number of terms in the match rule.
* @param[in] terms Array of num_terms entries, one entry per
@@ -322,7 +343,7 @@ typedef struct odp_pmr_match_t {
* underlying platform classification engine
* @retval <0 on failure
*/
-int odp_pmr_match_set_create(int num_terms, odp_pmr_match_t *terms,
+int odp_pmr_match_set_create(int num_terms, const odp_pmr_match_t *terms,
odp_pmr_set_t *pmr_set_id);
/**
diff --git a/include/odp/api/config.h b/include/odp/api/config.h
index 302eaf597..c9879d6d8 100644
--- a/include/odp/api/config.h
+++ b/include/odp/api/config.h
@@ -19,55 +19,73 @@ extern "C" {
#endif
/** @defgroup odp_config ODP CONFIG
- * Macro for maximum number of resources in ODP.
+ * Platform-specific configuration limits.
+ *
+ * @note The API calls defined for ODP configuration limits are the
+ * normative means of accessing platform-specific configuration limits.
+ * Platforms MAY in addition include \#defines for these limits for
+ * internal use in dimensioning arrays, however there is no guarantee
+ * that applications using such \#defines will be portable across all
+ * ODP implementations. Applications SHOULD expect that over time such
+ * \#defines will be deprecated and removed.
* @{
*/
/**
- * Maximum number of threads
+ * Maximum number of pools
+ * @return The maximum number of pools supported by this platform
*/
-#define ODP_CONFIG_MAX_THREADS 128
+int odp_config_pools(void);
/**
- * Maximum number of pools
+ * Maximum number of queues
+ * @return The maximum number of queues supported by this platform
*/
-#define ODP_CONFIG_POOLS 16
+int odp_config_queues(void);
/**
- * Maximum number of queues
+ * Maximum number of ordered locks per queue
+ * @return The maximum number of ordered locks per queue supported by
+ * this platform.
*/
-#define ODP_CONFIG_QUEUES 1024
+int odp_config_max_ordered_locks_per_queue(void);
/**
* Number of scheduling priorities
+ * @return The number of scheduling priorities supported by this platform
*/
-#define ODP_CONFIG_SCHED_PRIOS 8
+int odp_config_sched_prios(void);
/**
* Number of scheduling groups
+ * @return Number of scheduling groups supported by this platofmr
*/
-#define ODP_CONFIG_SCHED_GRPS 16
+int odp_config_sched_grps(void);
/**
* Maximum number of packet IO resources
+ * @return The maximum number of packet I/O resources supported by this
+ * platform
*/
-#define ODP_CONFIG_PKTIO_ENTRIES 64
+int odp_config_pktio_entries(void);
/**
* Minimum buffer alignment
*
- * This defines the minimum supported buffer alignment. Requests for values
- * below this will be rounded up to this value.
+ * @return The minimum buffer alignment supported by this platform
+ * @note Requests for values below this will be rounded up to this value.
*/
-#define ODP_CONFIG_BUFFER_ALIGN_MIN 16
+int odp_config_buffer_align_min(void);
/**
* Maximum buffer alignment
*
* This defines the maximum supported buffer alignment. Requests for values
* above this will fail.
+ *
+ * @return The maximum buffer alignment supported by this platform.
*/
-#define ODP_CONFIG_BUFFER_ALIGN_MAX (4*1024)
+int odp_config_buffer_align_max(void);
/**
* Default packet headroom
@@ -77,11 +95,9 @@ extern "C" {
* allocated packets. Implementations may reserve a larger than minimum headroom
* size e.g. due to HW or a protocol specific alignment requirement.
*
- * @internal In linux-generic implementation:
- * The default value (66) allows a 1500-byte packet to be received into a single
- * segment with Ethernet offset alignment and room for some header expansion.
+ * @return Default packet headroom in bytes
*/
-#define ODP_CONFIG_PACKET_HEADROOM 66
+int odp_config_packet_headroom(void);
/**
* Default packet tailroom
@@ -89,10 +105,11 @@ extern "C" {
* This defines the minimum number of tailroom bytes that newly created packets
* have by default. The default apply to both ODP packet input and user
* allocated packets. Implementations are free to add to this as desired
- * without restriction. Note that most implementations will automatically
- * consider any unused portion of the last segment of a packet as tailroom
+ * without restriction.
+ *
+ * @return The default packet tailroom in bytes
*/
-#define ODP_CONFIG_PACKET_TAILROOM 0
+int odp_config_packet_tailroom(void);
/**
* Minimum packet segment length
@@ -100,8 +117,10 @@ extern "C" {
* This defines the minimum packet segment buffer length in bytes. The user
* defined segment length (seg_len in odp_pool_param_t) will be rounded up into
* this value.
+ *
+ * @return The minimum packet seg_len supported by this platform
*/
-#define ODP_CONFIG_PACKET_SEG_LEN_MIN (1598)
+int odp_config_packet_seg_len_min(void);
/**
* Maximum packet segment length
@@ -109,8 +128,10 @@ extern "C" {
* This defines the maximum packet segment buffer length in bytes. The user
* defined segment length (seg_len in odp_pool_param_t) must not be larger than
* this.
+ *
+ * @return The maximum packet seg_len supported by this platform
*/
-#define ODP_CONFIG_PACKET_SEG_LEN_MAX (64*1024)
+int odp_config_packet_seg_len_max(void);
/**
* Maximum packet buffer length
@@ -120,17 +141,17 @@ extern "C" {
* (including default head- and tailrooms) or extend packets to sizes larger
* than this limit will fail.
*
- * @internal In linux-generic implementation:
- * - The value MUST be an integral number of segments
- * - The value SHOULD be large enough to accommodate jumbo packets (9K)
+ * @return The maximum packet buffer length supported by this platform
*/
-#define ODP_CONFIG_PACKET_BUF_LEN_MAX (ODP_CONFIG_PACKET_SEG_LEN_MIN*6)
+int odp_config_packet_buf_len_max(void);
/** Maximum number of shared memory blocks.
*
* This the the number of separate SHM areas that can be reserved concurrently
+ *
+ * @return The maximum number of shm areas supported by this platform
*/
-#define ODP_CONFIG_SHM_BLOCKS (ODP_CONFIG_POOLS + 48)
+int odp_config_shm_blocks(void);
/**
* @}
diff --git a/include/odp/api/cpu.h b/include/odp/api/cpu.h
index c38909321..50a7e3da5 100644
--- a/include/odp/api/cpu.h
+++ b/include/odp/api/cpu.h
@@ -18,6 +18,8 @@
extern "C" {
#endif
+#include <odp/std_types.h>
+
/** @defgroup odp_cpu ODP CPU
* @{
*/
@@ -44,6 +46,56 @@ int odp_cpu_id(void);
int odp_cpu_count(void);
/**
+ * Current CPU cycle count
+ *
+ * Return current CPU cycle count. Cycle count may not be reset at ODP init
+ * and thus may wrap back to zero between two calls. Use odp_cpu_cycles_max()
+ * to read the maximum count value after which it wraps. Cycle count frequency
+ * follows the CPU frequency and thus may change at any time. The count may
+ * advance in steps larger than one. Use odp_cpu_cycles_resolution() to read
+ * the step size.
+ *
+ * @note Do not use CPU count for time measurements since the frequency may
+ * vary.
+ *
+ * @return Current CPU cycle count
+ */
+uint64_t odp_cpu_cycles(void);
+
+/**
+ * CPU cycle count difference
+ *
+ * Calculate difference between cycle counts c1 and c2. Parameter c1 must be the
+ * first cycle count sample and c2 the second. The function handles correctly
+ * single cycle count wrap between c1 and c2.
+ *
+ * @param c1 First cycle count
+ * @param c2 Second cycle count
+ *
+ * @return CPU cycles from c1 to c2
+ */
+uint64_t odp_cpu_cycles_diff(uint64_t c1, uint64_t c2);
+
+/**
+ * Maximum CPU cycle count
+ *
+ * Maximum CPU cycle count value before it wraps back to zero.
+ *
+ * @return Maximum CPU cycle count value
+ */
+uint64_t odp_cpu_cycles_max(void);
+
+/**
+ * Resolution of CPU cycle count
+ *
+ * CPU cycle count may advance in steps larger than one. This function returns
+ * resolution of odp_cpu_cycles() in CPU cycles.
+ *
+ * @return CPU cycle count resolution in CPU cycles
+ */
+uint64_t odp_cpu_cycles_resolution(void);
+
+/**
* @}
*/
diff --git a/include/odp/api/cpumask.h b/include/odp/api/cpumask.h
index 2ad7fea2c..7480132b2 100644
--- a/include/odp/api/cpumask.h
+++ b/include/odp/api/cpumask.h
@@ -26,6 +26,12 @@ extern "C" {
*/
/**
+ * @def ODP_CPUMASK_SIZE
+ * Maximum cpumask size, this definition limits the number of individual CPUs
+ * that can be accessed in this system.
+ */
+
+/**
* @def ODP_CPUMASK_STR_SIZE
* Minimum size of output buffer for odp_cpumask_to_str()
*/
@@ -203,7 +209,7 @@ int odp_cpumask_next(const odp_cpumask_t *mask, int cpu);
* @param num Number of worker threads, zero for all available CPUs
* @return Actual number of CPUs used to create the mask
*/
-int odp_cpumask_def_worker(odp_cpumask_t *mask, int num);
+int odp_cpumask_default_worker(odp_cpumask_t *mask, int num);
/**
* Default cpumask for control threads
@@ -215,7 +221,7 @@ int odp_cpumask_def_worker(odp_cpumask_t *mask, int num);
* @param num Number of control threads, zero for all available CPUs
* @return Actual number of CPUs used to create the mask
*/
-int odp_cpumask_def_control(odp_cpumask_t *mask, int num);
+int odp_cpumask_default_control(odp_cpumask_t *mask, int num);
/**
* @}
diff --git a/include/odp/api/init.h b/include/odp/api/init.h
index 0683d8d38..737ff6d69 100644
--- a/include/odp/api/init.h
+++ b/include/odp/api/init.h
@@ -110,8 +110,18 @@ typedef void (*odp_abort_func_t)(void) ODP_NORETURN;
* @note It is expected that all unassigned members are zero
*/
typedef struct odp_init_t {
- odp_log_func_t log_fn; /**< Replacement for the default log fn */
- odp_abort_func_t abort_fn; /**< Replacement for the default abort fn */
+ /** Maximum number of worker threads the user will run concurrently.
+ Valid range is from 0 to platform specific maximum. Set both
+ num_worker and num_control to zero for default number of threads. */
+ int num_worker;
+ /** Maximum number of control threads the user will run concurrently.
+ Valid range is from 0 to platform specific maximum. Set both
+ num_worker and num_control to zero for default number of threads. */
+ int num_control;
+ /** Replacement for the default log fn */
+ odp_log_func_t log_fn;
+ /** Replacement for the default abort fn */
+ odp_abort_func_t abort_fn;
} odp_init_t;
/**
@@ -133,9 +143,10 @@ typedef struct odp_platform_init_t {
* functions.
*
* @param params Those parameters that are interpreted by the ODP API.
+ * Use NULL to set all parameters to their defaults.
* @param platform_params Those parameters that are passed without
* interpretation by the ODP API to the implementation.
- *
+ * Use NULL to set all parameters to their defaults.
* @retval 0 on success
* @retval <0 on failure
*
diff --git a/include/odp/api/packet.h b/include/odp/api/packet.h
index 3a454b5dc..5d46b7b91 100644
--- a/include/odp/api/packet.h
+++ b/include/odp/api/packet.h
@@ -605,6 +605,43 @@ uint32_t odp_packet_l4_offset(odp_packet_t pkt);
int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset);
/**
+ * Packet flow hash value
+ *
+ * Returns the hash generated from the packet header. Use
+ * odp_packet_has_flow_hash() to check if packet contains a hash.
+ *
+ * @param pkt Packet handle
+ *
+ * @return Hash value
+ *
+ * @note Zero can be a valid hash value.
+ * @note The hash algorithm and the header fields defining the flow (therefore
+ * used for hashing) is platform dependent. It is possible a platform doesn't
+ * generate any hash at all.
+ * @note The returned hash is either the platform generated (if any), or if
+ * odp_packet_flow_hash_set() were called then the value set there.
+ */
+uint32_t odp_packet_flow_hash(odp_packet_t pkt);
+
+/**
+ * Set packet flow hash value
+ *
+ * Store the packet flow hash for the packet and sets the flow hash flag. This
+ * enables (but does not require!) application to reflect packet header
+ * changes in the hash.
+ *
+ * @param pkt Packet handle
+ * @param flow_hash Hash value to set
+ *
+ * @note If the platform needs to keep the original hash value, it has to
+ * maintain it internally. Overwriting the platform provided value doesn't
+ * change how the platform handles this packet after it.
+ * @note The application is not required to keep this hash valid for new or
+ * modified packets.
+ */
+void odp_packet_flow_hash_set(odp_packet_t pkt, uint32_t flow_hash);
+
+/**
* Tests if packet is segmented
*
* @param pkt Packet handle
diff --git a/include/odp/api/packet_flags.h b/include/odp/api/packet_flags.h
index bfbcc945b..7c3b247a9 100644
--- a/include/odp/api/packet_flags.h
+++ b/include/odp/api/packet_flags.h
@@ -191,6 +191,15 @@ int odp_packet_has_sctp(odp_packet_t pkt);
int odp_packet_has_icmp(odp_packet_t pkt);
/**
+ * Check for packet flow hash
+ *
+ * @param pkt Packet handle
+ * @retval non-zero if packet contains a hash value
+ * @retval 0 if packet does not contain a hash value
+ */
+int odp_packet_has_flow_hash(odp_packet_t pkt);
+
+/**
* Set flag for L2 header, e.g. ethernet
*
* @param pkt Packet handle
@@ -327,6 +336,15 @@ void odp_packet_has_sctp_set(odp_packet_t pkt, int val);
void odp_packet_has_icmp_set(odp_packet_t pkt, int val);
/**
+ * Clear flag for packet flow hash
+ *
+ * @param pkt Packet handle
+ *
+ * @note Set this flag is only possible through odp_packet_flow_hash_set()
+ */
+void odp_packet_has_flow_hash_clr(odp_packet_t pkt);
+
+/**
* @}
*/
diff --git a/include/odp/api/packet_io.h b/include/odp/api/packet_io.h
index e00d011c4..003861017 100644
--- a/include/odp/api/packet_io.h
+++ b/include/odp/api/packet_io.h
@@ -19,7 +19,18 @@ extern "C" {
#endif
/** @defgroup odp_packet_io ODP PACKET IO
- * Operations on a packet.
+ * Operations on a packet Input/Output interface.
+ *
+ * Packet IO is the Ingress and Egress interface to ODP processing. It
+ * allows manipulation of the interface for setting such attributes as
+ * the mtu, mac etc.
+ * Pktio is usually followed by the classifier and a default class COS
+ * can be set so that the scheduler may distribute flows. The interface
+ * may be used directly in polled mode with odp_pktio_recv() &
+ * odp_pktio_send().
+ * Diagnostic messages can be enhanced by using odp_pktio_to_u64 which
+ * will generate a printable reference for a pktio handle for use with
+ * the logging.
* @{
*/
@@ -54,7 +65,9 @@ typedef enum odp_pktio_input_mode_t {
/** Packet input through scheduled queues */
ODP_PKTIN_MODE_SCHED,
/** Application polls packet input queues */
- ODP_PKTIN_MODE_POLL
+ ODP_PKTIN_MODE_POLL,
+ /** Application will never receive from this interface */
+ ODP_PKTIN_MODE_DISABLED
} odp_pktio_input_mode_t;
/**
@@ -64,7 +77,9 @@ typedef enum odp_pktio_output_mode_t {
/** Direct packet output on the interface with odp_pktio_send() */
ODP_PKTOUT_MODE_SEND = 0,
/** Packet output through traffic manager API */
- ODP_PKTOUT_MODE_TM
+ ODP_PKTOUT_MODE_TM,
+ /** Application will never send to this interface */
+ ODP_PKTOUT_MODE_DISABLED
} odp_pktio_output_mode_t;
/**
@@ -88,9 +103,14 @@ typedef struct odp_pktio_param_t {
* errno set. Use odp_pktio_lookup() to obtain a handle to an already open
* device. Packet IO parameters provide interface level configuration options.
*
+ * This call does not activate packet receive and transmit on the interface.
+ * The interface is activated with a call to odp_pktio_start(). If not
+ * specified otherwise, any interface level configuration must not be changed
+ * when the interface is active (between start and stop calls).
+ *
* @param dev Packet IO device name
- * @param pool Default pool from which to allocate buffers for storing packets
- * received over this packet IO
+ * @param pool Default pool from which to allocate storage for packets
+ * received over this interface, must be of type ODP_POOL_PACKET
* @param param Packet IO parameters
*
* @return Packet IO handle
@@ -106,6 +126,8 @@ typedef struct odp_pktio_param_t {
* assigned the packet to a specific CoS. The default pool specified
* here is applicable only for those packets that are not assigned to a
* more specific CoS.
+ *
+ * @see odp_pktio_start(), odp_pktio_stop(), odp_pktio_close()
*/
odp_pktio_t odp_pktio_open(const char *dev, odp_pool_t pool,
const odp_pktio_param_t *param);
@@ -113,30 +135,51 @@ odp_pktio_t odp_pktio_open(const char *dev, odp_pool_t pool,
/**
* Start packet receive and transmit
*
+ * Activate packet receive and transmit on a previously opened or stopped
+ * interface. The interface can be stopped with a call to odp_pktio_stop().
+ *
* @param pktio Packet IO handle
*
* @retval 0 on success
* @retval <0 on failure
+ *
+ * @see odp_pktio_open(), odp_pktio_stop()
*/
int odp_pktio_start(odp_pktio_t pktio);
/**
* Stop packet receive and transmit
*
+ * Stop packet receive and transmit on a previously started interface. New
+ * packets are not received from or transmitted to the network. Packets already
+ * received from the network may be still available from interface and
+ * application can receive those normally. New packets may not be accepted for
+ * transmit. Packets already stored for transmit are not freed. A following
+ * odp_packet_start() call restarts packet receive and transmit.
+ *
* @param pktio Packet IO handle
*
* @retval 0 on success
* @retval <0 on failure
+ *
+ * @see odp_pktio_start(), odp_pktio_close()
*/
int odp_pktio_stop(odp_pktio_t pktio);
/**
* Close a packet IO interface
*
+ * Close a stopped packet IO interface. This call frees all remaining packets
+ * stored in pktio receive and transmit side buffers. The pktio is destroyed
+ * and the handle must not be used for other calls. After a successful call,
+ * the same pktio device can be opened again with a odp_packet_open() call.
+ *
* @param pktio Packet IO handle
*
* @retval 0 on success
* @retval <0 on failure
+ *
+ * @see odp_pktio_stop(), odp_pktio_open()
*/
int odp_pktio_close(odp_pktio_t pktio);
@@ -334,6 +377,15 @@ int odp_pktio_headroom_set(odp_pktio_t pktio, uint32_t headroom);
uint64_t odp_pktio_to_u64(odp_pktio_t pktio);
/**
+ * Intiailize pktio params
+ *
+ * Initialize an odp_pktio_param_t to its default values for all fields
+ *
+ * @param param Address of the odp_pktio_param_t to be initialized
+ */
+void odp_pktio_param_init(odp_pktio_param_t *param);
+
+/**
* @}
*/
diff --git a/include/odp/api/queue.h b/include/odp/api/queue.h
index ce04eb4a2..df2a4c94d 100644
--- a/include/odp/api/queue.h
+++ b/include/odp/api/queue.h
@@ -245,6 +245,19 @@ odp_schedule_prio_t odp_queue_sched_prio(odp_queue_t queue);
odp_schedule_group_t odp_queue_sched_group(odp_queue_t queue);
/**
+ * Queue lock count
+ *
+ * Return number of ordered locks associated with this ordered queue.
+ * Lock count is defined in odp_schedule_param_t.
+ *
+ * @param queue Queue handle
+ *
+ * @return Number of ordered locks associated with this ordered queue
+ * @retval <0 Specified queue is not ordered
+ */
+int odp_queue_lock_count(odp_queue_t queue);
+
+/**
* Get printable value for an odp_queue_t
*
* @param hdl odp_queue_t handle to be printed
diff --git a/include/odp/api/schedule.h b/include/odp/api/schedule.h
index b0b7425ba..55191f951 100644
--- a/include/odp/api/schedule.h
+++ b/include/odp/api/schedule.h
@@ -31,11 +31,6 @@ extern "C" {
*/
/**
- * @typedef odp_schedule_order_lock_t
- * Scheduler ordered context lock
- */
-
-/**
* @def ODP_SCHED_WAIT
* Wait infinitely
*/
@@ -297,35 +292,33 @@ int odp_schedule_group_thrmask(odp_schedule_group_t group,
odp_thrmask_t *thrmask);
/**
- * Initialize ordered context lock
- *
- * Initialize an ordered queue context lock. The lock can be associated only
- * with ordered queues and used only within an ordered synchronization context.
- *
- * @param lock Ordered context lock
- * @param queue Ordered queue
- *
- * @retval 0 on success
- * @retval <0 on failure
- *
- * @note At present a thread may only use a single ordered lock. Attempts to
- * use multiple ordered locks within an order context are undefined.
- */
-int odp_schedule_order_lock_init(odp_schedule_order_lock_t *lock,
- odp_queue_t queue);
-
-/**
* Acquire ordered context lock
*
- * This call is valid only when holding an ordered synchronization context. The
- * lock is used to protect a critical section that is executed within an
- * ordered context. Threads enter the critical section in the order determined
- * by the context (source queue). Lock ordering is automatically skipped for
- * threads that release the context instead of calling the lock.
- *
- * @param lock Ordered context lock
+ * This call is valid only when holding an ordered synchronization context.
+ * Ordered locks are used to protect critical sections that are executed
+ * within an ordered context. Threads enter the critical section in the order
+ * determined by the context (source queue). Lock ordering is automatically
+ * skipped for threads that release the context instead of using the lock.
+ *
+ * The number of ordered locks available is set by the lock_count parameter of
+ * the schedule parameters passed to odp_queue_create(), which must be less
+ * than or equal to the ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE configuration
+ * option. If this routine is called outside of an ordered context or with a
+ * lock_index that exceeds the number of available ordered locks in this
+ * context results are undefined. The number of ordered locks associated with
+ * a given ordered queue may be queried by the odp_queue_lock_count() API.
+ *
+ * Each ordered lock may be used only once per ordered context. If events
+ * are to be processed with multiple ordered critical sections, each should
+ * be protected by its own ordered lock. This promotes maximum parallelism by
+ * allowing order to maintained on a more granular basis. If an ordered lock
+ * is used multiple times in the same ordered context results are undefined.
+ *
+ * @param lock_index Index of the ordered lock in the current context to be
+ * acquired. Must be in the range 0..odp_queue_lock_count()
+ * - 1
*/
-void odp_schedule_order_lock(odp_schedule_order_lock_t *lock);
+void odp_schedule_order_lock(unsigned lock_index);
/**
* Release ordered context lock
@@ -333,9 +326,12 @@ void odp_schedule_order_lock(odp_schedule_order_lock_t *lock);
* This call is valid only when holding an ordered synchronization context.
* Release a previously locked ordered context lock.
*
- * @param lock Ordered context lock
+ * @param lock_index Index of the ordered lock in the current context to be
+ * released. Results are undefined if the caller does not
+ * hold this lock. Must be in the range
+ * 0..odp_queue_lock_count() - 1
*/
-void odp_schedule_order_unlock(odp_schedule_order_lock_t *lock);
+void odp_schedule_order_unlock(unsigned lock_index);
/**
* @}
diff --git a/include/odp/api/schedule_types.h b/include/odp/api/schedule_types.h
index f7526ee0d..d4eda7838 100644
--- a/include/odp/api/schedule_types.h
+++ b/include/odp/api/schedule_types.h
@@ -131,6 +131,8 @@ typedef struct odp_schedule_param_t {
odp_schedule_sync_t sync;
/** Thread group */
odp_schedule_group_t group;
+ /** Ordered lock count for this queue */
+ unsigned lock_count;
} odp_schedule_param_t;
/**
diff --git a/include/odp/api/thread.h b/include/odp/api/thread.h
index 89eae2bc5..3029342c2 100644
--- a/include/odp/api/thread.h
+++ b/include/odp/api/thread.h
@@ -54,7 +54,7 @@ typedef enum odp_thread_type_e {
* Get thread identifier
*
* Returns the thread identifier of the current thread. Thread ids range from 0
- * to ODP_CONFIG_MAX_THREADS-1. The ODP thread id is assinged by
+ * to odp_thread_count_max() - 1. The ODP thread id is assigned by
* odp_init_local() and freed by odp_term_local(). Thread id is unique within
* the ODP instance.
*
@@ -68,13 +68,23 @@ int odp_thread_id(void);
* Returns the current ODP thread count. This is the number of active threads
* running the ODP instance. Each odp_init_local() call increments and each
* odp_term_local() call decrements the count. The count is always between 1 and
- * ODP_CONFIG_MAX_THREADS.
+ * odp_thread_count_max().
*
* @return Current thread count
*/
int odp_thread_count(void);
/**
+ * Maximum thread count
+ *
+ * Returns the maximum thread count, which is a constant value and set in
+ * ODP initialization phase.
+ *
+ * @return Maximum thread count
+ */
+int odp_thread_count_max(void);
+
+/**
* Thread type
*
* Returns the thread type of the current thread.
diff --git a/include/odp/api/version.h b/include/odp/api/version.h
index 1518201e7..c976f160f 100644
--- a/include/odp/api/version.h
+++ b/include/odp/api/version.h
@@ -37,7 +37,7 @@ extern "C" {
* Introduction of major new features or changes. APIs with different major
* versions are likely not backward compatible.
*/
-#define ODP_VERSION_API_MAJOR 3
+#define ODP_VERSION_API_MAJOR 4
/**
* ODP API minor version
diff --git a/m4/ax_valgrind_check.m4 b/m4/ax_valgrind_check.m4
index ff05f5640..ccee86b2e 100644
--- a/m4/ax_valgrind_check.m4
+++ b/m4/ax_valgrind_check.m4
@@ -59,7 +59,6 @@
AC_DEFUN([AX_VALGRIND_CHECK],[
dnl Check for --enable-valgrind
- AC_MSG_CHECKING([whether to enable Valgrind on the unit tests])
AC_ARG_ENABLE([valgrind],
[AS_HELP_STRING([--enable-valgrind], [Whether to enable Valgrind on the unit tests])],
[enable_valgrind=$enableval],[enable_valgrind=])
@@ -74,7 +73,6 @@ AC_DEFUN([AX_VALGRIND_CHECK],[
AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"])
AC_SUBST([VALGRIND_ENABLED],[$enable_valgrind])
- AC_MSG_RESULT([$enable_valgrind])
# Check for Valgrind tools we care about.
m4_define([valgrind_tool_list],[[memcheck], [helgrind], [drd], [exp-sgcheck]])
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 4c7973087..01359478f 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -120,6 +120,7 @@ noinst_HEADERS = \
${srcdir}/include/odp_classification_datamodel.h \
${srcdir}/include/odp_classification_inlines.h \
${srcdir}/include/odp_classification_internal.h \
+ ${srcdir}/include/odp_config_internal.h \
${srcdir}/include/odp_crypto_internal.h \
${srcdir}/include/odp_debug_internal.h \
${srcdir}/include/odp_forward_typedefs_internal.h \
@@ -127,18 +128,21 @@ noinst_HEADERS = \
${srcdir}/include/odp_packet_internal.h \
${srcdir}/include/odp_packet_io_internal.h \
${srcdir}/include/odp_packet_io_queue.h \
+ ${srcdir}/include/odp_packet_netmap.h \
${srcdir}/include/odp_packet_socket.h \
${srcdir}/include/odp_pool_internal.h \
${srcdir}/include/odp_queue_internal.h \
${srcdir}/include/odp_schedule_internal.h \
${srcdir}/include/odp_spin_internal.h \
${srcdir}/include/odp_timer_internal.h \
+ ${srcdir}/include/odp_cpu_internal.h \
${srcdir}/Makefile.inc
__LIB__libodp_la_SOURCES = \
odp_barrier.c \
odp_buffer.c \
odp_classification.c \
+ odp_cpu.c \
odp_cpumask.c \
odp_cpumask_task.c \
odp_crypto.c \
@@ -151,6 +155,7 @@ __LIB__libodp_la_SOURCES = \
odp_packet_io.c \
pktio/io_ops.c \
pktio/loop.c \
+ pktio/netmap.c \
pktio/socket.c \
pktio/socket_mmap.c \
odp_pool.c \
@@ -167,9 +172,13 @@ __LIB__libodp_la_SOURCES = \
odp_timer.c \
odp_version.c \
odp_weak.c \
- arch/@ARCH@/odp_time_cycles.c
+ arch/@ARCH@/odp_cpu_cycles.c
EXTRA_DIST = \
- arch/linux/odp_time_cycles.c \
- arch/mips64/odp_time_cycles.c \
- arch/x86/odp_time_cycles.c
+ arch/linux/odp_cpu_cycles.c \
+ arch/mips64/odp_cpu_cycles.c \
+ arch/x86/odp_cpu_cycles.c
+
+if HAVE_PCAP
+__LIB__libodp_la_SOURCES += pktio/pcap.c
+endif
diff --git a/platform/linux-generic/arch/linux/odp_time_cycles.c b/platform/linux-generic/arch/linux/odp_cpu_cycles.c
index 4dc0764ed..37a4d94ff 100644
--- a/platform/linux-generic/arch/linux/odp_time_cycles.c
+++ b/platform/linux-generic/arch/linux/odp_cpu_cycles.c
@@ -9,14 +9,14 @@
#include <stdlib.h>
#include <time.h>
-#include <odp/time.h>
+#include <odp/cpu.h>
#include <odp/hints.h>
#include <odp/system_info.h>
#include <odp_debug_internal.h>
#define GIGA 1000000000
-uint64_t odp_time_cycles(void)
+uint64_t odp_cpu_cycles(void)
{
struct timespec time;
uint64_t sec, ns, hz, cycles;
@@ -28,11 +28,21 @@ uint64_t odp_time_cycles(void)
ODP_ABORT("clock_gettime failed\n");
hz = odp_sys_cpu_hz();
- sec = (uint64_t) time.tv_sec;
- ns = (uint64_t) time.tv_nsec;
+ sec = (uint64_t)time.tv_sec;
+ ns = (uint64_t)time.tv_nsec;
cycles = sec * hz;
cycles += (ns * hz) / GIGA;
return cycles;
}
+
+uint64_t odp_cpu_cycles_max(void)
+{
+ return UINT64_MAX;
+}
+
+uint64_t odp_cpu_cycles_resolution(void)
+{
+ return 1;
+}
diff --git a/platform/linux-generic/arch/mips64/odp_time_cycles.c b/platform/linux-generic/arch/mips64/odp_cpu_cycles.c
index 4fb790b19..a20a31325 100644
--- a/platform/linux-generic/arch/mips64/odp_time_cycles.c
+++ b/platform/linux-generic/arch/mips64/odp_cpu_cycles.c
@@ -4,11 +4,11 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <odp/time.h>
+#include <odp/cpu.h>
#include <odp/hints.h>
#include <odp/system_info.h>
-uint64_t odp_time_cycles(void)
+uint64_t odp_cpu_cycles(void)
{
#define CVMX_TMP_STR(x) CVMX_TMP_STR2(x)
#define CVMX_TMP_STR2(x) #x
@@ -19,3 +19,13 @@ uint64_t odp_time_cycles(void)
return cycle;
}
+
+uint64_t odp_cpu_cycles_max(void)
+{
+ return UINT64_MAX;
+}
+
+uint64_t odp_cpu_cycles_resolution(void)
+{
+ return 1;
+}
diff --git a/platform/linux-generic/arch/x86/odp_time_cycles.c b/platform/linux-generic/arch/x86/odp_cpu_cycles.c
index a11156184..1c5c0ec7f 100644
--- a/platform/linux-generic/arch/x86/odp_time_cycles.c
+++ b/platform/linux-generic/arch/x86/odp_cpu_cycles.c
@@ -3,9 +3,9 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#include <odp/time.h>
+#include <odp/cpu.h>
-uint64_t odp_time_cycles(void)
+uint64_t odp_cpu_cycles(void)
{
union {
uint64_t tsc_64;
@@ -21,3 +21,13 @@ uint64_t odp_time_cycles(void)
return tsc.tsc_64;
}
+
+uint64_t odp_cpu_cycles_max(void)
+{
+ return UINT64_MAX;
+}
+
+uint64_t odp_cpu_cycles_resolution(void)
+{
+ return 1;
+}
diff --git a/platform/linux-generic/include/odp/config.h b/platform/linux-generic/include/odp/config.h
index 6fecd3891..ee23df35a 100644
--- a/platform/linux-generic/include/odp/config.h
+++ b/platform/linux-generic/include/odp/config.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, Linaro Limited
+/* Copyright (c) 2015, Linaro Limited
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -17,8 +17,182 @@
extern "C" {
#endif
+/** @ingroup odp_config ODP CONFIG
+ * Platform-specific configuration limits
+ * @{
+ */
+
+/**
+ * Maximum number of pools
+ */
+#define ODP_CONFIG_POOLS 16
+static inline int odp_config_pools(void)
+{
+ return ODP_CONFIG_POOLS;
+}
+
+/**
+ * Maximum number of queues
+ */
+#define ODP_CONFIG_QUEUES 1024
+static inline int odp_config_queues(void)
+{
+ return ODP_CONFIG_QUEUES;
+}
+
+/**
+ * Number of ordered locks per queue
+ */
+#define ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE 2
+static inline int odp_config_max_ordered_locks_per_queue(void)
+{
+ return ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE;
+}
+
+/**
+ * Number of scheduling priorities
+ */
+#define ODP_CONFIG_SCHED_PRIOS 8
+static inline int odp_config_sched_prios(void)
+{
+ return ODP_CONFIG_SCHED_PRIOS;
+}
+
+/**
+ * Number of scheduling groups
+ */
+#define ODP_CONFIG_SCHED_GRPS 16
+static inline int odp_config_sched_grps(void)
+{
+ return ODP_CONFIG_SCHED_GRPS;
+}
+
+/**
+ * Maximum number of packet IO resources
+ */
+#define ODP_CONFIG_PKTIO_ENTRIES 64
+static inline int odp_config_pktio_entries(void)
+{
+ return ODP_CONFIG_PKTIO_ENTRIES;
+}
+
+/**
+ * Minimum buffer alignment
+ *
+ * This defines the minimum supported buffer alignment. Requests for values
+ * below this will be rounded up to this value.
+ */
+#define ODP_CONFIG_BUFFER_ALIGN_MIN 16
+static inline int odp_config_buffer_align_min(void)
+{
+ return ODP_CONFIG_BUFFER_ALIGN_MIN;
+}
+
+/**
+ * Maximum buffer alignment
+ *
+ * This defines the maximum supported buffer alignment. Requests for values
+ * above this will fail.
+ */
+#define ODP_CONFIG_BUFFER_ALIGN_MAX (4 * 1024)
+static inline int odp_config_buffer_align_max(void)
+{
+ return ODP_CONFIG_BUFFER_ALIGN_MAX;
+}
+
+/**
+ * Default packet headroom
+ *
+ * This defines the minimum number of headroom bytes that newly created packets
+ * have by default. The default apply to both ODP packet input and user
+ * allocated packets. Implementations may reserve a larger than minimum headroom
+ * size e.g. due to HW or a protocol specific alignment requirement.
+ *
+ * @internal In linux-generic implementation:
+ * The default value (66) allows a 1500-byte packet to be received into a single
+ * segment with Ethernet offset alignment and room for some header expansion.
+ */
+#define ODP_CONFIG_PACKET_HEADROOM 66
+static inline int odp_config_packet_headroom(void)
+{
+ return ODP_CONFIG_PACKET_HEADROOM;
+}
+
+/**
+ * Default packet tailroom
+ *
+ * This defines the minimum number of tailroom bytes that newly created packets
+ * have by default. The default apply to both ODP packet input and user
+ * allocated packets. Implementations are free to add to this as desired
+ * without restriction. Note that most implementations will automatically
+ * consider any unused portion of the last segment of a packet as tailroom
+ */
+#define ODP_CONFIG_PACKET_TAILROOM 0
+static inline int odp_config_packet_tailroom(void)
+{
+ return ODP_CONFIG_PACKET_TAILROOM;
+}
+
+/**
+ * Minimum packet segment length
+ *
+ * This defines the minimum packet segment buffer length in bytes. The user
+ * defined segment length (seg_len in odp_pool_param_t) will be rounded up into
+ * this value.
+ */
+#define ODP_CONFIG_PACKET_SEG_LEN_MIN 1598
+static inline int odp_config_packet_seg_len_min(void)
+{
+ return ODP_CONFIG_PACKET_SEG_LEN_MIN;
+}
+
+/**
+ * Maximum packet segment length
+ *
+ * This defines the maximum packet segment buffer length in bytes. The user
+ * defined segment length (seg_len in odp_pool_param_t) must not be larger than
+ * this.
+ */
+#define ODP_CONFIG_PACKET_SEG_LEN_MAX (64 * 1024)
+static inline int odp_config_packet_seg_len_max(void)
+{
+ return ODP_CONFIG_PACKET_SEG_LEN_MAX;
+}
+
+/**
+ * Maximum packet buffer length
+ *
+ * This defines the maximum number of bytes that can be stored into a packet
+ * (maximum return value of odp_packet_buf_len(void)). Attempts to allocate
+ * (including default head- and tailrooms) or extend packets to sizes larger
+ * than this limit will fail.
+ *
+ * @internal In linux-generic implementation:
+ * - The value MUST be an integral number of segments
+ * - The value SHOULD be large enough to accommodate jumbo packets (9K)
+ */
+#define ODP_CONFIG_PACKET_BUF_LEN_MAX (ODP_CONFIG_PACKET_SEG_LEN_MIN * 6)
+static inline int odp_config_packet_buf_len_max(void)
+{
+ return ODP_CONFIG_PACKET_BUF_LEN_MAX;
+}
+
+/** Maximum number of shared memory blocks.
+ *
+ * This the the number of separate SHM areas that can be reserved concurrently
+ */
+#define ODP_CONFIG_SHM_BLOCKS (ODP_CONFIG_POOLS + 48)
+static inline int odp_config_shm_blocks(void)
+{
+ return ODP_CONFIG_SHM_BLOCKS;
+}
+
#include <odp/api/config.h>
+/**
+ * @}
+ */
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp/debug.h b/platform/linux-generic/include/odp/debug.h
index 987ced2c1..a2e59bf7d 100644
--- a/platform/linux-generic/include/odp/debug.h
+++ b/platform/linux-generic/include/odp/debug.h
@@ -17,14 +17,6 @@
extern "C" {
#endif
-/** @ingroup odp_ver_abt_log_dbg
- * @{
- */
-
-/**
- * @}
- */
-
#include <odp/api/debug.h>
#ifdef __cplusplus
diff --git a/platform/linux-generic/include/odp/plat/cpumask_types.h b/platform/linux-generic/include/odp/plat/cpumask_types.h
index 6fba83213..8923f3622 100644
--- a/platform/linux-generic/include/odp/plat/cpumask_types.h
+++ b/platform/linux-generic/include/odp/plat/cpumask_types.h
@@ -24,10 +24,9 @@ extern "C" {
#include <odp/std_types.h>
-/**
- * Minimum size of output buffer for odp_cpumask_to_str()
- */
-#define ODP_CPUMASK_STR_SIZE ((ODP_CONFIG_MAX_THREADS + 3) / 4 + 3)
+#define ODP_CPUMASK_SIZE 1024
+
+#define ODP_CPUMASK_STR_SIZE ((ODP_CPUMASK_SIZE + 3) / 4 + 3)
/**
* CPU mask
diff --git a/platform/linux-generic/include/odp/plat/schedule_types.h b/platform/linux-generic/include/odp/plat/schedule_types.h
index c48b6520b..21fcbb84c 100644
--- a/platform/linux-generic/include/odp/plat/schedule_types.h
+++ b/platform/linux-generic/include/odp/plat/schedule_types.h
@@ -22,8 +22,8 @@ extern "C" {
* @{
*/
-#define ODP_SCHED_WAIT 0
-#define ODP_SCHED_NO_WAIT 1
+#define ODP_SCHED_WAIT UINT64_MAX
+#define ODP_SCHED_NO_WAIT 0
typedef int odp_schedule_prio_t;
@@ -51,8 +51,6 @@ typedef int odp_schedule_group_t;
#define ODP_SCHED_GROUP_NAME_LEN 32
-typedef int odp_schedule_order_lock_t;
-
/**
* @}
*/
diff --git a/platform/linux-generic/include/odp_buffer_internal.h b/platform/linux-generic/include/odp_buffer_internal.h
index 4cacca10b..7f3fa1c08 100644
--- a/platform/linux-generic/include/odp_buffer_internal.h
+++ b/platform/linux-generic/include/odp_buffer_internal.h
@@ -30,6 +30,7 @@ extern "C" {
#include <odp/thread.h>
#include <odp/event.h>
#include <odp_forward_typedefs_internal.h>
+#include <odp_config_internal.h>
#define ODP_BITSIZE(x) \
((x) <= 2 ? 1 : \
@@ -137,13 +138,13 @@ struct odp_buffer_hdr_t {
queue_entry_t *origin_qe; /* ordered queue origin */
union {
queue_entry_t *target_qe; /* ordered queue target */
- uint64_t sync; /* for ordered synchronization */
+ uint64_t sync[ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE];
};
};
/** @internal Compile time assert that the
* allocator field can handle any allocator id*/
-_ODP_STATIC_ASSERT(INT16_MAX >= ODP_CONFIG_MAX_THREADS,
+_ODP_STATIC_ASSERT(INT16_MAX >= _ODP_INTERNAL_MAX_THREADS,
"ODP_BUFFER_HDR_T__ALLOCATOR__SIZE_ERROR");
typedef struct odp_buffer_hdr_stride {
diff --git a/platform/linux-generic/include/odp_classification_datamodel.h b/platform/linux-generic/include/odp_classification_datamodel.h
index 9da54c725..4358fcaed 100644
--- a/platform/linux-generic/include/odp_classification_datamodel.h
+++ b/platform/linux-generic/include/odp_classification_datamodel.h
@@ -57,6 +57,8 @@ typedef struct pmr_term_value {
odp_pmr_term_e term; /* PMR Term */
uint64_t val; /**< Value to be matched */
uint64_t mask; /**< Masked set of bits to be matched */
+ uint32_t offset; /**< Offset if term == ODP_PMR_CUSTOM_FRAME */
+ uint32_t val_sz; /**< Size of the value to be matched */
} pmr_term_value_t;
/*
@@ -70,6 +72,7 @@ struct cos_s {
uint32_t valid; /* validity Flag */
odp_drop_e drop_policy; /* Associated Drop Policy */
odp_queue_group_t queue_group; /* Associated Queue Group */
+ odp_queue_t queue_id; /* Associated Queue handle */
odp_cos_flow_set_t flow_set; /* Assigned Flow Set */
char name[ODP_COS_NAME_LEN]; /* name */
size_t headroom; /* Headroom for this CoS */
diff --git a/platform/linux-generic/include/odp_classification_inlines.h b/platform/linux-generic/include/odp_classification_inlines.h
index a093211c5..7f13530c0 100644
--- a/platform/linux-generic/include/odp_classification_inlines.h
+++ b/platform/linux-generic/include/odp_classification_inlines.h
@@ -223,6 +223,27 @@ static inline int verify_pmr_ld_vni(uint8_t *pkt_addr ODP_UNUSED,
ODP_UNIMPLEMENTED();
return 0;
}
+
+static inline int verify_pmr_custom_frame(uint8_t *pkt_addr,
+ odp_packet_hdr_t *pkt_hdr,
+ pmr_term_value_t *term_value)
+{
+ uint64_t val = 0;
+ uint32_t offset = term_value->offset;
+ uint32_t val_sz = term_value->val_sz;
+
+ ODP_ASSERT(val_sz <= ODP_PMR_TERM_BYTES_MAX);
+
+ if (pkt_hdr->frame_len <= offset + val_sz)
+ return 0;
+
+ memcpy(&val, pkt_addr + offset, val_sz);
+ if (term_value->val == (val & term_value->mask))
+ return 1;
+
+ return 0;
+}
+
static inline int verify_pmr_eth_type_0(uint8_t *pkt_addr ODP_UNUSED,
odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
pmr_term_value_t *term_value ODP_UNUSED)
diff --git a/platform/linux-generic/include/odp_config_internal.h b/platform/linux-generic/include/odp_config_internal.h
new file mode 100644
index 000000000..4f20ff8e0
--- /dev/null
+++ b/platform/linux-generic/include/odp_config_internal.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * Linux-generic platform internal configuration
+ */
+
+#ifndef ODP_CONFIG_INTERNAL_H_
+#define ODP_CONFIG_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Maximum number of threads
+ */
+#define _ODP_INTERNAL_MAX_THREADS 128
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp_cpu_internal.h b/platform/linux-generic/include/odp_cpu_internal.h
new file mode 100644
index 000000000..5eeabefec
--- /dev/null
+++ b/platform/linux-generic/include/odp_cpu_internal.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_CPU_INTERNAL_H_
+#define ODP_CPU_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/cpu.h>
+
+static inline
+uint64_t _odp_cpu_cycles_diff(uint64_t c1, uint64_t c2)
+{
+ if (odp_likely(c2 >= c1))
+ return c2 - c1;
+
+ return c2 + (odp_cpu_cycles_max() - c1) + 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h
index 6f0050f69..010b82f1f 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -52,6 +52,7 @@ int odp_shm_term_global(void);
int odp_shm_init_local(void);
int odp_pool_init_global(void);
+int odp_pool_init_local(void);
int odp_pool_term_global(void);
int odp_pool_term_local(void);
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
index 8c4149125..6f1521ca3 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -36,7 +36,8 @@ typedef union {
uint32_t all;
struct {
- uint32_t unparsed:1; /**< Set to inticate parse needed */
+ uint32_t parsed_l2:1; /**< L2 parsed */
+ uint32_t parsed_all:1;/**< Parsing complete */
uint32_t l2:1; /**< known L2 protocol present */
uint32_t l3:1; /**< known L3 protocol present */
@@ -137,6 +138,9 @@ typedef struct {
odp_pktio_t input;
+ uint32_t has_hash:1; /**< Flow hash present */
+ uint32_t flow_hash; /**< Flow hash value */
+
odp_crypto_generic_op_result_t op_result; /**< Result for crypto */
} odp_packet_hdr_t;
@@ -152,43 +156,6 @@ static inline odp_packet_hdr_t *odp_packet_hdr(odp_packet_t pkt)
return (odp_packet_hdr_t *)odp_buf_to_hdr((odp_buffer_t)pkt);
}
-/**
- * Initialize packet buffer
- */
-static inline void packet_init(pool_entry_t *pool,
- odp_packet_hdr_t *pkt_hdr,
- size_t size)
-{
- /*
- * Reset parser metadata. Note that we clear via memset to make
- * this routine indepenent of any additional adds to packet metadata.
- */
- const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr);
- uint8_t *start;
- size_t len;
-
- start = (uint8_t *)pkt_hdr + start_offset;
- len = sizeof(odp_packet_hdr_t) - start_offset;
- memset(start, 0, len);
-
- /* Set metadata items that initialize to non-zero values */
- pkt_hdr->l2_offset = ODP_PACKET_OFFSET_INVALID;
- pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
- pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
- pkt_hdr->payload_offset = ODP_PACKET_OFFSET_INVALID;
-
- /*
- * Packet headroom is set from the pool's headroom
- * Packet tailroom is rounded up to fill the last
- * segment occupied by the allocated length.
- */
- pkt_hdr->frame_len = size;
- pkt_hdr->headroom = pool->s.headroom;
- pkt_hdr->tailroom =
- (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
- (pool->s.headroom + size);
-}
-
static inline void copy_packet_parser_metadata(odp_packet_hdr_t *src_hdr,
odp_packet_hdr_t *dst_hdr)
{
@@ -250,12 +217,14 @@ static inline void packet_set_len(odp_packet_t pkt, uint32_t len)
odp_packet_hdr(pkt)->frame_len = len;
}
-#define ODP_PACKET_UNPARSED ~0
+static inline int packet_parse_l2_not_done(odp_packet_hdr_t *pkt_hdr)
+{
+ return !pkt_hdr->input_flags.parsed_l2;
+}
-static inline void _odp_packet_reset_parse(odp_packet_t pkt)
+static inline int packet_parse_not_complete(odp_packet_hdr_t *pkt_hdr)
{
- odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
- pkt_hdr->input_flags.all = ODP_PACKET_UNPARSED;
+ return !pkt_hdr->input_flags.parsed_all;
}
/* Forward declarations */
@@ -265,9 +234,16 @@ int _odp_packet_copy_to_packet(odp_packet_t srcpkt, uint32_t srcoffset,
void _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt);
-odp_packet_t _odp_packet_alloc(odp_pool_t pool_hdl);
+odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse);
+
+/* Fill in parser metadata for L2 */
+void packet_parse_l2(odp_packet_hdr_t *pkt_hdr);
+
+/* Perform full packet parse */
+int packet_parse_full(odp_packet_hdr_t *pkt_hdr);
-int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr);
+/* Reset parser metadata for a new parse */
+void packet_parse_reset(odp_packet_t pkt);
/* Convert a packet handle to a buffer handle */
odp_buffer_t _odp_packet_to_buffer(odp_packet_t pkt);
diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h
index a21c6838e..1a1118c83 100644
--- a/platform/linux-generic/include/odp_packet_io_internal.h
+++ b/platform/linux-generic/include/odp_packet_io_internal.h
@@ -19,7 +19,9 @@ extern "C" {
#endif
#include <odp/spinlock.h>
+#include <odp/ticketlock.h>
#include <odp_packet_socket.h>
+#include <odp_packet_netmap.h>
#include <odp_classification_datamodel.h>
#include <odp_align_internal.h>
#include <odp_debug_internal.h>
@@ -28,6 +30,14 @@ extern "C" {
#include <odp/hints.h>
#include <net/if.h>
+#define PKTIO_NAME_LEN 256
+
+/** Determine if a socket read/write error should be reported. Transient errors
+ * that simply require the caller to retry are ignored, the _send/_recv APIs
+ * are non-blocking and it is the caller's responsibility to retry if the
+ * requested number of packets were not handled. */
+#define SOCK_ERR_REPORT(e) (e != EAGAIN && e != EWOULDBLOCK && e != EINTR)
+
/* Forward declaration */
struct pktio_if_ops;
@@ -36,9 +46,24 @@ typedef struct {
odp_bool_t promisc; /**< promiscuous mode state */
} pkt_loop_t;
+#ifdef HAVE_PCAP
+typedef struct {
+ char *fname_rx; /**< name of pcap file for rx */
+ char *fname_tx; /**< name of pcap file for tx */
+ void *rx; /**< rx pcap handle */
+ void *tx; /**< tx pcap handle */
+ void *tx_dump; /**< tx pcap dumper handle */
+ odp_pool_t pool; /**< rx pool */
+ unsigned char *buf; /**< per-pktio temp buffer */
+ int loops; /**< number of times to loop rx pcap */
+ int loop_cnt; /**< number of loops completed */
+ odp_bool_t promisc; /**< promiscuous mode state */
+} pkt_pcap_t;
+#endif
+
struct pktio_entry {
const struct pktio_if_ops *ops; /**< Implementation specific methods */
- odp_spinlock_t lock; /**< entry spinlock */
+ odp_ticketlock_t lock; /**< entry ticketlock */
int taken; /**< is entry taken(1) or free(0) */
int cls_enabled; /**< is classifier enabled */
odp_pktio_t handle; /**< pktio handle */
@@ -49,13 +74,17 @@ struct pktio_entry {
pkt_sock_t pkt_sock; /**< using socket API for IO */
pkt_sock_mmap_t pkt_sock_mmap; /**< using socket mmap
* API for IO */
+ pkt_netmap_t pkt_nm; /**< using netmap API for IO */
+#ifdef HAVE_PCAP
+ pkt_pcap_t pkt_pcap; /**< Using pcap for IO */
+#endif
};
enum {
STATE_START = 0,
STATE_STOP
} state;
classifier_t cls; /**< classifier linked with this pktio*/
- char name[IF_NAMESIZE]; /**< name of pktio provided to
+ char name[PKTIO_NAME_LEN]; /**< name of pktio provided to
pktio_open() */
odp_pktio_param_t param;
};
@@ -109,11 +138,25 @@ static inline pktio_entry_t *get_pktio_entry(odp_pktio_t pktio)
return pktio_entry_ptr[pktio_to_id(pktio)];
}
+static inline int pktio_cls_enabled(pktio_entry_t *entry)
+{
+ return entry->s.cls_enabled;
+}
+
+static inline void pktio_cls_enabled_set(pktio_entry_t *entry, int ena)
+{
+ entry->s.cls_enabled = ena;
+}
+
int pktin_poll(pktio_entry_t *entry);
+extern const pktio_if_ops_t netmap_pktio_ops;
extern const pktio_if_ops_t sock_mmsg_pktio_ops;
extern const pktio_if_ops_t sock_mmap_pktio_ops;
extern const pktio_if_ops_t loopback_pktio_ops;
+#ifdef HAVE_PCAP
+extern const pktio_if_ops_t pcap_pktio_ops;
+#endif
extern const pktio_if_ops_t * const pktio_if_ops[];
#ifdef __cplusplus
diff --git a/platform/linux-generic/include/odp_packet_netmap.h b/platform/linux-generic/include/odp_packet_netmap.h
new file mode 100644
index 000000000..0577dfe20
--- /dev/null
+++ b/platform/linux-generic/include/odp_packet_netmap.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_PACKET_NETMAP_H
+#define ODP_PACKET_NETMAP_H
+
+#include <odp/pool.h>
+
+#include <linux/if_ether.h>
+
+/** Packet socket using netmap mmaped rings for both Rx and Tx */
+typedef struct {
+ odp_pool_t pool; /**< pool to alloc packets from */
+ size_t max_frame_len; /**< buf_size - sizeof(pkt_hdr) */
+ struct nm_desc *rx_desc; /**< netmap meta-data for the device */
+ struct nm_desc *tx_desc; /**< netmap meta-data for the device */
+ uint32_t if_flags; /**< interface flags */
+ int sockfd; /**< control socket */
+ unsigned char if_mac[ETH_ALEN]; /**< eth mac address */
+} pkt_netmap_t;
+
+#endif
diff --git a/platform/linux-generic/include/odp_packet_socket.h b/platform/linux-generic/include/odp_packet_socket.h
index d5427d93c..a5e0eb381 100644
--- a/platform/linux-generic/include/odp_packet_socket.h
+++ b/platform/linux-generic/include/odp_packet_socket.h
@@ -95,6 +95,11 @@ ethaddrs_equal(unsigned char mac_a[], unsigned char mac_b[])
}
/**
+ * Read the MAC address from a packet socket
+ */
+int mac_addr_get_fd(int fd, const char *name, unsigned char mac_dst[]);
+
+/**
* Read the MTU from a packet socket
*/
int mtu_get_fd(int fd, const char *name);
diff --git a/platform/linux-generic/include/odp_pool_internal.h b/platform/linux-generic/include/odp_pool_internal.h
index 136db2c21..94bf1faee 100644
--- a/platform/linux-generic/include/odp_pool_internal.h
+++ b/platform/linux-generic/include/odp_pool_internal.h
@@ -53,9 +53,14 @@ typedef struct _odp_buffer_pool_init_t {
/* Local cache for buffer alloc/free acceleration */
typedef struct local_cache_t {
- odp_buffer_hdr_t *buf_freelist; /* The local cache */
- uint64_t bufallocs; /* Local buffer alloc count */
- uint64_t buffrees; /* Local buffer free count */
+ union {
+ struct {
+ odp_buffer_hdr_t *buf_freelist; /* The local cache */
+ uint64_t bufallocs; /* Local buffer alloc count */
+ uint64_t buffrees; /* Local buffer free count */
+ };
+ uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(uint64_t))];
+ };
} local_cache_t;
/* Use ticketlock instead of spinlock */
@@ -133,6 +138,8 @@ struct pool_entry_s {
uint32_t low_wm;
uint32_t headroom;
uint32_t tailroom;
+
+ local_cache_t local_cache[_ODP_INTERNAL_MAX_THREADS] ODP_ALIGNED_CACHE;
};
typedef union pool_entry_u {
diff --git a/platform/linux-generic/include/odp_queue_internal.h b/platform/linux-generic/include/odp_queue_internal.h
index 19a0f0731..c322e6a02 100644
--- a/platform/linux-generic/include/odp_queue_internal.h
+++ b/platform/linux-generic/include/odp_queue_internal.h
@@ -83,8 +83,8 @@ struct queue_entry_s {
uint64_t order_out;
odp_buffer_hdr_t *reorder_head;
odp_buffer_hdr_t *reorder_tail;
- odp_atomic_u64_t sync_in;
- odp_atomic_u64_t sync_out;
+ odp_atomic_u64_t sync_in[ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE];
+ odp_atomic_u64_t sync_out[ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE];
};
union queue_entry_u {
@@ -109,12 +109,6 @@ int queue_pktout_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr,
int queue_pktout_enq_multi(queue_entry_t *queue,
odp_buffer_hdr_t *buf_hdr[], int num, int sustain);
-int queue_enq_dummy(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr);
-int queue_enq_multi_dummy(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
- int num);
-int queue_deq_multi_destroy(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
- int num);
-
void queue_lock(queue_entry_t *queue);
void queue_unlock(queue_entry_t *queue);
@@ -123,7 +117,7 @@ int queue_sched_atomic(odp_queue_t handle);
int release_order(queue_entry_t *origin_qe, uint64_t order,
odp_pool_t pool, int enq_called);
void get_sched_order(queue_entry_t **origin_qe, uint64_t *order);
-void get_sched_sync(queue_entry_t **origin_qe, uint64_t **sync);
+void get_sched_sync(queue_entry_t **origin_qe, uint64_t **sync, uint32_t ndx);
void sched_enq_called(void);
void sched_order_resolved(odp_buffer_hdr_t *buf_hdr);
@@ -194,12 +188,17 @@ static inline void reorder_enq(queue_entry_t *queue,
static inline void order_release(queue_entry_t *origin_qe, int count)
{
- uint64_t sync = odp_atomic_load_u64(&origin_qe->s.sync_out);
+ uint64_t sync;
+ uint32_t i;
origin_qe->s.order_out += count;
- if (sync < origin_qe->s.order_out)
- odp_atomic_fetch_add_u64(&origin_qe->s.sync_out,
- origin_qe->s.order_out - sync);
+
+ for (i = 0; i < origin_qe->s.param.sched.lock_count; i++) {
+ sync = odp_atomic_load_u64(&origin_qe->s.sync_out[i]);
+ if (sync < origin_qe->s.order_out)
+ odp_atomic_fetch_add_u64(&origin_qe->s.sync_out[i],
+ origin_qe->s.order_out - sync);
+ }
}
static inline int reorder_deq(queue_entry_t *queue,
diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4
index 965827410..df6dc640b 100644
--- a/platform/linux-generic/m4/configure.m4
+++ b/platform/linux-generic/m4/configure.m4
@@ -18,6 +18,8 @@ AC_LINK_IFELSE(
m4_include([platform/linux-generic/m4/odp_pthread.m4])
m4_include([platform/linux-generic/m4/odp_openssl.m4])
+m4_include([platform/linux-generic/m4/odp_netmap.m4])
+m4_include([platform/linux-generic/m4/odp_pcap.m4])
AC_CONFIG_FILES([platform/linux-generic/Makefile
platform/linux-generic/test/Makefile
diff --git a/platform/linux-generic/m4/odp_netmap.m4 b/platform/linux-generic/m4/odp_netmap.m4
new file mode 100644
index 000000000..72c3fab2e
--- /dev/null
+++ b/platform/linux-generic/m4/odp_netmap.m4
@@ -0,0 +1,47 @@
+##########################################################################
+# Enable netmap support
+##########################################################################
+AC_ARG_ENABLE([netmap_support],
+ [ --enable-netmap-support include netmap IO support],
+ [if test x$enableval = xyes; then
+ netmap_support=yes
+ fi])
+
+##########################################################################
+# Set optional netmap path
+##########################################################################
+AC_ARG_WITH([netmap-path],
+AC_HELP_STRING([--with-netmap-path=DIR path to netmap root directory],
+ [(or in the default path if not specified).]),
+ [NETMAP_PATH=$withval
+ AM_CPPFLAGS="$AM_CPPFLAGS -I$NETMAP_PATH/sys"
+ netmap_support=yes],[])
+
+##########################################################################
+# Save and set temporary compilation flags
+##########################################################################
+OLD_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$AM_CPPFLAGS $CPPFLAGS"
+
+##########################################################################
+# Check for netmap availability
+##########################################################################
+if test x$netmap_support = xyes
+then
+ AC_CHECK_HEADERS([net/netmap_user.h], [],
+ [AC_MSG_FAILURE(["can't find netmap header"])])
+ ODP_CFLAGS="$ODP_CFLAGS -DODP_NETMAP"
+else
+ netmap_support=no
+fi
+
+# Disable cast errors until the problem in netmap_user.h is fixed upstream
+if test x$netmap_support = xyes
+then
+ODP_CFLAGS_EXTRA="$ODP_CFLAGS_EXTRA -Wno-cast-qual"
+fi
+
+##########################################################################
+# Restore old saved variables
+##########################################################################
+CPPFLAGS=$OLD_CPPFLAGS \ No newline at end of file
diff --git a/platform/linux-generic/m4/odp_pcap.m4 b/platform/linux-generic/m4/odp_pcap.m4
new file mode 100644
index 000000000..734b79005
--- /dev/null
+++ b/platform/linux-generic/m4/odp_pcap.m4
@@ -0,0 +1,15 @@
+#########################################################################
+# Check for libpcap availability
+#########################################################################
+have_pcap=no
+AC_CHECK_HEADER(pcap/pcap.h,
+ [AC_CHECK_HEADER(pcap/bpf.h,
+ [AC_CHECK_LIB(pcap, pcap_open_offline, have_pcap=yes, [])],
+ [])],
+[])
+
+AM_CONDITIONAL([HAVE_PCAP], [test $have_pcap = yes])
+if test $have_pcap == yes; then
+ AM_CFLAGS="$AM_CFLAGS -DHAVE_PCAP"
+ LIBS="$LIBS -lpcap"
+fi
diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c
index 6c1aff4b8..1b6d5931a 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -265,7 +265,7 @@ int odp_cos_destroy(odp_cos_t cos_id)
return 0;
}
-int odp_cos_set_queue(odp_cos_t cos_id, odp_queue_t queue_id)
+int odp_cos_queue_set(odp_cos_t cos_id, odp_queue_t queue_id)
{
cos_t *cos = get_cos_entry(cos_id);
if (cos == NULL) {
@@ -275,13 +275,27 @@ int odp_cos_set_queue(odp_cos_t cos_id, odp_queue_t queue_id)
/* Locking is not required as intermittent stale
data during CoS modification is acceptable*/
cos->s.queue = queue_to_qentry(queue_id);
+ cos->s.queue_id = queue_id;
return 0;
}
-int odp_cos_set_drop(odp_cos_t cos_id, odp_drop_e drop_policy)
+odp_queue_t odp_cos_queue(odp_cos_t cos_id)
{
cos_t *cos = get_cos_entry(cos_id);
- if (cos == NULL) {
+
+ if (!cos) {
+ ODP_ERR("Invalid odp_cos_t handle");
+ return ODP_QUEUE_INVALID;
+ }
+
+ return cos->s.queue_id;
+}
+
+int odp_cos_drop_set(odp_cos_t cos_id, odp_drop_e drop_policy)
+{
+ cos_t *cos = get_cos_entry(cos_id);
+
+ if (!cos) {
ODP_ERR("Invalid odp_cos_t handle");
return -1;
}
@@ -291,10 +305,23 @@ int odp_cos_set_drop(odp_cos_t cos_id, odp_drop_e drop_policy)
return 0;
}
+odp_drop_e odp_cos_drop(odp_cos_t cos_id)
+{
+ cos_t *cos = get_cos_entry(cos_id);
+
+ if (!cos) {
+ ODP_ERR("Invalid odp_cos_t handle");
+ return -1;
+ }
+
+ return cos->s.drop_policy;
+}
+
int odp_pktio_default_cos_set(odp_pktio_t pktio_in, odp_cos_t default_cos)
{
pktio_entry_t *entry;
cos_t *cos;
+
entry = get_pktio_entry(pktio_in);
if (entry == NULL) {
ODP_ERR("Invalid odp_pktio_t handle");
@@ -307,6 +334,7 @@ int odp_pktio_default_cos_set(odp_pktio_t pktio_in, odp_cos_t default_cos)
}
entry->s.cls.default_cos = cos;
+ pktio_cls_enabled_set(entry, 1);
return 0;
}
@@ -378,6 +406,7 @@ int odp_cos_with_l2_priority(odp_pktio_t pktio_in,
l2_cos->cos[qos_table[i]] = cos;
}
}
+ pktio_cls_enabled_set(entry, 1);
UNLOCK(&l2_cos->lock);
return 0;
}
@@ -410,16 +439,29 @@ int odp_cos_with_l3_qos(odp_pktio_t pktio_in,
l3_cos->cos[qos_table[i]] = cos;
}
}
+ pktio_cls_enabled_set(entry, 1);
UNLOCK(&l3_cos->lock);
return 0;
}
-odp_pmr_t odp_pmr_create(odp_pmr_term_e term, const void *val,
- const void *mask, uint32_t val_sz)
+static void odp_pmr_create_term(pmr_term_value_t *value,
+ const odp_pmr_match_t *match)
+{
+ value->term = match->term;
+ value->offset = match->offset;
+ value->val_sz = match->val_sz;
+ value->val = 0;
+ value->mask = 0;
+ memcpy(&value->val, match->val, match->val_sz);
+ memcpy(&value->mask, match->mask, match->val_sz);
+ value->val &= value->mask;
+}
+
+odp_pmr_t odp_pmr_create(const odp_pmr_match_t *match)
{
pmr_t *pmr;
odp_pmr_t id;
- if (val_sz > ODP_PMR_TERM_BYTES_MAX) {
+ if (match->val_sz > ODP_PMR_TERM_BYTES_MAX) {
ODP_ERR("val_sz greater than max supported limit");
return ODP_PMR_INVAL;
}
@@ -430,12 +472,7 @@ odp_pmr_t odp_pmr_create(odp_pmr_term_e term, const void *val,
return ODP_PMR_INVAL;
pmr->s.num_pmr = 1;
- pmr->s.pmr_term_value[0].term = term;
- pmr->s.pmr_term_value[0].val = 0;
- pmr->s.pmr_term_value[0].mask = 0;
- memcpy(&pmr->s.pmr_term_value[0].val, val, val_sz);
- memcpy(&pmr->s.pmr_term_value[0].mask, mask, val_sz);
- pmr->s.pmr_term_value[0].val &= pmr->s.pmr_term_value[0].mask;
+ odp_pmr_create_term(&pmr->s.pmr_term_value[0], match);
UNLOCK(&pmr->s.lock);
return id;
}
@@ -488,6 +525,7 @@ int odp_pktio_pmr_cos(odp_pmr_t pmr_id,
pktio_entry->s.cls.pmr[num_pmr] = pmr;
pktio_entry->s.cls.cos[num_pmr] = cos;
pktio_entry->s.cls.num_pmr++;
+ pktio_cls_enabled_set(pktio_entry, 1);
UNLOCK(&pktio_entry->s.cls.lock);
return 0;
@@ -536,7 +574,7 @@ unsigned odp_pmr_terms_avail(void)
return count;
}
-int odp_pmr_match_set_create(int num_terms, odp_pmr_match_t *terms,
+int odp_pmr_match_set_create(int num_terms, const odp_pmr_match_t *terms,
odp_pmr_set_t *pmr_set_id)
{
pmr_t *pmr;
@@ -562,15 +600,7 @@ int odp_pmr_match_set_create(int num_terms, odp_pmr_match_t *terms,
val_sz = terms[i].val_sz;
if (val_sz > ODP_PMR_TERM_BYTES_MAX)
continue;
- pmr->s.pmr_term_value[i].term = terms[i].term;
- pmr->s.pmr_term_value[i].val = 0;
- pmr->s.pmr_term_value[i].mask = 0;
- memcpy(&pmr->s.pmr_term_value[i].val,
- terms[i].val, val_sz);
- memcpy(&pmr->s.pmr_term_value[i].mask,
- terms[i].mask, val_sz);
- pmr->s.pmr_term_value[i].val &= pmr->s
- .pmr_term_value[i].mask;
+ odp_pmr_create_term(&pmr->s.pmr_term_value[i], &terms[i]);
count++;
}
*pmr_set_id = id;
@@ -625,6 +655,7 @@ int odp_pktio_pmr_match_set_cos(odp_pmr_set_t pmr_set_id, odp_pktio_t src_pktio,
pktio_entry->s.cls.pmr[num_pmr] = pmr;
pktio_entry->s.cls.cos[num_pmr] = cos;
pktio_entry->s.cls.num_pmr++;
+ pktio_cls_enabled_set(pktio_entry, 1);
UNLOCK(&pktio_entry->s.cls.lock);
return 0;
@@ -732,6 +763,11 @@ int verify_pmr(pmr_t *pmr, uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr)
term_value))
pmr_failure = 1;
break;
+ case ODP_PMR_CUSTOM_FRAME:
+ if (!verify_pmr_custom_frame(pkt_addr, pkt_hdr,
+ term_value))
+ pmr_failure = 1;
+ break;
case ODP_PMR_INNER_HDR_OFF:
break;
}
@@ -824,8 +860,8 @@ cos_t *pktio_select_cos(pktio_entry_t *entry, uint8_t *pkt_addr,
cls = &entry->s.cls;
/* Check for lazy parse needed */
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
+ if (packet_parse_not_complete(pkt_hdr))
+ packet_parse_full(pkt_hdr);
/* Return error cos for error packet */
if (pkt_hdr->error_flags.all)
diff --git a/platform/linux-generic/odp_cpu.c b/platform/linux-generic/odp_cpu.c
new file mode 100644
index 000000000..e5ec4f08d
--- /dev/null
+++ b/platform/linux-generic/odp_cpu.c
@@ -0,0 +1,14 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/cpu.h>
+#include <odp/hints.h>
+#include <odp_cpu_internal.h>
+
+uint64_t odp_cpu_cycles_diff(uint64_t c1, uint64_t c2)
+{
+ return _odp_cpu_cycles_diff(c1, c2);
+}
diff --git a/platform/linux-generic/odp_cpumask_task.c b/platform/linux-generic/odp_cpumask_task.c
index 665e82ac9..535891c38 100644
--- a/platform/linux-generic/odp_cpumask_task.c
+++ b/platform/linux-generic/odp_cpumask_task.c
@@ -13,7 +13,7 @@
#include <odp/cpumask.h>
#include <odp_debug_internal.h>
-int odp_cpumask_def_worker(odp_cpumask_t *mask, int num)
+int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
{
int ret, cpu, i;
cpu_set_t cpuset;
@@ -43,7 +43,7 @@ int odp_cpumask_def_worker(odp_cpumask_t *mask, int num)
return cpu;
}
-int odp_cpumask_def_control(odp_cpumask_t *mask, int num ODP_UNUSED)
+int odp_cpumask_default_control(odp_cpumask_t *mask, int num ODP_UNUSED)
{
odp_cpumask_zero(mask);
/* By default all control threads on CPU 0 */
diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c
index 48d9b2036..5e19d86c6 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -138,6 +138,11 @@ int odp_init_local(odp_thread_type_t thr_type)
return -1;
}
+ if (odp_pool_init_local()) {
+ ODP_ERR("ODP pool local init failed.\n");
+ return -1;
+ }
+
if (odp_schedule_init_local()) {
ODP_ERR("ODP schedule local init failed.\n");
return -1;
diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c
index 5581cc429..1b496247f 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -25,8 +25,73 @@
*
*/
-odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len)
+static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr)
+{
+ pkt_hdr->input_flags.parsed_l2 = 1;
+ pkt_hdr->input_flags.parsed_all = 1;
+}
+
+void packet_parse_reset(odp_packet_t pkt)
{
+ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+ /* Reset parser metadata before new parse */
+ pkt_hdr->error_flags.all = 0;
+ pkt_hdr->input_flags.all = 0;
+ pkt_hdr->output_flags.all = 0;
+ pkt_hdr->l2_offset = 0;
+ pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
+ pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
+ pkt_hdr->payload_offset = ODP_PACKET_OFFSET_INVALID;
+ pkt_hdr->vlan_s_tag = 0;
+ pkt_hdr->vlan_c_tag = 0;
+ pkt_hdr->l3_protocol = 0;
+ pkt_hdr->l4_protocol = 0;
+}
+
+/**
+ * Initialize packet
+ */
+static void packet_init(pool_entry_t *pool, odp_packet_hdr_t *pkt_hdr,
+ size_t size, int parse)
+{
+ /*
+ * Reset parser metadata. Note that we clear via memset to make
+ * this routine indepenent of any additional adds to packet metadata.
+ */
+ const size_t start_offset = ODP_FIELD_SIZEOF(odp_packet_hdr_t, buf_hdr);
+ uint8_t *start;
+ size_t len;
+
+ start = (uint8_t *)pkt_hdr + start_offset;
+ len = sizeof(odp_packet_hdr_t) - start_offset;
+ memset(start, 0, len);
+
+ /* Set metadata items that initialize to non-zero values */
+ pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
+ pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
+ pkt_hdr->payload_offset = ODP_PACKET_OFFSET_INVALID;
+
+ /* Disable lazy parsing on user allocated packets */
+ if (!parse)
+ packet_parse_disable(pkt_hdr);
+
+ /*
+ * Packet headroom is set from the pool's headroom
+ * Packet tailroom is rounded up to fill the last
+ * segment occupied by the allocated length.
+ */
+ pkt_hdr->frame_len = size;
+ pkt_hdr->headroom = pool->s.headroom;
+ pkt_hdr->tailroom =
+ (pool->s.seg_size * pkt_hdr->buf_hdr.segcount) -
+ (pool->s.headroom + size);
+}
+
+odp_packet_t packet_alloc(odp_pool_t pool_hdl, uint32_t len, int parse)
+{
+ odp_packet_t pkt;
+ odp_packet_hdr_t *pkt_hdr;
pool_entry_t *pool = odp_pool_to_entry(pool_hdl);
if (pool->s.params.type != ODP_POOL_PACKET)
@@ -34,17 +99,32 @@ odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len)
/* Handle special case for zero-length packets */
if (len == 0) {
- odp_packet_t pkt =
- (odp_packet_t)buffer_alloc(pool_hdl,
- pool->s.params.buf.size);
- if (pkt != ODP_PACKET_INVALID)
- pull_tail(odp_packet_hdr(pkt),
- pool->s.params.buf.size);
-
- return pkt;
+ len = pool->s.params.buf.size;
+
+ pkt = (odp_packet_t)buffer_alloc(pool_hdl, len);
+
+ if (pkt == ODP_PACKET_INVALID)
+ return ODP_PACKET_INVALID;
+
+ pull_tail(odp_packet_hdr(pkt), len);
+
+ } else {
+ pkt = (odp_packet_t)buffer_alloc(pool_hdl, len);
+
+ if (pkt == ODP_PACKET_INVALID)
+ return ODP_PACKET_INVALID;
}
- return (odp_packet_t)buffer_alloc(pool_hdl, len);
+ pkt_hdr = odp_packet_hdr(pkt);
+
+ packet_init(pool, pkt_hdr, len, parse);
+
+ return pkt;
+}
+
+odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len)
+{
+ return packet_alloc(pool_hdl, len, 0);
}
void odp_packet_free(odp_packet_t pkt)
@@ -61,7 +141,8 @@ int odp_packet_reset(odp_packet_t pkt, uint32_t len)
if (totsize > pkt_hdr->buf_hdr.size)
return -1;
- packet_init(pool, pkt_hdr, len);
+ packet_init(pool, pkt_hdr, len, 0);
+
return 0;
}
@@ -242,16 +323,12 @@ uint32_t odp_packet_user_area_size(odp_packet_t pkt)
void *odp_packet_l2_ptr(odp_packet_t pkt, uint32_t *len)
{
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
return packet_map(pkt_hdr, pkt_hdr->l2_offset, len);
}
uint32_t odp_packet_l2_offset(odp_packet_t pkt)
{
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
return pkt_hdr->l2_offset;
}
@@ -262,8 +339,6 @@ int odp_packet_l2_offset_set(odp_packet_t pkt, uint32_t offset)
if (offset >= pkt_hdr->frame_len)
return -1;
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
pkt_hdr->l2_offset = offset;
return 0;
}
@@ -271,16 +346,16 @@ int odp_packet_l2_offset_set(odp_packet_t pkt, uint32_t offset)
void *odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len)
{
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
+ if (packet_parse_not_complete(pkt_hdr))
+ packet_parse_full(pkt_hdr);
return packet_map(pkt_hdr, pkt_hdr->l3_offset, len);
}
uint32_t odp_packet_l3_offset(odp_packet_t pkt)
{
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
+ if (packet_parse_not_complete(pkt_hdr))
+ packet_parse_full(pkt_hdr);
return pkt_hdr->l3_offset;
}
@@ -291,8 +366,8 @@ int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset)
if (offset >= pkt_hdr->frame_len)
return -1;
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
+ if (packet_parse_not_complete(pkt_hdr))
+ packet_parse_full(pkt_hdr);
pkt_hdr->l3_offset = offset;
return 0;
}
@@ -300,16 +375,16 @@ int odp_packet_l3_offset_set(odp_packet_t pkt, uint32_t offset)
void *odp_packet_l4_ptr(odp_packet_t pkt, uint32_t *len)
{
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
+ if (packet_parse_not_complete(pkt_hdr))
+ packet_parse_full(pkt_hdr);
return packet_map(pkt_hdr, pkt_hdr->l4_offset, len);
}
uint32_t odp_packet_l4_offset(odp_packet_t pkt)
{
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
+ if (packet_parse_not_complete(pkt_hdr))
+ packet_parse_full(pkt_hdr);
return pkt_hdr->l4_offset;
}
@@ -320,12 +395,27 @@ int odp_packet_l4_offset_set(odp_packet_t pkt, uint32_t offset)
if (offset >= pkt_hdr->frame_len)
return -1;
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
+ if (packet_parse_not_complete(pkt_hdr))
+ packet_parse_full(pkt_hdr);
pkt_hdr->l4_offset = offset;
return 0;
}
+uint32_t odp_packet_flow_hash(odp_packet_t pkt)
+{
+ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+ return pkt_hdr->flow_hash;
+}
+
+void odp_packet_flow_hash_set(odp_packet_t pkt, uint32_t flow_hash)
+{
+ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+ pkt_hdr->flow_hash = flow_hash;
+ pkt_hdr->has_hash = 1;
+}
+
int odp_packet_is_segmented(odp_packet_t pkt)
{
return odp_packet_hdr(pkt)->buf_hdr.segcount > 1;
@@ -427,22 +517,7 @@ odp_packet_t odp_packet_add_data(odp_packet_t pkt, uint32_t offset,
odp_packet_free(newpkt);
newpkt = ODP_PACKET_INVALID;
} else {
- odp_packet_hdr_t *new_hdr = odp_packet_hdr(newpkt);
- new_hdr->input = pkt_hdr->input;
- new_hdr->buf_hdr.buf_u64 = pkt_hdr->buf_hdr.buf_u64;
- if (new_hdr->buf_hdr.uarea_addr != NULL &&
- pkt_hdr->buf_hdr.uarea_addr != NULL)
- memcpy(new_hdr->buf_hdr.uarea_addr,
- pkt_hdr->buf_hdr.uarea_addr,
- new_hdr->buf_hdr.uarea_size <=
- pkt_hdr->buf_hdr.uarea_size ?
- new_hdr->buf_hdr.uarea_size :
- pkt_hdr->buf_hdr.uarea_size);
- odp_atomic_store_u32(
- &new_hdr->buf_hdr.ref_count,
- odp_atomic_load_u32(
- &pkt_hdr->buf_hdr.ref_count));
- copy_packet_parser_metadata(pkt_hdr, new_hdr);
+ _odp_packet_copy_md_to_packet(pkt, newpkt);
odp_packet_free(pkt);
}
}
@@ -471,22 +546,7 @@ odp_packet_t odp_packet_rem_data(odp_packet_t pkt, uint32_t offset,
odp_packet_free(newpkt);
newpkt = ODP_PACKET_INVALID;
} else {
- odp_packet_hdr_t *new_hdr = odp_packet_hdr(newpkt);
- new_hdr->input = pkt_hdr->input;
- new_hdr->buf_hdr.buf_u64 = pkt_hdr->buf_hdr.buf_u64;
- if (new_hdr->buf_hdr.uarea_addr != NULL &&
- pkt_hdr->buf_hdr.uarea_addr != NULL)
- memcpy(new_hdr->buf_hdr.uarea_addr,
- pkt_hdr->buf_hdr.uarea_addr,
- new_hdr->buf_hdr.uarea_size <=
- pkt_hdr->buf_hdr.uarea_size ?
- new_hdr->buf_hdr.uarea_size :
- pkt_hdr->buf_hdr.uarea_size);
- odp_atomic_store_u32(
- &new_hdr->buf_hdr.ref_count,
- odp_atomic_load_u32(
- &pkt_hdr->buf_hdr.ref_count));
- copy_packet_parser_metadata(pkt_hdr, new_hdr);
+ _odp_packet_copy_md_to_packet(pkt, newpkt);
odp_packet_free(pkt);
}
}
@@ -684,17 +744,6 @@ int _odp_packet_copy_to_packet(odp_packet_t srcpkt, uint32_t srcoffset,
return 0;
}
-odp_packet_t _odp_packet_alloc(odp_pool_t pool_hdl)
-{
- pool_entry_t *pool = odp_pool_to_entry(pool_hdl);
-
- if (pool->s.params.type != ODP_POOL_PACKET)
- return ODP_PACKET_INVALID;
-
- return (odp_packet_t)buffer_alloc(pool_hdl,
- pool->s.params.buf.size);
-}
-
/**
* Parser helper function for IPv4
*/
@@ -832,30 +881,11 @@ static inline void parse_udp(odp_packet_hdr_t *pkt_hdr,
}
/**
- * Simple packet parser
+ * Initialize L2 related parser flags and metadata
*/
-
-int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr)
+void packet_parse_l2(odp_packet_hdr_t *pkt_hdr)
{
- odph_ethhdr_t *eth;
- odph_vlanhdr_t *vlan;
- uint16_t ethtype;
- uint8_t *parseptr;
- uint32_t offset, seglen;
- uint8_t ip_proto = 0;
-
- /* Reset parser metadata for new parse */
- pkt_hdr->error_flags.all = 0;
- pkt_hdr->input_flags.all = 0;
- pkt_hdr->output_flags.all = 0;
- pkt_hdr->l2_offset = 0;
- pkt_hdr->l3_offset = ODP_PACKET_OFFSET_INVALID;
- pkt_hdr->l4_offset = ODP_PACKET_OFFSET_INVALID;
- pkt_hdr->payload_offset = ODP_PACKET_OFFSET_INVALID;
- pkt_hdr->vlan_s_tag = 0;
- pkt_hdr->vlan_c_tag = 0;
- pkt_hdr->l3_protocol = 0;
- pkt_hdr->l4_protocol = 0;
+ /* Packet alloc or reset have already init other offsets and flags */
/* We only support Ethernet for now */
pkt_hdr->input_flags.eth = 1;
@@ -867,6 +897,24 @@ int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr)
/* Assume valid L2 header, no CRC/FCS check in SW */
pkt_hdr->input_flags.l2 = 1;
+ pkt_hdr->input_flags.parsed_l2 = 1;
+}
+
+/**
+ * Simple packet parser
+ */
+int packet_parse_full(odp_packet_hdr_t *pkt_hdr)
+{
+ odph_ethhdr_t *eth;
+ odph_vlanhdr_t *vlan;
+ uint16_t ethtype;
+ uint8_t *parseptr;
+ uint32_t offset, seglen;
+ uint8_t ip_proto = 0;
+
+ if (packet_parse_l2_not_done(pkt_hdr))
+ packet_parse_l2(pkt_hdr);
+
eth = (odph_ethhdr_t *)packet_map(pkt_hdr, 0, &seglen);
offset = sizeof(odph_ethhdr_t);
parseptr = (uint8_t *)&eth->type;
@@ -978,5 +1026,6 @@ int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr)
pkt_hdr->payload_offset = offset;
parse_exit:
+ pkt_hdr->input_flags.parsed_all = 1;
return pkt_hdr->error_flags.all != 0;
}
diff --git a/platform/linux-generic/odp_packet_flags.c b/platform/linux-generic/odp_packet_flags.c
index 4f680a13d..dbc313748 100644
--- a/platform/linux-generic/odp_packet_flags.c
+++ b/platform/linux-generic/odp_packet_flags.c
@@ -9,23 +9,23 @@
#define retflag(p, x) do { \
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(p); \
- if (pkt_hdr->input_flags.unparsed) \
- _odp_packet_parse(pkt_hdr); \
+ if (packet_parse_not_complete(pkt_hdr)) \
+ packet_parse_full(pkt_hdr); \
return pkt_hdr->x; \
} while (0)
#define setflag(p, x, v) do { \
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(p); \
- if (pkt_hdr->input_flags.unparsed) \
- _odp_packet_parse(pkt_hdr); \
+ if (packet_parse_not_complete(pkt_hdr)) \
+ packet_parse_full(pkt_hdr); \
pkt_hdr->x = v & 1; \
} while (0)
int odp_packet_has_error(odp_packet_t pkt)
{
odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
- if (pkt_hdr->input_flags.unparsed)
- _odp_packet_parse(pkt_hdr);
+ if (packet_parse_not_complete(pkt_hdr))
+ packet_parse_full(pkt_hdr);
return odp_packet_hdr(pkt)->error_flags.all != 0;
}
@@ -33,7 +33,9 @@ int odp_packet_has_error(odp_packet_t pkt)
int odp_packet_has_l2(odp_packet_t pkt)
{
- retflag(pkt, input_flags.l2);
+ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+ return pkt_hdr->input_flags.l2;
}
int odp_packet_has_l3(odp_packet_t pkt)
@@ -48,12 +50,16 @@ int odp_packet_has_l4(odp_packet_t pkt)
int odp_packet_has_eth(odp_packet_t pkt)
{
- retflag(pkt, input_flags.eth);
+ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+ return pkt_hdr->input_flags.eth;
}
int odp_packet_has_jumbo(odp_packet_t pkt)
{
- retflag(pkt, input_flags.jumbo);
+ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+ return pkt_hdr->input_flags.jumbo;
}
int odp_packet_has_vlan(odp_packet_t pkt)
@@ -116,6 +122,13 @@ int odp_packet_has_icmp(odp_packet_t pkt)
retflag(pkt, input_flags.icmp);
}
+int odp_packet_has_flow_hash(odp_packet_t pkt)
+{
+ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+ return pkt_hdr->has_hash;
+}
+
/* Set Input Flags */
void odp_packet_has_l2_set(odp_packet_t pkt, int val)
@@ -202,3 +215,11 @@ void odp_packet_has_icmp_set(odp_packet_t pkt, int val)
{
setflag(pkt, input_flags.icmp, val);
}
+
+void odp_packet_has_flow_hash_clr(odp_packet_t pkt)
+{
+ odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+ pkt_hdr->has_hash = 0;
+}
+
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c
index d72493384..1246bff71 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -11,6 +11,7 @@
#include <odp_packet_internal.h>
#include <odp_internal.h>
#include <odp/spinlock.h>
+#include <odp/ticketlock.h>
#include <odp/shared_memory.h>
#include <odp_packet_socket.h>
#include <odp/config.h>
@@ -54,7 +55,7 @@ int odp_pktio_init_global(void)
for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
pktio_entry = &pktio_tbl->entries[id - 1];
- odp_spinlock_init(&pktio_entry->s.lock);
+ odp_ticketlock_init(&pktio_entry->s.lock);
odp_spinlock_init(&pktio_entry->s.cls.lock);
odp_spinlock_init(&pktio_entry->s.cls.l2_cos_table.lock);
odp_spinlock_init(&pktio_entry->s.cls.l3_cos_table.lock);
@@ -90,6 +91,12 @@ int odp_pktio_term_global(void)
int id;
int pktio_if;
+ for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
+ pktio_entry = &pktio_tbl->entries[id - 1];
+ odp_pktio_close(pktio_entry->s.handle);
+ odp_queue_destroy(pktio_entry->s.outq_default);
+ }
+
for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) {
if (pktio_if_ops[pktio_if]->term)
if (pktio_if_ops[pktio_if]->term())
@@ -97,11 +104,6 @@ int odp_pktio_term_global(void)
pktio_if);
}
- for (id = 1; id <= ODP_CONFIG_PKTIO_ENTRIES; ++id) {
- pktio_entry = &pktio_tbl->entries[id - 1];
- odp_queue_destroy(pktio_entry->s.outq_default);
- }
-
ret = odp_shm_free(odp_shm_lookup("odp_pktio_entries"));
if (ret < 0)
ODP_ERR("shm free failed for odp_pktio_entries");
@@ -131,32 +133,30 @@ static void set_taken(pktio_entry_t *entry)
static void lock_entry(pktio_entry_t *entry)
{
- odp_spinlock_lock(&entry->s.lock);
+ odp_ticketlock_lock(&entry->s.lock);
}
static void unlock_entry(pktio_entry_t *entry)
{
- odp_spinlock_unlock(&entry->s.lock);
+ odp_ticketlock_unlock(&entry->s.lock);
}
static void lock_entry_classifier(pktio_entry_t *entry)
{
- odp_spinlock_lock(&entry->s.lock);
+ odp_ticketlock_lock(&entry->s.lock);
odp_spinlock_lock(&entry->s.cls.lock);
}
static void unlock_entry_classifier(pktio_entry_t *entry)
{
odp_spinlock_unlock(&entry->s.cls.lock);
- odp_spinlock_unlock(&entry->s.lock);
+ odp_ticketlock_unlock(&entry->s.lock);
}
static void init_pktio_entry(pktio_entry_t *entry)
{
set_taken(entry);
- /* Currently classifier is enabled by default. It should be enabled
- only when used. */
- entry->s.cls_enabled = 1;
+ pktio_cls_enabled_set(entry, 0);
entry->s.inq_default = ODP_QUEUE_INVALID;
pktio_classifier_init(entry);
@@ -204,10 +204,10 @@ static odp_pktio_t setup_pktio_entry(const char *dev, odp_pool_t pool,
int ret = -1;
int pktio_if;
- if (strlen(dev) >= IF_NAMESIZE) {
+ if (strlen(dev) >= PKTIO_NAME_LEN - 1) {
/* ioctl names limitation */
ODP_ERR("pktio name %s is too big, limit is %d bytes\n",
- dev, IF_NAMESIZE);
+ dev, PKTIO_NAME_LEN - 1);
return ODP_PKTIO_INVALID;
}
@@ -239,7 +239,8 @@ static odp_pktio_t setup_pktio_entry(const char *dev, odp_pool_t pool,
id = ODP_PKTIO_INVALID;
ODP_ERR("Unable to init any I/O type.\n");
} else {
- snprintf(pktio_entry->s.name, IF_NAMESIZE, "%s", dev);
+ snprintf(pktio_entry->s.name,
+ sizeof(pktio_entry->s.name), "%s", dev);
pktio_entry->s.state = STATE_STOP;
unlock_entry_classifier(pktio_entry);
}
@@ -249,11 +250,26 @@ static odp_pktio_t setup_pktio_entry(const char *dev, odp_pool_t pool,
return id;
}
+static int pool_type_is_packet(odp_pool_t pool)
+{
+ odp_pool_info_t pool_info;
+
+ if (pool == ODP_POOL_INVALID)
+ return 0;
+
+ if (odp_pool_info(pool, &pool_info) != 0)
+ return 0;
+
+ return pool_info.params.type == ODP_POOL_PACKET;
+}
+
odp_pktio_t odp_pktio_open(const char *dev, odp_pool_t pool,
const odp_pktio_param_t *param)
{
odp_pktio_t id;
+ ODP_ASSERT(pool_type_is_packet(pool));
+
id = odp_pktio_lookup(dev);
if (id != ODP_PKTIO_INVALID) {
/* interface is already open */
@@ -344,7 +360,7 @@ odp_pktio_t odp_pktio_lookup(const char *dev)
lock_entry(entry);
if (!is_free(entry) &&
- strncmp(entry->s.name, dev, IF_NAMESIZE) == 0)
+ strncmp(entry->s.name, dev, sizeof(entry->s.name)) == 0)
id = _odp_cast_scalar(odp_pktio_t, i);
unlock_entry(entry);
@@ -542,30 +558,42 @@ odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
odp_buffer_hdr_t *buf_hdr;
odp_buffer_t buf;
odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
- odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
+ odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
int pkts, i, j;
+ odp_pktio_t pktio;
buf_hdr = queue_deq(qentry);
if (buf_hdr != NULL)
return buf_hdr;
- pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, QUEUE_MULTI_MAX);
+ pktio = qentry->s.pktin;
+
+ pkts = odp_pktio_recv(pktio, pkt_tbl, QUEUE_MULTI_MAX);
if (pkts <= 0)
return NULL;
- for (i = 0, j = 0; i < pkts; ++i) {
- buf = _odp_packet_to_buffer(pkt_tbl[i]);
- buf_hdr = odp_buf_to_hdr(buf);
- if (0 > packet_classifier(qentry->s.pktin, pkt_tbl[i]))
- tmp_hdr_tbl[j++] = buf_hdr;
+ if (pktio_cls_enabled(get_pktio_entry(pktio))) {
+ for (i = 0, j = 0; i < pkts; i++) {
+ if (0 > packet_classifier(pktio, pkt_tbl[i])) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ hdr_tbl[j++] = odp_buf_to_hdr(buf);
+ }
+ }
+ } else {
+ for (i = 0; i < pkts; i++) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ hdr_tbl[i] = odp_buf_to_hdr(buf);
+ }
+
+ j = pkts;
}
if (0 == j)
return NULL;
if (j > 1)
- queue_enq_multi(qentry, &tmp_hdr_tbl[1], j - 1, 0);
- buf_hdr = tmp_hdr_tbl[0];
+ queue_enq_multi(qentry, &hdr_tbl[1], j - 1, 0);
+ buf_hdr = hdr_tbl[0];
return buf_hdr;
}
@@ -581,10 +609,10 @@ int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
{
int nbr;
odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
- odp_buffer_hdr_t *tmp_hdr_tbl[QUEUE_MULTI_MAX];
- odp_buffer_hdr_t *tmp_hdr;
+ odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
odp_buffer_t buf;
int pkts, i, j;
+ odp_pktio_t pktio;
nbr = queue_deq_multi(qentry, buf_hdr, num);
if (odp_unlikely(nbr > num))
@@ -597,19 +625,37 @@ int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
if (nbr == num)
return nbr;
- pkts = odp_pktio_recv(qentry->s.pktin, pkt_tbl, QUEUE_MULTI_MAX);
+ pktio = qentry->s.pktin;
+
+ pkts = odp_pktio_recv(pktio, pkt_tbl, QUEUE_MULTI_MAX);
if (pkts <= 0)
return nbr;
- for (i = 0, j = 0; i < pkts; ++i) {
- buf = _odp_packet_to_buffer(pkt_tbl[i]);
- tmp_hdr = odp_buf_to_hdr(buf);
- if (0 > packet_classifier(qentry->s.pktin, pkt_tbl[i]))
- tmp_hdr_tbl[j++] = tmp_hdr;
+ if (pktio_cls_enabled(get_pktio_entry(pktio))) {
+ for (i = 0, j = 0; i < pkts; i++) {
+ if (0 > packet_classifier(pktio, pkt_tbl[i])) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ if (nbr < num)
+ buf_hdr[nbr++] = odp_buf_to_hdr(buf);
+ else
+ hdr_tbl[j++] = odp_buf_to_hdr(buf);
+ }
+ }
+ } else {
+ /* Fill in buf_hdr first */
+ for (i = 0; i < pkts && nbr < num; i++, nbr++) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ buf_hdr[nbr] = odp_buf_to_hdr(buf);
+ }
+ /* Queue the rest for later */
+ for (j = 0; i < pkts; i++, j++) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ hdr_tbl[j++] = odp_buf_to_hdr(buf);
+ }
}
if (j)
- queue_enq_multi(qentry, tmp_hdr_tbl, j, 0);
+ queue_enq_multi(qentry, hdr_tbl, j, 0);
return nbr;
}
@@ -618,6 +664,10 @@ int pktin_poll(pktio_entry_t *entry)
odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
int num, num_enq, i;
+ odp_buffer_t buf;
+ odp_pktio_t pktio;
+
+ pktio = entry->s.handle;
if (odp_unlikely(is_free(entry)))
return -1;
@@ -628,26 +678,30 @@ int pktin_poll(pktio_entry_t *entry)
if (entry->s.state == STATE_STOP)
return 0;
- num = odp_pktio_recv(entry->s.handle, pkt_tbl, QUEUE_MULTI_MAX);
+ num = odp_pktio_recv(pktio, pkt_tbl, QUEUE_MULTI_MAX);
+
+ if (num == 0)
+ return 0;
if (num < 0) {
ODP_ERR("Packet recv error\n");
return -1;
}
- for (i = 0, num_enq = 0; i < num; ++i) {
- odp_buffer_t buf;
- odp_buffer_hdr_t *hdr;
-
- buf = _odp_packet_to_buffer(pkt_tbl[i]);
- hdr = odp_buf_to_hdr(buf);
-
- if (entry->s.cls_enabled) {
- if (packet_classifier(entry->s.handle, pkt_tbl[i]) < 0)
- hdr_tbl[num_enq++] = hdr;
- } else {
- hdr_tbl[num_enq++] = hdr;
+ if (pktio_cls_enabled(entry)) {
+ for (i = 0, num_enq = 0; i < num; i++) {
+ if (packet_classifier(pktio, pkt_tbl[i]) < 0) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ hdr_tbl[num_enq++] = odp_buf_to_hdr(buf);
+ }
}
+ } else {
+ for (i = 0; i < num; i++) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ hdr_tbl[i] = odp_buf_to_hdr(buf);
+ }
+
+ num_enq = num;
}
if (num_enq) {
@@ -763,3 +817,8 @@ int odp_pktio_mac_addr(odp_pktio_t id, void *mac_addr, int addr_size)
return ret;
}
+
+void odp_pktio_param_init(odp_pktio_param_t *params)
+{
+ memset(params, 0, sizeof(odp_pktio_param_t));
+}
diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
index 30d4b2b65..76a4aa585 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -57,8 +57,8 @@ static const char SHM_DEFAULT_NAME[] = "odp_buffer_pools";
/* Pool entry pointers (for inlining) */
void *pool_entry_ptr[ODP_CONFIG_POOLS];
-/* Local cache for buffer alloc/free acceleration */
-static __thread local_cache_t local_cache[ODP_CONFIG_POOLS];
+/* Cache thread id locally for local cache performance */
+static __thread int local_id;
int odp_pool_init_global(void)
{
@@ -107,6 +107,12 @@ int odp_pool_init_global(void)
return 0;
}
+int odp_pool_init_local(void)
+{
+ local_id = odp_thread_id();
+ return 0;
+}
+
int odp_pool_term_global(void)
{
int i;
@@ -442,6 +448,7 @@ int odp_pool_destroy(odp_pool_t pool_hdl)
{
uint32_t pool_id = pool_handle_to_index(pool_hdl);
pool_entry_t *pool = get_pool_entry(pool_id);
+ int i;
if (pool == NULL)
return -1;
@@ -455,8 +462,9 @@ int odp_pool_destroy(odp_pool_t pool_hdl)
return -1;
}
- /* Make sure local cache is empty */
- flush_cache(&local_cache[pool_id], &pool->s);
+ /* Make sure local caches are empty */
+ for (i = 0; i < _ODP_INTERNAL_MAX_THREADS; i++)
+ flush_cache(&pool->s.local_cache[i], &pool->s);
/* Call fails if pool has allocated buffers */
if (odp_atomic_load_u32(&pool->s.bufcount) < pool->s.buf_num) {
@@ -485,8 +493,9 @@ odp_buffer_t buffer_alloc(odp_pool_t pool_hdl, size_t size)
return ODP_BUFFER_INVALID;
/* Try to satisfy request from the local cache */
- buf = (odp_anybuf_t *)(void *)get_local_buf(&local_cache[pool_id],
- &pool->s, totsize);
+ buf = (odp_anybuf_t *)
+ (void *)get_local_buf(&pool->s.local_cache[local_id],
+ &pool->s, totsize);
/* If cache is empty, satisfy request from the pool */
if (odp_unlikely(buf == NULL)) {
@@ -517,9 +526,6 @@ odp_buffer_t buffer_alloc(odp_pool_t pool_hdl, size_t size)
/* By default, buffers are not associated with an ordered queue */
buf->buf.origin_qe = NULL;
- if (buf->buf.type == ODP_EVENT_PACKET)
- packet_init(pool, &buf->pkt, size);
-
return odp_hdr_to_buf(&buf->buf);
}
@@ -537,7 +543,7 @@ void odp_buffer_free(odp_buffer_t buf)
if (odp_unlikely(pool->s.low_wm_assert))
ret_buf(&pool->s, buf_hdr);
else
- ret_local_buf(&local_cache[pool->s.pool_id], buf_hdr);
+ ret_local_buf(&pool->s.local_cache[local_id], buf_hdr);
}
void _odp_flush_caches(void)
@@ -546,7 +552,7 @@ void _odp_flush_caches(void)
for (i = 0; i < ODP_CONFIG_POOLS; i++) {
pool_entry_t *pool = get_pool_entry(i);
- flush_cache(&local_cache[i], &pool->s);
+ flush_cache(&pool->s.local_cache[local_id], &pool->s);
}
}
diff --git a/platform/linux-generic/odp_queue.c b/platform/linux-generic/odp_queue.c
index 9fae71084..a636a439f 100644
--- a/platform/linux-generic/odp_queue.c
+++ b/platform/linux-generic/odp_queue.c
@@ -53,14 +53,17 @@ queue_entry_t *get_qentry(uint32_t queue_id)
return &queue_tbl->queue[queue_id];
}
-static void queue_init(queue_entry_t *queue, const char *name,
- odp_queue_type_t type, odp_queue_param_t *param)
+static int queue_init(queue_entry_t *queue, const char *name,
+ odp_queue_type_t type, odp_queue_param_t *param)
{
strncpy(queue->s.name, name, ODP_QUEUE_NAME_LEN - 1);
queue->s.type = type;
if (param) {
memcpy(&queue->s.param, param, sizeof(odp_queue_param_t));
+ if (queue->s.param.sched.lock_count >
+ ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE)
+ return -1;
} else {
/* Defaults */
memset(&queue->s.param, 0, sizeof(odp_queue_param_t));
@@ -98,12 +101,13 @@ static void queue_init(queue_entry_t *queue, const char *name,
queue->s.pri_queue = ODP_QUEUE_INVALID;
queue->s.cmd_ev = ODP_EVENT_INVALID;
+ return 0;
}
int odp_queue_init_global(void)
{
- uint32_t i;
+ uint32_t i, j;
odp_shm_t shm;
ODP_DBG("Queue init ... ");
@@ -123,8 +127,10 @@ int odp_queue_init_global(void)
/* init locks */
queue_entry_t *queue = get_qentry(i);
LOCK_INIT(&queue->s.lock);
- odp_atomic_init_u64(&queue->s.sync_in, 0);
- odp_atomic_init_u64(&queue->s.sync_out, 0);
+ for (j = 0; j < ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE; j++) {
+ odp_atomic_init_u64(&queue->s.sync_in[j], 0);
+ odp_atomic_init_u64(&queue->s.sync_out[j], 0);
+ }
queue->s.handle = queue_from_id(i);
}
@@ -201,6 +207,14 @@ odp_schedule_group_t odp_queue_sched_group(odp_queue_t handle)
return queue->s.param.sched.group;
}
+int odp_queue_lock_count(odp_queue_t handle)
+{
+ queue_entry_t *queue = queue_to_qentry(handle);
+
+ return queue->s.param.sched.sync == ODP_SCHED_SYNC_ORDERED ?
+ (int)queue->s.param.sched.lock_count : -1;
+}
+
odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
odp_queue_param_t *param)
{
@@ -216,7 +230,10 @@ odp_queue_t odp_queue_create(const char *name, odp_queue_type_t type,
LOCK(&queue->s.lock);
if (queue->s.status == QUEUE_STATUS_FREE) {
- queue_init(queue, name, type, param);
+ if (queue_init(queue, name, type, param)) {
+ UNLOCK(&queue->s.lock);
+ return handle;
+ }
if (type == ODP_QUEUE_TYPE_SCHED ||
type == ODP_QUEUE_TYPE_PKTIN)
@@ -574,13 +591,14 @@ int odp_queue_enq(odp_queue_t handle, odp_event_t ev)
int queue_enq_internal(odp_buffer_hdr_t *buf_hdr)
{
- return buf_hdr->origin_qe->s.enqueue(buf_hdr->target_qe, buf_hdr,
+ return buf_hdr->target_qe->s.enqueue(buf_hdr->target_qe, buf_hdr,
buf_hdr->flags.sustain);
}
odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
{
odp_buffer_hdr_t *buf_hdr;
+ uint32_t i;
LOCK(&queue->s.lock);
@@ -604,7 +622,10 @@ odp_buffer_hdr_t *queue_deq(queue_entry_t *queue)
if (queue_is_ordered(queue)) {
buf_hdr->origin_qe = queue;
buf_hdr->order = queue->s.order_in++;
- buf_hdr->sync = odp_atomic_fetch_inc_u64(&queue->s.sync_in);
+ for (i = 0; i < queue->s.param.sched.lock_count; i++) {
+ buf_hdr->sync[i] =
+ odp_atomic_fetch_inc_u64(&queue->s.sync_in[i]);
+ }
buf_hdr->flags.sustain = 0;
} else {
buf_hdr->origin_qe = NULL;
@@ -625,6 +646,7 @@ int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], int num)
{
odp_buffer_hdr_t *hdr;
int i;
+ uint32_t j;
LOCK(&queue->s.lock);
if (odp_unlikely(queue->s.status < QUEUE_STATUS_READY)) {
@@ -652,8 +674,11 @@ int queue_deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[], int num)
if (queue_is_ordered(queue)) {
buf_hdr[i]->origin_qe = queue;
buf_hdr[i]->order = queue->s.order_in++;
- buf_hdr[i]->sync =
- odp_atomic_fetch_inc_u64(&queue->s.sync_in);
+ for (j = 0; j < queue->s.param.sched.lock_count; j++) {
+ buf_hdr[i]->sync[j] =
+ odp_atomic_fetch_inc_u64
+ (&queue->s.sync_in[j]);
+ }
buf_hdr[i]->flags.sustain = 0;
} else {
buf_hdr[i]->origin_qe = NULL;
@@ -762,7 +787,7 @@ int queue_pktout_enq(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr,
return -1;
} else {
rc = pktout_enqueue(queue, buf_hdr);
- if (!rc)
+ if (rc)
return rc;
}
@@ -970,39 +995,32 @@ int release_order(queue_entry_t *origin_qe, uint64_t order,
return 0;
}
-/* This routine is a no-op in linux-generic */
-int odp_schedule_order_lock_init(odp_schedule_order_lock_t *lock ODP_UNUSED,
- odp_queue_t queue ODP_UNUSED)
-{
- return 0;
-}
-
-void odp_schedule_order_lock(odp_schedule_order_lock_t *lock ODP_UNUSED)
+void odp_schedule_order_lock(unsigned lock_index)
{
queue_entry_t *origin_qe;
uint64_t *sync;
- get_sched_sync(&origin_qe, &sync);
- if (!origin_qe)
+ get_sched_sync(&origin_qe, &sync, lock_index);
+ if (!origin_qe || lock_index >= origin_qe->s.param.sched.lock_count)
return;
/* Wait until we are in order. Note that sync_out will be incremented
* both by unlocks as well as order resolution, so we're OK if only
* some events in the ordered flow need to lock.
*/
- while (*sync > odp_atomic_load_u64(&origin_qe->s.sync_out))
+ while (*sync > odp_atomic_load_u64(&origin_qe->s.sync_out[lock_index]))
odp_spin();
}
-void odp_schedule_order_unlock(odp_schedule_order_lock_t *lock ODP_UNUSED)
+void odp_schedule_order_unlock(unsigned lock_index)
{
queue_entry_t *origin_qe;
uint64_t *sync;
- get_sched_sync(&origin_qe, &sync);
- if (!origin_qe)
+ get_sched_sync(&origin_qe, &sync, lock_index);
+ if (!origin_qe || lock_index >= origin_qe->s.param.sched.lock_count)
return;
/* Release the ordered lock */
- odp_atomic_fetch_inc_u64(&origin_qe->s.sync_out);
+ odp_atomic_fetch_inc_u64(&origin_qe->s.sync_out[lock_index]);
}
diff --git a/platform/linux-generic/odp_schedule.c b/platform/linux-generic/odp_schedule.c
index c6619e509..6df8073de 100644
--- a/platform/linux-generic/odp_schedule.c
+++ b/platform/linux-generic/odp_schedule.c
@@ -86,7 +86,7 @@ typedef struct {
queue_entry_t *qe;
queue_entry_t *origin_qe;
uint64_t order;
- uint64_t sync;
+ uint64_t sync[ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE];
odp_pool_t pool;
int enq_called;
int num;
@@ -440,6 +440,7 @@ static int schedule(odp_queue_t *out_queue, odp_event_t out_ev[],
int i, j;
int thr;
int ret;
+ uint32_t k;
if (sched_local.num) {
ret = copy_events(out_ev, max_num);
@@ -551,8 +552,12 @@ static int schedule(odp_queue_t *out_queue, odp_event_t out_ev[],
sched_local.origin_qe = qe;
sched_local.order =
sched_local.buf_hdr[0]->order;
- sched_local.sync =
- sched_local.buf_hdr[0]->sync;
+ for (k = 0;
+ k < qe->s.param.sched.lock_count;
+ k++) {
+ sched_local.sync[k] =
+ sched_local.buf_hdr[0]->sync[k];
+ }
sched_local.enq_called = 0;
} else if (queue_is_atomic(qe)) {
/* Hold queue during atomic access */
@@ -646,9 +651,6 @@ void odp_schedule_resume(void)
uint64_t odp_schedule_wait_time(uint64_t ns)
{
- if (ns <= ODP_SCHED_NO_WAIT)
- ns = ODP_SCHED_NO_WAIT + 1;
-
return odp_time_ns_to_cycles(ns);
}
@@ -802,10 +804,10 @@ void get_sched_order(queue_entry_t **origin_qe, uint64_t *order)
*order = sched_local.order;
}
-void get_sched_sync(queue_entry_t **origin_qe, uint64_t **sync)
+void get_sched_sync(queue_entry_t **origin_qe, uint64_t **sync, uint32_t ndx)
{
*origin_qe = sched_local.origin_qe;
- *sync = &sched_local.sync;
+ *sync = &sched_local.sync[ndx];
}
void sched_order_resolved(odp_buffer_hdr_t *buf_hdr)
diff --git a/platform/linux-generic/odp_thread.c b/platform/linux-generic/odp_thread.c
index 770c64e18..2f3934374 100644
--- a/platform/linux-generic/odp_thread.c
+++ b/platform/linux-generic/odp_thread.c
@@ -18,6 +18,7 @@
#include <odp/shared_memory.h>
#include <odp/align.h>
#include <odp/cpu.h>
+#include <odp_config_internal.h>
#include <string.h>
#include <stdio.h>
@@ -31,7 +32,7 @@ typedef struct {
typedef struct {
- thread_state_t thr[ODP_CONFIG_MAX_THREADS];
+ thread_state_t thr[_ODP_INTERNAL_MAX_THREADS];
union {
/* struct order must be kept in sync with schedule_types.h */
struct {
@@ -101,10 +102,10 @@ static int alloc_id(odp_thread_type_t type)
int thr;
odp_thrmask_t *all = &thread_globals->all;
- if (thread_globals->num >= ODP_CONFIG_MAX_THREADS)
+ if (thread_globals->num >= _ODP_INTERNAL_MAX_THREADS)
return -1;
- for (thr = 0; thr < ODP_CONFIG_MAX_THREADS; thr++) {
+ for (thr = 0; thr < _ODP_INTERNAL_MAX_THREADS; thr++) {
if (odp_thrmask_isset(all, thr) == 0) {
odp_thrmask_set(all, thr);
@@ -128,7 +129,7 @@ static int free_id(int thr)
{
odp_thrmask_t *all = &thread_globals->all;
- if (thr < 0 || thr >= ODP_CONFIG_MAX_THREADS)
+ if (thr < 0 || thr >= _ODP_INTERNAL_MAX_THREADS)
return -1;
if (odp_thrmask_isset(all, thr) == 0)
@@ -204,6 +205,11 @@ int odp_thread_count(void)
return thread_globals->num;
}
+int odp_thread_count_max(void)
+{
+ return _ODP_INTERNAL_MAX_THREADS;
+}
+
odp_thread_type_t odp_thread_type(void)
{
return this_thread->type;
diff --git a/platform/linux-generic/odp_thrmask.c b/platform/linux-generic/odp_thrmask.c
index d10bbf1bb..a7c3c696d 100644
--- a/platform/linux-generic/odp_thrmask.c
+++ b/platform/linux-generic/odp_thrmask.c
@@ -9,11 +9,11 @@
#endif
#include <sched.h>
-#include <odp/config.h>
+#include <odp_config_internal.h>
#include <odp/thrmask.h>
#include <odp/cpumask.h>
-#if CPU_SETSIZE < ODP_CONFIG_MAX_THREADS
+#if CPU_SETSIZE < _ODP_INTERNAL_MAX_THREADS
#error Thread mask does not fit all thread IDs
#endif
diff --git a/platform/linux-generic/odp_time.c b/platform/linux-generic/odp_time.c
index a08833d0e..74f802b83 100644
--- a/platform/linux-generic/odp_time.c
+++ b/platform/linux-generic/odp_time.c
@@ -9,15 +9,19 @@
#include <odp/time.h>
#include <odp/hints.h>
#include <odp/system_info.h>
+#include <odp/cpu.h>
+#include <odp_cpu_internal.h>
#define GIGA 1000000000
-uint64_t odp_time_diff_cycles(uint64_t t1, uint64_t t2)
+uint64_t odp_time_cycles(void)
{
- if (odp_likely(t2 > t1))
- return t2 - t1;
+ return odp_cpu_cycles();
+}
- return t2 + (UINT64_MAX - t1);
+uint64_t odp_time_diff_cycles(uint64_t t1, uint64_t t2)
+{
+ return _odp_cpu_cycles_diff(t1, t2);
}
uint64_t odp_time_cycles_to_ns(uint64_t cycles)
diff --git a/platform/linux-generic/pktio/io_ops.c b/platform/linux-generic/pktio/io_ops.c
index 1d47e7492..3b344e6ad 100644
--- a/platform/linux-generic/pktio/io_ops.c
+++ b/platform/linux-generic/pktio/io_ops.c
@@ -12,6 +12,12 @@
* Array must be NULL terminated */
const pktio_if_ops_t * const pktio_if_ops[] = {
&loopback_pktio_ops,
+#ifdef ODP_NETMAP
+ &netmap_pktio_ops,
+#endif
+#ifdef HAVE_PCAP
+ &pcap_pktio_ops,
+#endif
&sock_mmap_pktio_ops,
&sock_mmsg_pktio_ops,
NULL
diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c
index 22f04758f..ce19add2b 100644
--- a/platform/linux-generic/pktio/loop.c
+++ b/platform/linux-generic/pktio/loop.c
@@ -20,8 +20,6 @@
#include <errno.h>
-/* MTU to be reported for the "loop" interface */
-#define PKTIO_LOOP_MTU 1500
/* MAC address for the "loop" interface */
static const char pktio_loop_mac[] = {0x02, 0xe9, 0x34, 0x80, 0x73, 0x01};
@@ -55,13 +53,16 @@ static int loopback_recv(pktio_entry_t *pktio_entry, odp_packet_t pkts[],
int nbr, i;
odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
queue_entry_t *qentry;
+ odp_packet_hdr_t *pkt_hdr;
qentry = queue_to_qentry(pktio_entry->s.pkt_loop.loopq);
nbr = queue_deq_multi(qentry, hdr_tbl, len);
for (i = 0; i < nbr; ++i) {
pkts[i] = _odp_packet_from_buffer(odp_hdr_to_buf(hdr_tbl[i]));
- _odp_packet_reset_parse(pkts[i]);
+ pkt_hdr = odp_packet_hdr(pkts[i]);
+ packet_parse_reset(pkts[i]);
+ packet_parse_l2(pkt_hdr);
}
return nbr;
@@ -83,7 +84,8 @@ static int loopback_send(pktio_entry_t *pktio_entry, odp_packet_t pkt_tbl[],
static int loopback_mtu_get(pktio_entry_t *pktio_entry ODP_UNUSED)
{
- return PKTIO_LOOP_MTU;
+ /* the loopback interface imposes no maximum transmit size limit */
+ return INT_MAX;
}
static int loopback_mac_addr_get(pktio_entry_t *pktio_entry ODP_UNUSED,
diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c
new file mode 100644
index 000000000..794c82ec8
--- /dev/null
+++ b/platform/linux-generic/pktio/netmap.c
@@ -0,0 +1,324 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifdef ODP_NETMAP
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <odp_packet_netmap.h>
+#include <odp_packet_socket.h>
+#include <odp_packet_io_internal.h>
+#include <odp_debug_internal.h>
+#include <odp/helper/eth.h>
+
+#include <sys/ioctl.h>
+#include <poll.h>
+#include <linux/ethtool.h>
+#include <linux/sockios.h>
+
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+
+static struct nm_desc mmap_desc; /** Used to store the mmap address;
+ filled in first time, used for
+ subsequent calls to nm_open */
+
+#define NM_OPEN_RETRIES 5
+#define NM_INJECT_RETRIES 10
+
+struct dispatch_args {
+ odp_packet_t *pkt_table;
+ unsigned nb_rx;
+ pktio_entry_t *pktio_entry;
+};
+
+static int netmap_do_ioctl(pktio_entry_t *pktio_entry, unsigned long cmd,
+ int subcmd)
+{
+ pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+ struct ethtool_value eval;
+ struct ifreq ifr;
+ int err;
+ int fd = pkt_nm->sockfd;
+
+ memset(&ifr, 0, sizeof(ifr));
+ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s",
+ pktio_entry->s.name);
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ ifr.ifr_flags = pkt_nm->if_flags & 0xffff;
+ break;
+ case SIOCETHTOOL:
+ eval.cmd = subcmd;
+ eval.data = 0;
+ ifr.ifr_data = (caddr_t)&eval;
+ break;
+ default:
+ break;
+ }
+ err = ioctl(fd, cmd, &ifr);
+ if (err)
+ goto done;
+
+ switch (cmd) {
+ case SIOCGIFFLAGS:
+ pkt_nm->if_flags = (ifr.ifr_flags << 16) |
+ (0xffff & ifr.ifr_flags);
+ break;
+ case SIOCETHTOOL:
+ if (subcmd == ETHTOOL_GLINK)
+ return !eval.data;
+ break;
+ default:
+ break;
+ }
+done:
+ if (err)
+ ODP_ERR("ioctl err %d %lu: %s\n", err, cmd, strerror(errno));
+
+ return err;
+}
+
+static int netmap_close(pktio_entry_t *pktio_entry)
+{
+ pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+
+ if (pkt_nm->rx_desc != NULL) {
+ nm_close(pkt_nm->rx_desc);
+ mmap_desc.mem = NULL;
+ }
+ if (pkt_nm->tx_desc != NULL)
+ nm_close(pkt_nm->tx_desc);
+
+ if (pkt_nm->sockfd != -1 && close(pkt_nm->sockfd) != 0) {
+ __odp_errno = errno;
+ ODP_ERR("close(sockfd): %s\n", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
+ const char *netdev, odp_pool_t pool)
+{
+ char ifname[IFNAMSIZ + 7]; /* netmap:<ifname> */
+ int err;
+ int sockfd;
+ int i;
+ pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+
+ if (getenv("ODP_PKTIO_DISABLE_NETMAP"))
+ return -1;
+
+ if (pool == ODP_POOL_INVALID)
+ return -1;
+
+ /* Init pktio entry */
+ memset(pkt_nm, 0, sizeof(*pkt_nm));
+ pkt_nm->sockfd = -1;
+ pkt_nm->pool = pool;
+
+ /* max frame len taking into account the l2-offset */
+ pkt_nm->max_frame_len = ODP_CONFIG_PACKET_BUF_LEN_MAX -
+ odp_buffer_pool_headroom(pool) -
+ odp_buffer_pool_tailroom(pool);
+
+ snprintf(pktio_entry->s.name, sizeof(pktio_entry->s.name), "%s",
+ netdev);
+ snprintf(ifname, sizeof(ifname), "netmap:%s", netdev);
+
+ if (mmap_desc.mem == NULL)
+ pkt_nm->rx_desc = nm_open(ifname, NULL, NETMAP_NO_TX_POLL,
+ NULL);
+ else
+ pkt_nm->rx_desc = nm_open(ifname, NULL, NETMAP_NO_TX_POLL |
+ NM_OPEN_NO_MMAP, &mmap_desc);
+ pkt_nm->tx_desc = nm_open(ifname, NULL, NM_OPEN_NO_MMAP, &mmap_desc);
+
+ if (pkt_nm->rx_desc == NULL || pkt_nm->tx_desc == NULL) {
+ ODP_ERR("nm_open(%s) failed\n", ifname);
+ goto error;
+ }
+
+ if (mmap_desc.mem == NULL) {
+ mmap_desc.mem = pkt_nm->rx_desc->mem;
+ mmap_desc.memsize = pkt_nm->rx_desc->memsize;
+ }
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd == -1) {
+ ODP_ERR("Cannot get device control socket\n");
+ goto error;
+ }
+ pkt_nm->sockfd = sockfd;
+
+ err = netmap_do_ioctl(pktio_entry, SIOCGIFFLAGS, 0);
+ if (err)
+ goto error;
+ if ((pkt_nm->if_flags & IFF_UP) == 0)
+ ODP_DBG("%s is down\n", pktio_entry->s.name);
+
+ err = mac_addr_get_fd(sockfd, netdev, pkt_nm->if_mac);
+ if (err)
+ goto error;
+
+ /* Wait for the link to come up */
+ for (i = 0; i < NM_OPEN_RETRIES; i++) {
+ err = netmap_do_ioctl(pktio_entry, SIOCETHTOOL, ETHTOOL_GLINK);
+ /* nm_open() causes the physical link to reset. When using a
+ * direct attached loopback cable there may be a small delay
+ * until the opposing end's interface comes back up again. In
+ * this case without the additional sleep pktio validation
+ * tests fail. */
+ sleep(1);
+ if (err == 0)
+ return 0;
+ }
+ ODP_ERR("%s didn't come up\n", pktio_entry->s.name);
+
+error:
+ netmap_close(pktio_entry);
+ return -1;
+}
+
+static void netmap_recv_cb(u_char *arg, const struct nm_pkthdr *hdr,
+ const u_char *buf)
+{
+ struct dispatch_args *args = (struct dispatch_args *)(void *)arg;
+ pkt_netmap_t *pkt_nm = &args->pktio_entry->s.pkt_nm;
+ odp_packet_t pkt;
+ odp_packet_hdr_t *pkt_hdr;
+ size_t frame_len = (size_t)hdr->len;
+
+ if (odp_unlikely(frame_len > pkt_nm->max_frame_len)) {
+ ODP_ERR("RX: frame too big %u %lu!\n", (unsigned)frame_len,
+ pkt_nm->max_frame_len);
+ return;
+ }
+
+ if (odp_unlikely(frame_len < ODPH_ETH_LEN_MIN)) {
+ ODP_ERR("RX: Frame truncated: %u\n", (unsigned)frame_len);
+ return;
+ }
+
+ pkt = packet_alloc(pkt_nm->pool, frame_len, 1);
+ if (pkt == ODP_PACKET_INVALID)
+ return;
+
+ pkt_hdr = odp_packet_hdr(pkt);
+
+ /* For now copy the data in the mbuf,
+ worry about zero-copy later */
+ if (odp_packet_copydata_in(pkt, 0, frame_len, buf) != 0) {
+ odp_packet_free(pkt);
+ return;
+ }
+
+ packet_parse_l2(pkt_hdr);
+
+ args->pkt_table[args->nb_rx++] = pkt;
+}
+
+static int netmap_recv(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
+ unsigned num)
+{
+ struct dispatch_args args;
+ struct nm_desc *nm_desc = pktio_entry->s.pkt_nm.rx_desc;
+ struct pollfd polld;
+
+ polld.fd = nm_desc->fd;
+ polld.events = POLLIN;
+
+ args.pkt_table = pkt_table;
+ args.nb_rx = 0;
+ args.pktio_entry = pktio_entry;
+
+ nm_dispatch(nm_desc, num, netmap_recv_cb, (u_char *)&args);
+ if (args.nb_rx == 0) {
+ if (odp_unlikely(poll(&polld, 1, 0) < 0))
+ ODP_ERR("RX: poll error\n");
+ }
+ return args.nb_rx;
+}
+
+static int netmap_send(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
+ unsigned num)
+{
+ struct pollfd polld;
+ struct nm_desc *nm_desc = pktio_entry->s.pkt_nm.tx_desc;
+ unsigned i, nb_tx;
+ uint8_t *frame;
+ uint32_t frame_len;
+
+ polld.fd = nm_desc->fd;
+ polld.events = POLLOUT;
+
+ for (nb_tx = 0; nb_tx < num; nb_tx++) {
+ frame_len = 0;
+ frame = odp_packet_l2_ptr(pkt_table[nb_tx], &frame_len);
+ for (i = 0; i < NM_INJECT_RETRIES; i++) {
+ if (nm_inject(nm_desc, frame, frame_len) == 0)
+ poll(&polld, 1, 0);
+ else
+ break;
+ }
+ if (odp_unlikely(i == NM_INJECT_RETRIES)) {
+ ioctl(nm_desc->fd, NIOCTXSYNC, NULL);
+ break;
+ }
+ }
+ /* Send pending packets */
+ poll(&polld, 1, 0);
+
+ for (i = 0; i < nb_tx; i++)
+ odp_packet_free(pkt_table[i]);
+
+ return nb_tx;
+}
+
+static int netmap_mac_addr_get(pktio_entry_t *pktio_entry, void *mac_addr)
+{
+ memcpy(mac_addr, pktio_entry->s.pkt_nm.if_mac, ETH_ALEN);
+ return ETH_ALEN;
+}
+
+static int netmap_mtu_get(pktio_entry_t *pktio_entry)
+{
+ return mtu_get_fd(pktio_entry->s.pkt_nm.sockfd, pktio_entry->s.name);
+}
+
+static int netmap_promisc_mode_set(pktio_entry_t *pktio_entry,
+ odp_bool_t enable)
+{
+ return promisc_mode_set_fd(pktio_entry->s.pkt_nm.sockfd,
+ pktio_entry->s.name, enable);
+}
+
+static int netmap_promisc_mode_get(pktio_entry_t *pktio_entry)
+{
+ return promisc_mode_get_fd(pktio_entry->s.pkt_nm.sockfd,
+ pktio_entry->s.name);
+}
+
+const pktio_if_ops_t netmap_pktio_ops = {
+ .init = NULL,
+ .term = NULL,
+ .open = netmap_open,
+ .close = netmap_close,
+ .start = NULL,
+ .stop = NULL,
+ .recv = netmap_recv,
+ .send = netmap_send,
+ .mtu_get = netmap_mtu_get,
+ .promisc_mode_set = netmap_promisc_mode_set,
+ .promisc_mode_get = netmap_promisc_mode_get,
+ .mac_get = netmap_mac_addr_get
+};
+
+#endif /* ODP_NETMAP */
diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c
new file mode 100644
index 000000000..0817bf595
--- /dev/null
+++ b/platform/linux-generic/pktio/pcap.c
@@ -0,0 +1,381 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * PCAP pktio type
+ *
+ * This file provides a pktio interface that allows for reading from
+ * and writing to pcap capture files. It is intended to be used as
+ * simple way of injecting test packets into an application for the
+ * purpose of functional testing.
+ *
+ * To use this interface the name passed to odp_pktio_open() must begin
+ * with "pcap:" and be in the format;
+ *
+ * pcap:in=test.pcap:out=test_out.pcap:loops=10
+ *
+ * in the name of the input pcap file. If no input file is given
+ * attempts to receive from the pktio will just return no
+ * packets. If an input file is specified it must exist and be
+ * a readable pcap file with a link type of DLT_EN10MB.
+ * out the name of the output pcap file. If no output file is
+ * given any packets transmitted over the interface will just
+ * be freed. If an output file is specified and the file
+ * doesn't exist it will be created, if it does exist it will
+ * be overwritten.
+ * loops the number of times to iterate through the input file, set
+ * to 0 to loop indefinitely. The default value is 1.
+ *
+ * The total length of the string is limited by PKTIO_NAME_LEN.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <odp.h>
+#include <odp_packet_internal.h>
+#include <odp_packet_io_internal.h>
+
+#include <odp/helper/eth.h>
+
+#include <errno.h>
+#include <pcap/pcap.h>
+#include <pcap/bpf.h>
+
+#define PKTIO_PCAP_MTU (64 * 1024)
+static const char pcap_mac[] = {0x02, 0xe9, 0x34, 0x80, 0x73, 0x04};
+
+static int _pcapif_parse_devname(pkt_pcap_t *pcap, const char *devname)
+{
+ char *tok;
+ char in[PKTIO_NAME_LEN];
+
+ if (strncmp(devname, "pcap:", 5) != 0)
+ return -1;
+
+ snprintf(in, sizeof(in), "%s", devname);
+
+ for (tok = strtok(in + 5, ":"); tok; tok = strtok(NULL, ":")) {
+ if (strncmp(tok, "in=", 3) == 0 && !pcap->fname_rx) {
+ tok += 3;
+ pcap->fname_rx = strdup(tok);
+ } else if (strncmp(tok, "out=", 4) == 0 && !pcap->fname_tx) {
+ tok += 4;
+ pcap->fname_tx = strdup(tok);
+ } else if (strncmp(tok, "loops=", 6) == 0) {
+ pcap->loops = atoi(tok + 6);
+ if (pcap->loops < 0) {
+ ODP_ERR("invalid loop count\n");
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int _pcapif_init_rx(pkt_pcap_t *pcap)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+ int linktype;
+
+ pcap->rx = pcap_open_offline(pcap->fname_rx, errbuf);
+ if (!pcap->rx) {
+ ODP_ERR("failed to open pcap file %s (%s)\n",
+ pcap->fname_rx, errbuf);
+ return -1;
+ }
+
+ linktype = pcap_datalink(pcap->rx);
+ if (linktype != DLT_EN10MB) {
+ ODP_ERR("unsupported datalink type: %d\n", linktype);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int _pcapif_init_tx(pkt_pcap_t *pcap)
+{
+ pcap_t *tx = pcap->rx;
+
+ if (!tx) {
+ /* if there is no rx pcap_t already open for rx, a dummy
+ * one needs to be opened for writing the dump */
+ tx = pcap_open_dead(DLT_EN10MB, PKTIO_PCAP_MTU);
+ if (!tx) {
+ ODP_ERR("failed to open TX dump\n");
+ return -1;
+ }
+
+ pcap->tx = tx;
+ }
+
+ pcap->buf = malloc(PKTIO_PCAP_MTU);
+ if (!pcap->buf) {
+ ODP_ERR("failed to malloc temp buffer\n");
+ return -1;
+ }
+
+ pcap->tx_dump = pcap_dump_open(tx, pcap->fname_tx);
+ if (!pcap->tx_dump) {
+ ODP_ERR("failed to open dump file %s (%s)\n",
+ pcap->fname_tx, pcap_geterr(tx));
+ return -1;
+ }
+
+ return pcap_dump_flush(pcap->tx_dump);
+}
+
+static int pcapif_init(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
+ const char *devname, odp_pool_t pool)
+{
+ pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap;
+ int ret;
+
+ memset(pcap, 0, sizeof(pkt_pcap_t));
+ pcap->loop_cnt = 1;
+ pcap->loops = 1;
+ pcap->pool = pool;
+ pcap->promisc = 1;
+
+ ret = _pcapif_parse_devname(pcap, devname);
+
+ if (ret == 0 && pcap->fname_rx)
+ ret = _pcapif_init_rx(pcap);
+
+ if (ret == 0 && pcap->fname_tx)
+ ret = _pcapif_init_tx(pcap);
+
+ if (ret == 0 && (!pcap->rx && !pcap->tx_dump))
+ ret = -1;
+
+ return ret;
+}
+
+static int pcapif_close(pktio_entry_t *pktio_entry)
+{
+ pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap;
+
+ if (pcap->tx_dump)
+ pcap_dump_close(pcap->tx_dump);
+
+ if (pcap->tx)
+ pcap_close(pcap->tx);
+
+ if (pcap->rx)
+ pcap_close(pcap->rx);
+
+ free(pcap->buf);
+ free(pcap->fname_rx);
+ free(pcap->fname_tx);
+
+ return 0;
+}
+
+static int _pcapif_reopen(pkt_pcap_t *pcap)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ if (pcap->loops != 0 && ++pcap->loop_cnt >= pcap->loops)
+ return 1;
+
+ if (pcap->rx)
+ pcap_close(pcap->rx);
+
+ pcap->rx = pcap_open_offline(pcap->fname_rx, errbuf);
+ if (!pcap->rx) {
+ ODP_ERR("failed to reopen pcap file %s (%s)\n",
+ pcap->fname_rx, errbuf);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, odp_packet_t pkts[],
+ unsigned len)
+{
+ unsigned i;
+ struct pcap_pkthdr *hdr;
+ const u_char *data;
+ odp_packet_t pkt;
+ odp_packet_hdr_t *pkt_hdr;
+ uint32_t pkt_len;
+ pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap;
+
+ ODP_ASSERT(pktio_entry->s.state == STATE_START);
+
+ if (!pcap->rx)
+ return 0;
+
+ pkt = ODP_PACKET_INVALID;
+ pkt_len = 0;
+
+ for (i = 0; i < len; ) {
+ int ret;
+
+ if (pkt == ODP_PACKET_INVALID) {
+ pkt = packet_alloc(pcap->pool, 0 /*default len*/, 1);
+ if (odp_unlikely(pkt == ODP_PACKET_INVALID))
+ break;
+ pkt_len = odp_packet_len(pkt);
+ }
+
+ ret = pcap_next_ex(pcap->rx, &hdr, &data);
+
+ /* end of file, attempt to reopen if within loop limit */
+ if (ret == -2 && _pcapif_reopen(pcap) == 0)
+ continue;
+
+ if (ret != 1)
+ break;
+
+ pkt_hdr = odp_packet_hdr(pkt);
+
+ if (!odp_packet_pull_tail(pkt, pkt_len - hdr->caplen)) {
+ ODP_ERR("failed to pull tail: pkt_len: %d caplen: %d\n",
+ pkt_len, hdr->caplen);
+ break;
+ }
+
+ if (odp_packet_copydata_in(pkt, 0, hdr->caplen, data) != 0) {
+ ODP_ERR("failed to copy packet data\n");
+ break;
+ }
+
+ packet_parse_l2(pkt_hdr);
+
+ pkts[i] = pkt;
+ pkt = ODP_PACKET_INVALID;
+
+ i++;
+ }
+
+ if (pkt != ODP_PACKET_INVALID)
+ odp_packet_free(pkt);
+
+ return i;
+}
+
+static int _pcapif_dump_pkt(pkt_pcap_t *pcap, odp_packet_t pkt)
+{
+ struct pcap_pkthdr hdr;
+
+ if (!pcap->tx_dump)
+ return 0;
+
+ hdr.caplen = odp_packet_len(pkt);
+ hdr.len = hdr.caplen;
+ (void)gettimeofday(&hdr.ts, NULL);
+
+ if (odp_packet_copydata_out(pkt, 0, hdr.len, pcap->buf) != 0)
+ return -1;
+
+ pcap_dump(pcap->tx_dump, &hdr, pcap->buf);
+ (void)pcap_dump_flush(pcap->tx_dump);
+
+ return 0;
+}
+
+static int pcapif_send_pkt(pktio_entry_t *pktio_entry, odp_packet_t pkts[],
+ unsigned len)
+{
+ pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap;
+ unsigned i;
+
+ ODP_ASSERT(pktio_entry->s.state == STATE_START);
+
+ for (i = 0; i < len; ++i) {
+ if (odp_packet_len(pkts[i]) > PKTIO_PCAP_MTU) {
+ if (i == 0)
+ return -1;
+ break;
+ }
+
+ if (_pcapif_dump_pkt(pcap, pkts[i]) != 0)
+ break;
+
+ odp_packet_free(pkts[i]);
+ }
+
+ return i;
+}
+
+static int pcapif_mtu_get(pktio_entry_t *pktio_entry ODP_UNUSED)
+{
+ return PKTIO_PCAP_MTU;
+}
+
+static int pcapif_mac_addr_get(pktio_entry_t *pktio_entry ODP_UNUSED,
+ void *mac_addr)
+{
+ memcpy(mac_addr, pcap_mac, ODPH_ETHADDR_LEN);
+
+ return ODPH_ETHADDR_LEN;
+}
+
+static int pcapif_promisc_mode_set(pktio_entry_t *pktio_entry,
+ odp_bool_t enable)
+{
+ char filter_exp[64] = {0};
+ struct bpf_program bpf;
+ pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap;
+
+ if (!pcap->rx) {
+ pcap->promisc = enable;
+ return 0;
+ }
+
+ if (!enable) {
+ char mac_str[18];
+
+ snprintf(mac_str, sizeof(mac_str),
+ "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ pcap_mac[0], pcap_mac[1], pcap_mac[2],
+ pcap_mac[3], pcap_mac[4], pcap_mac[5]);
+
+ snprintf(filter_exp, sizeof(filter_exp),
+ "ether dst %s or broadcast or multicast",
+ mac_str);
+ }
+
+ if (pcap_compile(pcap->rx, &bpf, filter_exp,
+ 0, PCAP_NETMASK_UNKNOWN) != 0) {
+ ODP_ERR("failed to compile promisc mode filter: %s\n",
+ pcap_geterr(pcap->rx));
+ return -1;
+ }
+
+ if (pcap_setfilter(pcap->rx, &bpf) != 0) {
+ ODP_ERR("failed to set promisc mode filter: %s\n",
+ pcap_geterr(pcap->rx));
+ return -1;
+ }
+
+ pcap->promisc = enable;
+
+ return 0;
+}
+
+static int pcapif_promisc_mode_get(pktio_entry_t *pktio_entry)
+{
+ return pktio_entry->s.pkt_pcap.promisc;
+}
+
+const pktio_if_ops_t pcap_pktio_ops = {
+ .open = pcapif_init,
+ .close = pcapif_close,
+ .recv = pcapif_recv_pkt,
+ .send = pcapif_send_pkt,
+ .mtu_get = pcapif_mtu_get,
+ .promisc_mode_set = pcapif_promisc_mode_set,
+ .promisc_mode_get = pcapif_promisc_mode_get,
+ .mac_get = pcapif_mac_addr_get
+};
diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c
index 7a40cd96b..5f5e0ae9d 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -88,9 +88,35 @@ int sendmmsg(int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
#define ETHBUF_ALIGN(buf_ptr) ((uint8_t *)ODP_ALIGN_ROUNDUP_PTR((buf_ptr), \
sizeof(uint32_t)) + ETHBUF_OFFSET)
+/**
+ * ODP_PACKET_SOCKET_MMSG:
+ * ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
+ */
+int mac_addr_get_fd(int fd, const char *name, unsigned char mac_dst[])
+{
+ struct ifreq ethreq;
+ int ret;
+
+ memset(&ethreq, 0, sizeof(ethreq));
+ snprintf(ethreq.ifr_name, IF_NAMESIZE, "%s", name);
+ ret = ioctl(fd, SIOCGIFHWADDR, &ethreq);
+ if (ret != 0) {
+ __odp_errno = errno;
+ ODP_ERR("ioctl(SIOCGIFHWADDR): %s: \"%s\".\n", strerror(errno),
+ ethreq.ifr_name);
+ return -1;
+ }
+
+ memcpy(mac_dst, (unsigned char *)ethreq.ifr_ifru.ifru_hwaddr.sa_data,
+ ETH_ALEN);
+ return 0;
+}
+
/*
* ODP_PACKET_SOCKET_MMSG:
* ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
*/
int mtu_get_fd(int fd, const char *name)
{
@@ -109,6 +135,7 @@ int mtu_get_fd(int fd, const char *name)
/*
* ODP_PACKET_SOCKET_MMSG:
* ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
*/
int promisc_mode_set_fd(int fd, const char *name, int enable)
{
@@ -138,6 +165,7 @@ int promisc_mode_set_fd(int fd, const char *name, int enable)
/*
* ODP_PACKET_SOCKET_MMSG:
* ODP_PACKET_SOCKET_MMAP:
+ * ODP_PACKET_NETMAP:
*/
int promisc_mode_get_fd(int fd, const char *name)
{
@@ -211,17 +239,9 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev,
}
if_idx = ethreq.ifr_ifindex;
- /* get MAC address */
- memset(&ethreq, 0, sizeof(ethreq));
- snprintf(ethreq.ifr_name, IF_NAMESIZE, "%s", netdev);
- err = ioctl(sockfd, SIOCGIFHWADDR, &ethreq);
- if (err != 0) {
- __odp_errno = errno;
- ODP_ERR("ioctl(SIOCGIFHWADDR): %s\n", strerror(errno));
+ err = mac_addr_get_fd(sockfd, netdev, pkt_sock->if_mac);
+ if (err != 0)
goto error;
- }
- ethaddr_copy(pkt_sock->if_mac,
- (unsigned char *)ethreq.ifr_ifru.ifru_hwaddr.sa_data);
/* bind socket to if */
memset(&sa_ll, 0, sizeof(sa_ll));
@@ -302,7 +322,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
memset(msgvec, 0, sizeof(msgvec));
for (i = 0; i < (int)len; i++) {
- pkt_table[i] = _odp_packet_alloc(pkt_sock->pool);
+ pkt_table[i] = packet_alloc(pkt_sock->pool, 0 /*default*/, 1);
if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID))
break;
@@ -316,6 +336,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len, MSG_DONTWAIT, NULL);
for (i = 0; i < recv_msgs; i++) {
+ odp_packet_hdr_t *pkt_hdr;
void *base = msgvec[i].msg_hdr.msg_iov->iov_base;
struct ethhdr *eth_hdr = base;
@@ -326,11 +347,13 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
continue;
}
- /* Parse and set packet header data */
+ pkt_hdr = odp_packet_hdr(pkt_table[i]);
+
odp_packet_pull_tail(pkt_table[i],
odp_packet_len(pkt_table[i]) -
msgvec[i].msg_len);
- _odp_packet_reset_parse(pkt_table[i]);
+
+ packet_parse_l2(pkt_hdr);
pkt_table[nb_rx] = pkt_table[i];
nb_rx++;
@@ -373,9 +396,7 @@ static int sock_mmsg_send(pktio_entry_t *pktio_entry,
struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_TX][ODP_BUFFER_MAX_SEG];
int ret;
int sockfd;
- unsigned i;
- unsigned sent_msgs = 0;
- unsigned flags;
+ unsigned n, i;
if (odp_unlikely(len > ODP_PACKET_SOCKET_MAX_BURST_TX))
return -1;
@@ -389,17 +410,24 @@ static int sock_mmsg_send(pktio_entry_t *pktio_entry,
iovecs[i]);
}
- flags = MSG_DONTWAIT;
- for (i = 0; i < len; i += sent_msgs) {
- ret = sendmmsg(sockfd, &msgvec[i], len - i, flags);
- sent_msgs = ret > 0 ? (unsigned)ret : 0;
- flags = 0; /* blocking for next rounds */
+ for (i = 0; i < len; ) {
+ ret = sendmmsg(sockfd, &msgvec[i], len - i, MSG_DONTWAIT);
+ if (odp_unlikely(ret <= -1)) {
+ if (i == 0 && SOCK_ERR_REPORT(errno)) {
+ __odp_errno = errno;
+ ODP_ERR("sendmmsg(): %s\n", strerror(errno));
+ return -1;
+ }
+ break;
+ }
+
+ i += ret;
}
- for (i = 0; i < len; i++)
- odp_packet_free(pkt_table[i]);
+ for (n = 0; n < i; ++n)
+ odp_packet_free(pkt_table[n]);
- return len;
+ return i;
}
/*
diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c
index 39b258b55..79ff82d07 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -118,6 +118,7 @@ static inline unsigned pkt_mmap_v2_rx(int sock, struct ring *ring,
uint8_t *pkt_buf;
int pkt_len;
struct ethhdr *eth_hdr;
+ odp_packet_hdr_t *pkt_hdr;
unsigned i = 0;
(void)sock;
@@ -142,20 +143,21 @@ static inline unsigned pkt_mmap_v2_rx(int sock, struct ring *ring,
continue;
}
- pkt_table[i] = odp_packet_alloc(pool, pkt_len);
+ pkt_table[i] = packet_alloc(pool, pkt_len, 1);
if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID))
break;
+ pkt_hdr = odp_packet_hdr(pkt_table[i]);
+
if (odp_packet_copydata_in(pkt_table[i], 0,
pkt_len, pkt_buf) != 0) {
odp_packet_free(pkt_table[i]);
break;
}
- mmap_rx_user_ready(ppd.raw);
+ packet_parse_l2(pkt_hdr);
- /* Parse and set packet header data */
- _odp_packet_reset_parse(pkt_table[i]);
+ mmap_rx_user_ready(ppd.raw);
frame_num = next_frame_num;
i++;
@@ -174,49 +176,73 @@ static inline unsigned pkt_mmap_v2_tx(int sock, struct ring *ring,
{
union frame_map ppd;
uint32_t pkt_len;
- unsigned frame_num, next_frame_num;
+ unsigned first_frame_num, frame_num, frame_count;
int ret;
- unsigned i = 0;
+ uint8_t *buf;
+ unsigned n, i = 0;
+ unsigned nb_tx = 0;
+ int send_errno;
- frame_num = ring->frame_num;
+ first_frame_num = ring->frame_num;
+ frame_num = first_frame_num;
+ frame_count = ring->rd_num;
while (i < len) {
- if (mmap_tx_kernel_ready(ring->rd[frame_num].iov_base)) {
- ppd.raw = ring->rd[frame_num].iov_base;
+ ppd.raw = ring->rd[frame_num].iov_base;
+ if (!odp_unlikely(mmap_tx_kernel_ready(ppd.raw)))
+ break;
- next_frame_num = (frame_num + 1) % ring->rd_num;
+ pkt_len = odp_packet_len(pkt_table[i]);
+ ppd.v2->tp_h.tp_snaplen = pkt_len;
+ ppd.v2->tp_h.tp_len = pkt_len;
- pkt_len = odp_packet_len(pkt_table[i]);
- ppd.v2->tp_h.tp_snaplen = pkt_len;
- ppd.v2->tp_h.tp_len = pkt_len;
+ buf = (uint8_t *)ppd.raw + TPACKET2_HDRLEN -
+ sizeof(struct sockaddr_ll);
+ odp_packet_copydata_out(pkt_table[i], 0, pkt_len, buf);
- odp_packet_copydata_out(pkt_table[i], 0, pkt_len,
- (uint8_t *)ppd.raw +
- TPACKET2_HDRLEN -
- sizeof(struct sockaddr_ll));
+ mmap_tx_user_ready(ppd.raw);
- mmap_tx_user_ready(ppd.raw);
+ if (++frame_num >= frame_count)
+ frame_num = 0;
- odp_packet_free(pkt_table[i]);
- frame_num = next_frame_num;
- i++;
- } else {
+ i++;
+ }
+
+ ret = sendto(sock, NULL, 0, MSG_DONTWAIT, NULL, 0);
+ send_errno = errno;
+
+ /* On success, the return value indicates the number of bytes sent. On
+ * failure a value of -1 is returned, even if the failure occurred
+ * after some of the packets in the ring have already been sent, so we
+ * need to inspect the packet status to determine which were sent. */
+ for (frame_num = first_frame_num, n = 0; n < i; ++n) {
+ struct tpacket2_hdr *hdr = ring->rd[frame_num].iov_base;
+
+ if (odp_likely(hdr->tp_status == TP_STATUS_AVAILABLE)) {
+ nb_tx++;
+ } else if (hdr->tp_status & TP_STATUS_WRONG_FORMAT) {
+ /* status will be cleared on the next send request */
break;
}
+
+ if (++frame_num >= frame_count)
+ frame_num = 0;
}
- ring->frame_num = frame_num;
+ ring->frame_num = (ring->frame_num + nb_tx) % frame_count;
- ret = sendto(sock, NULL, 0, MSG_DONTWAIT, NULL, 0);
- if (ret == -1) {
- if (errno != EAGAIN) {
- __odp_errno = errno;
- ODP_ERR("sendto(pkt mmap): %s\n", strerror(errno));
- return -1;
- }
+ if (odp_unlikely(ret == -1 &&
+ nb_tx == 0 &&
+ SOCK_ERR_REPORT(send_errno))) {
+ __odp_errno = send_errno;
+ ODP_ERR("sendto(pkt mmap): %s\n", strerror(send_errno));
+ return -1;
}
- return i;
+ for (i = 0; i < nb_tx; ++i)
+ odp_packet_free(pkt_table[i]);
+
+ return nb_tx;
}
static void mmap_fill_ring(struct ring *ring, odp_pool_t pool_hdl, int fanout)
@@ -260,21 +286,6 @@ static void mmap_fill_ring(struct ring *ring, odp_pool_t pool_hdl, int fanout)
ring->flen = ring->req.tp_frame_size;
}
-static int mmap_set_packet_loss_discard(int sock)
-{
- int ret, discard = 1;
-
- ret = setsockopt(sock, SOL_PACKET, PACKET_LOSS, (void *)&discard,
- sizeof(discard));
- if (ret == -1) {
- __odp_errno = errno;
- ODP_ERR("setsockopt(PACKET_LOSS): %s\n", strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
static int mmap_setup_ring(int sock, struct ring *ring, int type,
odp_pool_t pool_hdl, int fanout)
{
@@ -284,12 +295,6 @@ static int mmap_setup_ring(int sock, struct ring *ring, int type,
ring->type = type;
ring->version = TPACKET_V2;
- if (type == PACKET_TX_RING) {
- ret = mmap_set_packet_loss_discard(sock);
- if (ret != 0)
- return -1;
- }
-
mmap_fill_ring(ring, pool_hdl, fanout);
ret = setsockopt(sock, SOL_PACKET, type, &ring->req, sizeof(ring->req));
@@ -383,30 +388,6 @@ static int mmap_bind_sock(pkt_sock_mmap_t *pkt_sock, const char *netdev)
return 0;
}
-static int mmap_store_hw_addr(pkt_sock_mmap_t *const pkt_sock,
- const char *netdev)
-{
- struct ifreq ethreq;
- int ret;
-
- /* get MAC address */
- memset(&ethreq, 0, sizeof(ethreq));
- snprintf(ethreq.ifr_name, IF_NAMESIZE, "%s", netdev);
- ret = ioctl(pkt_sock->sockfd, SIOCGIFHWADDR, &ethreq);
- if (ret != 0) {
- __odp_errno = errno;
- ODP_ERR("ioctl(SIOCGIFHWADDR): %s: \"%s\".\n",
- strerror(errno),
- ethreq.ifr_name);
- return -1;
- }
-
- ethaddr_copy(pkt_sock->if_mac,
- (unsigned char *)ethreq.ifr_ifru.ifru_hwaddr.sa_data);
-
- return 0;
-}
-
static int sock_mmap_close(pktio_entry_t *entry)
{
pkt_sock_mmap_t *const pkt_sock = &entry->s.pkt_sock_mmap;
@@ -468,7 +449,7 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED,
if (ret != 0)
goto error;
- ret = mmap_store_hw_addr(pkt_sock, netdev);
+ ret = mac_addr_get_fd(pkt_sock->sockfd, netdev, pkt_sock->if_mac);
if (ret != 0)
goto error;
diff --git a/platform/linux-generic/test/Makefile.am b/platform/linux-generic/test/Makefile.am
index 7d1ce1b0b..11648d4b2 100644
--- a/platform/linux-generic/test/Makefile.am
+++ b/platform/linux-generic/test/Makefile.am
@@ -26,6 +26,11 @@ TESTS = pktio/pktio_run \
${top_builddir}/test/validation/system/system_main$(EXEEXT)
SUBDIRS = $(ODP_MODULES)
+
+if HAVE_PCAP
+TESTS += pktio/pktio_run_pcap
+endif
+
endif
#performance tests refer to pktio_env
diff --git a/platform/linux-generic/test/pktio/Makefile.am b/platform/linux-generic/test/pktio/Makefile.am
index 93281dd1b..6fe20139c 100644
--- a/platform/linux-generic/test/pktio/Makefile.am
+++ b/platform/linux-generic/test/pktio/Makefile.am
@@ -1,2 +1,6 @@
dist_bin_SCRIPTS = pktio_env \
pktio_run
+
+if HAVE_PCAP
+dist_bin_SCRIPTS += pktio_run_pcap
+endif
diff --git a/platform/linux-generic/test/pktio/pktio_env b/platform/linux-generic/test/pktio/pktio_env
index 5e547e47b..345b5bd56 100644
--- a/platform/linux-generic/test/pktio/pktio_env
+++ b/platform/linux-generic/test/pktio/pktio_env
@@ -18,10 +18,10 @@
# Network set up
# IF0 <---> IF1
# IF2 <---> IF3
-IF0=pktio-p0-p1
-IF1=pktio-p1-p0
-IF2=pktio-p2-p3
-IF3=pktio-p3-p2
+IF0=pktiop0p1
+IF1=pktiop1p0
+IF2=pktiop2p3
+IF3=pktiop3p2
if [ "$0" = "$BASH_SOURCE" ]; then
echo "Error: Platform specific env file has to be sourced."
diff --git a/platform/linux-generic/test/pktio/pktio_run_pcap b/platform/linux-generic/test/pktio/pktio_run_pcap
new file mode 100755
index 000000000..c130417c5
--- /dev/null
+++ b/platform/linux-generic/test/pktio/pktio_run_pcap
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright (c) 2015, Linaro Limited
+# All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# directories where pktio_main 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 intree.
+# -in the current directory.
+# running stand alone out of tree requires setting PATH
+PATH=${TEST_DIR}/pktio:$PATH
+PATH=$(dirname $0):$PATH
+PATH=$(dirname $0)/../../../../test/validation/pktio:$PATH
+PATH=.:$PATH
+
+pktio_main_path=$(which pktio_main${EXEEXT})
+if [ -x "$pktio_main_path" ] ; then
+ echo "running with $pktio_main_path"
+else
+ echo "cannot find pktio_main${EXEEXT}: please set you PATH for it."
+fi
+
+PCAP_FNAME=vald.pcap
+export ODP_PKTIO_IF0="pcap:out=${PCAP_FNAME}"
+export ODP_PKTIO_IF1="pcap:in=${PCAP_FNAME}"
+pktio_main${EXEEXT}
+ret=$?
+rm -f ${PCAP_FNAME}
+exit $ret
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 4983a0cee..16316b928 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3411,7 +3411,7 @@ sub process {
# function brace can't be on same line, except for #defines of do while,
# or if closed on same line
if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and
- !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) {
+ !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) {
if (ERROR("OPEN_BRACE",
"open brace '{' following function declarations go on the next line\n" . $herecurr) &&
$fix) {
@@ -3923,8 +3923,8 @@ sub process {
## }
#need space before brace following if, while, etc
- if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) ||
- $line =~ /do{/) {
+ if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\){/) ||
+ $line =~ /do\{/) {
if (ERROR("SPACING",
"space required before the open brace '{'\n" . $herecurr) &&
$fix) {
@@ -4377,7 +4377,7 @@ sub process {
$dstat !~ /^for\s*$Constant$/ && # for (...)
$dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar()
$dstat !~ /^do\s*{/ && # do {...
- $dstat !~ /^\({/ && # ({...
+ $dstat !~ /^\(\{/ && # ({...
$ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
{
$ctx =~ s/\n*$//;
diff --git a/scripts/git_hash.sh b/scripts/git_hash.sh
index 6cfec2f36..e15094e50 100755
--- a/scripts/git_hash.sh
+++ b/scripts/git_hash.sh
@@ -8,8 +8,8 @@ ROOTDIR=${1}
CUSTOM_STR=${CUSTOM_STR:-https://git.linaro.org/lng/odp.git}
if [ -d ${ROOTDIR}/.git ]; then
- hash=$(git describe | tr -d "\n")
- if git diff-index --name-only HEAD &>/dev/null ; then
+ hash=$(git --git-dir=${ROOTDIR}/.git describe | tr -d "\n")
+ if git --git-dir=${ROOTDIR}/.git diff-index --name-only HEAD &>/dev/null ; then
dirty=-dirty
fi
diff --git a/test/api_test/odp_common.c b/test/api_test/odp_common.c
index 0dbefa5b0..681d915e6 100644
--- a/test/api_test/odp_common.c
+++ b/test/api_test/odp_common.c
@@ -74,7 +74,7 @@ int odp_test_thread_create(void *func_ptr(void *), pthrd_arg *arg)
odp_cpumask_t cpumask;
/* Create and init additional threads */
- odp_cpumask_def_worker(&cpumask, arg->numthrds);
+ odp_cpumask_default_worker(&cpumask, arg->numthrds);
odph_linux_pthread_create(thread_tbl, &cpumask, func_ptr,
(void *)arg);
diff --git a/test/performance/odp_atomic.c b/test/performance/odp_atomic.c
index eefce06ce..1402a0c91 100644
--- a/test/performance/odp_atomic.c
+++ b/test/performance/odp_atomic.c
@@ -284,7 +284,7 @@ int odp_test_thread_create(void *func_ptr(void *), pthrd_arg *arg)
odp_cpumask_t cpumask;
/* Create and init additional threads */
- odp_cpumask_def_worker(&cpumask, arg->numthrds);
+ odp_cpumask_default_worker(&cpumask, arg->numthrds);
odph_linux_pthread_create(thread_tbl, &cpumask, func_ptr,
(void *)arg);
diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
index 64fc1b2aa..f415ba39f 100644
--- a/test/performance/odp_l2fwd.c
+++ b/test/performance/odp_l2fwd.c
@@ -41,25 +41,19 @@
#define SHM_PKT_POOL_BUF_SIZE 1856
/** @def MAX_PKT_BURST
- * @brief Maximum number of packet bursts
+ * @brief Maximum number of packet in a burst
*/
-#define MAX_PKT_BURST 16
+#define MAX_PKT_BURST 32
-/** @def APPL_MODE_PKT_BURST
- * @brief The application will handle pakcets in bursts
- */
-#define APPL_MODE_PKT_BURST 0
-
-/** @def APPL_MODE_PKT_QUEUE
- * @brief The application will handle packets in queues
- */
-#define APPL_MODE_PKT_QUEUE 1
-
-/** @def PRINT_APPL_MODE(x)
- * @brief Macro to print the current status of how the application handles
- * packets.
+/**
+ * Packet input mode
*/
-#define PRINT_APPL_MODE(x) printf("%s(%i)\n", #x, (x))
+typedef enum pkt_in_mode_t {
+ DIRECT_RECV,
+ SCHED_NONE,
+ SCHED_ATOMIC,
+ SCHED_ORDERED,
+} pkt_in_mode_t;
/** Get rid of path in filename - only for unix-type paths using '/' */
#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
@@ -71,10 +65,13 @@ typedef struct {
int cpu_count;
int if_count; /**< Number of interfaces to be used */
char **if_names; /**< Array of pointers to interface names */
- int mode; /**< Packet IO mode */
+ pkt_in_mode_t mode; /**< Packet input mode */
int time; /**< Time in seconds to run. */
int accuracy; /**< Number of seconds to get and print statistics */
char *if_str; /**< Storage for interface names */
+ int dst_change; /**< Change destination eth addresses */
+ int src_change; /**< Change source eth addresses */
+ int error_check; /**< Check packet errors */
} appl_args_t;
static int exit_threads; /**< Break workers loop if set to 1 */
@@ -82,29 +79,45 @@ static int exit_threads; /**< Break workers loop if set to 1 */
/**
* Statistics
*/
-typedef struct {
- uint64_t packets; /**< Number of forwarded packets. */
- uint64_t drops; /**< Number of dropped packets. */
-} stats_t;
+typedef union {
+ struct {
+ /** Number of forwarded packets */
+ uint64_t packets;
+ /** Packets dropped due to receive error */
+ uint64_t rx_drops;
+ /** Packets dropped due to transmit error */
+ uint64_t tx_drops;
+ } s;
+
+ uint8_t padding[ODP_CACHE_LINE_SIZE];
+} stats_t ODP_ALIGNED_CACHE;
/**
* Thread specific arguments
*/
typedef struct {
- int src_idx; /**< Source interface identifier */
- stats_t **stats; /**< Per thread packet stats */
+ int src_idx; /**< Source interface identifier */
+ stats_t *stats; /**< Pointer to per thread stats */
} thread_args_t;
/**
* Grouping of all global data
*/
typedef struct {
+ /** Per thread packet stats */
+ stats_t stats[MAX_WORKERS];
/** Application (parsed) arguments */
appl_args_t appl;
/** Thread specific arguments */
thread_args_t thread[MAX_WORKERS];
/** Table of pktio handles */
odp_pktio_t pktios[ODP_CONFIG_PKTIO_ENTRIES];
+ /** Table of port ethernet addresses */
+ odph_ethaddr_t port_eth_addr[ODP_CONFIG_PKTIO_ENTRIES];
+ /** Table of dst ethernet addresses */
+ odph_ethaddr_t dst_eth_addr[ODP_CONFIG_PKTIO_ENTRIES];
+ /** Table of dst ports */
+ int dst_port[ODP_CONFIG_PKTIO_ENTRIES];
} args_t;
/** Global pointer to args */
@@ -113,8 +126,11 @@ static args_t *gbl_args;
static odp_barrier_t barrier;
/* helper funcs */
-static inline odp_queue_t lookup_dest_q(odp_packet_t pkt);
-static int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned len);
+static inline int lookup_dest_port(odp_packet_t pkt);
+static inline int find_dest_port(int port);
+static inline int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned num);
+static void fill_eth_addrs(odp_packet_t pkt_tbl[], unsigned num,
+ int dst_port);
static void parse_args(int argc, char *argv[], appl_args_t *appl_args);
static void print_info(char *progname, appl_args_t *appl_args);
static void usage(char *progname);
@@ -126,55 +142,87 @@ static void usage(char *progname);
*/
static void *pktio_queue_thread(void *arg)
{
+ odp_event_t ev_tbl[MAX_PKT_BURST];
+ odp_packet_t pkt_tbl[MAX_PKT_BURST];
+ int pkts;
int thr;
- odp_queue_t outq_def;
- odp_packet_t pkt;
- odp_event_t ev;
+ uint64_t wait;
+ int dst_idx;
+ odp_pktio_t pktio_dst;
thread_args_t *thr_args = arg;
-
- stats_t *stats = calloc(1, sizeof(stats_t));
- *thr_args->stats = stats;
+ stats_t *stats = thr_args->stats;
thr = odp_thread_id();
printf("[%02i] QUEUE mode\n", thr);
odp_barrier_wait(&barrier);
+ wait = odp_schedule_wait_time(ODP_TIME_MSEC * 100);
+
/* Loop packets */
while (!exit_threads) {
- /* Use schedule to get buf from any input queue */
- ev = odp_schedule(NULL, ODP_SCHED_WAIT);
- pkt = odp_packet_from_event(ev);
+ int sent, i;
+ unsigned tx_drops;
+
+ pkts = odp_schedule_multi(NULL, wait, ev_tbl, MAX_PKT_BURST);
- /* Drop packets with errors */
- if (odp_unlikely(drop_err_pkts(&pkt, 1) == 0)) {
- stats->drops += 1;
+ if (pkts <= 0)
continue;
+
+ for (i = 0; i < pkts; i++)
+ pkt_tbl[i] = odp_packet_from_event(ev_tbl[i]);
+
+ if (gbl_args->appl.error_check) {
+ int rx_drops;
+
+ /* Drop packets with errors */
+ rx_drops = drop_err_pkts(pkt_tbl, pkts);
+
+ if (odp_unlikely(rx_drops)) {
+ stats->s.rx_drops += rx_drops;
+ if (pkts == rx_drops)
+ continue;
+
+ pkts -= rx_drops;
+ }
}
- outq_def = lookup_dest_q(pkt);
+ /* packets from the same queue are from the same interface */
+ dst_idx = lookup_dest_port(pkt_tbl[0]);
+ fill_eth_addrs(pkt_tbl, pkts, dst_idx);
+ pktio_dst = gbl_args->pktios[dst_idx];
- /* Enqueue the packet for output */
- if (odp_queue_enq(outq_def, ev)) {
- printf(" [%i] Queue enqueue failed.\n", thr);
- odp_packet_free(pkt);
- continue;
+ sent = odp_pktio_send(pktio_dst, pkt_tbl, pkts);
+
+ sent = odp_unlikely(sent < 0) ? 0 : sent;
+ tx_drops = pkts - sent;
+
+ if (odp_unlikely(tx_drops)) {
+ stats->s.tx_drops += tx_drops;
+
+ /* Drop rejected packets */
+ for (i = sent; i < pkts; i++)
+ odp_packet_free(pkt_tbl[i]);
}
- stats->packets += 1;
+ stats->s.packets += pkts;
}
- free(stats);
+ /* Make sure that the last stats write is visible to readers */
+ odp_sync_stores();
+
return NULL;
}
/**
- * Lookup the destination pktio for a given packet
+ * Lookup the destination port for a given packet
+ *
+ * @param pkt ODP packet handle
*/
-static inline odp_queue_t lookup_dest_q(odp_packet_t pkt)
+static inline int lookup_dest_port(odp_packet_t pkt)
{
- int i, src_idx, dst_idx;
- odp_pktio_t pktio_src, pktio_dst;
+ int i, src_idx;
+ odp_pktio_t pktio_src;
pktio_src = odp_packet_input(pkt);
@@ -185,39 +233,51 @@ static inline odp_queue_t lookup_dest_q(odp_packet_t pkt)
if (src_idx == -1)
LOG_ABORT("Failed to determine pktio input\n");
- dst_idx = (src_idx % 2 == 0) ? src_idx+1 : src_idx-1;
- pktio_dst = gbl_args->pktios[dst_idx];
+ return gbl_args->dst_port[src_idx];
+}
+
+/**
+ * Find the destination port for a given input port
+ *
+ * @param port Input port index
+ */
+static inline int find_dest_port(int port)
+{
+ /* Even number of ports */
+ if (gbl_args->appl.if_count % 2 == 0)
+ return (port % 2 == 0) ? port + 1 : port - 1;
- return odp_pktio_outq_getdef(pktio_dst);
+ /* Odd number of ports */
+ if (port == gbl_args->appl.if_count - 1)
+ return 0;
+ else
+ return port + 1;
}
/**
- * Packet IO worker thread using bursts from/to IO resources
+ * Packet IO worker thread accessing IO resources directly
*
* @param arg thread arguments of type 'thread_args_t *'
*/
-static void *pktio_ifburst_thread(void *arg)
+static void *pktio_direct_recv_thread(void *arg)
{
int thr;
- thread_args_t *thr_args;
- int pkts, pkts_ok;
+ int pkts;
odp_packet_t pkt_tbl[MAX_PKT_BURST];
int src_idx, dst_idx;
odp_pktio_t pktio_src, pktio_dst;
+ thread_args_t *thr_args = arg;
+ stats_t *stats = thr_args->stats;
thr = odp_thread_id();
- thr_args = arg;
-
- stats_t *stats = calloc(1, sizeof(stats_t));
- *thr_args->stats = stats;
src_idx = thr_args->src_idx;
- dst_idx = (src_idx % 2 == 0) ? src_idx+1 : src_idx-1;
+ dst_idx = gbl_args->dst_port[src_idx];
pktio_src = gbl_args->pktios[src_idx];
pktio_dst = gbl_args->pktios[dst_idx];
printf("[%02i] srcif:%s dstif:%s spktio:%02" PRIu64
- " dpktio:%02" PRIu64 " BURST mode\n",
+ " dpktio:%02" PRIu64 " DIRECT RECV mode\n",
thr,
gbl_args->appl.if_names[src_idx],
gbl_args->appl.if_names[dst_idx],
@@ -226,34 +286,49 @@ static void *pktio_ifburst_thread(void *arg)
/* Loop packets */
while (!exit_threads) {
+ int sent, i;
+ unsigned tx_drops;
+
pkts = odp_pktio_recv(pktio_src, pkt_tbl, MAX_PKT_BURST);
- if (pkts <= 0)
+ if (odp_unlikely(pkts <= 0))
continue;
- /* Drop packets with errors */
- pkts_ok = drop_err_pkts(pkt_tbl, pkts);
- if (pkts_ok > 0) {
- int sent = odp_pktio_send(pktio_dst, pkt_tbl, pkts_ok);
-
- sent = sent > 0 ? sent : 0;
- if (odp_unlikely(sent < pkts_ok)) {
- stats->drops += pkts_ok - sent;
- do
- odp_packet_free(pkt_tbl[sent]);
- while (++sent < pkts_ok);
+ if (gbl_args->appl.error_check) {
+ int rx_drops;
+
+ /* Drop packets with errors */
+ rx_drops = drop_err_pkts(pkt_tbl, pkts);
+
+ if (odp_unlikely(rx_drops)) {
+ stats->s.rx_drops += rx_drops;
+ if (pkts == rx_drops)
+ continue;
+
+ pkts -= rx_drops;
}
}
- if (odp_unlikely(pkts_ok != pkts))
- stats->drops += pkts - pkts_ok;
+ fill_eth_addrs(pkt_tbl, pkts, dst_idx);
- if (pkts_ok == 0)
- continue;
+ sent = odp_pktio_send(pktio_dst, pkt_tbl, pkts);
- stats->packets += pkts_ok;
+ sent = odp_unlikely(sent < 0) ? 0 : sent;
+ tx_drops = pkts - sent;
+
+ if (odp_unlikely(tx_drops)) {
+ stats->s.tx_drops += tx_drops;
+
+ /* Drop rejected packets */
+ for (i = sent; i < pkts; i++)
+ odp_packet_free(pkt_tbl[i]);
+ }
+
+ stats->s.packets += pkts;
}
- free(stats);
+ /* Make sure that the last stats write is visible to readers */
+ odp_sync_stores();
+
return NULL;
}
@@ -262,13 +337,11 @@ static void *pktio_ifburst_thread(void *arg)
*
* @param dev Name of device to open
* @param pool Pool to associate with device for packet RX/TX
- * @param mode Packet processing mode for this device (BURST or QUEUE)
*
* @return The handle of the created pktio object.
* @retval ODP_PKTIO_INVALID if the create fails.
*/
-static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool,
- int mode)
+static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool)
{
char inq_name[ODP_QUEUE_NAME_LEN];
odp_queue_param_t qparam;
@@ -276,10 +349,11 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool,
odp_pktio_t pktio;
int ret;
odp_pktio_param_t pktio_param;
+ odp_schedule_sync_t sync_mode;
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
- if (mode == APPL_MODE_PKT_BURST)
+ if (gbl_args->appl.mode == DIRECT_RECV)
pktio_param.in_mode = ODP_PKTIN_MODE_RECV;
else
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
@@ -293,13 +367,20 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool,
printf("created pktio %" PRIu64 " (%s)\n",
odp_pktio_to_u64(pktio), dev);
- /* no further setup needed for burst mode */
- if (mode == APPL_MODE_PKT_BURST)
+ /* no further setup needed for direct receive mode */
+ if (gbl_args->appl.mode == DIRECT_RECV)
return pktio;
+ if (gbl_args->appl.mode == SCHED_ATOMIC)
+ sync_mode = ODP_SCHED_SYNC_ATOMIC;
+ else if (gbl_args->appl.mode == SCHED_ORDERED)
+ sync_mode = ODP_SCHED_SYNC_ORDERED;
+ else
+ sync_mode = ODP_SCHED_SYNC_NONE;
+
odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
- qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC;
+ qparam.sched.sync = sync_mode;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
snprintf(inq_name, sizeof(inq_name), "%" PRIu64 "-pktio_inq_def",
odp_pktio_to_u64(pktio));
@@ -329,40 +410,56 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool,
* @param timeout Number of seconds for stats calculation
*
*/
-static int print_speed_stats(int num_workers, stats_t **thr_stats,
- int duration, int timeout)
+static int print_speed_stats(int num_workers, stats_t *thr_stats,
+ int duration, int timeout)
{
- uint64_t pkts, pkts_prev = 0, pps, drops, maximum_pps = 0;
- int i, elapsed = 0;
+ uint64_t pkts = 0;
+ uint64_t pkts_prev = 0;
+ uint64_t pps;
+ uint64_t rx_drops, tx_drops;
+ uint64_t maximum_pps = 0;
+ int i;
+ int elapsed = 0;
+ int stats_enabled = 1;
int loop_forever = (duration == 0);
+ if (timeout <= 0) {
+ stats_enabled = 0;
+ timeout = 1;
+ }
/* Wait for all threads to be ready*/
odp_barrier_wait(&barrier);
do {
pkts = 0;
- drops = 0;
+ rx_drops = 0;
+ tx_drops = 0;
sleep(timeout);
for (i = 0; i < num_workers; i++) {
- pkts += thr_stats[i]->packets;
- drops += thr_stats[i]->drops;
+ pkts += thr_stats[i].s.packets;
+ rx_drops += thr_stats[i].s.rx_drops;
+ tx_drops += thr_stats[i].s.tx_drops;
}
- pps = (pkts - pkts_prev) / timeout;
- if (pps > maximum_pps)
- maximum_pps = pps;
- printf("%" PRIu64 " pps, %" PRIu64 " max pps, ", pps,
- maximum_pps);
+ if (stats_enabled) {
+ pps = (pkts - pkts_prev) / timeout;
+ if (pps > maximum_pps)
+ maximum_pps = pps;
+ printf("%" PRIu64 " pps, %" PRIu64 " max pps, ", pps,
+ maximum_pps);
- printf(" %" PRIu64 " total drops\n", drops);
+ printf(" %" PRIu64 " rx drops, %" PRIu64 " tx drops\n",
+ rx_drops, tx_drops);
+ pkts_prev = pkts;
+ }
elapsed += timeout;
- pkts_prev = pkts;
} while (loop_forever || (elapsed < duration));
- printf("TEST RESULT: %" PRIu64 " maximum packets per second.\n",
- maximum_pps);
+ if (stats_enabled)
+ printf("TEST RESULT: %" PRIu64 " maximum packets per second.\n",
+ maximum_pps);
return pkts > 100 ? 0 : -1;
}
@@ -380,8 +477,11 @@ int main(int argc, char *argv[])
odp_shm_t shm;
odp_cpumask_t cpumask;
char cpumaskstr[ODP_CPUMASK_STR_SIZE];
+ odph_ethaddr_t new_addr;
+ odp_pktio_t pktio;
odp_pool_param_t params;
int ret;
+ stats_t *stats;
/* Init ODP before calling anything else */
if (odp_init_global(NULL, NULL)) {
@@ -418,7 +518,7 @@ int main(int argc, char *argv[])
num_workers = gbl_args->appl.cpu_count;
/* Get default worker cpumask */
- num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
+ num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
printf("num worker threads: %i\n", num_workers);
@@ -430,11 +530,6 @@ int main(int argc, char *argv[])
num_workers);
exit(EXIT_FAILURE);
}
- if (gbl_args->appl.if_count % 2 != 0) {
- LOG_ERR("Error: interface count %d is odd in fwd appl.\n",
- gbl_args->appl.if_count);
- exit(EXIT_FAILURE);
- }
/* Create packet pool */
odp_pool_param_init(&params);
@@ -452,24 +547,36 @@ int main(int argc, char *argv[])
odp_pool_print(pool);
for (i = 0; i < gbl_args->appl.if_count; ++i) {
- gbl_args->pktios[i] = create_pktio(gbl_args->appl.if_names[i],
- pool, gbl_args->appl.mode);
- if (gbl_args->pktios[i] == ODP_PKTIO_INVALID)
+ pktio = create_pktio(gbl_args->appl.if_names[i], pool);
+ if (pktio == ODP_PKTIO_INVALID)
exit(EXIT_FAILURE);
+ gbl_args->pktios[i] = pktio;
- ret = odp_pktio_start(gbl_args->pktios[i]);
- if (ret) {
- LOG_ERR("Error: unable to start %s\n",
- gbl_args->appl.if_names[i]);
+ /* Save interface ethernet address */
+ if (odp_pktio_mac_addr(pktio, gbl_args->port_eth_addr[i].addr,
+ ODPH_ETHADDR_LEN) != ODPH_ETHADDR_LEN) {
+ LOG_ERR("Error: interface ethernet address unknown\n");
exit(EXIT_FAILURE);
}
+ /* Save destination eth address */
+ if (gbl_args->appl.dst_change) {
+ /* 02:00:00:00:00:XX */
+ memset(&new_addr, 0, sizeof(odph_ethaddr_t));
+ new_addr.addr[0] = 0x02;
+ new_addr.addr[5] = i;
+ gbl_args->dst_eth_addr[i] = new_addr;
+ }
+
+ /* Save interface destination port */
+ gbl_args->dst_port[i] = find_dest_port(i);
}
+
gbl_args->pktios[i] = ODP_PKTIO_INVALID;
memset(thread_tbl, 0, sizeof(thread_tbl));
- stats_t **stats = calloc(1, sizeof(stats_t) * num_workers);
+ stats = gbl_args->stats;
odp_barrier_init(&barrier, num_workers + 1);
@@ -479,9 +586,9 @@ int main(int argc, char *argv[])
odp_cpumask_t thd_mask;
void *(*thr_run_func) (void *);
- if (gbl_args->appl.mode == APPL_MODE_PKT_BURST)
- thr_run_func = pktio_ifburst_thread;
- else /* APPL_MODE_PKT_QUEUE */
+ if (gbl_args->appl.mode == DIRECT_RECV)
+ thr_run_func = pktio_direct_recv_thread;
+ else /* SCHED_NONE / SCHED_ATOMIC / SCHED_ORDERED */
thr_run_func = pktio_queue_thread;
gbl_args->thread[i].src_idx = i % gbl_args->appl.if_count;
@@ -495,9 +602,19 @@ int main(int argc, char *argv[])
cpu = odp_cpumask_next(&cpumask, cpu);
}
+ /* Start packet receive and transmit */
+ for (i = 0; i < gbl_args->appl.if_count; ++i) {
+ pktio = gbl_args->pktios[i];
+ ret = odp_pktio_start(pktio);
+ if (ret) {
+ LOG_ERR("Error: unable to start %s\n",
+ gbl_args->appl.if_names[i]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
ret = print_speed_stats(num_workers, stats, gbl_args->appl.time,
gbl_args->appl.accuracy);
- free(stats);
exit_threads = 1;
/* Master thread waits for other threads to exit */
@@ -516,29 +633,59 @@ int main(int argc, char *argv[])
* Frees packets with error and modifies pkt_tbl[] to only contain packets with
* no detected errors.
*
- * @param pkt_tbl Array of packet
- * @param len Length of pkt_tbl[]
+ * @param pkt_tbl Array of packets
+ * @param num Number of packets in pkt_tbl[]
*
- * @return Number of packets with no detected error
+ * @return Number of packets dropped
*/
-static int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned len)
+static int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned num)
{
odp_packet_t pkt;
- unsigned pkt_cnt = len;
+ unsigned dropped = 0;
unsigned i, j;
- for (i = 0, j = 0; i < len; ++i) {
+ for (i = 0, j = 0; i < num; ++i) {
pkt = pkt_tbl[i];
if (odp_unlikely(odp_packet_has_error(pkt))) {
odp_packet_free(pkt); /* Drop */
- pkt_cnt--;
+ dropped++;
} else if (odp_unlikely(i != j++)) {
pkt_tbl[j-1] = pkt;
}
}
- return pkt_cnt;
+ return dropped;
+}
+
+/**
+ * Fill packets' eth addresses according to the destination port
+ *
+ * @param pkt_tbl Array of packets
+ * @param num Number of packets in the array
+ * @param dst_port Destination port
+ */
+static void fill_eth_addrs(odp_packet_t pkt_tbl[], unsigned num, int dst_port)
+{
+ odp_packet_t pkt;
+ odph_ethhdr_t *eth;
+ unsigned i;
+
+ if (!gbl_args->appl.dst_change && !gbl_args->appl.src_change)
+ return;
+
+ for (i = 0; i < num; ++i) {
+ pkt = pkt_tbl[i];
+ if (odp_packet_has_eth(pkt)) {
+ eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
+
+ if (gbl_args->appl.src_change)
+ eth->src = gbl_args->port_eth_addr[dst_port];
+
+ if (gbl_args->appl.dst_change)
+ eth->dst = gbl_args->dst_eth_addr[dst_port];
+ }
+ }
}
/**
@@ -559,18 +706,22 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
{"count", required_argument, NULL, 'c'},
{"time", required_argument, NULL, 't'},
{"accuracy", required_argument, NULL, 'a'},
- {"interface", required_argument, NULL, 'i'}, /* return 'i' */
- {"mode", required_argument, NULL, 'm'}, /* return 'm' */
- {"help", no_argument, NULL, 'h'}, /* return 'h' */
+ {"interface", required_argument, NULL, 'i'},
+ {"mode", required_argument, NULL, 'm'},
+ {"dst_change", required_argument, NULL, 'd'},
+ {"src_change", required_argument, NULL, 's'},
+ {"error_check", required_argument, NULL, 'e'},
+ {"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
appl_args->time = 0; /* loop forever if time to run is 0 */
appl_args->accuracy = 1; /* get and print pps stats second */
- appl_args->mode = -1; /* Invalid, must be changed by parsing */
+ appl_args->src_change = 1; /* change eth src address by default */
+ appl_args->error_check = 0; /* don't check packet errors by default */
while (1) {
- opt = getopt_long(argc, argv, "+c:+t:+a:i:m:h",
+ opt = getopt_long(argc, argv, "+c:+t:+a:i:m:d:s:e:h",
longopts, &long_index);
if (opt == -1)
@@ -626,26 +777,36 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
appl_args->if_names[i] = token;
}
break;
-
case 'm':
i = atoi(optarg);
- if (i == 0)
- appl_args->mode = APPL_MODE_PKT_BURST;
+ if (i == 1)
+ appl_args->mode = SCHED_NONE;
+ else if (i == 2)
+ appl_args->mode = SCHED_ATOMIC;
+ else if (i == 3)
+ appl_args->mode = SCHED_ORDERED;
else
- appl_args->mode = APPL_MODE_PKT_QUEUE;
+ appl_args->mode = DIRECT_RECV;
+ break;
+ case 'd':
+ appl_args->dst_change = atoi(optarg);
+ break;
+ case 's':
+ appl_args->src_change = atoi(optarg);
+ break;
+ case 'e':
+ appl_args->error_check = atoi(optarg);
break;
-
case 'h':
usage(argv[0]);
exit(EXIT_SUCCESS);
break;
-
default:
break;
}
}
- if (appl_args->if_count == 0 || appl_args->mode == -1) {
+ if (appl_args->if_count == 0) {
usage(argv[0]);
exit(EXIT_FAILURE);
}
@@ -681,10 +842,14 @@ static void print_info(char *progname, appl_args_t *appl_args)
printf(" %s", appl_args->if_names[i]);
printf("\n"
"Mode: ");
- if (appl_args->mode == APPL_MODE_PKT_BURST)
- PRINT_APPL_MODE(APPL_MODE_PKT_BURST);
- else
- PRINT_APPL_MODE(APPL_MODE_PKT_QUEUE);
+ if (appl_args->mode == DIRECT_RECV)
+ printf("DIRECT_RECV");
+ else if (appl_args->mode == SCHED_NONE)
+ printf("SCHED_NONE");
+ else if (appl_args->mode == SCHED_ATOMIC)
+ printf("SCHED_ATOMIC");
+ else if (appl_args->mode == SCHED_ORDERED)
+ printf("SCHED_ORDERED");
printf("\n\n");
fflush(NULL);
}
@@ -705,16 +870,25 @@ static void usage(char *progname)
"\n"
"Mandatory OPTIONS:\n"
" -i, --interface Eth interfaces (comma-separated, no spaces)\n"
- " -m, --mode 0: Burst send&receive packets (no queues)\n"
- " 1: Send&receive packets through ODP queues.\n"
"\n"
"Optional OPTIONS\n"
+ " -m, --mode 0: Send&receive packets directly from NIC (default)\n"
+ " 1: Send&receive packets through scheduler sync none queues\n"
+ " 2: Send&receive packets through scheduler sync atomic queues\n"
+ " 3: Send&receive packets through scheduler sync ordered queues\n"
" -c, --count <number> CPU count.\n"
" -t, --time <number> Time in seconds to run.\n"
" -a, --accuracy <number> Time in seconds get print statistics\n"
" (default is 1 second).\n"
+ " -d, --dst_change 0: Don't change packets' dst eth addresses (default)\n"
+ " 1: Change packets' dst eth addresses\n"
+ " -s, --src_change 0: Don't change packets' src eth addresses\n"
+ " 1: Change packets' src eth addresses (default)\n"
+ " -e, --error_check 0: Don't check packet errors (default)\n"
+ " 1: Check packet errors\n"
" -h, --help Display help and exit.\n\n"
- " environment variables: ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
+ " environment variables: ODP_PKTIO_DISABLE_NETMAP\n"
+ " ODP_PKTIO_DISABLE_SOCKET_MMAP\n"
" ODP_PKTIO_DISABLE_SOCKET_MMSG\n"
" can be used to advanced pkt I/O selection for linux-generic\n"
"\n", NO_PATH(progname), NO_PATH(progname)
diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
index 709becfa3..efd26dc73 100644
--- a/test/performance/odp_pktio_perf.c
+++ b/test/performance/odp_pktio_perf.c
@@ -121,10 +121,12 @@ typedef struct {
odp_barrier_t tx_barrier;
odp_pktio_t pktio_tx;
odp_pktio_t pktio_rx;
- pkt_rx_stats_t rx_stats[ODP_CONFIG_MAX_THREADS];
- pkt_tx_stats_t tx_stats[ODP_CONFIG_MAX_THREADS];
+ pkt_rx_stats_t *rx_stats;
+ pkt_tx_stats_t *tx_stats;
uint8_t src_mac[ODPH_ETHADDR_LEN];
uint8_t dst_mac[ODPH_ETHADDR_LEN];
+ uint32_t rx_stats_size;
+ uint32_t tx_stats_size;
} test_globals_t;
/* Status of max rate search */
@@ -303,7 +305,7 @@ static void *run_thread_tx(void *arg)
int thr_id;
odp_queue_t outq;
pkt_tx_stats_t *stats;
- uint64_t next_tx_cycles, end_cycles, cur_cycles;
+ uint64_t burst_start_cycles, start_cycles, cur_cycles, send_duration;
uint64_t burst_gap_cycles;
uint32_t batch_len;
int unsent_pkts = 0;
@@ -328,18 +330,18 @@ static void *run_thread_tx(void *arg)
burst_gap_cycles = odp_time_ns_to_cycles(
ODP_TIME_SEC / (targs->pps / targs->batch_len));
+ send_duration = odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
odp_barrier_wait(&globals->tx_barrier);
cur_cycles = odp_time_cycles();
- next_tx_cycles = cur_cycles;
- end_cycles = cur_cycles +
- odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
-
- while (cur_cycles < end_cycles) {
+ start_cycles = cur_cycles;
+ burst_start_cycles = odp_time_diff_cycles(burst_gap_cycles, cur_cycles);
+ while (odp_time_diff_cycles(start_cycles, cur_cycles) < send_duration) {
unsigned alloc_cnt = 0, tx_cnt;
- if (cur_cycles < next_tx_cycles) {
+ if (odp_time_diff_cycles(burst_start_cycles, cur_cycles)
+ < burst_gap_cycles) {
cur_cycles = odp_time_cycles();
if (idle_start == 0)
idle_start = cur_cycles;
@@ -352,7 +354,7 @@ static void *run_thread_tx(void *arg)
idle_start = 0;
}
- next_tx_cycles += burst_gap_cycles;
+ burst_start_cycles += burst_gap_cycles;
alloc_cnt = alloc_packets(tx_event, batch_len - unsent_pkts);
if (alloc_cnt != batch_len)
@@ -468,7 +470,7 @@ static int process_results(uint64_t expected_tx_cnt,
char str[512];
int len = 0;
- for (i = 0; i < ODP_CONFIG_MAX_THREADS; ++i) {
+ for (i = 0; i < odp_thread_count_max(); ++i) {
rx_pkts += gbl_args->rx_stats[i].s.rx_cnt;
tx_pkts += gbl_args->tx_stats[i].s.tx_cnt;
}
@@ -544,8 +546,9 @@ static int setup_txrx_masks(odp_cpumask_t *thd_mask_tx,
int num_workers, num_tx_workers, num_rx_workers;
int i, cpu;
- num_workers = odp_cpumask_def_worker(&cpumask,
- gbl_args->args.cpu_count);
+ num_workers =
+ odp_cpumask_default_worker(&cpumask,
+ gbl_args->args.cpu_count);
if (num_workers < 2) {
LOG_ERR("Need at least two cores\n");
return -1;
@@ -610,8 +613,8 @@ static int run_test_single(odp_cpumask_t *thd_mask_tx,
odp_atomic_store_u32(&shutdown, 0);
memset(thd_tbl, 0, sizeof(thd_tbl));
- memset(&gbl_args->rx_stats, 0, sizeof(gbl_args->rx_stats));
- memset(&gbl_args->tx_stats, 0, sizeof(gbl_args->tx_stats));
+ memset(gbl_args->rx_stats, 0, gbl_args->rx_stats_size);
+ memset(gbl_args->tx_stats, 0, gbl_args->tx_stats_size);
expected_tx_cnt = status->pps_curr * gbl_args->args.duration;
@@ -701,7 +704,7 @@ static odp_pktio_t create_pktio(const char *iface, int schedule)
if (pool == ODP_POOL_INVALID)
return ODP_PKTIO_INVALID;
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
if (schedule)
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
@@ -989,6 +992,7 @@ int main(int argc, char **argv)
{
int ret;
odp_shm_t shm;
+ int max_thrs;
if (odp_init_global(NULL, NULL) != 0)
LOG_ABORT("Failed global init.\n");
@@ -1003,6 +1007,33 @@ int main(int argc, char **argv)
LOG_ABORT("Shared memory reserve failed.\n");
memset(gbl_args, 0, sizeof(test_globals_t));
+ max_thrs = odp_thread_count_max();
+
+ gbl_args->rx_stats_size = max_thrs * sizeof(pkt_rx_stats_t);
+ gbl_args->tx_stats_size = max_thrs * sizeof(pkt_tx_stats_t);
+
+ shm = odp_shm_reserve("test_globals.rx_stats",
+ gbl_args->rx_stats_size,
+ ODP_CACHE_LINE_SIZE, 0);
+
+ gbl_args->rx_stats = odp_shm_addr(shm);
+
+ if (gbl_args->rx_stats == NULL)
+ LOG_ABORT("Shared memory reserve failed.\n");
+
+ memset(gbl_args->rx_stats, 0, gbl_args->rx_stats_size);
+
+ shm = odp_shm_reserve("test_globals.tx_stats",
+ gbl_args->tx_stats_size,
+ ODP_CACHE_LINE_SIZE, 0);
+
+ gbl_args->tx_stats = odp_shm_addr(shm);
+
+ if (gbl_args->tx_stats == NULL)
+ LOG_ABORT("Shared memory reserve failed.\n");
+
+ memset(gbl_args->tx_stats, 0, gbl_args->tx_stats_size);
+
parse_args(argc, argv, &gbl_args->args);
ret = test_init();
diff --git a/test/performance/odp_scheduling.c b/test/performance/odp_scheduling.c
index 2a7e531fa..73eeb7245 100644
--- a/test/performance/odp_scheduling.c
+++ b/test/performance/odp_scheduling.c
@@ -183,9 +183,9 @@ static int test_alloc_single(int thr, odp_pool_t pool)
{
int i;
odp_buffer_t temp_buf;
- uint64_t t1, t2, cycles, ns;
+ uint64_t c1, c2, cycles;
- t1 = odp_time_cycles();
+ c1 = odp_cpu_cycles();
for (i = 0; i < ALLOC_ROUNDS; i++) {
temp_buf = odp_buffer_alloc(pool);
@@ -198,12 +198,12 @@ static int test_alloc_single(int thr, odp_pool_t pool)
odp_buffer_free(temp_buf);
}
- t2 = odp_time_cycles();
- cycles = odp_time_diff_cycles(t1, t2);
- ns = odp_time_cycles_to_ns(cycles);
+ c2 = odp_cpu_cycles();
+ cycles = odp_cpu_cycles_diff(c1, c2);
+ cycles = cycles / ALLOC_ROUNDS;
- printf(" [%i] alloc_sng alloc+free %"PRIu64" cycles, %"PRIu64" ns\n",
- thr, cycles/ALLOC_ROUNDS, ns/ALLOC_ROUNDS);
+ printf(" [%i] alloc_sng alloc+free %6" PRIu64 " CPU cycles\n",
+ thr, cycles);
return 0;
}
@@ -220,9 +220,9 @@ static int test_alloc_multi(int thr, odp_pool_t pool)
{
int i, j;
odp_buffer_t temp_buf[MAX_ALLOCS];
- uint64_t t1, t2, cycles, ns;
+ uint64_t c1, c2, cycles;
- t1 = odp_time_cycles();
+ c1 = odp_cpu_cycles();
for (i = 0; i < ALLOC_ROUNDS; i++) {
for (j = 0; j < MAX_ALLOCS; j++) {
@@ -238,13 +238,12 @@ static int test_alloc_multi(int thr, odp_pool_t pool)
odp_buffer_free(temp_buf[j-1]);
}
- t2 = odp_time_cycles();
- cycles = odp_time_diff_cycles(t1, t2);
- ns = odp_time_cycles_to_ns(cycles);
+ c2 = odp_cpu_cycles();
+ cycles = odp_cpu_cycles_diff(c1, c2);
+ cycles = cycles / (ALLOC_ROUNDS * MAX_ALLOCS);
- printf(" [%i] alloc_multi alloc+free %"PRIu64" cycles, %"PRIu64" ns\n",
- thr, cycles/(ALLOC_ROUNDS*MAX_ALLOCS),
- ns/(ALLOC_ROUNDS*MAX_ALLOCS));
+ printf(" [%i] alloc_multi alloc+free %6" PRIu64 " CPU cycles\n",
+ thr, cycles);
return 0;
}
@@ -265,7 +264,7 @@ static int test_poll_queue(int thr, odp_pool_t msg_pool)
odp_buffer_t buf;
test_message_t *t_msg;
odp_queue_t queue;
- uint64_t t1, t2, cycles, ns;
+ uint64_t c1, c2, cycles;
int i;
/* Alloc test message */
@@ -289,7 +288,7 @@ static int test_poll_queue(int thr, odp_pool_t msg_pool)
return -1;
}
- t1 = odp_time_cycles();
+ c1 = odp_cpu_cycles();
for (i = 0; i < QUEUE_ROUNDS; i++) {
ev = odp_buffer_to_event(buf);
@@ -310,12 +309,12 @@ static int test_poll_queue(int thr, odp_pool_t msg_pool)
}
}
- t2 = odp_time_cycles();
- cycles = odp_time_diff_cycles(t1, t2);
- ns = odp_time_cycles_to_ns(cycles);
+ c2 = odp_cpu_cycles();
+ cycles = odp_cpu_cycles_diff(c1, c2);
+ cycles = cycles / QUEUE_ROUNDS;
- printf(" [%i] poll_queue enq+deq %"PRIu64" cycles, %"PRIu64" ns\n",
- thr, cycles/QUEUE_ROUNDS, ns/QUEUE_ROUNDS);
+ printf(" [%i] poll_queue enq+deq %6" PRIu64 " CPU cycles\n",
+ thr, cycles);
odp_buffer_free(buf);
return 0;
@@ -341,14 +340,14 @@ static int test_schedule_single(const char *str, int thr,
{
odp_event_t ev;
odp_queue_t queue;
- uint64_t t1, t2, cycles, ns;
+ uint64_t c1, c2, cycles;
uint32_t i;
uint32_t tot;
if (create_queue(thr, msg_pool, prio))
return -1;
- t1 = odp_time_cycles();
+ c1 = odp_cpu_cycles();
for (i = 0; i < QUEUE_ROUNDS; i++) {
ev = odp_schedule(&queue, ODP_SCHED_WAIT);
@@ -382,18 +381,15 @@ static int test_schedule_single(const char *str, int thr,
odp_schedule_resume();
- t2 = odp_time_cycles();
- cycles = odp_time_diff_cycles(t1, t2);
- ns = odp_time_cycles_to_ns(cycles);
+ c2 = odp_cpu_cycles();
+ cycles = odp_cpu_cycles_diff(c1, c2);
odp_barrier_wait(barrier);
clear_sched_queues();
- cycles = cycles/tot;
- ns = ns/tot;
+ cycles = cycles / tot;
- printf(" [%i] %s enq+deq %"PRIu64" cycles, %"PRIu64" ns\n",
- thr, str, cycles, ns);
+ printf(" [%i] %s enq+deq %6" PRIu64 " CPU cycles\n", thr, str, cycles);
return 0;
}
@@ -419,9 +415,7 @@ static int test_schedule_many(const char *str, int thr,
{
odp_event_t ev;
odp_queue_t queue;
- uint64_t t1;
- uint64_t t2;
- uint64_t cycles, ns;
+ uint64_t c1, c2, cycles;
uint32_t i;
uint32_t tot;
@@ -429,7 +423,7 @@ static int test_schedule_many(const char *str, int thr,
return -1;
/* Start sched-enq loop */
- t1 = odp_time_cycles();
+ c1 = odp_cpu_cycles();
for (i = 0; i < QUEUE_ROUNDS; i++) {
ev = odp_schedule(&queue, ODP_SCHED_WAIT);
@@ -463,18 +457,15 @@ static int test_schedule_many(const char *str, int thr,
odp_schedule_resume();
- t2 = odp_time_cycles();
- cycles = odp_time_diff_cycles(t1, t2);
- ns = odp_time_cycles_to_ns(cycles);
+ c2 = odp_cpu_cycles();
+ cycles = odp_cpu_cycles_diff(c1, c2);
odp_barrier_wait(barrier);
clear_sched_queues();
- cycles = cycles/tot;
- ns = ns/tot;
+ cycles = cycles / tot;
- printf(" [%i] %s enq+deq %"PRIu64" cycles, %"PRIu64" ns\n",
- thr, str, cycles, ns);
+ printf(" [%i] %s enq+deq %6" PRIu64 " CPU cycles\n", thr, str, cycles);
return 0;
}
@@ -496,9 +487,7 @@ static int test_schedule_multi(const char *str, int thr,
{
odp_event_t ev[MULTI_BUFS_MAX];
odp_queue_t queue;
- uint64_t t1;
- uint64_t t2;
- uint64_t cycles, ns;
+ uint64_t c1, c2, cycles;
int i, j;
int num;
uint32_t tot = 0;
@@ -547,7 +536,7 @@ static int test_schedule_multi(const char *str, int thr,
}
/* Start sched-enq loop */
- t1 = odp_time_cycles();
+ c1 = odp_cpu_cycles();
for (i = 0; i < QUEUE_ROUNDS; i++) {
num = odp_schedule_multi(&queue, ODP_SCHED_WAIT, ev,
@@ -584,23 +573,18 @@ static int test_schedule_multi(const char *str, int thr,
odp_schedule_resume();
- t2 = odp_time_cycles();
- cycles = odp_time_diff_cycles(t1, t2);
- ns = odp_time_cycles_to_ns(cycles);
+ c2 = odp_cpu_cycles();
+ cycles = odp_cpu_cycles_diff(c1, c2);
odp_barrier_wait(barrier);
clear_sched_queues();
- if (tot) {
- cycles = cycles/tot;
- ns = ns/tot;
- } else {
+ if (tot)
+ cycles = cycles / tot;
+ else
cycles = 0;
- ns = 0;
- }
- printf(" [%i] %s enq+deq %"PRIu64" cycles, %"PRIu64" ns\n",
- thr, str, cycles, ns);
+ printf(" [%i] %s enq+deq %6" PRIu64 " CPU cycles\n", thr, str, cycles);
return 0;
}
@@ -714,22 +698,25 @@ static void *run_thread(void *arg)
}
/**
- * @internal Test cycle counter accuracy
+ * @internal Test cycle counter frequency
*/
-static void test_time(void)
+static void test_cpu_freq(void)
{
struct timespec tp1, tp2;
- uint64_t t1, t2;
- uint64_t ns1, ns2, cycles;
- double err;
+ uint64_t c1, c2, cycles;
+ uint64_t nsec;
+ double diff_max_hz, max_cycles;
+
+ printf("\nCPU cycle count frequency test (runs about %i sec)\n",
+ TEST_SEC);
if (clock_gettime(CLOCK_MONOTONIC, &tp2)) {
LOG_ERR("clock_gettime failed.\n");
return;
}
- printf("\nTime accuracy test (%i sec)\n", TEST_SEC);
-
+ /* Wait until clock moves to the next second. It enables easy comparison
+ * during the measurement. */
do {
if (clock_gettime(CLOCK_MONOTONIC, &tp1)) {
LOG_ERR("clock_gettime failed.\n");
@@ -738,7 +725,8 @@ static void test_time(void)
} while (tp1.tv_sec == tp2.tv_sec);
- t1 = odp_time_cycles();
+ /* Start the measurement */
+ c1 = odp_cpu_cycles();
do {
if (clock_gettime(CLOCK_MONOTONIC, &tp2)) {
@@ -748,24 +736,25 @@ static void test_time(void)
} while ((tp2.tv_sec - tp1.tv_sec) < TEST_SEC);
- t2 = odp_time_cycles();
+ c2 = odp_cpu_cycles();
- ns1 = (tp2.tv_sec - tp1.tv_sec)*1000000000;
+ nsec = (tp2.tv_sec - tp1.tv_sec) * 1000000000;
if (tp2.tv_nsec > tp1.tv_nsec)
- ns1 += tp2.tv_nsec - tp1.tv_nsec;
+ nsec += tp2.tv_nsec - tp1.tv_nsec;
else
- ns1 -= tp1.tv_nsec - tp2.tv_nsec;
+ nsec -= tp1.tv_nsec - tp2.tv_nsec;
- cycles = odp_time_diff_cycles(t1, t2);
- ns2 = odp_time_cycles_to_ns(cycles);
+ cycles = odp_cpu_cycles_diff(c1, c2);
+ max_cycles = (nsec * odp_sys_cpu_hz()) / 1000000000.0;
- err = ((double)(ns2) - (double)ns1) / (double)ns1;
+ /* Compare measured CPU cycles to maximum theoretical CPU cycle count */
+ diff_max_hz = ((double)(cycles) - max_cycles) / max_cycles;
- printf("clock_gettime %"PRIu64" ns\n", ns1);
- printf("odp_time_cycles %"PRIu64" cycles\n", cycles);
- printf("odp_time_cycles_to_ns %"PRIu64" ns\n", ns2);
- printf("odp get cycle error %f%%\n", err*100.0);
+ printf("clock_gettime %" PRIu64 " ns\n", nsec);
+ printf("odp_cpu_cycles %" PRIu64 " CPU cycles\n", cycles);
+ printf("odp_sys_cpu_hz %" PRIu64 " hz\n", odp_sys_cpu_hz());
+ printf("Diff from max CPU freq %f%%\n", diff_max_hz * 100.0);
printf("\n");
}
@@ -879,7 +868,7 @@ int main(int argc, char *argv[])
printf("---------------\n");
printf("ODP API version: %s\n", odp_version_api_str());
printf("CPU model: %s\n", odp_sys_cpu_model_str());
- printf("CPU freq (hz): %"PRIu64"\n", odp_sys_cpu_hz());
+ printf("CPU freq (hz): %" PRIu64 "\n", odp_sys_cpu_hz());
printf("Cache line size: %i\n", odp_sys_cache_line_size());
printf("Max CPU count: %i\n", odp_cpu_count());
@@ -891,15 +880,15 @@ int main(int argc, char *argv[])
num_workers = args.cpu_count;
/* Get default worker cpumask */
- num_workers = odp_cpumask_def_worker(&cpumask, num_workers);
+ num_workers = odp_cpumask_default_worker(&cpumask, num_workers);
(void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
printf("num worker threads: %i\n", num_workers);
printf("first CPU: %i\n", odp_cpumask_first(&cpumask));
printf("cpu mask: %s\n", cpumaskstr);
- /* Test cycle count accuracy */
- test_time();
+ /* Test cycle count frequency */
+ test_cpu_freq();
shm = odp_shm_reserve("test_globals",
sizeof(test_globals_t), ODP_CACHE_LINE_SIZE, 0);
diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am
index 5d8e93b28..f49009a32 100644
--- a/test/validation/Makefile.am
+++ b/test/validation/Makefile.am
@@ -1,5 +1,6 @@
ODP_MODULES = buffer \
## classification \
+ config \
cpumask \
crypto \
errno \
diff --git a/test/validation/README b/test/validation/README
index 2d0c258a1..1baebaafc 100644
--- a/test/validation/README
+++ b/test/validation/README
@@ -4,47 +4,32 @@ All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
-To add tests in here, please observe the following rules:
+To add tests in here, please observe the rules listed below. This list
+is a brief overview, for a more detailed explanation of the test
+framework refer to the ODP Implementers' Guide, which can built as
+follows:
-1. Tests should be placed in the directory of the module they belong to.
+ ./configure --enable-user-guides
+ make
+Output will be in doc/output/. If this fails, check the documentation
+section of the DEPENDENCIES file.
-2. Test under test/validation/... should be platform agnostic, i.e.
- -they should be written in plain C only
- -they may only used Clib functions, C_UNIT functions and of course ODP
- functions.
- -they should be expected to pass on all ODP implementation
-
- Tests that do not follow these rules should be placed in the platform
- specific test area (currently platform/<platform>/test*)
-
-
-3. If a new ODP API module is created, please update the Makefile.am and
- the odptest.h file
+Rules for all tests under this tree:
+1. Tests must be placed in the directory of the module they belong to.
-4. Respect the following name convention for the names exported in the library:
+2. Tests must be platform agnostic, i.e.
- * Tests, i.e. functions which are used in CUNIT test suites are named:
- *<Module>_test_*
+ - should be written in plain C only.
+ - may only use C standard library functions, CUnit functions and of
+ course ODP functions
+ - should be expected to pass on all ODP implementations
- * Test arrays, i.e. arrays of CU_TestInfo, listing the test functions
- belonging to a suite, are called:
- <Module>_suite[_*]
- where the possible suffix can be used if many suites are declared.
-
- * CUNIT suite init and termination functions are called:
- <Module>_suite[_*]_init() and <Module>_suite[_*]_term()
- respectively.
-
- * Suite arrays, i.e. arrays of CU_SuiteInfo used in executables are called:
- <Module>_suites[_*]
- where the possible suffix identifies the executable using it, if many.
+ Tests that do not follow these rules should be placed in the platform
+ specific test area (currently platform/<platform>/test/).
- * Main executable function(s), are called:
- <Module>_main[_*]*
- where the possible suffix identifies the executable using it
+3. If a new ODP API module is created, please update the Makefile.am.
- * Init/term function for the whole executable are called:
- <Module>_init
- <Module>_term
+4. Symbols exported from test libraries must respect the naming
+ convention detailed in the ODP Implementers' Guide.
diff --git a/test/validation/buffer/Makefile.am b/test/validation/buffer/Makefile.am
index 05da40bb9..3f92c3eb0 100644
--- a/test/validation/buffer/Makefile.am
+++ b/test/validation/buffer/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libbuffer.la
-libbuffer_la_SOURCES = buffer.c
+noinst_LTLIBRARIES = libtestbuffer.la
+libtestbuffer_la_SOURCES = buffer.c
bin_PROGRAMS = buffer_main$(EXEEXT)
dist_buffer_main_SOURCES = buffer_main.c
-buffer_main_LDADD = libbuffer.la $(LIBCUNIT_COMMON) $(LIBODP)
+buffer_main_LDADD = libtestbuffer.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = buffer.h
diff --git a/test/validation/buffer/buffer.c b/test/validation/buffer/buffer.c
index c62938d0a..257e95cb3 100644
--- a/test/validation/buffer/buffer.c
+++ b/test/validation/buffer/buffer.c
@@ -139,23 +139,24 @@ void buffer_test_management_basic(void)
CU_ASSERT(odp_event_to_u64(ev) != odp_event_to_u64(ODP_EVENT_INVALID));
}
-CU_TestInfo buffer_suite[] = {
- _CU_TEST_INFO(buffer_test_pool_alloc),
- _CU_TEST_INFO(buffer_test_pool_free),
- _CU_TEST_INFO(buffer_test_management_basic),
- CU_TEST_INFO_NULL,
+odp_testinfo_t buffer_suite[] = {
+ ODP_TEST_INFO(buffer_test_pool_alloc),
+ ODP_TEST_INFO(buffer_test_pool_free),
+ ODP_TEST_INFO(buffer_test_management_basic),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo buffer_suites[] = {
- { .pName = "buffer tests",
- .pTests = buffer_suite,
- .pInitFunc = buffer_suite_init,
- .pCleanupFunc = buffer_suite_term,
- },
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t buffer_suites[] = {
+ {"buffer tests", buffer_suite_init, buffer_suite_term, buffer_suite},
+ ODP_SUITE_INFO_NULL,
};
int buffer_main(void)
{
- return odp_cunit_run(buffer_suites);
+ int ret = odp_cunit_register(buffer_suites);
+
+ if (ret == 0)
+ odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/buffer/buffer.h b/test/validation/buffer/buffer.h
index 49166247f..8b61bf527 100644
--- a/test/validation/buffer/buffer.h
+++ b/test/validation/buffer/buffer.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_BUFFER_H_
#define _ODP_TEST_BUFFER_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void buffer_test_pool_alloc(void);
@@ -15,14 +15,14 @@ void buffer_test_pool_free(void);
void buffer_test_management_basic(void);
/* test arrays: */
-extern CU_TestInfo buffer_suite[];
+extern odp_testinfo_t buffer_suite[];
/* test array init/term functions: */
int buffer_suite_init(void);
int buffer_suite_term(void);
/* test registry: */
-extern CU_SuiteInfo buffer_suites[];
+extern odp_suiteinfo_t buffer_suites[];
/* main test program: */
int buffer_main(void);
diff --git a/test/validation/classification/Makefile.am b/test/validation/classification/Makefile.am
index 7ab1dd902..423530950 100644
--- a/test/validation/classification/Makefile.am
+++ b/test/validation/classification/Makefile.am
@@ -1,12 +1,14 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libclassification.la
-libclassification_la_SOURCES = odp_classification_basic.c \
+noinst_LTLIBRARIES = libtestclassification.la
+libtestclassification_la_SOURCES = odp_classification_basic.c \
odp_classification_tests.c \
+ odp_classification_test_pmr.c \
+ odp_classification_common.c \
classification.c
bin_PROGRAMS = classification_main$(EXEEXT)
dist_classification_main_SOURCES = classification_main.c
-classification_main_LDADD = libclassification.la $(LIBCUNIT_COMMON) $(LIBODP)
+classification_main_LDADD = libtestclassification.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = classification.h odp_classification_testsuites.h
diff --git a/test/validation/classification/classification.c b/test/validation/classification/classification.c
index d0fef934c..9c3dbbb69 100644
--- a/test/validation/classification/classification.c
+++ b/test/validation/classification/classification.c
@@ -9,19 +9,29 @@
#include "odp_classification_testsuites.h"
#include "classification.h"
-CU_SuiteInfo classification_suites[] = {
+odp_suiteinfo_t classification_suites[] = {
{ .pName = "classification basic",
.pTests = classification_suite_basic,
},
+ { .pName = "classification pmr tests",
+ .pTests = classification_suite_pmr,
+ .pInitFunc = classification_suite_pmr_init,
+ .pCleanupFunc = classification_suite_pmr_term,
+ },
{ .pName = "classification tests",
.pTests = classification_suite,
.pInitFunc = classification_suite_init,
.pCleanupFunc = classification_suite_term,
},
- CU_SUITE_INFO_NULL,
+ ODP_SUITE_INFO_NULL,
};
int classification_main(void)
{
- return odp_cunit_run(classification_suites);
+ int ret = odp_cunit_register(classification_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/classification/classification.h b/test/validation/classification/classification.h
index d2847e52a..6a7e8a5ab 100644
--- a/test/validation/classification/classification.h
+++ b/test/validation/classification/classification.h
@@ -7,7 +7,51 @@
#ifndef _ODP_TEST_CLASSIFICATION_H_
#define _ODP_TEST_CLASSIFICATION_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
+
+#define SHM_PKT_NUM_BUFS 32
+#define SHM_PKT_BUF_SIZE 1024
+
+/* Config values for Default CoS */
+#define TEST_DEFAULT 1
+#define CLS_DEFAULT 0
+#define CLS_DEFAULT_SADDR "10.0.0.1/32"
+#define CLS_DEFAULT_DADDR "10.0.0.100/32"
+#define CLS_DEFAULT_SPORT 1024
+#define CLS_DEFAULT_DPORT 2048
+
+/* Config values for Error CoS */
+#define TEST_ERROR 1
+#define CLS_ERROR 1
+
+/* Config values for PMR_CHAIN */
+#define TEST_PMR_CHAIN 1
+#define CLS_PMR_CHAIN_SRC 2
+#define CLS_PMR_CHAIN_DST 3
+#define CLS_PMR_CHAIN_SADDR "10.0.0.5/32"
+#define CLS_PMR_CHAIN_SPORT 3000
+
+/* Config values for PMR */
+#define TEST_PMR 1
+#define CLS_PMR 4
+#define CLS_PMR_SPORT 4000
+
+/* Config values for PMR SET */
+#define TEST_PMR_SET 1
+#define CLS_PMR_SET 5
+#define CLS_PMR_SET_SADDR "10.0.0.6/32"
+#define CLS_PMR_SET_SPORT 5000
+
+/* Config values for CoS L2 Priority */
+#define TEST_L2_QOS 1
+#define CLS_L2_QOS_0 6
+#define CLS_L2_QOS_MAX 5
+
+#define CLS_ENTRIES (CLS_L2_QOS_0 + CLS_L2_QOS_MAX)
+
+/* Test Packet values */
+#define DATA_MAGIC 0x01020304
+#define TEST_SEQ_INVALID ((uint32_t)~0)
/* test functions: */
void classification_test_create_cos(void);
@@ -27,15 +71,15 @@ void classification_test_pktio_configure(void);
void classification_test_pktio_test(void);
/* test arrays: */
-extern CU_TestInfo classification_suite_basic[];
-extern CU_TestInfo classification_suite[];
+extern odp_testinfo_t classification_suite_basic[];
+extern odp_testinfo_t classification_suite[];
/* test array init/term functions: */
int classification_suite_init(void);
int classification_suite_term(void);
/* test registry: */
-extern CU_SuiteInfo classification_suites[];
+extern odp_suiteinfo_t classification_suites[];
/* main test program: */
int classification_main(void);
diff --git a/test/validation/classification/odp_classification_basic.c b/test/validation/classification/odp_classification_basic.c
index 3ae012879..20c157f4e 100644
--- a/test/validation/classification/odp_classification_basic.c
+++ b/test/validation/classification/odp_classification_basic.c
@@ -40,9 +40,16 @@ void classification_test_create_pmr_match(void)
odp_pmr_t pmr;
uint16_t val;
uint16_t mask;
+ odp_pmr_match_t match;
+
val = 1024;
mask = 0xffff;
- pmr = odp_pmr_create(ODP_PMR_TCP_SPORT, &val, &mask, sizeof(val));
+ match.term = ODP_PMR_TCP_SPORT;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
+
+ pmr = odp_pmr_create(&match);
CU_ASSERT(pmr != ODP_PMR_INVAL);
CU_ASSERT(odp_pmr_to_u64(pmr) != odp_pmr_to_u64(ODP_PMR_INVAL));
odp_pmr_destroy(pmr);
@@ -54,9 +61,16 @@ void classification_test_destroy_pmr(void)
uint16_t val;
uint16_t mask;
int retval;
+ odp_pmr_match_t match;
+
val = 1024;
mask = 0xffff;
- pmr = odp_pmr_create(ODP_PMR_TCP_SPORT, &val, &mask, sizeof(val));
+ match.term = ODP_PMR_TCP_SPORT;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
+
+ pmr = odp_pmr_create(&match);
retval = odp_pmr_destroy(pmr);
CU_ASSERT(retval == 0);
retval = odp_pmr_destroy(ODP_PMR_INVAL);
@@ -76,6 +90,7 @@ void classification_test_cos_set_queue(void)
cos_queue = odp_cos_create(cosname);
CU_ASSERT_FATAL(cos_queue != ODP_COS_INVALID);
+ odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
@@ -83,7 +98,7 @@ void classification_test_cos_set_queue(void)
queue_cos = odp_queue_create(queuename,
ODP_QUEUE_TYPE_SCHED, &qparam);
- retval = odp_cos_set_queue(cos_queue, queue_cos);
+ retval = odp_cos_queue_set(cos_queue, queue_cos);
CU_ASSERT(retval == 0);
odp_cos_destroy(cos_queue);
odp_queue_destroy(queue_cos);
@@ -98,9 +113,9 @@ void classification_test_cos_set_drop(void)
cos_drop = odp_cos_create(cosname);
CU_ASSERT_FATAL(cos_drop != ODP_COS_INVALID);
- retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_POOL);
+ retval = odp_cos_drop_set(cos_drop, ODP_COS_DROP_POOL);
CU_ASSERT(retval == 0);
- retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_NEVER);
+ retval = odp_cos_drop_set(cos_drop, ODP_COS_DROP_NEVER);
CU_ASSERT(retval == 0);
odp_cos_destroy(cos_drop);
}
@@ -155,14 +170,14 @@ void classification_test_pmr_match_set_destroy(void)
CU_ASSERT(retval == 0);
}
-CU_TestInfo classification_suite_basic[] = {
- _CU_TEST_INFO(classification_test_create_cos),
- _CU_TEST_INFO(classification_test_destroy_cos),
- _CU_TEST_INFO(classification_test_create_pmr_match),
- _CU_TEST_INFO(classification_test_destroy_pmr),
- _CU_TEST_INFO(classification_test_cos_set_queue),
- _CU_TEST_INFO(classification_test_cos_set_drop),
- _CU_TEST_INFO(classification_test_pmr_match_set_create),
- _CU_TEST_INFO(classification_test_pmr_match_set_destroy),
- CU_TEST_INFO_NULL,
+odp_testinfo_t classification_suite_basic[] = {
+ ODP_TEST_INFO(classification_test_create_cos),
+ ODP_TEST_INFO(classification_test_destroy_cos),
+ ODP_TEST_INFO(classification_test_create_pmr_match),
+ ODP_TEST_INFO(classification_test_destroy_pmr),
+ ODP_TEST_INFO(classification_test_cos_set_queue),
+ ODP_TEST_INFO(classification_test_cos_set_drop),
+ ODP_TEST_INFO(classification_test_pmr_match_set_create),
+ ODP_TEST_INFO(classification_test_pmr_match_set_destroy),
+ ODP_TEST_INFO_NULL,
};
diff --git a/test/validation/classification/odp_classification_common.c b/test/validation/classification/odp_classification_common.c
new file mode 100644
index 000000000..e2999ad0c
--- /dev/null
+++ b/test/validation/classification/odp_classification_common.c
@@ -0,0 +1,285 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "odp_classification_testsuites.h"
+#include "classification.h"
+#include <odp_cunit_common.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+#include <odp/helper/udp.h>
+#include <odp/helper/tcp.h>
+
+typedef struct cls_test_packet {
+ uint32be_t magic;
+ uint32be_t seq;
+} cls_test_packet_t;
+
+int destroy_inq(odp_pktio_t pktio)
+{
+ odp_queue_t inq;
+ odp_event_t ev;
+
+ inq = odp_pktio_inq_getdef(pktio);
+
+ if (inq == ODP_QUEUE_INVALID) {
+ CU_FAIL("attempting to destroy invalid inq");
+ return -1;
+ }
+
+ if (0 > odp_pktio_inq_remdef(pktio))
+ return -1;
+
+ while (1) {
+ ev = odp_schedule(NULL, ODP_SCHED_NO_WAIT);
+
+ if (ev != ODP_EVENT_INVALID)
+ odp_event_free(ev);
+ else
+ break;
+ }
+
+ return odp_queue_destroy(inq);
+}
+
+int cls_pkt_set_seq(odp_packet_t pkt)
+{
+ static uint32_t seq;
+ cls_test_packet_t data;
+ uint32_t offset;
+ odph_ipv4hdr_t *ip;
+ odph_tcphdr_t *tcp;
+ int status;
+
+ data.magic = DATA_MAGIC;
+ data.seq = ++seq;
+
+ ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
+ offset = odp_packet_l4_offset(pkt);
+ CU_ASSERT_FATAL(offset != 0);
+
+ if (ip->proto == ODPH_IPPROTO_UDP)
+ status = odp_packet_copydata_in(pkt, offset + ODPH_UDPHDR_LEN,
+ sizeof(data), &data);
+ else {
+ tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ status = odp_packet_copydata_in(pkt, offset + tcp->hl * 4,
+ sizeof(data), &data);
+ }
+
+ return status;
+}
+
+uint32_t cls_pkt_get_seq(odp_packet_t pkt)
+{
+ uint32_t offset;
+ cls_test_packet_t data;
+ odph_ipv4hdr_t *ip;
+ odph_tcphdr_t *tcp;
+
+ ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
+ offset = odp_packet_l4_offset(pkt);
+
+ if (!offset && !ip)
+ return TEST_SEQ_INVALID;
+
+ if (ip->proto == ODPH_IPPROTO_UDP)
+ odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
+ sizeof(data), &data);
+ else {
+ tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ odp_packet_copydata_out(pkt, offset + tcp->hl * 4,
+ sizeof(data), &data);
+ }
+
+ if (data.magic == DATA_MAGIC)
+ return data.seq;
+
+ return TEST_SEQ_INVALID;
+}
+
+int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask)
+{
+ int b[4];
+ int qualifier = 32;
+ int converted;
+
+ if (strchr(ipaddress, '/')) {
+ converted = sscanf(ipaddress, "%d.%d.%d.%d/%d",
+ &b[3], &b[2], &b[1], &b[0],
+ &qualifier);
+ if (5 != converted)
+ return -1;
+ } else {
+ converted = sscanf(ipaddress, "%d.%d.%d.%d",
+ &b[3], &b[2], &b[1], &b[0]);
+ if (4 != converted)
+ return -1;
+ }
+
+ if ((b[0] > 255) || (b[1] > 255) || (b[2] > 255) || (b[3] > 255))
+ return -1;
+ if (!qualifier || (qualifier > 32))
+ return -1;
+
+ *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24;
+ if (mask)
+ *mask = ~(0xFFFFFFFF & ((1ULL << (32 - qualifier)) - 1));
+
+ return 0;
+}
+
+void enqueue_pktio_interface(odp_packet_t pkt, odp_pktio_t pktio)
+{
+ odp_event_t ev;
+ odp_queue_t defqueue;
+
+ defqueue = odp_pktio_outq_getdef(pktio);
+ CU_ASSERT(defqueue != ODP_QUEUE_INVALID);
+
+ ev = odp_packet_to_event(pkt);
+ CU_ASSERT(odp_queue_enq(defqueue, ev) == 0);
+}
+
+odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns)
+{
+ odp_event_t ev;
+
+ ev = odp_schedule(queue, ns);
+ return odp_packet_from_event(ev);
+}
+
+odp_queue_t queue_create(char *queuename, bool sched)
+{
+ odp_queue_t queue;
+ odp_queue_param_t qparam;
+
+ if (sched) {
+ odp_queue_param_init(&qparam);
+ qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST;
+ qparam.sched.sync = ODP_SCHED_SYNC_NONE;
+ qparam.sched.group = ODP_SCHED_GROUP_ALL;
+
+ queue = odp_queue_create(queuename,
+ ODP_QUEUE_TYPE_SCHED,
+ &qparam);
+ } else {
+ queue = odp_queue_create(queuename,
+ ODP_QUEUE_TYPE_POLL,
+ NULL);
+ }
+
+ return queue;
+}
+
+odp_packet_t create_packet(odp_pool_t pool, bool vlan,
+ odp_atomic_u32_t *seq, bool flag_udp)
+{
+ uint32_t seqno;
+ odph_ethhdr_t *ethhdr;
+ odph_udphdr_t *udp;
+ odph_tcphdr_t *tcp;
+ odph_ipv4hdr_t *ip;
+ uint8_t payload_len;
+ char src_mac[ODPH_ETHADDR_LEN] = {0};
+ char dst_mac[ODPH_ETHADDR_LEN] = {0};
+ uint32_t addr = 0;
+ uint32_t mask;
+ int offset;
+ odp_packet_t pkt;
+ int packet_len = 0;
+
+ payload_len = sizeof(cls_test_packet_t);
+ packet_len += ODPH_ETHHDR_LEN;
+ packet_len += ODPH_IPV4HDR_LEN;
+ if (flag_udp)
+ packet_len += ODPH_UDPHDR_LEN;
+ else
+ packet_len += ODPH_TCPHDR_LEN;
+ packet_len += payload_len;
+
+ if (vlan)
+ packet_len += ODPH_VLANHDR_LEN;
+
+ pkt = odp_packet_alloc(pool, packet_len);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
+
+ /* Ethernet Header */
+ offset = 0;
+ odp_packet_l2_offset_set(pkt, offset);
+ ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
+ memcpy(ethhdr->src.addr, src_mac, ODPH_ETHADDR_LEN);
+ memcpy(ethhdr->dst.addr, dst_mac, ODPH_ETHADDR_LEN);
+ offset += sizeof(odph_ethhdr_t);
+ if (vlan) {
+ /* Default vlan header */
+ uint8_t *parseptr;
+ odph_vlanhdr_t *vlan;
+
+ vlan = (odph_vlanhdr_t *)(&ethhdr->type);
+ parseptr = (uint8_t *)vlan;
+ vlan->tci = odp_cpu_to_be_16(0);
+ vlan->tpid = odp_cpu_to_be_16(ODPH_ETHTYPE_VLAN);
+ offset += sizeof(odph_vlanhdr_t);
+ parseptr += sizeof(odph_vlanhdr_t);
+ uint16be_t *type = (uint16be_t *)(void *)parseptr;
+ *type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4);
+ } else {
+ ethhdr->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4);
+ }
+
+ odp_packet_l3_offset_set(pkt, offset);
+
+ /* ipv4 */
+ ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
+
+ parse_ipv4_string(CLS_DEFAULT_SADDR, &addr, &mask);
+ ip->dst_addr = odp_cpu_to_be_32(addr);
+
+ parse_ipv4_string(CLS_DEFAULT_DADDR, &addr, &mask);
+ ip->src_addr = odp_cpu_to_be_32(addr);
+ ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN;
+ if (flag_udp)
+ ip->tot_len = odp_cpu_to_be_16(ODPH_UDPHDR_LEN + payload_len +
+ ODPH_IPV4HDR_LEN);
+ else
+ ip->tot_len = odp_cpu_to_be_16(ODPH_TCPHDR_LEN + payload_len +
+ ODPH_IPV4HDR_LEN);
+
+ ip->ttl = 128;
+ if (flag_udp)
+ ip->proto = ODPH_IPPROTO_UDP;
+ else
+ ip->proto = ODPH_IPPROTO_TCP;
+
+ seqno = odp_atomic_fetch_inc_u32(seq);
+ ip->id = odp_cpu_to_be_16(seqno);
+ ip->chksum = 0;
+ ip->chksum = odph_ipv4_csum_update(pkt);
+ offset += ODPH_IPV4HDR_LEN;
+
+ /* udp */
+ if (flag_udp) {
+ odp_packet_l4_offset_set(pkt, offset);
+ udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ udp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT);
+ udp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT);
+ udp->length = odp_cpu_to_be_16(payload_len + ODPH_UDPHDR_LEN);
+ udp->chksum = 0;
+ } else {
+ odp_packet_l4_offset_set(pkt, offset);
+ tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ tcp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT);
+ tcp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT);
+ tcp->hl = ODPH_TCPHDR_LEN / 4;
+ /* TODO: checksum field has to be updated */
+ tcp->cksm = 0;
+ }
+
+ /* set pkt sequence number */
+ cls_pkt_set_seq(pkt);
+
+ return pkt;
+}
diff --git a/test/validation/classification/odp_classification_test_pmr.c b/test/validation/classification/odp_classification_test_pmr.c
new file mode 100644
index 000000000..73ba6f5d5
--- /dev/null
+++ b/test/validation/classification/odp_classification_test_pmr.c
@@ -0,0 +1,543 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "odp_classification_testsuites.h"
+#include "classification.h"
+#include <odp_cunit_common.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+#include <odp/helper/udp.h>
+#include <odp/helper/tcp.h>
+
+static odp_pool_t pool_default;
+
+/** sequence number of IP packets */
+odp_atomic_u32_t seq;
+
+int classification_suite_pmr_init(void)
+{
+ odp_pool_param_t param;
+
+ odp_pool_param_init(&param);
+ param.pkt.seg_len = SHM_PKT_BUF_SIZE;
+ param.pkt.len = SHM_PKT_BUF_SIZE;
+ param.pkt.num = SHM_PKT_NUM_BUFS;
+ param.type = ODP_POOL_PACKET;
+
+ pool_default = odp_pool_create("classification_pmr_pool", &param);
+ if (ODP_POOL_INVALID == pool_default) {
+ fprintf(stderr, "Packet pool creation failed.\n");
+ return -1;
+ }
+
+ odp_atomic_init_u32(&seq, 0);
+ return 0;
+}
+
+odp_pktio_t create_pktio(odp_queue_type_t q_type)
+{
+ odp_pktio_t pktio;
+ odp_pktio_param_t pktio_param;
+ int ret;
+
+ if (pool_default == ODP_POOL_INVALID)
+ return ODP_PKTIO_INVALID;
+
+ odp_pktio_param_init(&pktio_param);
+ if (q_type == ODP_QUEUE_TYPE_POLL)
+ pktio_param.in_mode = ODP_PKTIN_MODE_POLL;
+ else
+ pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
+
+ pktio = odp_pktio_open("loop", pool_default, &pktio_param);
+ if (pktio == ODP_PKTIO_INVALID) {
+ ret = odp_pool_destroy(pool_default);
+ if (ret)
+ fprintf(stderr, "unable to destroy pool.\n");
+ return ODP_PKTIO_INVALID;
+ }
+
+ ret = odp_pktio_start(pktio);
+ if (ret) {
+ fprintf(stderr, "unable to start loop\n");
+ return ODP_PKTIO_INVALID;
+ }
+
+ return pktio;
+}
+
+odp_queue_t create_default_inq(odp_pktio_t pktio, odp_queue_type_t qtype)
+{
+ odp_queue_param_t qparam;
+ odp_queue_t inq_def;
+ char inq_name[ODP_QUEUE_NAME_LEN];
+
+ odp_queue_param_init(&qparam);
+ qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
+ qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC;
+ qparam.sched.group = ODP_SCHED_GROUP_ALL;
+
+ snprintf(inq_name, sizeof(inq_name), "inq-pktio-%" PRIu64,
+ odp_pktio_to_u64(pktio));
+ inq_def = odp_queue_lookup(inq_name);
+ if (inq_def == ODP_QUEUE_INVALID)
+ inq_def = odp_queue_create(
+ inq_name,
+ ODP_QUEUE_TYPE_PKTIN,
+ qtype == ODP_QUEUE_TYPE_POLL ? NULL : &qparam);
+
+ CU_ASSERT(inq_def != ODP_QUEUE_INVALID);
+
+ if (0 > odp_pktio_inq_setdef(pktio, inq_def))
+ return ODP_QUEUE_INVALID;
+
+ return inq_def;
+}
+
+int classification_suite_pmr_term(void)
+{
+ int retcode = 0;
+
+ if (0 != odp_pool_destroy(pool_default)) {
+ fprintf(stderr, "pool_default destroy failed.\n");
+ retcode = -1;
+ }
+
+ return retcode;
+}
+
+static void classification_test_pmr_term_tcp_dport(void)
+{
+ odp_packet_t pkt;
+ odph_tcphdr_t *tcp;
+ uint32_t seqno;
+ uint16_t val;
+ uint16_t mask;
+ int retval;
+ odp_pktio_t pktio;
+ odp_queue_t queue;
+ odp_queue_t retqueue;
+ odp_queue_t defqueue;
+ odp_pmr_t pmr;
+ odp_cos_t cos;
+ char cosname[ODP_QUEUE_NAME_LEN];
+ char queuename[ODP_QUEUE_NAME_LEN];
+ odp_pmr_match_t match;
+
+ val = CLS_DEFAULT_DPORT;
+ mask = 0xffff;
+ seqno = 0;
+
+ pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(pktio != ODP_PKTIO_INVALID);
+ defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(defqueue != ODP_QUEUE_INVALID);
+
+ match.term = ODP_PMR_TCP_DPORT;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
+
+ pmr = odp_pmr_create(&match);
+ CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+ sprintf(cosname, "tcp_dport");
+ cos = odp_cos_create(cosname);
+ CU_ASSERT(cos != ODP_COS_INVALID);
+
+ sprintf(queuename, "%s", "tcp_dport1");
+
+ queue = queue_create(queuename, true);
+ CU_ASSERT(queue != ODP_QUEUE_INVALID);
+
+ retval = odp_cos_queue_set(cos, queue);
+ CU_ASSERT(retval == 0);
+
+ retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+ CU_ASSERT(retval == 0);
+
+ pkt = create_packet(pool_default, false, &seq, false);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ tcp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(retqueue == queue);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+
+ odp_packet_free(pkt);
+
+ /* Other packets are delivered to default queue */
+ pkt = create_packet(pool_default, false, &seq, false);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ tcp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT + 1);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == defqueue);
+
+ odp_packet_free(pkt);
+ odp_cos_destroy(cos);
+ odp_pmr_destroy(pmr);
+ destroy_inq(pktio);
+ odp_queue_destroy(queue);
+ odp_pktio_close(pktio);
+}
+
+static void classification_test_pmr_term_tcp_sport(void)
+{
+ odp_packet_t pkt;
+ odph_tcphdr_t *tcp;
+ uint32_t seqno;
+ uint16_t val;
+ uint16_t mask;
+ int retval;
+ odp_pktio_t pktio;
+ odp_queue_t queue;
+ odp_queue_t retqueue;
+ odp_queue_t defqueue;
+ odp_pmr_t pmr;
+ odp_cos_t cos;
+ char cosname[ODP_QUEUE_NAME_LEN];
+ char queuename[ODP_QUEUE_NAME_LEN];
+ odp_pmr_match_t match;
+
+ val = CLS_DEFAULT_SPORT;
+ mask = 0xffff;
+ seqno = 0;
+
+ pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+ defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+ match.term = ODP_PMR_TCP_SPORT;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
+
+ pmr = odp_pmr_create(&match);
+ CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+ sprintf(cosname, "tcp_sport");
+ cos = odp_cos_create(cosname);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+ sprintf(queuename, "%s", "tcp_sport");
+
+ queue = queue_create(queuename, true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ retval = odp_cos_queue_set(cos, queue);
+ CU_ASSERT(retval == 0);
+
+ retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+ CU_ASSERT(retval == 0);
+
+ pkt = create_packet(pool_default, false, &seq, false);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ tcp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == queue);
+ odp_packet_free(pkt);
+
+ pkt = create_packet(pool_default, false, &seq, false);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ tcp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT + 1);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == defqueue);
+
+ odp_packet_free(pkt);
+ odp_cos_destroy(cos);
+ odp_pmr_destroy(pmr);
+ destroy_inq(pktio);
+ odp_queue_destroy(queue);
+ odp_pktio_close(pktio);
+}
+
+static void classification_test_pmr_term_udp_dport(void)
+{
+ odp_packet_t pkt;
+ odph_udphdr_t *udp;
+ uint32_t seqno;
+ uint16_t val;
+ uint16_t mask;
+ int retval;
+ odp_pktio_t pktio;
+ odp_queue_t queue;
+ odp_queue_t retqueue;
+ odp_queue_t defqueue;
+ odp_pmr_t pmr;
+ odp_cos_t cos;
+ char cosname[ODP_QUEUE_NAME_LEN];
+ char queuename[ODP_QUEUE_NAME_LEN];
+ odp_pmr_match_t match;
+
+ val = CLS_DEFAULT_DPORT;
+ mask = 0xffff;
+ seqno = 0;
+
+ pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+ defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+ match.term = ODP_PMR_UDP_DPORT;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
+
+ pmr = odp_pmr_create(&match);
+ CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+ sprintf(cosname, "udp_dport");
+ cos = odp_cos_create(cosname);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+ sprintf(queuename, "%s", "udp_dport");
+
+ queue = queue_create(queuename, true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ retval = odp_cos_queue_set(cos, queue);
+ CU_ASSERT(retval == 0);
+
+ retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+ CU_ASSERT(retval == 0);
+
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ udp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == queue);
+ odp_packet_free(pkt);
+
+ /* Other packets received in default queue */
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ udp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT + 1);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == defqueue);
+
+ odp_packet_free(pkt);
+ odp_cos_destroy(cos);
+ odp_pmr_destroy(pmr);
+ destroy_inq(pktio);
+ odp_queue_destroy(queue);
+ odp_pktio_close(pktio);
+}
+
+static void classification_test_pmr_term_udp_sport(void)
+{
+ odp_packet_t pkt;
+ odph_udphdr_t *udp;
+ uint32_t seqno;
+ uint16_t val;
+ uint16_t mask;
+ int retval;
+ odp_pktio_t pktio;
+ odp_queue_t queue;
+ odp_queue_t retqueue;
+ odp_queue_t defqueue;
+ odp_pmr_t pmr;
+ odp_cos_t cos;
+ char cosname[ODP_QUEUE_NAME_LEN];
+ char queuename[ODP_QUEUE_NAME_LEN];
+ odp_pmr_match_t match;
+
+ val = CLS_DEFAULT_SPORT;
+ mask = 0xffff;
+ seqno = 0;
+
+ pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+ defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+ match.term = ODP_PMR_UDP_SPORT;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
+
+ pmr = odp_pmr_create(&match);
+ CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+ sprintf(cosname, "udp_sport");
+ cos = odp_cos_create(cosname);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+ sprintf(queuename, "%s", "udp_sport");
+
+ queue = queue_create(queuename, true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ retval = odp_cos_queue_set(cos, queue);
+ CU_ASSERT(retval == 0);
+
+ retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+ CU_ASSERT(retval == 0);
+
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ udp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == queue);
+ odp_packet_free(pkt);
+
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+ udp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT + 1);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == defqueue);
+ odp_packet_free(pkt);
+
+ odp_cos_destroy(cos);
+ odp_pmr_destroy(pmr);
+ destroy_inq(pktio);
+ odp_queue_destroy(queue);
+ odp_pktio_close(pktio);
+}
+
+static void classification_test_pmr_term_ipproto(void)
+{
+ odp_packet_t pkt;
+ uint32_t seqno;
+ uint8_t val;
+ uint8_t mask;
+ int retval;
+ odp_pktio_t pktio;
+ odp_queue_t queue;
+ odp_queue_t retqueue;
+ odp_queue_t defqueue;
+ odp_pmr_t pmr;
+ odp_cos_t cos;
+ char cosname[ODP_QUEUE_NAME_LEN];
+ char queuename[ODP_QUEUE_NAME_LEN];
+ odp_pmr_match_t match;
+
+ val = ODPH_IPPROTO_UDP;
+ mask = 0xff;
+ seqno = 0;
+
+ pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+ defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+ match.term = ODP_PMR_IPPROTO;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
+
+ pmr = odp_pmr_create(&match);
+ CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+ sprintf(cosname, "ipproto");
+ cos = odp_cos_create(cosname);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+ sprintf(queuename, "%s", "ipproto");
+
+ queue = queue_create(queuename, true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ retval = odp_cos_queue_set(cos, queue);
+ CU_ASSERT(retval == 0);
+
+ retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+ CU_ASSERT(retval == 0);
+
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == queue);
+ odp_packet_free(pkt);
+
+ /* Other packets delivered to default queue */
+ pkt = create_packet(pool_default, false, &seq, false);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ CU_ASSERT(retqueue == defqueue);
+
+ odp_cos_destroy(cos);
+ odp_pmr_destroy(pmr);
+ odp_packet_free(pkt);
+ destroy_inq(pktio);
+ odp_queue_destroy(queue);
+ odp_pktio_close(pktio);
+}
+
+odp_testinfo_t classification_suite_pmr[] = {
+ ODP_TEST_INFO(classification_test_pmr_term_tcp_dport),
+ ODP_TEST_INFO(classification_test_pmr_term_tcp_sport),
+ ODP_TEST_INFO(classification_test_pmr_term_udp_dport),
+ ODP_TEST_INFO(classification_test_pmr_term_udp_sport),
+ ODP_TEST_INFO(classification_test_pmr_term_ipproto),
+ ODP_TEST_INFO_NULL,
+};
diff --git a/test/validation/classification/odp_classification_tests.c b/test/validation/classification/odp_classification_tests.c
index 9e8ac1be3..823e30fec 100644
--- a/test/validation/classification/odp_classification_tests.c
+++ b/test/validation/classification/odp_classification_tests.c
@@ -11,50 +11,6 @@
#include <odp/helper/ip.h>
#include <odp/helper/udp.h>
-#define SHM_PKT_NUM_BUFS 32
-#define SHM_PKT_BUF_SIZE 1024
-
-/* Config values for Default CoS */
-#define TEST_DEFAULT 1
-#define CLS_DEFAULT 0
-#define CLS_DEFAULT_SADDR "10.0.0.1/32"
-#define CLS_DEFAULT_DADDR "10.0.0.100/32"
-#define CLS_DEFAULT_SPORT 1024
-#define CLS_DEFAULT_DPORT 2048
-
-/* Config values for Error CoS */
-#define TEST_ERROR 1
-#define CLS_ERROR 1
-
-/* Config values for PMR_CHAIN */
-#define TEST_PMR_CHAIN 1
-#define CLS_PMR_CHAIN_SRC 2
-#define CLS_PMR_CHAIN_DST 3
-#define CLS_PMR_CHAIN_SADDR "10.0.0.5/32"
-#define CLS_PMR_CHAIN_SPORT 3000
-
-/* Config values for PMR */
-#define TEST_PMR 1
-#define CLS_PMR 4
-#define CLS_PMR_SPORT 4000
-
-/* Config values for PMR SET */
-#define TEST_PMR_SET 1
-#define CLS_PMR_SET 5
-#define CLS_PMR_SET_SADDR "10.0.0.6/32"
-#define CLS_PMR_SET_SPORT 5000
-
-/* Config values for CoS L2 Priority */
-#define TEST_L2_QOS 1
-#define CLS_L2_QOS_0 6
-#define CLS_L2_QOS_MAX 5
-
-#define CLS_ENTRIES (CLS_L2_QOS_0 + CLS_L2_QOS_MAX)
-
-/* Test Packet values */
-#define DATA_MAGIC 0x01020304
-#define TEST_SEQ_INVALID ((uint32_t)~0)
-
static odp_cos_t cos_list[CLS_ENTRIES];
static odp_pmr_t pmr_list[CLS_ENTRIES];
static odp_queue_t queue_list[CLS_ENTRIES];
@@ -66,212 +22,8 @@ static odp_pktio_t pktio_loop;
/** sequence number of IP packets */
odp_atomic_u32_t seq;
-typedef struct cls_test_packet {
- uint32be_t magic;
- uint32be_t seq;
-} cls_test_packet_t;
-
-static inline
-int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask)
-{
- int b[4];
- int qualifier = 32;
- int converted;
-
- if (strchr(ipaddress, '/')) {
- converted = sscanf(ipaddress, "%d.%d.%d.%d/%d",
- &b[3], &b[2], &b[1], &b[0],
- &qualifier);
- if (5 != converted)
- return -1;
- } else {
- converted = sscanf(ipaddress, "%d.%d.%d.%d",
- &b[3], &b[2], &b[1], &b[0]);
- if (4 != converted)
- return -1;
- }
-
- if ((b[0] > 255) || (b[1] > 255) || (b[2] > 255) || (b[3] > 255))
- return -1;
- if (!qualifier || (qualifier > 32))
- return -1;
-
- *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24;
- if (mask)
- *mask = ~(0xFFFFFFFF & ((1ULL << (32 - qualifier)) - 1));
-
- return 0;
-}
-
-static inline
-void enqueue_loop_interface(odp_packet_t pkt)
-{
- odp_event_t ev;
- odp_queue_t defqueue = odp_pktio_outq_getdef(pktio_loop);
-
- ev = odp_packet_to_event(pkt);
- if (!(CU_ASSERT(odp_queue_enq(defqueue, ev) == 0)))
- odp_packet_free(pkt);
-}
-
-static inline
-odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns)
-{
- odp_event_t ev;
-
- ev = odp_schedule(queue, ns);
- return odp_packet_from_event(ev);
-}
-
-static int cls_pkt_set_seq(odp_packet_t pkt)
-{
- static uint32_t seq;
- cls_test_packet_t data;
- uint32_t offset;
- int status;
-
- data.magic = DATA_MAGIC;
- data.seq = ++seq;
-
- offset = odp_packet_l4_offset(pkt);
- CU_ASSERT_FATAL(offset != 0);
-
- status = odp_packet_copydata_in(pkt, offset + ODPH_UDPHDR_LEN,
- sizeof(data), &data);
-
- return status;
-}
-
-static uint32_t cls_pkt_get_seq(odp_packet_t pkt)
-{
- uint32_t offset;
- cls_test_packet_t data;
-
- offset = odp_packet_l4_offset(pkt);
- if (offset) {
- odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
- sizeof(data), &data);
-
- if (data.magic == DATA_MAGIC)
- return data.seq;
- }
-
- return TEST_SEQ_INVALID;
-}
-
-static int destroy_inq(odp_pktio_t pktio)
-{
- odp_queue_t inq;
- odp_event_t ev;
-
- inq = odp_pktio_inq_getdef(pktio);
-
- if (inq == ODP_QUEUE_INVALID) {
- CU_FAIL("attempting to destroy invalid inq");
- return -1;
- }
-
- if (0 > odp_pktio_inq_remdef(pktio))
- return -1;
-
- while (1) {
- ev = odp_schedule(NULL, ODP_SCHED_NO_WAIT);
-
- if (ev != ODP_EVENT_INVALID)
- odp_event_free(ev);
- else
- break;
- }
-
- return odp_queue_destroy(inq);
-}
-odp_packet_t create_packet(bool vlan)
-{
- uint32_t seqno;
- odph_ethhdr_t *ethhdr;
- odph_udphdr_t *udp;
- odph_ipv4hdr_t *ip;
- uint8_t payload_len;
- char src_mac[ODPH_ETHADDR_LEN] = {0};
- char dst_mac[ODPH_ETHADDR_LEN] = {0};
- uint32_t addr = 0;
- uint32_t mask;
- int offset;
- odp_packet_t pkt;
- int packet_len = 0;
-
- payload_len = sizeof(cls_test_packet_t);
- packet_len += ODPH_ETHHDR_LEN;
- packet_len += ODPH_IPV4HDR_LEN;
- packet_len += ODPH_UDPHDR_LEN;
- packet_len += payload_len;
-
- if (vlan)
- packet_len += ODPH_VLANHDR_LEN;
-
- pkt = odp_packet_alloc(pool_default, packet_len);
- CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
-
- /* Ethernet Header */
- offset = 0;
- odp_packet_l2_offset_set(pkt, offset);
- ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
- memcpy(ethhdr->src.addr, src_mac, ODPH_ETHADDR_LEN);
- memcpy(ethhdr->dst.addr, dst_mac, ODPH_ETHADDR_LEN);
- offset += sizeof(odph_ethhdr_t);
- if (vlan) {
- /* Default vlan header */
- uint8_t *parseptr;
- odph_vlanhdr_t *vlan = (odph_vlanhdr_t *)(&ethhdr->type);
- parseptr = (uint8_t *)vlan;
- vlan->tci = odp_cpu_to_be_16(0);
- vlan->tpid = odp_cpu_to_be_16(ODPH_ETHTYPE_VLAN);
- offset += sizeof(odph_vlanhdr_t);
- parseptr += sizeof(odph_vlanhdr_t);
- uint16be_t *type = (uint16be_t *)(void *)parseptr;
- *type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4);
- } else {
- ethhdr->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4);
- }
-
- odp_packet_l3_offset_set(pkt, offset);
-
- /* ipv4 */
- ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
-
- parse_ipv4_string(CLS_DEFAULT_SADDR, &addr, &mask);
- ip->dst_addr = odp_cpu_to_be_32(addr);
-
- parse_ipv4_string(CLS_DEFAULT_DADDR, &addr, &mask);
- ip->src_addr = odp_cpu_to_be_32(addr);
- ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN;
- ip->tot_len = odp_cpu_to_be_16(ODPH_UDPHDR_LEN + payload_len +
- ODPH_IPV4HDR_LEN);
- ip->ttl = 128;
- ip->proto = ODPH_IPPROTO_UDP;
- seqno = odp_atomic_fetch_inc_u32(&seq);
- ip->id = odp_cpu_to_be_16(seqno);
- ip->chksum = 0;
- ip->chksum = odp_cpu_to_be_16(odph_ipv4_csum_update(pkt));
- offset += ODPH_IPV4HDR_LEN;
-
- /* udp */
- odp_packet_l4_offset_set(pkt, offset);
- udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
- udp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT);
- udp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT);
- udp->length = odp_cpu_to_be_16(payload_len + ODPH_UDPHDR_LEN);
- udp->chksum = 0;
-
- /* set pkt sequence number */
- cls_pkt_set_seq(pkt);
-
- return pkt;
-}
-
int classification_suite_init(void)
{
- odp_pool_t pool;
odp_pool_param_t param;
odp_queue_t inq_def;
odp_queue_param_t qparam;
@@ -280,23 +32,19 @@ int classification_suite_init(void)
int ret;
odp_pktio_param_t pktio_param;
- memset(&param, 0, sizeof(param));
+ odp_pool_param_init(&param);
param.pkt.seg_len = SHM_PKT_BUF_SIZE;
param.pkt.len = SHM_PKT_BUF_SIZE;
param.pkt.num = SHM_PKT_NUM_BUFS;
param.type = ODP_POOL_PACKET;
- pool = odp_pool_create("classification_pool", &param);
- if (ODP_POOL_INVALID == pool) {
+ pool_default = odp_pool_create("classification_pool", &param);
+ if (ODP_POOL_INVALID == pool_default) {
fprintf(stderr, "Packet pool creation failed.\n");
return -1;
}
- pool_default = odp_pool_lookup("classification_pool");
- if (pool_default == ODP_POOL_INVALID)
- return -1;
-
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
pktio_loop = odp_pktio_open("loop", pool_default, &pktio_param);
@@ -306,6 +54,7 @@ int classification_suite_init(void)
fprintf(stderr, "unable to destroy pool.\n");
return -1;
}
+ odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
@@ -383,14 +132,17 @@ void configure_cls_pmr_chain(void)
char queuename[ODP_QUEUE_NAME_LEN];
uint32_t addr;
uint32_t mask;
+ odp_pmr_match_t match;
sprintf(cosname, "SrcCos");
cos_list[CLS_PMR_CHAIN_SRC] = odp_cos_create(cosname);
- CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_SRC] != ODP_COS_INVALID)
+ CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_SRC] != ODP_COS_INVALID);
+ odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_NORMAL;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
+ qparam.sched.lock_count = ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE;
sprintf(queuename, "%s", "SrcQueue");
queue_list[CLS_PMR_CHAIN_SRC] = odp_queue_create(queuename,
@@ -398,7 +150,7 @@ void configure_cls_pmr_chain(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_SRC] != ODP_QUEUE_INVALID);
- retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_SRC],
+ retval = odp_cos_queue_set(cos_list[CLS_PMR_CHAIN_SRC],
queue_list[CLS_PMR_CHAIN_SRC]);
CU_ASSERT(retval == 0);
@@ -406,6 +158,7 @@ void configure_cls_pmr_chain(void)
cos_list[CLS_PMR_CHAIN_DST] = odp_cos_create(cosname);
CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_DST] != ODP_COS_INVALID);
+ odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_NORMAL;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
@@ -416,19 +169,25 @@ void configure_cls_pmr_chain(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_DST] != ODP_QUEUE_INVALID);
- retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_DST],
+ retval = odp_cos_queue_set(cos_list[CLS_PMR_CHAIN_DST],
queue_list[CLS_PMR_CHAIN_DST]);
CU_ASSERT(retval == 0);
parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
- pmr_list[CLS_PMR_CHAIN_SRC] = odp_pmr_create(ODP_PMR_SIP_ADDR, &addr,
- &mask, sizeof(addr));
+ match.term = ODP_PMR_SIP_ADDR;
+ match.val = &addr;
+ match.mask = &mask;
+ match.val_sz = sizeof(addr);
+ pmr_list[CLS_PMR_CHAIN_SRC] = odp_pmr_create(&match);
CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_SRC] != ODP_PMR_INVAL);
val = CLS_PMR_CHAIN_SPORT;
maskport = 0xffff;
- pmr_list[CLS_PMR_CHAIN_DST] = odp_pmr_create(ODP_PMR_UDP_SPORT, &val,
- &maskport, sizeof(val));
+ match.term = ODP_PMR_UDP_SPORT;
+ match.val = &val;
+ match.mask = &maskport;
+ match.val_sz = sizeof(val);
+ pmr_list[CLS_PMR_CHAIN_DST] = odp_pmr_create(&match);
CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_DST] != ODP_PMR_INVAL);
retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR_CHAIN_SRC], pktio_loop,
@@ -449,38 +208,44 @@ void test_cls_pmr_chain(void)
odp_queue_t queue;
uint32_t addr = 0;
uint32_t mask;
- uint32_t seq;
+ uint32_t seqno = 0;
+
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
- pkt = create_packet(false);
- seq = cls_pkt_get_seq(pkt);
ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
ip->src_addr = odp_cpu_to_be_32(addr);
ip->chksum = 0;
- ip->chksum = odp_cpu_to_be_16(odph_ipv4_csum_update(pkt));
+ ip->chksum = odph_ipv4_csum_update(pkt);
udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
udp->src_port = odp_cpu_to_be_16(CLS_PMR_CHAIN_SPORT);
- enqueue_loop_interface(pkt);
+ enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]);
- CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
- pkt = create_packet(false);
- seq = cls_pkt_get_seq(pkt);
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
ip->src_addr = odp_cpu_to_be_32(addr);
ip->chksum = 0;
- ip->chksum = odp_cpu_to_be_16(odph_ipv4_csum_update(pkt));
+ ip->chksum = odph_ipv4_csum_update(pkt);
- enqueue_loop_interface(pkt);
+ enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]);
- CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
}
@@ -495,6 +260,7 @@ void configure_pktio_default_cos(void)
cos_list[CLS_DEFAULT] = odp_cos_create(cosname);
CU_ASSERT_FATAL(cos_list[CLS_DEFAULT] != ODP_COS_INVALID);
+ odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
@@ -503,7 +269,7 @@ void configure_pktio_default_cos(void)
ODP_QUEUE_TYPE_SCHED, &qparam);
CU_ASSERT_FATAL(queue_list[CLS_DEFAULT] != ODP_QUEUE_INVALID);
- retval = odp_cos_set_queue(cos_list[CLS_DEFAULT],
+ retval = odp_cos_queue_set(cos_list[CLS_DEFAULT],
queue_list[CLS_DEFAULT]);
CU_ASSERT(retval == 0);
@@ -515,16 +281,19 @@ void test_pktio_default_cos(void)
{
odp_packet_t pkt;
odp_queue_t queue;
- uint32_t seq;
+ uint32_t seqno = 0;
/* create a default packet */
- pkt = create_packet(false);
- seq = cls_pkt_get_seq(pkt);
- enqueue_loop_interface(pkt);
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
/* Default packet should be received in default queue */
CU_ASSERT(queue == queue_list[CLS_DEFAULT]);
- CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
}
@@ -536,6 +305,7 @@ void configure_pktio_error_cos(void)
char queuename[ODP_QUEUE_NAME_LEN];
char cosname[ODP_COS_NAME_LEN];
+ odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_LOWEST;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
@@ -550,7 +320,7 @@ void configure_pktio_error_cos(void)
cos_list[CLS_ERROR] = odp_cos_create(cosname);
CU_ASSERT_FATAL(cos_list[CLS_ERROR] != ODP_COS_INVALID);
- retval = odp_cos_set_queue(cos_list[CLS_ERROR], queue_list[CLS_ERROR]);
+ retval = odp_cos_queue_set(cos_list[CLS_ERROR], queue_list[CLS_ERROR]);
CU_ASSERT(retval == 0);
retval = odp_pktio_error_cos_set(pktio_loop, cos_list[CLS_ERROR]);
@@ -563,15 +333,16 @@ void test_pktio_error_cos(void)
odp_packet_t pkt;
/*Create an error packet */
- pkt = create_packet(false);
+ pkt = create_packet(pool_default, false, &seq, true);
odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
/* Incorrect IpV4 version */
ip->ver_ihl = 8 << 4 | ODPH_IPV4HDR_IHL_MIN;
ip->chksum = 0;
- enqueue_loop_interface(pkt);
+ enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
/* Error packet should be received in error queue */
CU_ASSERT(queue == queue_list[CLS_ERROR]);
odp_packet_free(pkt);
@@ -622,6 +393,7 @@ void configure_cos_with_l2_priority(void)
for (i = 0; i < CLS_L2_QOS_MAX; i++)
qos_tbl[i] = 0;
+ odp_queue_param_init(&qparam);
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
for (i = 0; i < num_qos; i++) {
@@ -637,7 +409,7 @@ void configure_cos_with_l2_priority(void)
&qparam);
CU_ASSERT_FATAL(queue_tbl[i] != ODP_QUEUE_INVALID);
queue_list[CLS_L2_QOS_0 + i] = queue_tbl[i];
- retval = odp_cos_set_queue(cos_tbl[i], queue_tbl[i]);
+ retval = odp_cos_queue_set(cos_tbl[i], queue_tbl[i]);
CU_ASSERT(retval == 0);
qos_tbl[i] = i;
}
@@ -653,19 +425,21 @@ void test_cos_with_l2_priority(void)
odph_ethhdr_t *ethhdr;
odph_vlanhdr_t *vlan;
odp_queue_t queue;
- uint32_t seq;
+ uint32_t seqno = 0;
uint8_t i;
for (i = 0; i < CLS_L2_QOS_MAX; i++) {
- pkt = create_packet(true);
- seq = cls_pkt_get_seq(pkt);
+ pkt = create_packet(pool_default, true, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
vlan = (odph_vlanhdr_t *)(&ethhdr->type);
vlan->tci = odp_cpu_to_be_16(i << 13);
- enqueue_loop_interface(pkt);
+ enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]);
- CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
}
}
@@ -675,20 +449,26 @@ void configure_pmr_cos(void)
uint16_t val;
uint16_t mask;
int retval;
- val = CLS_PMR_SPORT;
- mask = 0xffff;
+ odp_pmr_match_t match;
odp_queue_param_t qparam;
char cosname[ODP_COS_NAME_LEN];
char queuename[ODP_QUEUE_NAME_LEN];
- pmr_list[CLS_PMR] = odp_pmr_create(ODP_PMR_UDP_SPORT, &val,
- &mask, sizeof(val));
+ val = CLS_PMR_SPORT;
+ mask = 0xffff;
+ match.term = ODP_PMR_UDP_SPORT;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
+
+ pmr_list[CLS_PMR] = odp_pmr_create(&match);
CU_ASSERT(pmr_list[CLS_PMR] != ODP_PMR_INVAL);
sprintf(cosname, "PMR_CoS");
cos_list[CLS_PMR] = odp_cos_create(cosname);
CU_ASSERT_FATAL(cos_list[CLS_PMR] != ODP_COS_INVALID);
+ odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
@@ -699,7 +479,7 @@ void configure_pmr_cos(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_PMR] != ODP_QUEUE_INVALID);
- retval = odp_cos_set_queue(cos_list[CLS_PMR],
+ retval = odp_cos_queue_set(cos_list[CLS_PMR],
queue_list[CLS_PMR]);
CU_ASSERT(retval == 0);
@@ -713,16 +493,18 @@ void test_pmr_cos(void)
odp_packet_t pkt;
odph_udphdr_t *udp;
odp_queue_t queue;
- uint32_t seq;
+ uint32_t seqno = 0;
- pkt = create_packet(false);
- seq = cls_pkt_get_seq(pkt);
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT);
- enqueue_loop_interface(pkt);
+ enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_PMR]);
- CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
}
@@ -758,8 +540,9 @@ void configure_pktio_pmr_match_set_cos(void)
sprintf(cosname, "cos_pmr_set");
cos_list[CLS_PMR_SET] = odp_cos_create(cosname);
- CU_ASSERT_FATAL(cos_list[CLS_PMR_SET] != ODP_COS_INVALID)
+ CU_ASSERT_FATAL(cos_list[CLS_PMR_SET] != ODP_COS_INVALID);
+ odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
@@ -770,7 +553,7 @@ void configure_pktio_pmr_match_set_cos(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_PMR_SET] != ODP_QUEUE_INVALID);
- retval = odp_cos_set_queue(cos_list[CLS_PMR_SET],
+ retval = odp_cos_queue_set(cos_list[CLS_PMR_SET],
queue_list[CLS_PMR_SET]);
CU_ASSERT(retval == 0);
@@ -787,22 +570,25 @@ void test_pktio_pmr_match_set_cos(void)
odph_udphdr_t *udp;
odp_packet_t pkt;
odp_queue_t queue;
- uint32_t seq;
+ uint32_t seqno = 0;
+
+ pkt = create_packet(pool_default, false, &seq, true);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
- pkt = create_packet(false);
- seq = cls_pkt_get_seq(pkt);
ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask);
ip->src_addr = odp_cpu_to_be_32(addr);
ip->chksum = 0;
- ip->chksum = odp_cpu_to_be_16(odph_ipv4_csum_update(pkt));
+ ip->chksum = odph_ipv4_csum_update(pkt);
udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT);
- enqueue_loop_interface(pkt);
+ enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC);
+ CU_ASSERT(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_PMR_SET]);
- CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
}
@@ -857,12 +643,12 @@ void classification_test_pktio_test(void)
test_pktio_pmr_match_set_cos();
}
-CU_TestInfo classification_suite[] = {
- _CU_TEST_INFO(classification_test_pmr_terms_avail),
- _CU_TEST_INFO(classification_test_pktio_set_skip),
- _CU_TEST_INFO(classification_test_pktio_set_headroom),
- _CU_TEST_INFO(classification_test_pmr_terms_cap),
- _CU_TEST_INFO(classification_test_pktio_configure),
- _CU_TEST_INFO(classification_test_pktio_test),
- CU_TEST_INFO_NULL,
+odp_testinfo_t classification_suite[] = {
+ ODP_TEST_INFO(classification_test_pmr_terms_avail),
+ ODP_TEST_INFO(classification_test_pktio_set_skip),
+ ODP_TEST_INFO(classification_test_pktio_set_headroom),
+ ODP_TEST_INFO(classification_test_pmr_terms_cap),
+ ODP_TEST_INFO(classification_test_pktio_configure),
+ ODP_TEST_INFO(classification_test_pktio_test),
+ ODP_TEST_INFO_NULL,
};
diff --git a/test/validation/classification/odp_classification_testsuites.h b/test/validation/classification/odp_classification_testsuites.h
index 37c019d65..7d27d95b5 100644
--- a/test/validation/classification/odp_classification_testsuites.h
+++ b/test/validation/classification/odp_classification_testsuites.h
@@ -8,16 +8,28 @@
#define ODP_CLASSIFICATION_TESTSUITES_H_
#include <odp.h>
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
-extern CU_TestInfo classification_suite[];
-extern CU_TestInfo classification_suite_basic[];
+extern odp_testinfo_t classification_suite[];
+extern odp_testinfo_t classification_suite_basic[];
+extern odp_testinfo_t classification_suite_pmr[];
int classification_suite_init(void);
int classification_suite_term(void);
-odp_packet_t create_packet(bool vlan);
+int classification_suite_pmr_term(void);
+int classification_suite_pmr_init(void);
+
+odp_packet_t create_packet(odp_pool_t pool, bool vlan,
+ odp_atomic_u32_t *seq, bool udp);
+int cls_pkt_set_seq(odp_packet_t pkt);
+uint32_t cls_pkt_get_seq(odp_packet_t pkt);
+odp_pktio_t create_pktio(odp_queue_type_t q_type);
+odp_queue_t create_default_inq(odp_pktio_t pktio, odp_queue_type_t qtype);
+int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask);
+void enqueue_pktio_interface(odp_packet_t pkt, odp_pktio_t pktio);
+odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns);
+odp_queue_t queue_create(char *queuename, bool sched);
void configure_pktio_default_cos(void);
void test_pktio_default_cos(void);
void configure_pktio_error_cos(void);
@@ -30,6 +42,6 @@ void configure_pmr_cos(void);
void test_pmr_cos(void);
void configure_pktio_pmr_match_set_cos(void);
void test_pktio_pmr_match_set_cos(void);
-
+int destroy_inq(odp_pktio_t pktio);
#endif /* ODP_BUFFER_TESTSUITES_H_ */
diff --git a/test/validation/common/odp_cunit_common.c b/test/validation/common/odp_cunit_common.c
index d995ad3d2..a98042d2d 100644
--- a/test/validation/common/odp_cunit_common.c
+++ b/test/validation/common/odp_cunit_common.c
@@ -22,13 +22,15 @@ static struct {
int (*global_term_ptr)(void);
} global_init_term = {tests_global_init, tests_global_term};
+static odp_suiteinfo_t *global_testsuites;
+
/** create test thread */
int odp_cunit_thread_create(void *func_ptr(void *), pthrd_arg *arg)
{
odp_cpumask_t cpumask;
/* Create and init additional threads */
- odp_cpumask_def_worker(&cpumask, arg->numthrds);
+ odp_cpumask_default_worker(&cpumask, arg->numthrds);
return odph_linux_pthread_create(thread_tbl, &cpumask, func_ptr,
(void *)arg);
@@ -90,22 +92,196 @@ void odp_cunit_register_global_term(int (*func_term_ptr)(void))
global_init_term.global_term_ptr = func_term_ptr;
}
-int odp_cunit_run(CU_SuiteInfo testsuites[])
+static odp_suiteinfo_t *cunit_get_suite_info(const char *suite_name)
{
- int ret;
+ odp_suiteinfo_t *sinfo;
- printf("\tODP API version: %s\n", odp_version_api_str());
- printf("\tODP implementation version: %s\n", odp_version_impl_str());
+ for (sinfo = global_testsuites; sinfo->pName; sinfo++)
+ if (strcmp(sinfo->pName, suite_name) == 0)
+ return sinfo;
- /* call test executable init hook, if any */
- if (global_init_term.global_init_ptr &&
- ((*global_init_term.global_init_ptr)() != 0))
+ return NULL;
+}
+
+static odp_testinfo_t *cunit_get_test_info(odp_suiteinfo_t *sinfo,
+ const char *test_name)
+{
+ odp_testinfo_t *tinfo;
+
+ for (tinfo = sinfo->pTests; tinfo->testinfo.pName; tinfo++)
+ if (strcmp(tinfo->testinfo.pName, test_name) == 0)
+ return tinfo;
+
+ return NULL;
+}
+
+/* A wrapper for the suite's init function. This is done to allow for a
+ * potential runtime check to determine whether each test in the suite
+ * is active (enabled by using ODP_TEST_INFO_CONDITIONAL()). If present,
+ * the conditional check is run after the suite's init function.
+ */
+static int _cunit_suite_init(void)
+{
+ int ret = 0;
+ CU_pSuite cur_suite = CU_get_current_suite();
+ odp_suiteinfo_t *sinfo;
+ odp_testinfo_t *tinfo;
+
+ /* find the suite currently being run */
+ cur_suite = CU_get_current_suite();
+ if (!cur_suite)
return -1;
- CU_set_error_action(CUEA_ABORT);
+ sinfo = cunit_get_suite_info(cur_suite->pName);
+ if (!sinfo)
+ return -1;
+
+ /* execute its init function */
+ if (sinfo->pInitFunc) {
+ ret = sinfo->pInitFunc();
+ if (ret)
+ return ret;
+ }
+
+ /* run any configured conditional checks and mark inactive tests */
+ for (tinfo = sinfo->pTests; tinfo->testinfo.pName; tinfo++) {
+ CU_pTest ptest;
+ CU_ErrorCode err;
+
+ if (!tinfo->check_active || tinfo->check_active())
+ continue;
+
+ /* test is inactive, mark it as such */
+ ptest = CU_get_test_by_name(tinfo->testinfo.pName, cur_suite);
+ if (ptest)
+ err = CU_set_test_active(ptest, CU_FALSE);
+ else
+ err = CUE_NOTEST;
+
+ if (err != CUE_SUCCESS) {
+ fprintf(stderr, "%s: failed to set test %s inactive\n",
+ __func__, tinfo->testinfo.pName);
+ return -1;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Register suites and tests with CUnit.
+ *
+ * Similar to CU_register_suites() but using locally defined wrapper
+ * types.
+ */
+static int cunit_register_suites(odp_suiteinfo_t testsuites[])
+{
+ odp_suiteinfo_t *sinfo;
+ odp_testinfo_t *tinfo;
+ CU_pSuite suite;
+ CU_pTest test;
+
+ for (sinfo = testsuites; sinfo->pName; sinfo++) {
+ suite = CU_add_suite(sinfo->pName,
+ _cunit_suite_init, sinfo->pCleanupFunc);
+ if (!suite)
+ return CU_get_error();
+
+ for (tinfo = sinfo->pTests; tinfo->testinfo.pName; tinfo++) {
+ test = CU_add_test(suite, tinfo->testinfo.pName,
+ tinfo->testinfo.pTestFunc);
+ if (!test)
+ return CU_get_error();
+ }
+ }
+
+ return 0;
+}
+
+static int cunit_update_test(CU_pSuite suite,
+ odp_suiteinfo_t *sinfo,
+ odp_testinfo_t *updated_tinfo)
+{
+ CU_pTest test = NULL;
+ CU_ErrorCode err;
+ odp_testinfo_t *tinfo;
+ const char *test_name = updated_tinfo->testinfo.pName;
+
+ tinfo = cunit_get_test_info(sinfo, test_name);
+ if (tinfo)
+ test = CU_get_test(suite, test_name);
+
+ if (!tinfo || !test) {
+ fprintf(stderr, "%s: unable to find existing test named %s\n",
+ __func__, test_name);
+ return -1;
+ }
+
+ err = CU_set_test_func(test, updated_tinfo->testinfo.pTestFunc);
+ if (err != CUE_SUCCESS) {
+ fprintf(stderr, "%s: failed to update test func for %s\n",
+ __func__, test_name);
+ return -1;
+ }
+
+ tinfo->check_active = updated_tinfo->check_active;
+
+ return 0;
+}
+
+static int cunit_update_suite(odp_suiteinfo_t *updated_sinfo)
+{
+ CU_pSuite suite = NULL;
+ CU_ErrorCode err;
+ odp_suiteinfo_t *sinfo;
+ odp_testinfo_t *tinfo;
+
+ /* find previously registered suite with matching name */
+ sinfo = cunit_get_suite_info(updated_sinfo->pName);
+
+ if (sinfo) {
+ /* lookup the associated CUnit suite */
+ suite = CU_get_suite_by_name(updated_sinfo->pName,
+ CU_get_registry());
+ }
+
+ if (!sinfo || !suite) {
+ fprintf(stderr, "%s: unable to find existing suite named %s\n",
+ __func__, updated_sinfo->pName);
+ return -1;
+ }
+
+ sinfo->pInitFunc = updated_sinfo->pInitFunc;
+ sinfo->pCleanupFunc = updated_sinfo->pCleanupFunc;
+
+ err = CU_set_suite_cleanupfunc(suite, updated_sinfo->pCleanupFunc);
+ if (err != CUE_SUCCESS) {
+ fprintf(stderr, "%s: failed to update cleanup func for %s\n",
+ __func__, updated_sinfo->pName);
+ return -1;
+ }
+
+ for (tinfo = updated_sinfo->pTests; tinfo->testinfo.pName; tinfo++) {
+ int ret;
+
+ ret = cunit_update_test(suite, sinfo, tinfo);
+ if (ret != 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * Run tests previously registered via odp_cunit_register()
+ */
+int odp_cunit_run(void)
+{
+ int ret;
+
+ printf("\tODP API version: %s\n", odp_version_api_str());
+ printf("\tODP implementation version: %s\n", odp_version_impl_str());
- CU_initialize_registry();
- CU_register_suites(testsuites);
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
@@ -120,3 +296,41 @@ int odp_cunit_run(CU_SuiteInfo testsuites[])
return (ret) ? -1 : 0;
}
+
+/*
+ * Update suites/tests previously registered via odp_cunit_register().
+ *
+ * Note that this is intended for modifying the properties of already
+ * registered suites/tests. New suites/tests can only be registered via
+ * odp_cunit_register().
+ */
+int odp_cunit_update(odp_suiteinfo_t testsuites[])
+{
+ int ret = 0;
+ odp_suiteinfo_t *sinfo;
+
+ for (sinfo = testsuites; sinfo->pName && ret == 0; sinfo++)
+ ret = cunit_update_suite(sinfo);
+
+ return ret;
+}
+
+/*
+ * Register test suites to be run via odp_cunit_run()
+ */
+int odp_cunit_register(odp_suiteinfo_t testsuites[])
+{
+ /* call test executable init hook, if any */
+ if (global_init_term.global_init_ptr &&
+ ((*global_init_term.global_init_ptr)() != 0))
+ return -1;
+
+ CU_set_error_action(CUEA_ABORT);
+
+ CU_initialize_registry();
+ global_testsuites = testsuites;
+ cunit_register_suites(testsuites);
+ CU_set_fail_on_inactive(CU_FALSE);
+
+ return 0;
+}
diff --git a/test/validation/common/odp_cunit_common.h b/test/validation/common/odp_cunit_common.h
index 6cafaaaa7..c68905466 100644
--- a/test/validation/common/odp_cunit_common.h
+++ b/test/validation/common/odp_cunit_common.h
@@ -15,14 +15,45 @@
#include <stdint.h>
#include "CUnit/Basic.h"
+#include "CUnit/TestDB.h"
#define MAX_WORKERS 32 /**< Maximum number of work threads */
-/* the function, called by module main(), to run the testsuites: */
-int odp_cunit_run(CU_SuiteInfo testsuites[]);
+typedef int (*cunit_test_check_active)(void);
-/* the macro used to have test names (strings) matching function symbols */
-#define _CU_TEST_INFO(test_func) {#test_func, test_func}
+typedef struct {
+ CU_TestInfo testinfo;
+ cunit_test_check_active check_active;
+} odp_testinfo_t;
+
+typedef struct {
+ const char *pName;
+ CU_InitializeFunc pInitFunc;
+ CU_CleanupFunc pCleanupFunc;
+ odp_testinfo_t *pTests;
+} odp_suiteinfo_t;
+
+static inline int odp_cunit_test_inactive(void) { return 0; }
+static inline void odp_cunit_test_missing(void) { }
+
+/* An active test case, with the test name matching the test function name */
+#define ODP_TEST_INFO(test_func) \
+ {{#test_func, test_func}, NULL}
+
+/* A test case that is unconditionally inactive. Its name will be registered
+ * with CUnit but it won't be executed and will be reported as inactive in
+ * the result summary. */
+#define ODP_TEST_INFO_INACTIVE(test_func) \
+ {{#test_func, odp_cunit_test_missing}, odp_cunit_test_inactive}
+
+/* A test case that may be marked as inactive at runtime based on the
+ * return value of the cond_func function. A return value of 0 means
+ * inactive, anything else is active. */
+#define ODP_TEST_INFO_CONDITIONAL(test_func, cond_func) \
+ {{#test_func, test_func}, cond_func}
+
+#define ODP_TEST_INFO_NULL {CU_TEST_INFO_NULL, NULL}
+#define ODP_SUITE_INFO_NULL {NULL, NULL, NULL, NULL}
typedef struct {
uint32_t foo;
@@ -37,9 +68,16 @@ typedef struct {
int numthrds; /**< no of pthreads to create */
} pthrd_arg;
+/* register suites to be run via odp_cunit_run() */
+int odp_cunit_register(odp_suiteinfo_t testsuites[]);
+/* update tests previously registered via odp_cunit_register() */
+int odp_cunit_update(odp_suiteinfo_t testsuites[]);
+/* the function, called by module main(), to run the testsuites: */
+int odp_cunit_run(void);
+
/** create thread fro start_routine function */
-extern int odp_cunit_thread_create(void *func_ptr(void *), pthrd_arg *arg);
-extern int odp_cunit_thread_exit(pthrd_arg *);
+int odp_cunit_thread_create(void *func_ptr(void *), pthrd_arg *arg);
+int odp_cunit_thread_exit(pthrd_arg *);
/**
* Global tests initialization/termination.
diff --git a/test/validation/config/.gitignore b/test/validation/config/.gitignore
new file mode 100644
index 000000000..dbfed8a22
--- /dev/null
+++ b/test/validation/config/.gitignore
@@ -0,0 +1 @@
+config_main \ No newline at end of file
diff --git a/test/validation/config/Makefile.am b/test/validation/config/Makefile.am
new file mode 100644
index 000000000..084e10408
--- /dev/null
+++ b/test/validation/config/Makefile.am
@@ -0,0 +1,10 @@
+include ../Makefile.inc
+
+noinst_LTLIBRARIES = libtestconfig.la
+libtestconfig_la_SOURCES = config.c
+
+bin_PROGRAMS = config_main$(EXEEXT)
+dist_config_main_SOURCES = config_main.c
+config_main_LDADD = libtestconfig.la $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST = config.h
diff --git a/test/validation/config/config.c b/test/validation/config/config.c
new file mode 100644
index 000000000..f957150cf
--- /dev/null
+++ b/test/validation/config/config.c
@@ -0,0 +1,62 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp.h>
+#include "odp_cunit_common.h"
+#include "config.h"
+
+int config_suite_init(void)
+{
+ return 0;
+}
+
+int config_suite_term(void)
+{
+ return 0;
+}
+
+void config_test(void)
+{
+ CU_ASSERT(odp_config_pools() == ODP_CONFIG_POOLS);
+ CU_ASSERT(odp_config_queues() == ODP_CONFIG_QUEUES);
+ CU_ASSERT(odp_config_max_ordered_locks_per_queue() ==
+ ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE);
+ CU_ASSERT(odp_config_sched_prios() == ODP_CONFIG_SCHED_PRIOS);
+ CU_ASSERT(odp_config_sched_grps() == ODP_CONFIG_SCHED_GRPS);
+ CU_ASSERT(odp_config_pktio_entries() == ODP_CONFIG_PKTIO_ENTRIES);
+ CU_ASSERT(odp_config_buffer_align_min() == ODP_CONFIG_BUFFER_ALIGN_MIN);
+ CU_ASSERT(odp_config_buffer_align_max() == ODP_CONFIG_BUFFER_ALIGN_MAX);
+ CU_ASSERT(odp_config_packet_headroom() == ODP_CONFIG_PACKET_HEADROOM);
+ CU_ASSERT(odp_config_packet_tailroom() == ODP_CONFIG_PACKET_TAILROOM);
+ CU_ASSERT(odp_config_packet_seg_len_min() ==
+ ODP_CONFIG_PACKET_SEG_LEN_MIN);
+ CU_ASSERT(odp_config_packet_seg_len_max() ==
+ ODP_CONFIG_PACKET_SEG_LEN_MAX);
+ CU_ASSERT(odp_config_packet_buf_len_max() ==
+ ODP_CONFIG_PACKET_BUF_LEN_MAX);
+ CU_ASSERT(odp_config_shm_blocks() == ODP_CONFIG_SHM_BLOCKS);
+}
+
+odp_testinfo_t config_suite[] = {
+ ODP_TEST_INFO(config_test),
+ ODP_TEST_INFO_NULL,
+};
+
+odp_suiteinfo_t config_suites[] = {
+ {"config tests", config_suite_init,config_suite_term,
+ config_suite},
+ ODP_SUITE_INFO_NULL,
+};
+
+int config_main(void)
+{
+ int ret = odp_cunit_register(config_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
+}
diff --git a/test/validation/config/config.h b/test/validation/config/config.h
new file mode 100644
index 000000000..55cb5399c
--- /dev/null
+++ b/test/validation/config/config.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _ODP_TEST_CONFIG_H_
+#define _ODP_TEST_CONFIG_H_
+
+#include <odp_cunit_common.h>
+
+/* test functions: */
+void config_test(void);
+
+/* test arrays: */
+extern odp_testinfo_t config_suite[];
+
+/* test array init/term functions: */
+int config_suite_init(void);
+int config_suite_term(void);
+
+/* test registry: */
+extern odp_suiteinfo_t config_suites[];
+
+/* main test program: */
+int config_main(void);
+
+#endif
diff --git a/test/validation/config/config_main.c b/test/validation/config/config_main.c
new file mode 100644
index 000000000..4e2038fae
--- /dev/null
+++ b/test/validation/config/config_main.c
@@ -0,0 +1,11 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "config.h"
+
+int main(void)
+{
+ return config_main();
+}
diff --git a/test/validation/cpumask/Makefile.am b/test/validation/cpumask/Makefile.am
index 5a05c7ab9..7a9c560a5 100644
--- a/test/validation/cpumask/Makefile.am
+++ b/test/validation/cpumask/Makefile.am
@@ -1,11 +1,11 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libcpumask.la
-libcpumask_la_SOURCES = cpumask.c
-libcpumask_la_LIBADD = $(LIBCPUMASK_COMMON)
+noinst_LTLIBRARIES = libtestcpumask.la
+libtestcpumask_la_SOURCES = cpumask.c
+libtestcpumask_la_LIBADD = $(LIBCPUMASK_COMMON)
bin_PROGRAMS = cpumask_main$(EXEEXT)
dist_cpumask_main_SOURCES = cpumask_main.c
-cpumask_main_LDADD = libcpumask.la $(LIBCUNIT_COMMON) $(LIBODP)
+cpumask_main_LDADD = libtestcpumask.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = cpumask.h
diff --git a/test/validation/cpumask/cpumask.c b/test/validation/cpumask/cpumask.c
index 6d57028e3..2419f47dc 100644
--- a/test/validation/cpumask/cpumask.c
+++ b/test/validation/cpumask/cpumask.c
@@ -20,7 +20,7 @@ void cpumask_test_odp_cpumask_def_control(void)
unsigned max_cpus = mask_capacity();
odp_cpumask_t mask;
- num = odp_cpumask_def_control(&mask, ALL_AVAILABLE);
+ num = odp_cpumask_default_control(&mask, ALL_AVAILABLE);
mask_count = odp_cpumask_count(&mask);
CU_ASSERT(mask_count == num);
@@ -35,7 +35,7 @@ void cpumask_test_odp_cpumask_def_worker(void)
unsigned max_cpus = mask_capacity();
odp_cpumask_t mask;
- num = odp_cpumask_def_worker(&mask, ALL_AVAILABLE);
+ num = odp_cpumask_default_worker(&mask, ALL_AVAILABLE);
mask_count = odp_cpumask_count(&mask);
CU_ASSERT(mask_count == num);
@@ -59,11 +59,11 @@ void cpumask_test_odp_cpumask_def(void)
requested_cpus = available_cpus - 1;
else
requested_cpus = available_cpus;
- num_worker = odp_cpumask_def_worker(&mask, requested_cpus);
+ num_worker = odp_cpumask_default_worker(&mask, requested_cpus);
mask_count = odp_cpumask_count(&mask);
CU_ASSERT(mask_count == num_worker);
- num_control = odp_cpumask_def_control(&mask, 1);
+ num_control = odp_cpumask_default_control(&mask, 1);
mask_count = odp_cpumask_count(&mask);
CU_ASSERT(mask_count == num_control);
@@ -72,34 +72,39 @@ void cpumask_test_odp_cpumask_def(void)
CU_ASSERT(num_worker > 0);
}
-CU_TestInfo cpumask_suite[] = {
- _CU_TEST_INFO(cpumask_test_odp_cpumask_to_from_str),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_equal),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_zero),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_set),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_clr),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_isset),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_count),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_and),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_or),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_xor),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_copy),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_first),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_last),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_next),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_setall),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_def_control),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_def_worker),
- _CU_TEST_INFO(cpumask_test_odp_cpumask_def),
- CU_TEST_INFO_NULL,
+odp_testinfo_t cpumask_suite[] = {
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_to_from_str),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_equal),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_zero),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_set),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_clr),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_isset),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_count),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_and),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_or),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_xor),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_copy),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_first),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_last),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_next),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_setall),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_def_control),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_def_worker),
+ ODP_TEST_INFO(cpumask_test_odp_cpumask_def),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo cpumask_suites[] = {
- {"Cpumask", NULL, NULL, NULL, NULL, cpumask_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t cpumask_suites[] = {
+ {"Cpumask", NULL, NULL, cpumask_suite},
+ ODP_SUITE_INFO_NULL,
};
int cpumask_main(void)
{
- return odp_cunit_run(cpumask_suites);
+ int ret = odp_cunit_register(cpumask_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/cpumask/cpumask.h b/test/validation/cpumask/cpumask.h
index 7a58b5d0e..c6f9cde9d 100644
--- a/test/validation/cpumask/cpumask.h
+++ b/test/validation/cpumask/cpumask.h
@@ -8,7 +8,7 @@
#define _ODP_TEST_CPUMASK_H_
#include <odp.h>
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
#include "mask_common.h"
@@ -17,10 +17,10 @@ void cpumask_test_odp_cpumask_def_worker(void);
void cpumask_test_odp_cpumask_def(void);
/* test arrays: */
-extern CU_TestInfo cpumask_suite[];
+extern odp_testinfo_t cpumask_suite[];
/* test registry: */
-extern CU_SuiteInfo cpumask_suites[];
+extern odp_suiteinfo_t cpumask_suites[];
/* main test program: */
int cpumask_main(void);
diff --git a/test/validation/crypto/Makefile.am b/test/validation/crypto/Makefile.am
index ee04d3444..a555ee237 100644
--- a/test/validation/crypto/Makefile.am
+++ b/test/validation/crypto/Makefile.am
@@ -1,11 +1,11 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libcrypto.la
-libcrypto_la_SOURCES = crypto.c \
+noinst_LTLIBRARIES = libtestcrypto.la
+libtestcrypto_la_SOURCES = crypto.c \
odp_crypto_test_inp.c
bin_PROGRAMS = crypto_main$(EXEEXT)
dist_crypto_main_SOURCES = crypto_main.c
-crypto_main_LDADD = libcrypto.la $(LIBCUNIT_COMMON) $(LIBODP)
+crypto_main_LDADD = libtestcrypto.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = crypto.h odp_crypto_test_inp.h test_vectors.h test_vectors_len.h
diff --git a/test/validation/crypto/crypto.c b/test/validation/crypto/crypto.c
index cad660163..9229cab95 100644
--- a/test/validation/crypto/crypto.c
+++ b/test/validation/crypto/crypto.c
@@ -5,7 +5,7 @@
*/
#include <odp.h>
-#include "odp_cunit_common.h"
+#include <odp_cunit_common.h>
#include "odp_crypto_test_inp.h"
#include "crypto.h"
@@ -15,12 +15,10 @@
#define SHM_COMPL_POOL_SIZE (128 * 1024)
#define SHM_COMPL_POOL_BUF_SIZE 128
-CU_SuiteInfo crypto_suites[] = {
- {ODP_CRYPTO_SYNC_INP, crypto_suite_sync_init, NULL, NULL, NULL,
- crypto_suite},
- {ODP_CRYPTO_ASYNC_INP, crypto_suite_async_init, NULL, NULL, NULL,
- crypto_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t crypto_suites[] = {
+ {ODP_CRYPTO_SYNC_INP, crypto_suite_sync_init, NULL, crypto_suite},
+ {ODP_CRYPTO_ASYNC_INP, crypto_suite_async_init, NULL, crypto_suite},
+ ODP_SUITE_INFO_NULL,
};
int crypto_init(void)
@@ -96,7 +94,15 @@ int crypto_term(void)
int crypto_main(void)
{
+ int ret;
+
odp_cunit_register_global_init(crypto_init);
odp_cunit_register_global_term(crypto_term);
- return odp_cunit_run(crypto_suites);
+
+ ret = odp_cunit_register(crypto_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/crypto/crypto.h b/test/validation/crypto/crypto.h
index 41dd4ed7d..7cb60d4a7 100644
--- a/test/validation/crypto/crypto.h
+++ b/test/validation/crypto/crypto.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_CRYPTO_H_
#define _ODP_TEST_CRYPTO_H_
-#include <CUnit/Basic.h>
+#include "odp_cunit_common.h"
/* test functions: */
void crypto_test_enc_alg_3des_cbc(void);
@@ -17,14 +17,14 @@ void crypto_test_dec_alg_3des_cbc_ovr_iv(void);
void crypto_test_alg_hmac_md5(void);
/* test arrays: */
-extern CU_TestInfo crypto_suite[];
+extern odp_testinfo_t crypto_suite[];
/* test array init/term functions: */
int crypto_suite_sync_init(void);
int crypto_suite_async_init(void);
/* test registry: */
-extern CU_SuiteInfo crypto_suites[];
+extern odp_suiteinfo_t crypto_suites[];
/* executable init/term functions: */
int crypto_init(void);
diff --git a/test/validation/crypto/odp_crypto_test_inp.c b/test/validation/crypto/odp_crypto_test_inp.c
index 187a04c28..69325a4a7 100644
--- a/test/validation/crypto/odp_crypto_test_inp.c
+++ b/test/validation/crypto/odp_crypto_test_inp.c
@@ -319,11 +319,11 @@ int crypto_suite_async_init(void)
return 0;
}
-CU_TestInfo crypto_suite[] = {
- _CU_TEST_INFO(crypto_test_enc_alg_3des_cbc),
- _CU_TEST_INFO(crypto_test_dec_alg_3des_cbc),
- _CU_TEST_INFO(crypto_test_enc_alg_3des_cbc_ovr_iv),
- _CU_TEST_INFO(crypto_test_dec_alg_3des_cbc_ovr_iv),
- _CU_TEST_INFO(crypto_test_alg_hmac_md5),
- CU_TEST_INFO_NULL,
+odp_testinfo_t crypto_suite[] = {
+ ODP_TEST_INFO(crypto_test_enc_alg_3des_cbc),
+ ODP_TEST_INFO(crypto_test_dec_alg_3des_cbc),
+ ODP_TEST_INFO(crypto_test_enc_alg_3des_cbc_ovr_iv),
+ ODP_TEST_INFO(crypto_test_dec_alg_3des_cbc_ovr_iv),
+ ODP_TEST_INFO(crypto_test_alg_hmac_md5),
+ ODP_TEST_INFO_NULL,
};
diff --git a/test/validation/crypto/odp_crypto_test_inp.h b/test/validation/crypto/odp_crypto_test_inp.h
index d46994fb7..8bda34472 100644
--- a/test/validation/crypto/odp_crypto_test_inp.h
+++ b/test/validation/crypto/odp_crypto_test_inp.h
@@ -6,14 +6,14 @@
#ifndef ODP_CRYPTO_TEST_ASYNC_INP_
#define ODP_CRYPTO_TEST_ASYNC_INP_
-#include "CUnit/TestDB.h"
+#include <odp_cunit_common.h>
/* Suite names */
#define ODP_CRYPTO_ASYNC_INP "odp_crypto_async_inp"
#define ODP_CRYPTO_SYNC_INP "odp_crypto_sync_inp"
/* Suite test array */
-extern CU_TestInfo crypto_suite[];
+extern odp_testinfo_t crypto_suite[];
int crypto_suite_sync_init(void);
int crypto_suite_async_init(void);
diff --git a/test/validation/errno/Makefile.am b/test/validation/errno/Makefile.am
index 44575d971..f86b673b9 100644
--- a/test/validation/errno/Makefile.am
+++ b/test/validation/errno/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = liberrno.la
-liberrno_la_SOURCES = errno.c
+noinst_LTLIBRARIES = libtesterrno.la
+libtesterrno_la_SOURCES = errno.c
bin_PROGRAMS = errno_main$(EXEEXT)
dist_errno_main_SOURCES = errno_main.c
-errno_main_LDADD = liberrno.la $(LIBCUNIT_COMMON) $(LIBODP)
+errno_main_LDADD = libtesterrno.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = errno.h
diff --git a/test/validation/errno/errno.c b/test/validation/errno/errno.c
index c4f4aabee..d0e2128c6 100644
--- a/test/validation/errno/errno.c
+++ b/test/validation/errno/errno.c
@@ -19,17 +19,22 @@ void errno_test_odp_errno_sunny_day(void)
CU_ASSERT_PTR_NOT_NULL(odp_errno_str(my_errno));
}
-CU_TestInfo errno_suite[] = {
- _CU_TEST_INFO(errno_test_odp_errno_sunny_day),
- CU_TEST_INFO_NULL,
+odp_testinfo_t errno_suite[] = {
+ ODP_TEST_INFO(errno_test_odp_errno_sunny_day),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo errno_suites[] = {
- {"Errno", NULL, NULL, NULL, NULL, errno_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t errno_suites[] = {
+ {"Errno", NULL, NULL, errno_suite},
+ ODP_SUITE_INFO_NULL,
};
int errno_main(void)
{
- return odp_cunit_run(errno_suites);
+ int ret = odp_cunit_register(errno_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/errno/errno.h b/test/validation/errno/errno.h
index 374a3c96a..3e217b5d4 100644
--- a/test/validation/errno/errno.h
+++ b/test/validation/errno/errno.h
@@ -7,16 +7,16 @@
#ifndef _ODP_TEST_ERRNO_H_
#define _ODP_TEST_ERRNO_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void errno_test_odp_errno_sunny_day(void);
/* test arrays: */
-extern CU_TestInfo errno_suite[];
+extern odp_testinfo_t errno_suite[];
/* test registry: */
-extern CU_SuiteInfo errno_suites[];
+extern odp_suiteinfo_t errno_suites[];
/* main test program: */
int errno_main(void);
diff --git a/test/validation/init/Makefile.am b/test/validation/init/Makefile.am
index 51cb4adb2..a030aa08f 100644
--- a/test/validation/init/Makefile.am
+++ b/test/validation/init/Makefile.am
@@ -1,6 +1,6 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libinit.la
-libinit_la_SOURCES = init.c
+noinst_LTLIBRARIES = libtestinit.la
+libtestinit_la_SOURCES = init.c
# most platforms are expected not to support multiple ODP inits
# following each other: therefore 3 separate binaries are
@@ -9,8 +9,8 @@ bin_PROGRAMS = init_main_abort$(EXEEXT) init_main_log$(EXEEXT) init_main_ok$(EXE
dist_init_main_abort_SOURCES = init_main_abort.c
dist_init_main_log_SOURCES = init_main_log.c
dist_init_main_ok_SOURCES = init_main_ok.c
-init_main_abort_LDADD = libinit.la $(LIBCUNIT_COMMON) $(LIBODP)
-init_main_log_LDADD = libinit.la $(LIBCUNIT_COMMON) $(LIBODP)
-init_main_ok_LDADD = libinit.la $(LIBCUNIT_COMMON) $(LIBODP)
+init_main_abort_LDADD = libtestinit.la $(LIBCUNIT_COMMON) $(LIBODP)
+init_main_log_LDADD = libtestinit.la $(LIBCUNIT_COMMON) $(LIBODP)
+init_main_ok_LDADD = libtestinit.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = init.h
diff --git a/test/validation/init/init.c b/test/validation/init/init.c
index ee4483cb7..a8a564063 100644
--- a/test/validation/init/init.c
+++ b/test/validation/init/init.c
@@ -8,7 +8,6 @@
#include <stdlib.h>
#include <odp.h>
#include <CUnit/Basic.h>
-#include "odp_cunit_common.h"
#include "init.h"
/* flag set when the replacement logging function is used */
@@ -37,14 +36,14 @@ void init_test_odp_init_global_replace_abort(void)
CU_ASSERT(status == 0);
}
-CU_TestInfo init_suite_abort[] = {
- _CU_TEST_INFO(init_test_odp_init_global_replace_abort),
- CU_TEST_INFO_NULL,
+odp_testinfo_t init_suite_abort[] = {
+ ODP_TEST_INFO(init_test_odp_init_global_replace_abort),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo init_suites_abort[] = {
- {"Init", NULL, NULL, NULL, NULL, init_suite_abort},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t init_suites_abort[] = {
+ {"Init", NULL, NULL, init_suite_abort},
+ ODP_SUITE_INFO_NULL,
};
static void odp_init_abort(void)
@@ -54,12 +53,19 @@ static void odp_init_abort(void)
int init_main_abort(void)
{
+ int ret;
+
/* prevent default ODP init: */
odp_cunit_register_global_init(NULL);
odp_cunit_register_global_term(NULL);
/* run the tests: */
- return odp_cunit_run(init_suites_abort);
+ ret = odp_cunit_register(init_suites_abort);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
/* test ODP global init, with alternate log function */
@@ -76,20 +82,20 @@ void init_test_odp_init_global_replace_log(void)
status = odp_init_global(&init_data, NULL);
CU_ASSERT_FATAL(status == 0);
- CU_ASSERT_TRUE(replacement_logging_used);
+ CU_ASSERT_TRUE(replacement_logging_used || ODP_DEBUG_PRINT == 0);
status = odp_term_global();
CU_ASSERT(status == 0);
}
-CU_TestInfo init_suite_log[] = {
- _CU_TEST_INFO(init_test_odp_init_global_replace_log),
- CU_TEST_INFO_NULL,
+odp_testinfo_t init_suite_log[] = {
+ ODP_TEST_INFO(init_test_odp_init_global_replace_log),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo init_suites_log[] = {
- {"Init", NULL, NULL, NULL, NULL, init_suite_log},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t init_suites_log[] = {
+ {"Init", NULL, NULL, init_suite_log},
+ ODP_SUITE_INFO_NULL,
};
static int odp_init_log(odp_log_level_e level __attribute__((unused)),
@@ -110,12 +116,20 @@ static int odp_init_log(odp_log_level_e level __attribute__((unused)),
int init_main_log(void)
{
+ int ret;
+
/* prevent default ODP init: */
odp_cunit_register_global_init(NULL);
odp_cunit_register_global_term(NULL);
+ /* register the tests: */
+ ret = odp_cunit_register(init_suites_log);
+
/* run the tests: */
- return odp_cunit_run(init_suites_log);
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
/* test normal ODP global init */
@@ -130,22 +144,30 @@ void init_test_odp_init_global(void)
CU_ASSERT(status == 0);
}
-CU_TestInfo init_suite_ok[] = {
- _CU_TEST_INFO(init_test_odp_init_global),
- CU_TEST_INFO_NULL,
+odp_testinfo_t init_suite_ok[] = {
+ ODP_TEST_INFO(init_test_odp_init_global),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo init_suites_ok[] = {
- {"Init", NULL, NULL, NULL, NULL, init_suite_ok},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t init_suites_ok[] = {
+ {"Init", NULL, NULL, init_suite_ok},
+ ODP_SUITE_INFO_NULL,
};
int init_main_ok(void)
{
+ int ret;
+
/* prevent default ODP init: */
odp_cunit_register_global_init(NULL);
odp_cunit_register_global_term(NULL);
+ /* register the tests: */
+ ret = odp_cunit_register(init_suites_ok);
+
/* run the tests: */
- return odp_cunit_run(init_suites_ok);
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/init/init.h b/test/validation/init/init.h
index 08f09e55c..272d42652 100644
--- a/test/validation/init/init.h
+++ b/test/validation/init/init.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_INIT_H_
#define _ODP_TEST_INIT_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void init_test_odp_init_global_replace_abort(void);
@@ -15,14 +15,14 @@ void init_test_odp_init_global_replace_log(void);
void init_test_odp_init_global(void);
/* test arrays: */
-extern CU_TestInfo init_suite_abort[];
-extern CU_TestInfo init_suite_log[];
-extern CU_TestInfo init_suite_ok[];
+extern odp_testinfo_t init_suite_abort[];
+extern odp_testinfo_t init_suite_log[];
+extern odp_testinfo_t init_suite_ok[];
/* test registry: */
-extern CU_SuiteInfo init_suites_abort[];
-extern CU_SuiteInfo init_suites_log[];
-extern CU_SuiteInfo init_suites_ok[];
+extern odp_suiteinfo_t init_suites_abort[];
+extern odp_suiteinfo_t init_suites_log[];
+extern odp_suiteinfo_t init_suites_ok[];
/* main test program: */
int init_main_abort(void);
diff --git a/test/validation/packet/Makefile.am b/test/validation/packet/Makefile.am
index 9c783d5b7..3d6e3c082 100644
--- a/test/validation/packet/Makefile.am
+++ b/test/validation/packet/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libpacket.la
-libpacket_la_SOURCES = packet.c
+noinst_LTLIBRARIES = libtestpacket.la
+libtestpacket_la_SOURCES = packet.c
bin_PROGRAMS = packet_main$(EXEEXT)
dist_packet_main_SOURCES = packet_main.c
-packet_main_LDADD = libpacket.la $(LIBCUNIT_COMMON) $(LIBODP)
+packet_main_LDADD = libtestpacket.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = packet.h
diff --git a/test/validation/packet/packet.c b/test/validation/packet/packet.c
index 97ffd14fe..1694293ce 100644
--- a/test/validation/packet/packet.c
+++ b/test/validation/packet/packet.c
@@ -7,7 +7,7 @@
#include <stdlib.h>
#include <odp.h>
-#include "odp_cunit_common.h"
+#include <odp_cunit_common.h>
#include "packet.h"
#define PACKET_BUF_LEN ODP_CONFIG_PACKET_SEG_LEN_MIN
@@ -18,8 +18,8 @@ static odp_pool_t packet_pool;
static const uint32_t packet_len = PACKET_BUF_LEN -
PACKET_TAILROOM_RESERVE;
-static const uint32_t segmented_packet_len = PACKET_BUF_LEN * 5 -
- PACKET_TAILROOM_RESERVE;
+static uint32_t segmented_packet_len = ODP_CONFIG_PACKET_BUF_LEN_MAX;
+static odp_bool_t segmentation_supported = true;
odp_packet_t test_packet, segmented_test_packet;
@@ -52,13 +52,22 @@ int packet_suite_init(void)
return -1;
test_packet = odp_packet_alloc(packet_pool, packet_len);
- segmented_test_packet = odp_packet_alloc(packet_pool,
- segmented_packet_len);
+
+ /* Try to allocate the largest possible packet to see
+ * if segmentation is supported */
+ do {
+ segmented_test_packet = odp_packet_alloc(packet_pool,
+ segmented_packet_len);
+ if (segmented_test_packet == ODP_PACKET_INVALID)
+ segmented_packet_len -= ODP_CONFIG_BUFFER_ALIGN_MIN;
+ } while (segmented_test_packet == ODP_PACKET_INVALID);
if (odp_packet_is_valid(test_packet) == 0 ||
odp_packet_is_valid(segmented_test_packet) == 0)
return -1;
+ segmentation_supported = odp_packet_is_segmented(segmented_test_packet);
+
udat = odp_packet_user_area(test_packet);
udat_size = odp_packet_user_area_size(test_packet);
if (!udat || udat_size != sizeof(struct udata_struct))
@@ -133,6 +142,8 @@ void packet_test_alloc_segmented(void)
pkt = odp_packet_alloc(packet_pool, len);
CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(odp_packet_len(pkt) == len);
+ if (segmentation_supported)
+ CU_ASSERT(odp_packet_is_segmented(pkt) == 1);
odp_packet_free(pkt);
}
@@ -161,6 +172,12 @@ void packet_test_basic_metadata(void)
CU_ASSERT(odp_packet_pool(pkt) != ODP_POOL_INVALID);
/* Packet was allocated by application so shouldn't have valid pktio. */
CU_ASSERT(odp_packet_input(pkt) == ODP_PKTIO_INVALID);
+
+ odp_packet_flow_hash_set(pkt, UINT32_MAX);
+ CU_ASSERT(odp_packet_has_flow_hash(pkt));
+ CU_ASSERT(odp_packet_flow_hash(pkt) == UINT32_MAX);
+ odp_packet_has_flow_hash_clr(pkt);
+ CU_ASSERT(!odp_packet_has_flow_hash(pkt));
}
void packet_test_length(void)
@@ -403,7 +420,8 @@ void packet_test_segments(void)
}
CU_ASSERT(odp_packet_is_segmented(pkt) == 0);
- CU_ASSERT(odp_packet_is_segmented(seg_pkt) == 1);
+ if (segmentation_supported)
+ CU_ASSERT(odp_packet_is_segmented(seg_pkt) == 1);
seg = odp_packet_first_seg(pkt);
buf_len = 0;
@@ -555,7 +573,7 @@ void packet_test_add_rem_data(void)
void *usr_ptr;
struct udata_struct *udat, *new_udat;
- pkt = odp_packet_alloc(packet_pool, PACKET_BUF_LEN);
+ pkt = odp_packet_alloc(packet_pool, packet_len);
CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
pkt_len = odp_packet_len(pkt);
@@ -565,9 +583,16 @@ void packet_test_add_rem_data(void)
sizeof(struct udata_struct));
memcpy(udat, &test_packet_udata, sizeof(struct udata_struct));
- /* Insert one more packet length in the middle of a packet */
offset = pkt_len / 2;
- add_len = pkt_len;
+
+ if (segmentation_supported) {
+ /* Insert one more packet length in the middle of a packet */
+ add_len = PACKET_BUF_LEN;
+ } else {
+ /* Add diff between largest and smaller packets
+ * which is at least tailroom */
+ add_len = segmented_packet_len - packet_len;
+ }
new_pkt = odp_packet_add_data(pkt, offset, add_len);
CU_ASSERT(new_pkt != ODP_PACKET_INVALID);
@@ -753,38 +778,43 @@ void packet_test_offset(void)
CU_ASSERT_PTR_NOT_NULL(ptr);
}
-CU_TestInfo packet_suite[] = {
- _CU_TEST_INFO(packet_test_alloc_free),
- _CU_TEST_INFO(packet_test_alloc_segmented),
- _CU_TEST_INFO(packet_test_basic_metadata),
- _CU_TEST_INFO(packet_test_debug),
- _CU_TEST_INFO(packet_test_length),
- _CU_TEST_INFO(packet_test_headroom),
- _CU_TEST_INFO(packet_test_tailroom),
- _CU_TEST_INFO(packet_test_context),
- _CU_TEST_INFO(packet_test_event_conversion),
- _CU_TEST_INFO(packet_test_layer_offsets),
- _CU_TEST_INFO(packet_test_segments),
- _CU_TEST_INFO(packet_test_segment_last),
- _CU_TEST_INFO(packet_test_in_flags),
- _CU_TEST_INFO(packet_test_error_flags),
- _CU_TEST_INFO(packet_test_add_rem_data),
- _CU_TEST_INFO(packet_test_copy),
- _CU_TEST_INFO(packet_test_copydata),
- _CU_TEST_INFO(packet_test_offset),
- CU_TEST_INFO_NULL,
+odp_testinfo_t packet_suite[] = {
+ ODP_TEST_INFO(packet_test_alloc_free),
+ ODP_TEST_INFO(packet_test_alloc_segmented),
+ ODP_TEST_INFO(packet_test_basic_metadata),
+ ODP_TEST_INFO(packet_test_debug),
+ ODP_TEST_INFO(packet_test_length),
+ ODP_TEST_INFO(packet_test_headroom),
+ ODP_TEST_INFO(packet_test_tailroom),
+ ODP_TEST_INFO(packet_test_context),
+ ODP_TEST_INFO(packet_test_event_conversion),
+ ODP_TEST_INFO(packet_test_layer_offsets),
+ ODP_TEST_INFO(packet_test_segments),
+ ODP_TEST_INFO(packet_test_segment_last),
+ ODP_TEST_INFO(packet_test_in_flags),
+ ODP_TEST_INFO(packet_test_error_flags),
+ ODP_TEST_INFO(packet_test_add_rem_data),
+ ODP_TEST_INFO(packet_test_copy),
+ ODP_TEST_INFO(packet_test_copydata),
+ ODP_TEST_INFO(packet_test_offset),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo packet_suites[] = {
+odp_suiteinfo_t packet_suites[] = {
{ .pName = "packet tests",
.pTests = packet_suite,
.pInitFunc = packet_suite_init,
.pCleanupFunc = packet_suite_term,
},
- CU_SUITE_INFO_NULL,
+ ODP_SUITE_INFO_NULL,
};
int packet_main(void)
{
- return odp_cunit_run(packet_suites);
+ int ret = odp_cunit_register(packet_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/packet/packet.h b/test/validation/packet/packet.h
index f8a16a8e2..096a1e2b1 100644
--- a/test/validation/packet/packet.h
+++ b/test/validation/packet/packet.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_PACKET_H_
#define _ODP_TEST_PACKET_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void packet_test_alloc_free(void);
@@ -30,14 +30,14 @@ void packet_test_copydata(void);
void packet_test_offset(void);
/* test arrays: */
-extern CU_TestInfo packet_suite[];
+extern odp_testinfo_t packet_suite[];
/* test array init/term functions: */
int packet_suite_init(void);
int packet_suite_term(void);
/* test registry: */
-extern CU_SuiteInfo packet_suites[];
+extern odp_suiteinfo_t packet_suites[];
/* main test program: */
int packet_main(void);
diff --git a/test/validation/pktio/Makefile.am b/test/validation/pktio/Makefile.am
index 37efeaae8..9fbf45603 100644
--- a/test/validation/pktio/Makefile.am
+++ b/test/validation/pktio/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libpktio.la
-libpktio_la_SOURCES = pktio.c
+noinst_LTLIBRARIES = libtestpktio.la
+libtestpktio_la_SOURCES = pktio.c
bin_PROGRAMS = pktio_main$(EXEEXT)
dist_pktio_main_SOURCES = pktio_main.c
-pktio_main_LDADD = libpktio.la $(LIBCUNIT_COMMON) $(LIBODP)
+pktio_main_LDADD = libtestpktio.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = pktio.h
diff --git a/test/validation/pktio/pktio.c b/test/validation/pktio/pktio.c
index 5c0799bdf..9c16e944d 100644
--- a/test/validation/pktio/pktio.c
+++ b/test/validation/pktio/pktio.c
@@ -21,6 +21,7 @@
#define MAX_NUM_IFACES 2
#define TEST_SEQ_INVALID ((uint32_t)~0)
#define TEST_SEQ_MAGIC 0x92749451
+#define TX_BATCH_LEN 4
/** interface names used for testing */
static const char *iface_name[MAX_NUM_IFACES];
@@ -34,6 +35,7 @@ typedef struct {
odp_pktio_t id;
odp_queue_t outq;
odp_queue_t inq;
+ odp_pktio_input_mode_t in_mode;
} pktio_info_t;
/** magic number and sequence at start of UDP payload */
@@ -250,20 +252,17 @@ static int default_pool_create(void)
return 0;
}
-static odp_pktio_t create_pktio(const char *iface, odp_queue_type_t q_type,
- int num)
+static odp_pktio_t create_pktio(int iface_idx, odp_pktio_input_mode_t mode)
{
odp_pktio_t pktio;
odp_pktio_param_t pktio_param;
+ const char *iface = iface_name[iface_idx];
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
- if (q_type == ODP_QUEUE_TYPE_POLL)
- pktio_param.in_mode = ODP_PKTIN_MODE_POLL;
- else
- pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
+ pktio_param.in_mode = mode;
- pktio = odp_pktio_open(iface, pool[num], &pktio_param);
+ pktio = odp_pktio_open(iface, pool[iface_idx], &pktio_param);
if (pktio == ODP_PKTIO_INVALID)
pktio = odp_pktio_lookup(iface);
CU_ASSERT(pktio != ODP_PKTIO_INVALID);
@@ -348,33 +347,41 @@ static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
return ODP_EVENT_INVALID;
}
-static odp_packet_t wait_for_packet(odp_queue_t queue,
+static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
uint32_t seq, uint64_t ns)
{
uint64_t start, now, diff;
odp_event_t ev;
- odp_packet_t pkt = ODP_PACKET_INVALID;
+ odp_packet_t pkt;
uint64_t wait;
start = odp_time_cycles();
wait = odp_schedule_wait_time(ns);
do {
- if (queue != ODP_QUEUE_INVALID &&
- odp_queue_type(queue) == ODP_QUEUE_TYPE_POLL)
- ev = queue_deq_wait_time(queue, ns);
- else
- ev = odp_schedule(NULL, wait);
-
- if (ev != ODP_EVENT_INVALID) {
- if (odp_event_type(ev) == ODP_EVENT_PACKET) {
- pkt = odp_packet_from_event(ev);
- if (pktio_pkt_seq(pkt) == seq)
- return pkt;
+ pkt = ODP_PACKET_INVALID;
+
+ if (pktio_rx->in_mode == ODP_PKTIN_MODE_RECV) {
+ odp_pktio_recv(pktio_rx->id, &pkt, 1);
+ } else {
+ if (pktio_rx->in_mode == ODP_PKTIN_MODE_POLL)
+ ev = queue_deq_wait_time(pktio_rx->inq, ns);
+ else
+ ev = odp_schedule(NULL, wait);
+
+ if (ev != ODP_EVENT_INVALID) {
+ if (odp_event_type(ev) == ODP_EVENT_PACKET)
+ pkt = odp_packet_from_event(ev);
+ else
+ odp_event_free(ev);
}
+ }
- /* not interested in this event */
- odp_event_free(ev);
+ if (pkt != ODP_PACKET_INVALID) {
+ if (pktio_pkt_seq(pkt) == seq)
+ return pkt;
+
+ odp_packet_free(pkt);
}
now = odp_time_cycles();
@@ -438,7 +445,7 @@ static void pktio_txrx_multi(pktio_info_t *pktio_a, pktio_info_t *pktio_b,
/* and wait for them to arrive back */
for (i = 0; i < num_pkts; ++i) {
- rx_pkt = wait_for_packet(pktio_b->inq, tx_seq[i], ODP_TIME_SEC);
+ rx_pkt = wait_for_packet(pktio_b, tx_seq[i], ODP_TIME_SEC);
if (rx_pkt == ODP_PACKET_INVALID)
break;
@@ -450,7 +457,7 @@ static void pktio_txrx_multi(pktio_info_t *pktio_a, pktio_info_t *pktio_b,
CU_ASSERT(i == num_pkts);
}
-static void test_txrx(odp_queue_type_t q_type, int num_pkts)
+static void test_txrx(odp_pktio_input_mode_t in_mode, int num_pkts)
{
int ret, i, if_b;
pktio_info_t pktios[MAX_NUM_IFACES];
@@ -461,17 +468,21 @@ static void test_txrx(odp_queue_type_t q_type, int num_pkts)
io = &pktios[i];
io->name = iface_name[i];
- io->id = create_pktio(iface_name[i], q_type, i);
+ io->id = create_pktio(i, in_mode);
if (io->id == ODP_PKTIO_INVALID) {
CU_FAIL("failed to open iface");
return;
}
- create_inq(io->id, q_type);
io->outq = odp_pktio_outq_getdef(io->id);
- if (q_type == ODP_QUEUE_TYPE_POLL)
+ io->in_mode = in_mode;
+
+ if (in_mode == ODP_PKTIN_MODE_POLL) {
+ create_inq(io->id, ODP_QUEUE_TYPE_POLL);
io->inq = odp_pktio_inq_getdef(io->id);
- else
+ } else if (in_mode == ODP_PKTIN_MODE_SCHED) {
+ create_inq(io->id, ODP_QUEUE_TYPE_SCHED);
io->inq = ODP_QUEUE_INVALID;
+ }
ret = odp_pktio_start(io->id);
CU_ASSERT(ret == 0);
@@ -483,7 +494,8 @@ static void test_txrx(odp_queue_type_t q_type, int num_pkts)
pktio_txrx_multi(&pktios[0], &pktios[if_b], num_pkts);
for (i = 0; i < num_ifaces; ++i) {
- destroy_inq(pktios[i].id);
+ if (in_mode != ODP_PKTIN_MODE_RECV)
+ destroy_inq(pktios[i].id);
ret = odp_pktio_close(pktios[i].id);
CU_ASSERT(ret == 0);
}
@@ -491,22 +503,32 @@ static void test_txrx(odp_queue_type_t q_type, int num_pkts)
void pktio_test_poll_queue(void)
{
- test_txrx(ODP_QUEUE_TYPE_POLL, 1);
+ test_txrx(ODP_PKTIN_MODE_POLL, 1);
}
void pktio_test_poll_multi(void)
{
- test_txrx(ODP_QUEUE_TYPE_POLL, 4);
+ test_txrx(ODP_PKTIN_MODE_POLL, TX_BATCH_LEN);
}
void pktio_test_sched_queue(void)
{
- test_txrx(ODP_QUEUE_TYPE_SCHED, 1);
+ test_txrx(ODP_PKTIN_MODE_SCHED, 1);
}
void pktio_test_sched_multi(void)
{
- test_txrx(ODP_QUEUE_TYPE_SCHED, 4);
+ test_txrx(ODP_PKTIN_MODE_SCHED, TX_BATCH_LEN);
+}
+
+void pktio_test_recv(void)
+{
+ test_txrx(ODP_PKTIN_MODE_RECV, 1);
+}
+
+void pktio_test_recv_multi(void)
+{
+ test_txrx(ODP_PKTIN_MODE_RECV, TX_BATCH_LEN);
}
void pktio_test_jumbo(void)
@@ -520,7 +542,9 @@ void pktio_test_mtu(void)
{
int ret;
int mtu;
- odp_pktio_t pktio = create_pktio(iface_name[0], ODP_QUEUE_TYPE_SCHED, 0);
+
+ odp_pktio_t pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
mtu = odp_pktio_mtu(pktio);
CU_ASSERT(mtu > 0);
@@ -534,7 +558,9 @@ void pktio_test_mtu(void)
void pktio_test_promisc(void)
{
int ret;
- odp_pktio_t pktio = create_pktio(iface_name[0], ODP_QUEUE_TYPE_SCHED, 0);
+
+ odp_pktio_t pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
ret = odp_pktio_promisc_mode_set(pktio, 1);
CU_ASSERT(0 == ret);
@@ -561,7 +587,8 @@ void pktio_test_mac(void)
int ret;
odp_pktio_t pktio;
- pktio = create_pktio(iface_name[0], ODP_QUEUE_TYPE_SCHED, 0);
+ pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
printf("testing mac for %s\n", iface_name[0]);
@@ -588,8 +615,8 @@ void pktio_test_inq_remdef(void)
uint64_t wait;
int i;
- pktio = create_pktio(iface_name[0], ODP_QUEUE_TYPE_SCHED, 0);
- CU_ASSERT(pktio != ODP_PKTIO_INVALID);
+ pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
CU_ASSERT(create_inq(pktio, ODP_QUEUE_TYPE_POLL) == 0);
inq = odp_pktio_inq_getdef(pktio);
CU_ASSERT(inq != ODP_QUEUE_INVALID);
@@ -616,12 +643,12 @@ void pktio_test_open(void)
/* test the sequence open->close->open->close() */
for (i = 0; i < 2; ++i) {
- pktio = create_pktio(iface_name[0], ODP_QUEUE_TYPE_SCHED, 0);
- CU_ASSERT(pktio != ODP_PKTIO_INVALID);
+ pktio = create_pktio(0, ODP_PKTIN_MODE_SCHED);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
CU_ASSERT(odp_pktio_close(pktio) == 0);
}
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
pktio = odp_pktio_open("nothere", default_pkt_pool, &pktio_param);
@@ -633,7 +660,7 @@ void pktio_test_lookup(void)
odp_pktio_t pktio, pktio_inval;
odp_pktio_param_t pktio_param;
- memset(&pktio_param, 0, sizeof(pktio_param));
+ odp_pktio_param_init(&pktio_param);
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
pktio = odp_pktio_open(iface_name[0], default_pkt_pool, &pktio_param);
@@ -655,8 +682,8 @@ void pktio_test_inq(void)
{
odp_pktio_t pktio;
- pktio = create_pktio(iface_name[0], ODP_QUEUE_TYPE_SCHED, 0);
- CU_ASSERT(pktio != ODP_PKTIO_INVALID);
+ pktio = create_pktio(0, ODP_PKTIN_MODE_POLL);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
CU_ASSERT(create_inq(pktio, ODP_QUEUE_TYPE_POLL) == 0);
CU_ASSERT(destroy_inq(pktio) == 0);
@@ -674,66 +701,70 @@ static void pktio_test_start_stop(void)
uint64_t wait = odp_schedule_wait_time(ODP_TIME_MSEC);
for (i = 0; i < num_ifaces; i++) {
- pktio[i] = create_pktio(iface_name[i], ODP_QUEUE_TYPE_SCHED, 0);
- CU_ASSERT(pktio[i] != ODP_PKTIO_INVALID);
+ pktio[i] = create_pktio(i, ODP_PKTIN_MODE_SCHED);
+ CU_ASSERT_FATAL(pktio[i] != ODP_PKTIO_INVALID);
create_inq(pktio[i], ODP_QUEUE_TYPE_SCHED);
}
- for (alloc = 0; alloc < 1000; alloc++) {
- pkt = odp_packet_alloc(default_pkt_pool, packet_len);
- if (pkt == ODP_PACKET_INVALID)
- break;
- pktio_init_packet(pkt);
- tx_ev[alloc] = odp_packet_to_event(pkt);
- }
-
outq = odp_pktio_outq_getdef(pktio[0]);
ret = odp_pktio_stop(pktio[0]);
CU_ASSERT(ret == 0);
- /* start first and queue packets */
+ /* start first */
ret = odp_pktio_start(pktio[0]);
CU_ASSERT(ret == 0);
- /* stop second and send packets*/
+
+ /* Test Rx on a stopped interface. Only works if there are 2 */
if (num_ifaces > 1) {
+ for (alloc = 0; alloc < 1000; alloc++) {
+ pkt = odp_packet_alloc(default_pkt_pool, packet_len);
+ if (pkt == ODP_PACKET_INVALID)
+ break;
+ pktio_init_packet(pkt);
+ tx_ev[alloc] = odp_packet_to_event(pkt);
+ }
+
+ /* stop second and send packets*/
ret = odp_pktio_stop(pktio[1]);
CU_ASSERT(ret == 0);
- }
- for (pkts = 0; pkts != alloc; ) {
- ret = odp_queue_enq_multi(outq, &tx_ev[pkts], alloc - pkts);
- if (ret < 0) {
- CU_FAIL("unable to enqueue packet\n");
- break;
+
+ for (pkts = 0; pkts != alloc; ) {
+ ret = odp_queue_enq_multi(outq, &tx_ev[pkts],
+ alloc - pkts);
+ if (ret < 0) {
+ CU_FAIL("unable to enqueue packet\n");
+ break;
+ }
+ pkts += ret;
}
- pkts += ret;
- }
- /* check that packets did not arrive */
- for (i = 0, pkts = 0; i < 1000; i++) {
- ev = odp_schedule(NULL, wait);
- if (ev != ODP_EVENT_INVALID) {
+ /* check that packets did not arrive */
+ for (i = 0, pkts = 0; i < 1000; i++) {
+ ev = odp_schedule(NULL, wait);
+ if (ev == ODP_EVENT_INVALID)
+ continue;
+
if (odp_event_type(ev) == ODP_EVENT_PACKET) {
+ pkt = odp_packet_from_event(ev);
if (pktio_pkt_seq(pkt) != TEST_SEQ_INVALID)
pkts++;
}
odp_event_free(ev);
}
- }
- if (pkts)
- CU_FAIL("pktio stopped, received unexpected events");
+ if (pkts)
+ CU_FAIL("pktio stopped, received unexpected events");
- /* start both, send and get packets */
- /* 0 already started */
- if (num_ifaces > 1) {
+ /* start both, send and get packets */
+ /* 0 already started */
ret = odp_pktio_start(pktio[1]);
CU_ASSERT(ret == 0);
- }
- /* flush packets with magic number in pipes */
- for (i = 0; i < 1000; i++) {
- ev = odp_schedule(NULL, wait);
- if (ev != ODP_EVENT_INVALID)
- odp_event_free(ev);
+ /* flush packets with magic number in pipes */
+ for (i = 0; i < 1000; i++) {
+ ev = odp_schedule(NULL, wait);
+ if (ev != ODP_EVENT_INVALID)
+ odp_event_free(ev);
+ }
}
/* alloc */
@@ -775,6 +806,146 @@ static void pktio_test_start_stop(void)
}
}
+/*
+ * This is a pre-condition check that the pktio_test_send_failure()
+ * test case can be run. If the TX interface MTU is larger that the
+ * biggest packet we can allocate then the test won't be able to
+ * attempt to send packets larger than the MTU, so skip the test.
+ */
+static int pktio_check_send_failure(void)
+{
+ odp_pktio_t pktio_tx;
+ int mtu;
+ odp_pktio_param_t pktio_param;
+ int iface_idx = 0;
+ const char *iface = iface_name[iface_idx];
+
+ memset(&pktio_param, 0, sizeof(pktio_param));
+
+ pktio_param.in_mode = ODP_PKTIN_MODE_RECV;
+
+ pktio_tx = odp_pktio_open(iface, pool[iface_idx], &pktio_param);
+ if (pktio_tx == ODP_PKTIO_INVALID) {
+ fprintf(stderr, "%s: failed to open pktio\n", __func__);
+ return 0;
+ }
+
+ /* read the MTU from the transmit interface */
+ mtu = odp_pktio_mtu(pktio_tx);
+
+ odp_pktio_close(pktio_tx);
+
+ return (mtu <= ODP_CONFIG_PACKET_BUF_LEN_MAX - 32);
+}
+
+static void pktio_test_send_failure(void)
+{
+ odp_pktio_t pktio_tx, pktio_rx;
+ odp_packet_t pkt_tbl[TX_BATCH_LEN];
+ uint32_t pkt_seq[TX_BATCH_LEN];
+ int ret, mtu, i, alloc_pkts;
+ odp_pool_param_t pool_params;
+ odp_pool_t pkt_pool;
+ int long_pkt_idx = TX_BATCH_LEN / 2;
+ pktio_info_t info_rx;
+
+ pktio_tx = create_pktio(0, ODP_PKTIN_MODE_RECV);
+ if (pktio_tx == ODP_PKTIO_INVALID) {
+ CU_FAIL("failed to open pktio");
+ return;
+ }
+
+ /* read the MTU from the transmit interface */
+ mtu = odp_pktio_mtu(pktio_tx);
+
+ ret = odp_pktio_start(pktio_tx);
+ CU_ASSERT_FATAL(ret == 0);
+
+ /* configure the pool so that we can generate test packets larger
+ * than the interface MTU */
+ memset(&pool_params, 0, sizeof(pool_params));
+ pool_params.pkt.len = mtu + 32;
+ pool_params.pkt.seg_len = pool_params.pkt.len;
+ pool_params.pkt.num = TX_BATCH_LEN + 1;
+ pool_params.type = ODP_POOL_PACKET;
+ pkt_pool = odp_pool_create("pkt_pool_oversize", &pool_params);
+ CU_ASSERT_FATAL(pkt_pool != ODP_POOL_INVALID);
+
+ if (num_ifaces > 1) {
+ pktio_rx = create_pktio(1, ODP_PKTIN_MODE_RECV);
+ ret = odp_pktio_start(pktio_rx);
+ CU_ASSERT_FATAL(ret == 0);
+ } else {
+ pktio_rx = pktio_tx;
+ }
+
+ /* generate a batch of packets with a single overly long packet
+ * in the middle */
+ for (i = 0; i < TX_BATCH_LEN; ++i) {
+ uint32_t pkt_len;
+
+ if (i == long_pkt_idx)
+ pkt_len = pool_params.pkt.len;
+ else
+ pkt_len = PKT_LEN_NORMAL;
+
+ pkt_tbl[i] = odp_packet_alloc(pkt_pool, pkt_len);
+ if (pkt_tbl[i] == ODP_PACKET_INVALID)
+ break;
+
+ pkt_seq[i] = pktio_init_packet(pkt_tbl[i]);
+ if (pkt_seq[i] == TEST_SEQ_INVALID)
+ break;
+ }
+ alloc_pkts = i;
+
+ if (alloc_pkts == TX_BATCH_LEN) {
+ /* try to send the batch with the long packet in the middle,
+ * the initial short packets should be sent successfully */
+ odp_errno_zero();
+ ret = odp_pktio_send(pktio_tx, pkt_tbl, TX_BATCH_LEN);
+ CU_ASSERT(ret == long_pkt_idx);
+ CU_ASSERT(odp_errno() == 0);
+
+ info_rx.id = pktio_rx;
+ info_rx.outq = ODP_QUEUE_INVALID;
+ info_rx.inq = ODP_QUEUE_INVALID;
+ info_rx.in_mode = ODP_PKTIN_MODE_RECV;
+
+ for (i = 0; i < ret; ++i) {
+ pkt_tbl[i] = wait_for_packet(&info_rx,
+ pkt_seq[i], ODP_TIME_SEC);
+ if (pkt_tbl[i] == ODP_PACKET_INVALID)
+ break;
+ }
+
+ if (i == ret) {
+ /* now try to send starting with the too-long packet
+ * and verify it fails */
+ odp_errno_zero();
+ ret = odp_pktio_send(pktio_tx,
+ &pkt_tbl[long_pkt_idx],
+ TX_BATCH_LEN - long_pkt_idx);
+ CU_ASSERT(ret == -1);
+ CU_ASSERT(odp_errno() != 0);
+ } else {
+ CU_FAIL("failed to receive transmitted packets\n");
+ }
+ } else {
+ CU_FAIL("failed to generate test packets\n");
+ }
+
+ for (i = 0; i < alloc_pkts; ++i) {
+ if (pkt_tbl[i] != ODP_PACKET_INVALID)
+ odp_packet_free(pkt_tbl[i]);
+ }
+
+ if (pktio_rx != pktio_tx)
+ CU_ASSERT(odp_pktio_close(pktio_rx) == 0);
+ CU_ASSERT(odp_pktio_close(pktio_tx) == 0);
+ CU_ASSERT(odp_pool_destroy(pkt_pool) == 0);
+}
+
static int create_pool(const char *iface, int num)
{
char pool_name[ODP_POOL_NAME_LEN];
@@ -790,7 +961,8 @@ static int create_pool(const char *iface, int num)
pool[num] = odp_pool_create(pool_name, &params);
if (ODP_POOL_INVALID == pool[num]) {
- CU_FAIL("unable to create pool");
+ fprintf(stderr, "%s: failed to create pool: %d",
+ __func__, odp_errno());
return -1;
}
@@ -871,41 +1043,54 @@ int pktio_suite_term(void)
return ret;
}
-CU_TestInfo pktio_suite_unsegmented[] = {
- _CU_TEST_INFO(pktio_test_open),
- _CU_TEST_INFO(pktio_test_lookup),
- _CU_TEST_INFO(pktio_test_inq),
- _CU_TEST_INFO(pktio_test_poll_queue),
- _CU_TEST_INFO(pktio_test_poll_multi),
- _CU_TEST_INFO(pktio_test_sched_queue),
- _CU_TEST_INFO(pktio_test_sched_multi),
- _CU_TEST_INFO(pktio_test_jumbo),
- _CU_TEST_INFO(pktio_test_mtu),
- _CU_TEST_INFO(pktio_test_promisc),
- _CU_TEST_INFO(pktio_test_mac),
- _CU_TEST_INFO(pktio_test_inq_remdef),
- _CU_TEST_INFO(pktio_test_start_stop),
- CU_TEST_INFO_NULL
+odp_testinfo_t pktio_suite_unsegmented[] = {
+ ODP_TEST_INFO(pktio_test_open),
+ ODP_TEST_INFO(pktio_test_lookup),
+ ODP_TEST_INFO(pktio_test_inq),
+ ODP_TEST_INFO(pktio_test_poll_queue),
+ ODP_TEST_INFO(pktio_test_poll_multi),
+ ODP_TEST_INFO(pktio_test_sched_queue),
+ ODP_TEST_INFO(pktio_test_sched_multi),
+ ODP_TEST_INFO(pktio_test_recv),
+ ODP_TEST_INFO(pktio_test_recv_multi),
+ ODP_TEST_INFO(pktio_test_jumbo),
+ ODP_TEST_INFO_CONDITIONAL(pktio_test_send_failure,
+ pktio_check_send_failure),
+ ODP_TEST_INFO(pktio_test_mtu),
+ ODP_TEST_INFO(pktio_test_promisc),
+ ODP_TEST_INFO(pktio_test_mac),
+ ODP_TEST_INFO(pktio_test_inq_remdef),
+ ODP_TEST_INFO(pktio_test_start_stop),
+ ODP_TEST_INFO_NULL
};
-CU_TestInfo pktio_suite_segmented[] = {
- {"pktio poll queues", pktio_test_poll_queue},
- {"pktio poll multi", pktio_test_poll_multi},
- {"pktio sched queues", pktio_test_sched_queue},
- {"pktio sched multi", pktio_test_sched_multi},
- {"pktio jumbo frames", pktio_test_jumbo},
- CU_TEST_INFO_NULL
+odp_testinfo_t pktio_suite_segmented[] = {
+ ODP_TEST_INFO(pktio_test_poll_queue),
+ ODP_TEST_INFO(pktio_test_poll_multi),
+ ODP_TEST_INFO(pktio_test_sched_queue),
+ ODP_TEST_INFO(pktio_test_sched_multi),
+ ODP_TEST_INFO(pktio_test_recv),
+ ODP_TEST_INFO(pktio_test_recv_multi),
+ ODP_TEST_INFO(pktio_test_jumbo),
+ ODP_TEST_INFO_CONDITIONAL(pktio_test_send_failure,
+ pktio_check_send_failure),
+ ODP_TEST_INFO_NULL
};
-CU_SuiteInfo pktio_suites[] = {
+odp_suiteinfo_t pktio_suites[] = {
{"Packet I/O Unsegmented", pktio_suite_init_unsegmented,
- pktio_suite_term, NULL, NULL, pktio_suite_unsegmented},
+ pktio_suite_term, pktio_suite_unsegmented},
{"Packet I/O Segmented", pktio_suite_init_segmented,
- pktio_suite_term, NULL, NULL, pktio_suite_segmented},
- CU_SUITE_INFO_NULL
+ pktio_suite_term, pktio_suite_segmented},
+ ODP_SUITE_INFO_NULL
};
int pktio_main(void)
{
- return odp_cunit_run(pktio_suites);
+ int ret = odp_cunit_register(pktio_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/pktio/pktio.h b/test/validation/pktio/pktio.h
index feaf7fb70..f22ff25ae 100644
--- a/test/validation/pktio/pktio.h
+++ b/test/validation/pktio/pktio.h
@@ -7,13 +7,15 @@
#ifndef _ODP_TEST_PKTIO_H_
#define _ODP_TEST_PKTIO_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void pktio_test_poll_queue(void);
void pktio_test_poll_multi(void);
void pktio_test_sched_queue(void);
void pktio_test_sched_multi(void);
+void pktio_test_recv(void);
+void pktio_test_recv_multi(void);
void pktio_test_jumbo(void);
void pktio_test_mtu(void);
void pktio_test_promisc(void);
@@ -24,7 +26,7 @@ void pktio_test_lookup(void);
void pktio_test_inq(void);
/* test arrays: */
-extern CU_TestInfo pktio_suite[];
+extern odp_testinfo_t pktio_suite[];
/* test array init/term functions: */
int pktio_suite_term(void);
@@ -32,7 +34,7 @@ int pktio_suite_init_segmented(void);
int pktio_suite_init_unsegmented(void);
/* test registry: */
-extern CU_SuiteInfo pktio_suites[];
+extern odp_suiteinfo_t pktio_suites[];
/* main test program: */
int pktio_main(void);
diff --git a/test/validation/pool/Makefile.am b/test/validation/pool/Makefile.am
index 8f626e7f1..4f434e929 100644
--- a/test/validation/pool/Makefile.am
+++ b/test/validation/pool/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libpool.la
-libpool_la_SOURCES = pool.c
+noinst_LTLIBRARIES = libtestpool.la
+libtestpool_la_SOURCES = pool.c
bin_PROGRAMS = pool_main$(EXEEXT)
dist_pool_main_SOURCES = pool_main.c
-pool_main_LDADD = libpool.la $(LIBCUNIT_COMMON) $(LIBODP)
+pool_main_LDADD = libtestpool.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = pool.h
diff --git a/test/validation/pool/pool.c b/test/validation/pool/pool.c
index 44ba155c6..bca210aa4 100644
--- a/test/validation/pool/pool.c
+++ b/test/validation/pool/pool.c
@@ -99,22 +99,27 @@ void pool_test_lookup_info_print(void)
CU_ASSERT(odp_pool_destroy(pool) == 0);
}
-CU_TestInfo pool_suite[] = {
- _CU_TEST_INFO(pool_test_create_destroy_buffer),
- _CU_TEST_INFO(pool_test_create_destroy_packet),
- _CU_TEST_INFO(pool_test_create_destroy_timeout),
- _CU_TEST_INFO(pool_test_lookup_info_print),
- CU_TEST_INFO_NULL,
+odp_testinfo_t pool_suite[] = {
+ ODP_TEST_INFO(pool_test_create_destroy_buffer),
+ ODP_TEST_INFO(pool_test_create_destroy_packet),
+ ODP_TEST_INFO(pool_test_create_destroy_timeout),
+ ODP_TEST_INFO(pool_test_lookup_info_print),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo pool_suites[] = {
+odp_suiteinfo_t pool_suites[] = {
{ .pName = "Pool tests",
.pTests = pool_suite,
},
- CU_SUITE_INFO_NULL,
+ ODP_SUITE_INFO_NULL,
};
int pool_main(void)
{
- return odp_cunit_run(pool_suites);
+ int ret = odp_cunit_register(pool_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/pool/pool.h b/test/validation/pool/pool.h
index 12c6193d8..6a83a2e72 100644
--- a/test/validation/pool/pool.h
+++ b/test/validation/pool/pool.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_POOL_H_
#define _ODP_TEST_POOL_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void pool_test_create_destroy_buffer(void);
@@ -17,10 +17,10 @@ void pool_test_create_destroy_buffer_shm(void);
void pool_test_lookup_info_print(void);
/* test arrays: */
-extern CU_TestInfo pool_suite[];
+extern odp_testinfo_t pool_suite[];
/* test registry: */
-extern CU_SuiteInfo pool_suites[];
+extern odp_suiteinfo_t pool_suites[];
/* main test program: */
int pool_main(void);
diff --git a/test/validation/queue/Makefile.am b/test/validation/queue/Makefile.am
index c4e5f9647..af01b70d8 100644
--- a/test/validation/queue/Makefile.am
+++ b/test/validation/queue/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libqueue.la
-libqueue_la_SOURCES = queue.c
+noinst_LTLIBRARIES = libtestqueue.la
+libtestqueue_la_SOURCES = queue.c
bin_PROGRAMS = queue_main$(EXEEXT)
dist_queue_main_SOURCES = queue_main.c
-queue_main_LDADD = libqueue.la $(LIBCUNIT_COMMON) $(LIBODP)
+queue_main_LDADD = libtestqueue.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = queue.h
diff --git a/test/validation/queue/queue.c b/test/validation/queue/queue.c
index 02a553817..98da2ec0c 100644
--- a/test/validation/queue/queue.c
+++ b/test/validation/queue/queue.c
@@ -125,18 +125,22 @@ void queue_test_sunnydays(void)
CU_ASSERT(odp_queue_destroy(queue_id) == 0);
}
-CU_TestInfo queue_suite[] = {
- _CU_TEST_INFO(queue_test_sunnydays),
- CU_TEST_INFO_NULL,
+odp_testinfo_t queue_suite[] = {
+ ODP_TEST_INFO(queue_test_sunnydays),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo queue_suites[] = {
- {"Queue", queue_suite_init, queue_suite_term,
- NULL, NULL, queue_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t queue_suites[] = {
+ {"Queue", queue_suite_init, queue_suite_term, queue_suite},
+ ODP_SUITE_INFO_NULL,
};
int queue_main(void)
{
- return odp_cunit_run(queue_suites);
+ int ret = odp_cunit_register(queue_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/queue/queue.h b/test/validation/queue/queue.h
index d2765ce46..5de7b2c23 100644
--- a/test/validation/queue/queue.h
+++ b/test/validation/queue/queue.h
@@ -7,20 +7,20 @@
#ifndef _ODP_TEST_QUEUE_H_
#define _ODP_TEST_QUEUE_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void queue_test_sunnydays(void);
/* test arrays: */
-extern CU_TestInfo queue_suite[];
+extern odp_testinfo_t queue_suite[];
/* test array init/term functions: */
int queue_suite_init(void);
int queue_suite_term(void);
/* test registry: */
-extern CU_SuiteInfo queue_suites[];
+extern odp_suiteinfo_t queue_suites[];
/* main test program: */
int queue_main(void);
diff --git a/test/validation/random/Makefile.am b/test/validation/random/Makefile.am
index 8f871bc18..3037e7acf 100644
--- a/test/validation/random/Makefile.am
+++ b/test/validation/random/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = librandom.la
-librandom_la_SOURCES = random.c
+noinst_LTLIBRARIES = libtestrandom.la
+libtestrandom_la_SOURCES = random.c
bin_PROGRAMS = random_main$(EXEEXT)
dist_random_main_SOURCES = random_main.c
-random_main_LDADD = librandom.la $(LIBCUNIT_COMMON) $(LIBODP)
+random_main_LDADD = libtestrandom.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = random.h
diff --git a/test/validation/random/random.c b/test/validation/random/random.c
index b6426f4c0..8ed594420 100644
--- a/test/validation/random/random.c
+++ b/test/validation/random/random.c
@@ -17,17 +17,22 @@ void random_test_get_size(void)
CU_ASSERT(ret == sizeof(buf));
}
-CU_TestInfo random_suite[] = {
- _CU_TEST_INFO(random_test_get_size),
- CU_TEST_INFO_NULL,
+odp_testinfo_t random_suite[] = {
+ ODP_TEST_INFO(random_test_get_size),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo random_suites[] = {
- {"Random", NULL, NULL, NULL, NULL, random_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t random_suites[] = {
+ {"Random", NULL, NULL, random_suite},
+ ODP_SUITE_INFO_NULL,
};
int random_main(void)
{
- return odp_cunit_run(random_suites);
+ int ret = odp_cunit_register(random_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/random/random.h b/test/validation/random/random.h
index cda1843e4..4101ef17d 100644
--- a/test/validation/random/random.h
+++ b/test/validation/random/random.h
@@ -7,16 +7,16 @@
#ifndef _ODP_TEST_RANDOM_H_
#define _ODP_TEST_RANDOM_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void random_test_get_size(void);
/* test arrays: */
-extern CU_TestInfo random_suite[];
+extern odp_testinfo_t random_suite[];
/* test registry: */
-extern CU_SuiteInfo random_suites[];
+extern odp_suiteinfo_t random_suites[];
/* main test program: */
int random_main(void);
diff --git a/test/validation/scheduler/Makefile.am b/test/validation/scheduler/Makefile.am
index e3947fae6..a180fc335 100644
--- a/test/validation/scheduler/Makefile.am
+++ b/test/validation/scheduler/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libscheduler.la
-libscheduler_la_SOURCES = scheduler.c
+noinst_LTLIBRARIES = libtestscheduler.la
+libtestscheduler_la_SOURCES = scheduler.c
bin_PROGRAMS = scheduler_main$(EXEEXT)
dist_scheduler_main_SOURCES = scheduler_main.c
-scheduler_main_LDADD = libscheduler.la $(LIBCUNIT_COMMON) $(LIBODP)
+scheduler_main_LDADD = libtestscheduler.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = scheduler.h
diff --git a/test/validation/scheduler/scheduler.c b/test/validation/scheduler/scheduler.c
index 1874889e7..89c1099c1 100644
--- a/test/validation/scheduler/scheduler.c
+++ b/test/validation/scheduler/scheduler.c
@@ -62,13 +62,13 @@ typedef struct {
typedef struct {
uint64_t sequence;
+ uint64_t lock_sequence[ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE];
} buf_contents;
typedef struct {
odp_buffer_t ctx_handle;
uint64_t sequence;
- uint64_t lock_sequence;
- odp_schedule_order_lock_t order_lock;
+ uint64_t lock_sequence[ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE];
} queue_context;
odp_pool_t pool;
@@ -95,9 +95,7 @@ void scheduler_test_wait_time(void)
uint64_t wait_time;
wait_time = odp_schedule_wait_time(0);
-
wait_time = odp_schedule_wait_time(1);
- CU_ASSERT(wait_time > 0);
wait_time = odp_schedule_wait_time((uint64_t)-1LL);
CU_ASSERT(wait_time > 0);
@@ -419,14 +417,20 @@ static void *schedule_common_(void *arg)
continue;
if (sync == ODP_SCHED_SYNC_ORDERED) {
+ uint32_t ndx;
+ uint32_t ndx_max = odp_queue_lock_count(from);
+
qctx = odp_queue_context(from);
bctx = odp_buffer_addr(
odp_buffer_from_event(events[0]));
- odp_schedule_order_lock(&qctx->order_lock);
- CU_ASSERT(bctx->sequence ==
- qctx->lock_sequence);
- qctx->lock_sequence += num;
- odp_schedule_order_unlock(&qctx->order_lock);
+
+ for (ndx = 0; ndx < ndx_max; ndx++) {
+ odp_schedule_order_lock(ndx);
+ CU_ASSERT(bctx->sequence ==
+ qctx->lock_sequence[ndx]);
+ qctx->lock_sequence[ndx] += num;
+ odp_schedule_order_unlock(ndx);
+ }
}
for (j = 0; j < num; j++)
@@ -438,13 +442,19 @@ static void *schedule_common_(void *arg)
continue;
num = 1;
if (sync == ODP_SCHED_SYNC_ORDERED) {
+ uint32_t ndx;
+ uint32_t ndx_max = odp_queue_lock_count(from);
+
qctx = odp_queue_context(from);
bctx = odp_buffer_addr(buf);
- odp_schedule_order_lock(&qctx->order_lock);
- CU_ASSERT(bctx->sequence ==
- qctx->lock_sequence);
- qctx->lock_sequence += num;
- odp_schedule_order_unlock(&qctx->order_lock);
+
+ for (ndx = 0; ndx < ndx_max; ndx++) {
+ odp_schedule_order_lock(ndx);
+ CU_ASSERT(bctx->sequence ==
+ qctx->lock_sequence[ndx]);
+ qctx->lock_sequence[ndx] += num;
+ odp_schedule_order_unlock(ndx);
+ }
}
odp_buffer_free(buf);
}
@@ -570,8 +580,12 @@ static void reset_queues(thread_args_t *args)
for (k = 0; k < args->num_bufs; k++) {
queue_context *qctx =
odp_queue_context(queue);
+ uint32_t ndx;
+ uint32_t ndx_max =
+ odp_queue_lock_count(queue);
qctx->sequence = 0;
- qctx->lock_sequence = 0;
+ for (ndx = 0; ndx < ndx_max; ndx++)
+ qctx->lock_sequence[ndx] = 0;
}
}
}
@@ -902,6 +916,7 @@ static int create_queues(void)
odp_pool_param_t params;
odp_buffer_t queue_ctx_buf;
queue_context *qctx;
+ uint32_t ndx;
prios = odp_schedule_num_prio();
odp_pool_param_init(&params);
@@ -946,12 +961,23 @@ static int create_queues(void)
snprintf(name, sizeof(name), "sched_%d_%d_o", i, j);
p.sched.sync = ODP_SCHED_SYNC_ORDERED;
+ p.sched.lock_count =
+ ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE;
q = odp_queue_create(name, ODP_QUEUE_TYPE_SCHED, &p);
if (q == ODP_QUEUE_INVALID) {
printf("Schedule queue create failed.\n");
return -1;
}
+ if (odp_queue_lock_count(q) !=
+ ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE) {
+ printf("Queue %" PRIu64 " created with "
+ "%d locks instead of expected %d\n",
+ odp_queue_to_u64(q),
+ odp_queue_lock_count(q),
+ ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE);
+ return -1;
+ }
queue_ctx_buf = odp_buffer_alloc(queue_ctx_pool);
@@ -963,12 +989,11 @@ static int create_queues(void)
qctx = odp_buffer_addr(queue_ctx_buf);
qctx->ctx_handle = queue_ctx_buf;
qctx->sequence = 0;
- qctx->lock_sequence = 0;
- rc = odp_schedule_order_lock_init(&qctx->order_lock, q);
- if (rc != 0) {
- printf("Ordered lock init failed\n");
- return -1;
+ for (ndx = 0;
+ ndx < ODP_CONFIG_MAX_ORDERED_LOCKS_PER_QUEUE;
+ ndx++) {
+ qctx->lock_sequence[ndx] = 0;
}
rc = odp_queue_context_set(q, qctx);
@@ -1017,7 +1042,7 @@ int scheduler_suite_init(void)
memset(globals, 0, sizeof(test_globals_t));
- globals->num_workers = odp_cpumask_def_worker(&mask, 0);
+ globals->num_workers = odp_cpumask_default_worker(&mask, 0);
if (globals->num_workers > MAX_WORKERS)
globals->num_workers = MAX_WORKERS;
@@ -1105,49 +1130,54 @@ int scheduler_suite_term(void)
return 0;
}
-CU_TestInfo scheduler_suite[] = {
- _CU_TEST_INFO(scheduler_test_wait_time),
- _CU_TEST_INFO(scheduler_test_num_prio),
- _CU_TEST_INFO(scheduler_test_queue_destroy),
- _CU_TEST_INFO(scheduler_test_groups),
- _CU_TEST_INFO(scheduler_test_1q_1t_n),
- _CU_TEST_INFO(scheduler_test_1q_1t_a),
- _CU_TEST_INFO(scheduler_test_1q_1t_o),
- _CU_TEST_INFO(scheduler_test_mq_1t_n),
- _CU_TEST_INFO(scheduler_test_mq_1t_a),
- _CU_TEST_INFO(scheduler_test_mq_1t_o),
- _CU_TEST_INFO(scheduler_test_mq_1t_prio_n),
- _CU_TEST_INFO(scheduler_test_mq_1t_prio_a),
- _CU_TEST_INFO(scheduler_test_mq_1t_prio_o),
- _CU_TEST_INFO(scheduler_test_mq_mt_prio_n),
- _CU_TEST_INFO(scheduler_test_mq_mt_prio_a),
- _CU_TEST_INFO(scheduler_test_mq_mt_prio_o),
- _CU_TEST_INFO(scheduler_test_1q_mt_a_excl),
- _CU_TEST_INFO(scheduler_test_multi_1q_1t_n),
- _CU_TEST_INFO(scheduler_test_multi_1q_1t_a),
- _CU_TEST_INFO(scheduler_test_multi_1q_1t_o),
- _CU_TEST_INFO(scheduler_test_multi_mq_1t_n),
- _CU_TEST_INFO(scheduler_test_multi_mq_1t_a),
- _CU_TEST_INFO(scheduler_test_multi_mq_1t_o),
- _CU_TEST_INFO(scheduler_test_multi_mq_1t_prio_n),
- _CU_TEST_INFO(scheduler_test_multi_mq_1t_prio_a),
- _CU_TEST_INFO(scheduler_test_multi_mq_1t_prio_o),
- _CU_TEST_INFO(scheduler_test_multi_mq_mt_prio_n),
- _CU_TEST_INFO(scheduler_test_multi_mq_mt_prio_a),
- _CU_TEST_INFO(scheduler_test_multi_mq_mt_prio_o),
- _CU_TEST_INFO(scheduler_test_multi_1q_mt_a_excl),
- _CU_TEST_INFO(scheduler_test_pause_resume),
- CU_TEST_INFO_NULL,
+odp_testinfo_t scheduler_suite[] = {
+ ODP_TEST_INFO(scheduler_test_wait_time),
+ ODP_TEST_INFO(scheduler_test_num_prio),
+ ODP_TEST_INFO(scheduler_test_queue_destroy),
+ ODP_TEST_INFO(scheduler_test_groups),
+ ODP_TEST_INFO(scheduler_test_1q_1t_n),
+ ODP_TEST_INFO(scheduler_test_1q_1t_a),
+ ODP_TEST_INFO(scheduler_test_1q_1t_o),
+ ODP_TEST_INFO(scheduler_test_mq_1t_n),
+ ODP_TEST_INFO(scheduler_test_mq_1t_a),
+ ODP_TEST_INFO(scheduler_test_mq_1t_o),
+ ODP_TEST_INFO(scheduler_test_mq_1t_prio_n),
+ ODP_TEST_INFO(scheduler_test_mq_1t_prio_a),
+ ODP_TEST_INFO(scheduler_test_mq_1t_prio_o),
+ ODP_TEST_INFO(scheduler_test_mq_mt_prio_n),
+ ODP_TEST_INFO(scheduler_test_mq_mt_prio_a),
+ ODP_TEST_INFO(scheduler_test_mq_mt_prio_o),
+ ODP_TEST_INFO(scheduler_test_1q_mt_a_excl),
+ ODP_TEST_INFO(scheduler_test_multi_1q_1t_n),
+ ODP_TEST_INFO(scheduler_test_multi_1q_1t_a),
+ ODP_TEST_INFO(scheduler_test_multi_1q_1t_o),
+ ODP_TEST_INFO(scheduler_test_multi_mq_1t_n),
+ ODP_TEST_INFO(scheduler_test_multi_mq_1t_a),
+ ODP_TEST_INFO(scheduler_test_multi_mq_1t_o),
+ ODP_TEST_INFO(scheduler_test_multi_mq_1t_prio_n),
+ ODP_TEST_INFO(scheduler_test_multi_mq_1t_prio_a),
+ ODP_TEST_INFO(scheduler_test_multi_mq_1t_prio_o),
+ ODP_TEST_INFO(scheduler_test_multi_mq_mt_prio_n),
+ ODP_TEST_INFO(scheduler_test_multi_mq_mt_prio_a),
+ ODP_TEST_INFO(scheduler_test_multi_mq_mt_prio_o),
+ ODP_TEST_INFO(scheduler_test_multi_1q_mt_a_excl),
+ ODP_TEST_INFO(scheduler_test_pause_resume),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo scheduler_suites[] = {
+odp_suiteinfo_t scheduler_suites[] = {
{"Scheduler",
- scheduler_suite_init, scheduler_suite_term, NULL, NULL, scheduler_suite
+ scheduler_suite_init, scheduler_suite_term, scheduler_suite
},
- CU_SUITE_INFO_NULL,
+ ODP_SUITE_INFO_NULL,
};
int scheduler_main(void)
{
- return odp_cunit_run(scheduler_suites);
+ int ret = odp_cunit_register(scheduler_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/scheduler/scheduler.h b/test/validation/scheduler/scheduler.h
index eab8787b7..c869e414f 100644
--- a/test/validation/scheduler/scheduler.h
+++ b/test/validation/scheduler/scheduler.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_SCHEDULER_H_
#define _ODP_TEST_SCHEDULER_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void scheduler_test_wait_time(void);
@@ -43,14 +43,14 @@ void scheduler_test_multi_1q_mt_a_excl(void);
void scheduler_test_pause_resume(void);
/* test arrays: */
-extern CU_TestInfo scheduler_suite[];
+extern odp_testinfo_t scheduler_suite[];
/* test array init/term functions: */
int scheduler_suite_init(void);
int scheduler_suite_term(void);
/* test registry: */
-extern CU_SuiteInfo scheduler_suites[];
+extern odp_suiteinfo_t scheduler_suites[];
/* main test program: */
int scheduler_main(void);
diff --git a/test/validation/shmem/Makefile.am b/test/validation/shmem/Makefile.am
index b2d94ed66..6d1f32414 100644
--- a/test/validation/shmem/Makefile.am
+++ b/test/validation/shmem/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libshmem.la
-libshmem_la_SOURCES = shmem.c
+noinst_LTLIBRARIES = libtestshmem.la
+libtestshmem_la_SOURCES = shmem.c
bin_PROGRAMS = shmem_main$(EXEEXT)
dist_shmem_main_SOURCES = shmem_main.c
-shmem_main_LDADD = libshmem.la $(LIBCUNIT_COMMON) $(LIBODP)
+shmem_main_LDADD = libtestshmem.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = shmem.h
diff --git a/test/validation/shmem/shmem.c b/test/validation/shmem/shmem.c
index 6dc579a39..5524b5cc1 100644
--- a/test/validation/shmem/shmem.c
+++ b/test/validation/shmem/shmem.c
@@ -76,17 +76,22 @@ void shmem_test_odp_shm_sunnyday(void)
odp_cunit_thread_exit(&thrdarg);
}
-CU_TestInfo shmem_suite[] = {
- _CU_TEST_INFO(shmem_test_odp_shm_sunnyday),
- CU_TEST_INFO_NULL,
+odp_testinfo_t shmem_suite[] = {
+ ODP_TEST_INFO(shmem_test_odp_shm_sunnyday),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo shmem_suites[] = {
- {"Shared Memory", NULL, NULL, NULL, NULL, shmem_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t shmem_suites[] = {
+ {"Shared Memory", NULL, NULL, shmem_suite},
+ ODP_SUITE_INFO_NULL,
};
int shmem_main(void)
{
- return odp_cunit_run(shmem_suites);
+ int ret = odp_cunit_register(shmem_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/shmem/shmem.h b/test/validation/shmem/shmem.h
index 8de0bc660..d60cf6482 100644
--- a/test/validation/shmem/shmem.h
+++ b/test/validation/shmem/shmem.h
@@ -7,16 +7,16 @@
#ifndef _ODP_TEST_SHMEM_H_
#define _ODP_TEST_SHMEM_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void shmem_test_odp_shm_sunnyday(void);
/* test arrays: */
-extern CU_TestInfo shmem_suite[];
+extern odp_testinfo_t shmem_suite[];
/* test registry: */
-extern CU_SuiteInfo shmem_suites[];
+extern odp_suiteinfo_t shmem_suites[];
/* main test program: */
int shmem_main(void);
diff --git a/test/validation/synchronizers/Makefile.am b/test/validation/synchronizers/Makefile.am
index 4cd313c2e..96f98b5c5 100644
--- a/test/validation/synchronizers/Makefile.am
+++ b/test/validation/synchronizers/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libsynchronizers.la
-libsynchronizers_la_SOURCES = synchronizers.c
+noinst_LTLIBRARIES = libtestsynchronizers.la
+libtestsynchronizers_la_SOURCES = synchronizers.c
bin_PROGRAMS = synchronizers_main$(EXEEXT)
dist_synchronizers_main_SOURCES = synchronizers_main.c
-synchronizers_main_LDADD = libsynchronizers.la $(LIBCUNIT_COMMON) $(LIBODP)
+synchronizers_main_LDADD = libtestsynchronizers.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = synchronizers.h
diff --git a/test/validation/synchronizers/synchronizers.c b/test/validation/synchronizers/synchronizers.c
index 0a31a40ef..2406c7706 100644
--- a/test/validation/synchronizers/synchronizers.c
+++ b/test/validation/synchronizers/synchronizers.c
@@ -253,9 +253,10 @@ static void *no_barrier_functional_test(void *arg UNUSED)
* Note that the following CU_ASSERT MAY appear incorrect, but for the
* no_barrier test it should see barrier_errs or else there is something
* wrong with the test methodology or the ODP thread implementation.
- * So this test PASSES only if it sees barrier_errs!
+ * So this test PASSES only if it sees barrier_errs or a single
+ * worker was used.
*/
- CU_ASSERT(barrier_errs != 0);
+ CU_ASSERT(barrier_errs != 0 || global_mem->g_num_threads == 1);
thread_finalize(per_thread_mem);
return NULL;
@@ -447,9 +448,10 @@ static void *no_lock_functional_test(void *arg UNUSED)
/* Note that the following CU_ASSERT MAY appear incorrect, but for the
* no_lock test it should see sync_failures or else there is something
* wrong with the test methodology or the ODP thread implementation.
- * So this test PASSES only if it sees sync_failures
+ * So this test PASSES only if it sees sync_failures or a single
+ * worker was used.
*/
- CU_ASSERT(sync_failures != 0);
+ CU_ASSERT(sync_failures != 0 || global_mem->g_num_threads == 1);
thread_finalize(per_thread_mem);
@@ -940,10 +942,10 @@ void synchronizers_test_barrier_functional(void)
odp_cunit_thread_exit(&arg);
}
-CU_TestInfo synchronizers_suite_barrier[] = {
- _CU_TEST_INFO(synchronizers_test_no_barrier_functional),
- _CU_TEST_INFO(synchronizers_test_barrier_functional),
- CU_TEST_INFO_NULL
+odp_testinfo_t synchronizers_suite_barrier[] = {
+ ODP_TEST_INFO(synchronizers_test_no_barrier_functional),
+ ODP_TEST_INFO(synchronizers_test_barrier_functional),
+ ODP_TEST_INFO_NULL
};
/* Thread-unsafe tests */
@@ -956,9 +958,9 @@ void synchronizers_test_no_lock_functional(void)
odp_cunit_thread_exit(&arg);
}
-CU_TestInfo synchronizers_suite_no_locking[] = {
- _CU_TEST_INFO(synchronizers_test_no_lock_functional),
- CU_TEST_INFO_NULL
+odp_testinfo_t synchronizers_suite_no_locking[] = {
+ ODP_TEST_INFO(synchronizers_test_no_lock_functional),
+ ODP_TEST_INFO_NULL
};
/* Spin lock tests */
@@ -981,10 +983,10 @@ void synchronizers_test_spinlock_functional(void)
odp_cunit_thread_exit(&arg);
}
-CU_TestInfo synchronizers_suite_spinlock[] = {
- _CU_TEST_INFO(synchronizers_test_spinlock_api),
- _CU_TEST_INFO(synchronizers_test_spinlock_functional),
- CU_TEST_INFO_NULL
+odp_testinfo_t synchronizers_suite_spinlock[] = {
+ ODP_TEST_INFO(synchronizers_test_spinlock_api),
+ ODP_TEST_INFO(synchronizers_test_spinlock_functional),
+ ODP_TEST_INFO_NULL
};
/* Ticket lock tests */
@@ -1008,10 +1010,10 @@ void synchronizers_test_ticketlock_functional(void)
odp_cunit_thread_exit(&arg);
}
-CU_TestInfo synchronizers_suite_ticketlock[] = {
- _CU_TEST_INFO(synchronizers_test_ticketlock_api),
- _CU_TEST_INFO(synchronizers_test_ticketlock_functional),
- CU_TEST_INFO_NULL
+odp_testinfo_t synchronizers_suite_ticketlock[] = {
+ ODP_TEST_INFO(synchronizers_test_ticketlock_api),
+ ODP_TEST_INFO(synchronizers_test_ticketlock_functional),
+ ODP_TEST_INFO_NULL
};
/* RW lock tests */
@@ -1034,10 +1036,10 @@ void synchronizers_test_rwlock_functional(void)
odp_cunit_thread_exit(&arg);
}
-CU_TestInfo synchronizers_suite_rwlock[] = {
- _CU_TEST_INFO(synchronizers_test_rwlock_api),
- _CU_TEST_INFO(synchronizers_test_rwlock_functional),
- CU_TEST_INFO_NULL
+odp_testinfo_t synchronizers_suite_rwlock[] = {
+ ODP_TEST_INFO(synchronizers_test_rwlock_api),
+ ODP_TEST_INFO(synchronizers_test_rwlock_functional),
+ ODP_TEST_INFO_NULL
};
int synchronizers_suite_init(void)
@@ -1082,7 +1084,7 @@ int synchronizers_init(void)
global_mem->g_iterations = MAX_ITERATIONS;
global_mem->g_verbose = VERBOSE;
- workers_count = odp_cpumask_def_worker(&mask, 0);
+ workers_count = odp_cpumask_default_worker(&mask, 0);
max_threads = (workers_count >= MAX_WORKERS) ?
MAX_WORKERS : workers_count;
@@ -1186,32 +1188,40 @@ void synchronizers_test_atomic_fetch_add_sub(void)
test_atomic_functional(test_atomic_fetch_add_sub_thread);
}
-CU_TestInfo synchronizers_suite_atomic[] = {
- _CU_TEST_INFO(synchronizers_test_atomic_inc_dec),
- _CU_TEST_INFO(synchronizers_test_atomic_add_sub),
- _CU_TEST_INFO(synchronizers_test_atomic_fetch_inc_dec),
- _CU_TEST_INFO(synchronizers_test_atomic_fetch_add_sub),
- CU_TEST_INFO_NULL,
+odp_testinfo_t synchronizers_suite_atomic[] = {
+ ODP_TEST_INFO(synchronizers_test_atomic_inc_dec),
+ ODP_TEST_INFO(synchronizers_test_atomic_add_sub),
+ ODP_TEST_INFO(synchronizers_test_atomic_fetch_inc_dec),
+ ODP_TEST_INFO(synchronizers_test_atomic_fetch_add_sub),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo synchronizers_suites[] = {
- {"barrier", NULL,
- NULL, NULL, NULL, synchronizers_suite_barrier},
- {"nolocking", synchronizers_suite_init,
- NULL, NULL, NULL, synchronizers_suite_no_locking},
- {"spinlock", synchronizers_suite_init,
- NULL, NULL, NULL, synchronizers_suite_spinlock},
- {"ticketlock", synchronizers_suite_init,
- NULL, NULL, NULL, synchronizers_suite_ticketlock},
- {"rwlock", synchronizers_suite_init,
- NULL, NULL, NULL, synchronizers_suite_rwlock},
- {"atomic", NULL, NULL, NULL, NULL,
- synchronizers_suite_atomic},
- CU_SUITE_INFO_NULL
+odp_suiteinfo_t synchronizers_suites[] = {
+ {"barrier", NULL, NULL,
+ synchronizers_suite_barrier},
+ {"nolocking", synchronizers_suite_init, NULL,
+ synchronizers_suite_no_locking},
+ {"spinlock", synchronizers_suite_init, NULL,
+ synchronizers_suite_spinlock},
+ {"ticketlock", synchronizers_suite_init, NULL,
+ synchronizers_suite_ticketlock},
+ {"rwlock", synchronizers_suite_init, NULL,
+ synchronizers_suite_rwlock},
+ {"atomic", NULL, NULL,
+ synchronizers_suite_atomic},
+ ODP_SUITE_INFO_NULL
};
int synchronizers_main(void)
{
+ int ret;
+
odp_cunit_register_global_init(synchronizers_init);
- return odp_cunit_run(synchronizers_suites);
+
+ ret = odp_cunit_register(synchronizers_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/synchronizers/synchronizers.h b/test/validation/synchronizers/synchronizers.h
index 45b90e946..f16477cb9 100644
--- a/test/validation/synchronizers/synchronizers.h
+++ b/test/validation/synchronizers/synchronizers.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_SYNCHRONIZERS_H_
#define _ODP_TEST_SYNCHRONIZERS_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void synchronizers_test_no_barrier_functional(void);
@@ -25,18 +25,18 @@ void synchronizers_test_atomic_fetch_inc_dec(void);
void synchronizers_test_atomic_fetch_add_sub(void);
/* test arrays: */
-extern CU_TestInfo synchronizers_suite_barrier[];
-extern CU_TestInfo synchronizers_suite_no_locking[];
-extern CU_TestInfo synchronizers_suite_spinlock[];
-extern CU_TestInfo synchronizers_suite_ticketlock[];
-extern CU_TestInfo synchronizers_suite_rwlock[];
-extern CU_TestInfo synchronizers_suite_atomic[];
+extern odp_testinfo_t synchronizers_suite_barrier[];
+extern odp_testinfo_t synchronizers_suite_no_locking[];
+extern odp_testinfo_t synchronizers_suite_spinlock[];
+extern odp_testinfo_t synchronizers_suite_ticketlock[];
+extern odp_testinfo_t synchronizers_suite_rwlock[];
+extern odp_testinfo_t synchronizers_suite_atomic[];
/* test array init/term functions: */
int synchronizers_suite_init(void);
/* test registry: */
-extern CU_SuiteInfo synchronizers_suites[];
+extern odp_suiteinfo_t synchronizers_suites[];
/* executable init/term functions: */
int synchronizers_init(void);
diff --git a/test/validation/system/Makefile.am b/test/validation/system/Makefile.am
index 1c7de86f0..110d0491e 100644
--- a/test/validation/system/Makefile.am
+++ b/test/validation/system/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libsystem.la
-libsystem_la_SOURCES = system.c
+noinst_LTLIBRARIES = libtestsystem.la
+libtestsystem_la_SOURCES = system.c
bin_PROGRAMS = system_main$(EXEEXT)
dist_system_main_SOURCES = system_main.c
-system_main_LDADD = libsystem.la $(LIBCUNIT_COMMON) $(LIBODP)
+system_main_LDADD = libtestsystem.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = system.h
diff --git a/test/validation/system/system.c b/test/validation/system/system.c
index 15f3ac467..7dc2cc0c0 100644
--- a/test/validation/system/system.c
+++ b/test/validation/system/system.c
@@ -83,23 +83,28 @@ void system_test_odp_sys_cpu_hz(void)
CU_ASSERT(0 < hz);
}
-CU_TestInfo system_suite[] = {
- _CU_TEST_INFO(system_test_odp_version_numbers),
- _CU_TEST_INFO(system_test_odp_cpu_count),
- _CU_TEST_INFO(system_test_odp_sys_cache_line_size),
- _CU_TEST_INFO(system_test_odp_sys_cpu_model_str),
- _CU_TEST_INFO(system_test_odp_sys_page_size),
- _CU_TEST_INFO(system_test_odp_sys_huge_page_size),
- _CU_TEST_INFO(system_test_odp_sys_cpu_hz),
- CU_TEST_INFO_NULL,
+odp_testinfo_t system_suite[] = {
+ ODP_TEST_INFO(system_test_odp_version_numbers),
+ ODP_TEST_INFO(system_test_odp_cpu_count),
+ ODP_TEST_INFO(system_test_odp_sys_cache_line_size),
+ ODP_TEST_INFO(system_test_odp_sys_cpu_model_str),
+ ODP_TEST_INFO(system_test_odp_sys_page_size),
+ ODP_TEST_INFO(system_test_odp_sys_huge_page_size),
+ ODP_TEST_INFO(system_test_odp_sys_cpu_hz),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo system_suites[] = {
- {"System Info", NULL, NULL, NULL, NULL, system_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t system_suites[] = {
+ {"System Info", NULL, NULL, system_suite},
+ ODP_SUITE_INFO_NULL,
};
int system_main(void)
{
- return odp_cunit_run(system_suites);
+ int ret = odp_cunit_register(system_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/system/system.h b/test/validation/system/system.h
index c8bd2d4d7..869aaff41 100644
--- a/test/validation/system/system.h
+++ b/test/validation/system/system.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_SYSTEM_H_
#define _ODP_TEST_SYSTEM_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void system_test_odp_version_numbers(void);
@@ -19,10 +19,10 @@ void system_test_odp_sys_huge_page_size(void);
void system_test_odp_sys_cpu_hz(void);
/* test arrays: */
-extern CU_TestInfo system_suite[];
+extern odp_testinfo_t system_suite[];
/* test registry: */
-extern CU_SuiteInfo system_suites[];
+extern odp_suiteinfo_t system_suites[];
/* main test program: */
int system_main(void);
diff --git a/test/validation/thread/Makefile.am b/test/validation/thread/Makefile.am
index 20b7f13d8..afe2828a9 100644
--- a/test/validation/thread/Makefile.am
+++ b/test/validation/thread/Makefile.am
@@ -1,12 +1,12 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libthread.la
-libthread_la_SOURCES = thread.c
-libthread_la_CFLAGS = $(AM_CFLAGS) -DTEST_THRMASK
-libthread_la_LIBADD = $(LIBTHRMASK_COMMON)
+noinst_LTLIBRARIES = libtestthread.la
+libtestthread_la_SOURCES = thread.c
+libtestthread_la_CFLAGS = $(AM_CFLAGS) -DTEST_THRMASK
+libtestthread_la_LIBADD = $(LIBTHRMASK_COMMON)
bin_PROGRAMS = thread_main$(EXEEXT)
dist_thread_main_SOURCES = thread_main.c
-thread_main_LDADD = libthread.la $(LIBCUNIT_COMMON) $(LIBODP)
+thread_main_LDADD = libtestthread.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = thread.h
diff --git a/test/validation/thread/thread.c b/test/validation/thread/thread.c
index d4f3ee0f9..03bf3cd2d 100644
--- a/test/validation/thread/thread.c
+++ b/test/validation/thread/thread.c
@@ -74,7 +74,7 @@ void thread_test_odp_thrmask_worker(void)
ret = odp_thrmask_worker(&mask);
CU_ASSERT(ret == odp_thrmask_count(&mask));
CU_ASSERT(ret == args.numthrds);
- CU_ASSERT(ret <= ODP_CONFIG_MAX_THREADS);
+ CU_ASSERT(ret <= odp_thread_count_max());
/* allow thread(s) to exit */
odp_barrier_wait(&bar_exit);
@@ -95,35 +95,40 @@ void thread_test_odp_thrmask_control(void)
CU_ASSERT(ret == 1);
}
-CU_TestInfo thread_suite[] = {
- _CU_TEST_INFO(thread_test_odp_cpu_id),
- _CU_TEST_INFO(thread_test_odp_thread_id),
- _CU_TEST_INFO(thread_test_odp_thread_count),
- _CU_TEST_INFO(thread_test_odp_thrmask_to_from_str),
- _CU_TEST_INFO(thread_test_odp_thrmask_equal),
- _CU_TEST_INFO(thread_test_odp_thrmask_zero),
- _CU_TEST_INFO(thread_test_odp_thrmask_set),
- _CU_TEST_INFO(thread_test_odp_thrmask_clr),
- _CU_TEST_INFO(thread_test_odp_thrmask_isset),
- _CU_TEST_INFO(thread_test_odp_thrmask_count),
- _CU_TEST_INFO(thread_test_odp_thrmask_and),
- _CU_TEST_INFO(thread_test_odp_thrmask_or),
- _CU_TEST_INFO(thread_test_odp_thrmask_xor),
- _CU_TEST_INFO(thread_test_odp_thrmask_copy),
- _CU_TEST_INFO(thread_test_odp_thrmask_first),
- _CU_TEST_INFO(thread_test_odp_thrmask_last),
- _CU_TEST_INFO(thread_test_odp_thrmask_next),
- _CU_TEST_INFO(thread_test_odp_thrmask_worker),
- _CU_TEST_INFO(thread_test_odp_thrmask_control),
- CU_TEST_INFO_NULL,
+odp_testinfo_t thread_suite[] = {
+ ODP_TEST_INFO(thread_test_odp_cpu_id),
+ ODP_TEST_INFO(thread_test_odp_thread_id),
+ ODP_TEST_INFO(thread_test_odp_thread_count),
+ ODP_TEST_INFO(thread_test_odp_thrmask_to_from_str),
+ ODP_TEST_INFO(thread_test_odp_thrmask_equal),
+ ODP_TEST_INFO(thread_test_odp_thrmask_zero),
+ ODP_TEST_INFO(thread_test_odp_thrmask_set),
+ ODP_TEST_INFO(thread_test_odp_thrmask_clr),
+ ODP_TEST_INFO(thread_test_odp_thrmask_isset),
+ ODP_TEST_INFO(thread_test_odp_thrmask_count),
+ ODP_TEST_INFO(thread_test_odp_thrmask_and),
+ ODP_TEST_INFO(thread_test_odp_thrmask_or),
+ ODP_TEST_INFO(thread_test_odp_thrmask_xor),
+ ODP_TEST_INFO(thread_test_odp_thrmask_copy),
+ ODP_TEST_INFO(thread_test_odp_thrmask_first),
+ ODP_TEST_INFO(thread_test_odp_thrmask_last),
+ ODP_TEST_INFO(thread_test_odp_thrmask_next),
+ ODP_TEST_INFO(thread_test_odp_thrmask_worker),
+ ODP_TEST_INFO(thread_test_odp_thrmask_control),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo thread_suites[] = {
- {"thread", NULL, NULL, NULL, NULL, thread_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t thread_suites[] = {
+ {"thread", NULL, NULL, thread_suite},
+ ODP_SUITE_INFO_NULL,
};
int thread_main(void)
{
- return odp_cunit_run(thread_suites);
+ int ret = odp_cunit_register(thread_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/thread/thread.h b/test/validation/thread/thread.h
index ef645b4b0..6cbc69432 100644
--- a/test/validation/thread/thread.h
+++ b/test/validation/thread/thread.h
@@ -8,7 +8,7 @@
#define _ODP_TEST_THREAD_H_
#include <odp.h>
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
#ifndef TEST_THRMASK
@@ -22,10 +22,10 @@ void thread_test_odp_thrmask_control(void);
void thread_test_odp_thrmask_worker(void);
/* test arrays: */
-extern CU_TestInfo thread_suite[];
+extern odp_testinfo_t thread_suite[];
/* test registry: */
-extern CU_SuiteInfo thread_suites[];
+extern odp_suiteinfo_t thread_suites[];
/* main test program: */
int thread_main(void);
diff --git a/test/validation/time/Makefile.am b/test/validation/time/Makefile.am
index 0e8742e82..da6c13b12 100644
--- a/test/validation/time/Makefile.am
+++ b/test/validation/time/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libtime.la
-libtime_la_SOURCES = time.c
+noinst_LTLIBRARIES = libtesttime.la
+libtesttime_la_SOURCES = time.c
bin_PROGRAMS = time_main$(EXEEXT)
dist_time_main_SOURCES = time_main.c
-time_main_LDADD = libtime.la $(LIBCUNIT_COMMON) $(LIBODP)
+time_main_LDADD = libtesttime.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = time.h
diff --git a/test/validation/time/time.c b/test/validation/time/time.c
index 4b81c2c0b..41db0e954 100644
--- a/test/validation/time/time.c
+++ b/test/validation/time/time.c
@@ -61,19 +61,24 @@ void time_test_odp_time_conversion(void)
CU_ASSERT((ns2 <= upper_limit) && (ns2 >= lower_limit));
}
-CU_TestInfo time_suite_time[] = {
- _CU_TEST_INFO(time_test_odp_cycles_diff),
- _CU_TEST_INFO(time_test_odp_cycles_negative_diff),
- _CU_TEST_INFO(time_test_odp_time_conversion),
- CU_TEST_INFO_NULL
+odp_testinfo_t time_suite_time[] = {
+ ODP_TEST_INFO(time_test_odp_cycles_diff),
+ ODP_TEST_INFO(time_test_odp_cycles_negative_diff),
+ ODP_TEST_INFO(time_test_odp_time_conversion),
+ ODP_TEST_INFO_NULL
};
-CU_SuiteInfo time_suites[] = {
- {"Time", NULL, NULL, NULL, NULL, time_suite_time},
- CU_SUITE_INFO_NULL
+odp_suiteinfo_t time_suites[] = {
+ {"Time", NULL, NULL, time_suite_time},
+ ODP_SUITE_INFO_NULL
};
int time_main(void)
{
- return odp_cunit_run(time_suites);
+ int ret = odp_cunit_register(time_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/time/time.h b/test/validation/time/time.h
index 1f6982633..9ccdeb762 100644
--- a/test/validation/time/time.h
+++ b/test/validation/time/time.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_TIME_H_
#define _ODP_TEST_TIME_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void time_test_odp_cycles_diff(void);
@@ -15,10 +15,10 @@ void time_test_odp_cycles_negative_diff(void);
void time_test_odp_time_conversion(void);
/* test arrays: */
-extern CU_TestInfo time_suite_time[];
+extern odp_testinfo_t time_suite_time[];
/* test registry: */
-extern CU_SuiteInfo time_suites[];
+extern odp_suiteinfo_t time_suites[];
/* main test program: */
int time_main(void);
diff --git a/test/validation/timer/Makefile.am b/test/validation/timer/Makefile.am
index 01e4fd3da..78bbc9f1b 100644
--- a/test/validation/timer/Makefile.am
+++ b/test/validation/timer/Makefile.am
@@ -1,10 +1,10 @@
include ../Makefile.inc
-noinst_LTLIBRARIES = libtimer.la
-libtimer_la_SOURCES = timer.c
+noinst_LTLIBRARIES = libtesttimer.la
+libtesttimer_la_SOURCES = timer.c
bin_PROGRAMS = timer_main$(EXEEXT)
dist_timer_main_SOURCES = timer_main.c
-timer_main_LDADD = libtimer.la $(LIBCUNIT_COMMON) $(LIBODP)
+timer_main_LDADD = libtesttimer.la $(LIBCUNIT_COMMON) $(LIBODP)
EXTRA_DIST = timer.h
diff --git a/test/validation/timer/timer.c b/test/validation/timer/timer.c
index 7a8b98a17..645dc5882 100644
--- a/test/validation/timer/timer.c
+++ b/test/validation/timer/timer.c
@@ -529,20 +529,25 @@ void timer_test_odp_timer_all(void)
CU_PASS("ODP timer test");
}
-CU_TestInfo timer_suite[] = {
- _CU_TEST_INFO(timer_test_timeout_pool_alloc),
- _CU_TEST_INFO(timer_test_timeout_pool_free),
- _CU_TEST_INFO(timer_test_odp_timer_cancel),
- _CU_TEST_INFO(timer_test_odp_timer_all),
- CU_TEST_INFO_NULL,
+odp_testinfo_t timer_suite[] = {
+ ODP_TEST_INFO(timer_test_timeout_pool_alloc),
+ ODP_TEST_INFO(timer_test_timeout_pool_free),
+ ODP_TEST_INFO(timer_test_odp_timer_cancel),
+ ODP_TEST_INFO(timer_test_odp_timer_all),
+ ODP_TEST_INFO_NULL,
};
-CU_SuiteInfo timer_suites[] = {
- {"Timer", NULL, NULL, NULL, NULL, timer_suite},
- CU_SUITE_INFO_NULL,
+odp_suiteinfo_t timer_suites[] = {
+ {"Timer", NULL, NULL, timer_suite},
+ ODP_SUITE_INFO_NULL,
};
int timer_main(void)
{
- return odp_cunit_run(timer_suites);
+ int ret = odp_cunit_register(timer_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
}
diff --git a/test/validation/timer/timer.h b/test/validation/timer/timer.h
index 3694671f0..46ea8d768 100644
--- a/test/validation/timer/timer.h
+++ b/test/validation/timer/timer.h
@@ -7,7 +7,7 @@
#ifndef _ODP_TEST_TIMER_H_
#define _ODP_TEST_TIMER_H_
-#include <CUnit/Basic.h>
+#include <odp_cunit_common.h>
/* test functions: */
void timer_test_timeout_pool_alloc(void);
@@ -16,10 +16,10 @@ void timer_test_odp_timer_cancel(void);
void timer_test_odp_timer_all(void);
/* test arrays: */
-extern CU_TestInfo timer_suite[];
+extern odp_testinfo_t timer_suite[];
/* test registry: */
-extern CU_SuiteInfo timer_suites[];
+extern odp_suiteinfo_t timer_suites[];
/* main test program: */
int timer_main(void);