aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Uvarov <maxim.uvarov@linaro.org>2015-12-31 11:15:35 +0300
committerMaxim Uvarov <maxim.uvarov@linaro.org>2015-12-31 11:15:35 +0300
commit4320d76520e1bf352d1aa2a94a3e8ffe74e003d2 (patch)
treec699d1e969b2f285bf1dd2e2fa7e770d5db49166
parenta0a20997629be7045222980da6e393bca9a9fa37 (diff)
parent4b22a3a0853b16b785a88a6a709a3a098cdccc2d (diff)
Merge branch 'next'v1.6.0.0
-rw-r--r--CHANGELOG104
-rw-r--r--configure.ac2
-rw-r--r--doc/users-guide/users-guide.adoc29
-rw-r--r--example/classifier/odp_classifier.c146
-rw-r--r--example/generator/odp_generator.c10
-rw-r--r--include/odp.h4
-rw-r--r--include/odp/api/atomic.h112
-rw-r--r--include/odp/api/barrier.h11
-rw-r--r--include/odp/api/classification.h69
-rw-r--r--include/odp/api/crypto.h4
-rw-r--r--include/odp/api/hash.h98
-rw-r--r--include/odp/api/init.h4
-rw-r--r--include/odp/api/packet_io.h9
-rw-r--r--include/odp/api/rwlock.h19
-rw-r--r--include/odp/api/rwlock_recursive.h97
-rw-r--r--include/odp/api/spinlock.h11
-rw-r--r--include/odp/api/spinlock_recursive.h85
-rw-r--r--include/odp/api/std_clib.h64
-rw-r--r--include/odp/api/sync.h82
-rw-r--r--include/odp/api/thread.h9
-rw-r--r--include/odp/api/thrmask.h2
-rw-r--r--include/odp/api/ticketlock.h16
-rw-r--r--include/odp/api/time.h58
-rw-r--r--include/odp/api/version.h49
-rw-r--r--pkg/debian/changelog5
-rw-r--r--pkg/rpm/odp.spec2
-rw-r--r--platform/Makefile.inc4
-rw-r--r--platform/linux-generic/Makefile.am13
-rw-r--r--platform/linux-generic/include/odp/atomic.h2
-rw-r--r--platform/linux-generic/include/odp/barrier.h8
-rw-r--r--platform/linux-generic/include/odp/hash.h (renamed from platform/linux-generic/include/odp_config_internal.h)15
-rw-r--r--platform/linux-generic/include/odp/plat/atomic_types.h8
-rw-r--r--platform/linux-generic/include/odp/plat/barrier_types.h8
-rw-r--r--platform/linux-generic/include/odp/plat/rwlock_recursive_types.h38
-rw-r--r--platform/linux-generic/include/odp/plat/rwlock_types.h13
-rw-r--r--platform/linux-generic/include/odp/plat/spinlock_recursive_types.h36
-rw-r--r--platform/linux-generic/include/odp/plat/spinlock_types.h14
-rw-r--r--platform/linux-generic/include/odp/plat/thread_types.h34
-rw-r--r--platform/linux-generic/include/odp/plat/ticketlock_types.h13
-rw-r--r--platform/linux-generic/include/odp/plat/time_types.h11
-rw-r--r--platform/linux-generic/include/odp/rwlock.h8
-rw-r--r--platform/linux-generic/include/odp/rwlock_recursive.h28
-rw-r--r--platform/linux-generic/include/odp/spinlock.h8
-rw-r--r--platform/linux-generic/include/odp/spinlock_recursive.h28
-rw-r--r--platform/linux-generic/include/odp/std_clib.h30
-rw-r--r--platform/linux-generic/include/odp/sync.h17
-rw-r--r--platform/linux-generic/include/odp/thread.h8
-rw-r--r--platform/linux-generic/include/odp/ticketlock.h9
-rw-r--r--platform/linux-generic/include/odp_atomic_internal.h9
-rw-r--r--platform/linux-generic/include/odp_buffer_internal.h3
-rw-r--r--platform/linux-generic/include/odp_classification_datamodel.h3
-rw-r--r--platform/linux-generic/include/odp_classification_inlines.h73
-rw-r--r--platform/linux-generic/include/odp_classification_internal.h23
-rw-r--r--platform/linux-generic/include/odp_cpu_internal.h29
-rw-r--r--platform/linux-generic/include/odp_crypto_internal.h3
-rw-r--r--platform/linux-generic/include/odp_internal.h2
-rw-r--r--platform/linux-generic/include/odp_packet_internal.h8
-rw-r--r--platform/linux-generic/include/odp_packet_io_internal.h4
-rw-r--r--platform/linux-generic/include/odp_packet_socket.h2
-rw-r--r--platform/linux-generic/include/odp_pool_internal.h3
-rw-r--r--platform/linux-generic/odp_classification.c146
-rw-r--r--platform/linux-generic/odp_cpu.c6
-rw-r--r--platform/linux-generic/odp_crypto.c183
-rw-r--r--platform/linux-generic/odp_hash.c487
-rw-r--r--platform/linux-generic/odp_init.c4
-rw-r--r--platform/linux-generic/odp_packet.c79
-rw-r--r--platform/linux-generic/odp_packet_io.c120
-rw-r--r--platform/linux-generic/odp_pool.c3
-rw-r--r--platform/linux-generic/odp_queue.c4
-rw-r--r--platform/linux-generic/odp_rwlock_recursive.c70
-rw-r--r--platform/linux-generic/odp_schedule.c18
-rw-r--r--platform/linux-generic/odp_spinlock_recursive.c70
-rw-r--r--platform/linux-generic/odp_thread.c11
-rw-r--r--platform/linux-generic/odp_thrmask.c1
-rw-r--r--platform/linux-generic/odp_time.c190
-rw-r--r--platform/linux-generic/pktio/loop.c29
-rw-r--r--platform/linux-generic/pktio/netmap.c36
-rw-r--r--platform/linux-generic/pktio/pktio_common.c57
-rw-r--r--platform/linux-generic/pktio/socket.c132
-rw-r--r--platform/linux-generic/pktio/socket_mmap.c87
-rw-r--r--platform/linux-generic/test/Makefile.am2
-rw-r--r--test/performance/odp_l2fwd.c8
-rw-r--r--test/performance/odp_pktio_perf.c32
-rw-r--r--test/performance/odp_scheduling.c37
-rw-r--r--test/validation/Makefile.am2
-rw-r--r--test/validation/classification/classification.h1
-rw-r--r--test/validation/classification/odp_classification_basic.c137
-rw-r--r--test/validation/classification/odp_classification_common.c15
-rw-r--r--test/validation/classification/odp_classification_test_pmr.c527
-rw-r--r--test/validation/classification/odp_classification_tests.c201
-rw-r--r--test/validation/classification/odp_classification_testsuites.h7
-rw-r--r--test/validation/crypto/crypto.h4
-rw-r--r--test/validation/crypto/odp_crypto_test_inp.c235
-rw-r--r--test/validation/crypto/test_vectors.h152
-rw-r--r--test/validation/crypto/test_vectors_len.h7
-rw-r--r--test/validation/hash/.gitignore1
-rw-r--r--test/validation/hash/Makefile.am10
-rw-r--r--test/validation/hash/hash.c49
-rw-r--r--test/validation/hash/hash.h24
-rw-r--r--test/validation/hash/hash_main.c12
-rw-r--r--test/validation/pktio/pktio.c25
-rw-r--r--test/validation/scheduler/scheduler.c45
-rw-r--r--test/validation/std_clib/.gitignore1
-rw-r--r--test/validation/std_clib/Makefile.am10
-rw-r--r--test/validation/std_clib/std_clib.c66
-rw-r--r--test/validation/std_clib/std_clib.h21
-rw-r--r--test/validation/std_clib/std_clib_main.c12
-rw-r--r--test/validation/synchronizers/synchronizers.c442
-rw-r--r--test/validation/synchronizers/synchronizers.h7
-rw-r--r--test/validation/time/time.c416
-rw-r--r--test/validation/time/time.h21
111 files changed, 4923 insertions, 955 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 4e9db28f3..bd5b9982d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,107 @@
+opendataplane (1.6.0.0)
+ * API:
+ - api: atomic: clean atomic API documentation
+ - api: clib: added standard c library api
+ - api: hash: Added crc32 and crc32c hash functions
+ - api/linux-generic: classification: rename odp_drop_e to odp_cls_drop_t
+ - api/validation/linux-generic: classification: implement class of service create api
+ - api: time: add global time API
+ - api: time: add resolution and wait API calls
+ - api: time: make odp_local_time to be monotonic wall time
+ - api: init: allow implementation to use private ways for its own configuration
+ - api: classification: add odp_cls_cos_pool_set() api
+ - api: doc: re-organize doxygen doc for synchronizer
+ - api: rwlock_recursive: added recursive rwlock
+ - api: spinlock_recursive: added recursive spinlock
+ - api: crypto: Add AES128-GCM support
+ - api: thread: added THREAD_COUNT_MAX define
+ - api: thrmask: correct specification error
+ - api: pktio: add odp_pktio_print() API
+ - api: version: added implementation name str
+ - api: sync: removed odp_sync_stores
+ - api: barrier: added memory barriers
+ * ODP docs:
+ - doc/users-guide: add time API section
+ - doc/users-guide: add cryptographic services section
+ - doc: userguide: add application programming section
+ - doc: process-guide: add release process
+ - doc: images: replace overview with editable svg src
+ - doc: guides: embed icons and images in html
+ - doc: re-organize doxygen doc for synchronizer
+ * Validation
+ - api/validation/linux-generic: classification: implement class of service create api
+ - api: hash: Added crc32 and crc32c hash functions
+ - classification: add odp_cls_cos_pool_set() api
+ - classification: adds additional ASSERTS for stability
+ - classification: check return value of pktio stop
+ - classification: start pktio after setting inq and stop it before removing it
+ - classification: stronger checks to avoid SEGV on pktio failure
+ - crypto: add test for AES128-GCM
+ - crypto: allow custom auth/cipher range
+ - crypto: support validating both cipher and auth at the same time
+ - performance: pktio_perf: use odp_time_wait_ns() function instead of looping
+ - performance: sched: use ODP time API instead of clock_gettime
+ - performance: set a packet rate pass threshold for l2fwd
+ - pktio : Fix UDP checksum computation
+ - pktio: ability to wait for external network
+ - pktio: add customizable out mode for pktios
+ - pktio: add test for start when started and stop when stopped()
+ - pktio: add tests for rrecv() on WONLY, and send on RONLY pktios
+ - pktio: initialize mac addresses for all packets
+ - pktio: refactor error handling during sequence check
+ - pktio: remove unneeded stop as interface is stopped after open()
+ - pktio: stop interfaces before removing the default inq
+ - pktio: test odp_pktio_print()
+ - queue: refactor test to avoid coverity issues
+ - sched: improve scheduler validation test to check sched time correctly
+ - scheduler: use fail timeout when waiting on events in chaos
+ - std_clib: added validation tests
+ - synchronizers: add missing rwlock read lock functional test
+ - synchronizers: add recursive lock tests
+ - test/example: use local time API as wall time
+ - test: performance: pktio: don't use direct arithmetic operations with odp_time_t
+ - time: add test convertsion on 0
+ - time: add test for odp_time_local_res() and use resolution
+ - time: add test for odp_time_wait_ns() and odp_time_wait_until()
+ - time: don't assign int directly to odp_time_t
+ - time: test time constants in ns
+ - time: update to tes global time API
+ - validation: time: align tests with current time API
+ * General:
+ - align with new wall time API
+ - classification: add null check for pool assigned to CoS
+ - classification: define pkt_addr as const
+ - classification: implement class of service create api
+ - classification: implements odp_cls_cos_pool_set() api
+ - classification: rename odp_drop_e to odp_cls_drop_t
+ - clib: added standard c library api
+ - crypto: Add AES128-GCM support
+ - fix tap compilation
+ - hash: Added crc32 and crc32c hash functions
+ - include netmap headers with -isystem
+ - odp_time: don't use cpu cycle API to get time
+ - packet: _odp_parse_common: arm build fix
+ - pktio: add odp_pktio_print() API
+ - pktio: add tap pktio type
+ - pktio: add test for tap pktio
+ - pktio: check for pktio_start when started and pktio_stop when stopped
+ - pktio: check interface mode is compatible before receiving or sending
+ - pktio: configuration functions check that interface is stopped
+ - queue: fix memory corruption in reorder_enq()
+ - rwlock_recursive: added recursive rwlock
+ - schedule: set sched_local.pool correctly
+ - schedule: use schedule time in ns
+ - socket: set up __odp_errno on ioctl failures
+ - spinlock_recursive: added recursive spinlock
+ - thread: added THREAD_COUNT_MAX define
+ - thread: removed internal max threads define
+ - time: add global time API
+ - time: add resolution and wait API calls
+ - time: remove posix bleed through on odp_time_t
+ - timer: include event_types instead of buffer_types
+ - validation: pktio: report test as skipped when setup fails
+ - validation: run config tests
+
opendataplane (1.5.0.0)
* API:
- api: buffer: add functions to alloc/free multiple buffers at once
diff --git a/configure.ac b/configure.ac
index e45d90a04..2626fd7ca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -355,6 +355,7 @@ AC_CONFIG_FILES([Makefile
test/validation/common/Makefile
test/validation/crypto/Makefile
test/validation/errno/Makefile
+ test/validation/hash/Makefile
test/validation/init/Makefile
test/validation/packet/Makefile
test/validation/pktio/Makefile
@@ -362,6 +363,7 @@ AC_CONFIG_FILES([Makefile
test/validation/queue/Makefile
test/validation/random/Makefile
test/validation/scheduler/Makefile
+ test/validation/std_clib/Makefile
test/validation/synchronizers/Makefile
test/validation/thread/Makefile
test/validation/time/Makefile
diff --git a/doc/users-guide/users-guide.adoc b/doc/users-guide/users-guide.adoc
index 7ec795746..8bc8521ee 100644
--- a/doc/users-guide/users-guide.adoc
+++ b/doc/users-guide/users-guide.adoc
@@ -197,7 +197,7 @@ precise syntax and semantics of each API.
ODP programs are built around several conceptual structures that every
application programmer needs to be familiar with to use ODP effectively. The
main ODP concepts are:
-Thread, Event, Queue, Pool, Shared Memory, Buffer, Packet, PktIO, Timer,
+Thread, Event, Queue, Pool, Shared Memory, Buffer, Packet, PktIO, Time, Timer,
and Synchronizer.
=== Thread
@@ -305,6 +305,33 @@ or may represent a device attached via a PCIE or other bus.
PktIOs are represented by handles of abstract type +odp_pktio_t+.
+=== Time
+The time API is used to measure time intervals and track time flow of an
+application and presents a convenient way to get access to a time source.
+The time API consists of two main parts: local time API and global time API.
+
+==== Local time
+The local time API is designed to be used within one thread and can be faster
+than the global time API. The local time API cannot be used between threads as
+time consistency is not guaranteed, and in some cases that's enough.
+So, local time stamps are local to the calling thread and must not be shared
+with other threads. Current local time can be read with +odp_time_local()+.
+
+==== Global time
+The global time API is designed to be used for tracking time between threads.
+So, global time stamps can be shared between threads. Current global time can
+be read with +odp_time_global()+.
+
+Both, local and global time is not wrapped during the application life cycle.
+The time API includes functions to operate with time, such as +odp_time_diff()+,
++odp_time_sum()+, +odp_time_cmp()+, conversion functions like
++odp_time_to_ns()+, +odp_time_local_from_ns()+, +odp_time_global_from_ns()+.
+To get rate of time source +odp_time_local_res()+, +odp_time_global_res()+
+are used. To wait, +odp_time_wait_ns()+ and +odp_time_wait_until()+ are used,
+during witch a thread potentially busy loop the entire wait time.
+
+The +odp_time_t+ opaque type represents local or global timestamps.
+
=== Timer
Timers are how ODP applications measure and respond to the passage of time.
Timers are drawn from specialized pools called timer pools that have their
diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c
index 6cf459684..fe1c3b6e1 100644
--- a/example/classifier/odp_classifier.c
+++ b/example/classifier/odp_classifier.c
@@ -49,10 +49,12 @@
typedef struct {
odp_queue_t queue; /**< Associated queue handle */
+ odp_pool_t pool; /**< Associated pool handle */
odp_cos_t cos; /**< Associated cos handle */
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 */
+ odp_atomic_u64_t queue_pkt_count; /**< count of received packets */
+ odp_atomic_u64_t pool_pkt_count; /**< count of received packets */
+ char cos_name[ODP_COS_NAME_LEN]; /**< cos name */
struct {
odp_pmr_term_e term; /**< odp pmr term value */
uint64_t val; /**< pmr term value */
@@ -85,8 +87,8 @@ static void swap_pkt_addrs(odp_packet_t pkt_tbl[], unsigned len);
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);
-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 void configure_cos(odp_pktio_t pktio, appl_args_t *args);
+static void configure_default_cos(odp_pktio_t pktio, appl_args_t *args);
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);
@@ -109,12 +111,12 @@ void print_cls_statistics(appl_args_t *args)
printf("\n");
printf("CONFIGURATION\n");
printf("\n");
- printf("QUEUE\tVALUE\t\tMASK\n");
+ printf("COS\tVALUE\t\tMASK\n");
for (i = 0; i < 40; i++)
printf("-");
printf("\n");
for (i = 0; i < args->policy_count - 1; i++) {
- printf("%s\t", args->stats[i].queue_name);
+ printf("%s\t", args->stats[i].cos_name);
printf("%s\t", args->stats[i].value);
printf("%s\n", args->stats[i].mask);
}
@@ -124,9 +126,12 @@ void print_cls_statistics(appl_args_t *args)
printf("-");
printf("\n");
for (i = 0; i < args->policy_count; i++)
- printf("%-12s ", args->stats[i].queue_name);
+ printf("%-12s |", args->stats[i].cos_name);
printf("Total Packets");
printf("\n");
+ for (i = 0; i < args->policy_count; i++)
+ printf("%-6s %-6s|", "queue", "pool");
+ printf("\n");
timeout = args->time;
@@ -136,10 +141,14 @@ void print_cls_statistics(appl_args_t *args)
infinite = 1;
for (; timeout > 0 || infinite; timeout--) {
- for (i = 0; i < args->policy_count; i++)
- printf("%-12" PRIu64 " ",
+ for (i = 0; i < args->policy_count; i++) {
+ printf("%-6" PRIu64 " ",
odp_atomic_load_u64(&args->stats[i]
- .packet_count));
+ .queue_pkt_count));
+ printf("%-6" PRIu64 "|",
+ odp_atomic_load_u64(&args->stats[i]
+ .pool_pkt_count));
+ }
printf("%-" PRIu64, odp_atomic_load_u64(&args->
total_packets));
@@ -278,6 +287,7 @@ static void *pktio_receive_thread(void *arg)
int thr;
odp_queue_t outq_def;
odp_packet_t pkt;
+ odp_pool_t pool;
odp_event_t ev;
unsigned long err_cnt = 0;
odp_queue_t queue;
@@ -317,13 +327,16 @@ static void *pktio_receive_thread(void *arg)
return NULL;
}
+ pool = odp_packet_pool(pkt);
+
/* Swap Eth MACs and possibly IP-addrs before sending back */
swap_pkt_addrs(&pkt, 1);
-
for (i = 0; i < MAX_PMR_COUNT; i++) {
stats = &appl->stats[i];
if (queue == stats->queue)
- odp_atomic_inc_u64(&stats->packet_count);
+ odp_atomic_inc_u64(&stats->queue_pkt_count);
+ if (pool == stats->pool)
+ odp_atomic_inc_u64(&stats->pool_pkt_count);
}
if (appl->appl_mode == APPL_MODE_DROP)
@@ -340,17 +353,19 @@ static void *pktio_receive_thread(void *arg)
return NULL;
}
-static void configure_default_queue(odp_pktio_t pktio, appl_args_t *args)
+static void configure_default_cos(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];
const char *queue_name = "DefaultQueue";
+ const char *pool_name = "DefaultPool";
+ const char *cos_name = "DefaultCos";
odp_queue_t queue_default;
+ odp_pool_t pool_default;
+ odp_cos_t cos_default;
+ odp_pool_param_t pool_params;
+ odp_cls_cos_param_t cls_param;
global_statistics *stats = args->stats;
- 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;
@@ -358,9 +373,31 @@ static void configure_default_queue(odp_pktio_t pktio, appl_args_t *args)
qparam.sched.group = ODP_SCHED_GROUP_ALL;
queue_default = odp_queue_create(queue_name,
ODP_QUEUE_TYPE_SCHED, &qparam);
+ if (queue_default == ODP_QUEUE_INVALID) {
+ EXAMPLE_ERR("Error: default queue create failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ odp_pool_param_init(&pool_params);
+ pool_params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
+ pool_params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
+ pool_params.pkt.num = SHM_PKT_POOL_SIZE / SHM_PKT_POOL_BUF_SIZE;
+ pool_params.type = ODP_POOL_PACKET;
+ pool_default = odp_pool_create(pool_name, &pool_params);
- if (0 > odp_cos_queue_set(cos_default, queue_default)) {
- EXAMPLE_ERR("odp_cos_queue_set failed");
+ if (pool_default == ODP_POOL_INVALID) {
+ EXAMPLE_ERR("Error: default pool create failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool_default;
+ cls_param.queue = queue_default;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_default = odp_cls_cos_create(cos_name, &cls_param);
+
+ if (cos_default == ODP_COS_INVALID) {
+ EXAMPLE_ERR("Error: default cos create failed.\n");
exit(EXIT_FAILURE);
}
@@ -371,26 +408,28 @@ static void configure_default_queue(odp_pktio_t pktio, appl_args_t *args)
stats[args->policy_count].cos = cos_default;
/* add default queue to global stats */
stats[args->policy_count].queue = queue_default;
- 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);
+ stats[args->policy_count].pool = pool_default;
+ snprintf(stats[args->policy_count].cos_name,
+ sizeof(stats[args->policy_count].cos_name),
+ "%s", cos_name);
+ odp_atomic_init_u64(&stats[args->policy_count].queue_pkt_count, 0);
+ odp_atomic_init_u64(&stats[args->policy_count].pool_pkt_count, 0);
args->policy_count++;
}
-static void configure_cos_queue(odp_pktio_t pktio, appl_args_t *args)
+static void configure_cos(odp_pktio_t pktio, appl_args_t *args)
{
char cos_name[ODP_COS_NAME_LEN];
char queue_name[ODP_QUEUE_NAME_LEN];
+ char pool_name[ODP_POOL_NAME_LEN];
+ odp_pool_param_t pool_params;
+ odp_cls_cos_param_t cls_param;
int i;
global_statistics *stats;
odp_queue_param_t qparam;
for (i = 0; i < args->policy_count; i++) {
stats = &args->stats[i];
- snprintf(cos_name, sizeof(cos_name), "CoS%s",
- stats->queue_name);
- stats->cos = odp_cos_create(cos_name);
const odp_pmr_match_t match = {
.term = stats->rule.term,
@@ -406,22 +445,47 @@ static void configure_cos_queue(odp_pktio_t pktio, appl_args_t *args)
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
- snprintf(queue_name, sizeof(queue_name), "%s%d",
- args->stats[i].queue_name, i);
+ snprintf(queue_name, sizeof(queue_name), "%sQueue%d",
+ args->stats[i].cos_name, i);
stats->queue = odp_queue_create(queue_name,
ODP_QUEUE_TYPE_SCHED,
&qparam);
- if (0 > odp_cos_queue_set(stats->cos, stats->queue)) {
- EXAMPLE_ERR("odp_cos_queue_set failed");
+ if (ODP_QUEUE_INVALID == stats->queue) {
+ EXAMPLE_ERR("odp_queue_create failed");
+ exit(EXIT_FAILURE);
+ }
+
+ odp_pool_param_init(&pool_params);
+ pool_params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
+ pool_params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
+ pool_params.pkt.num = SHM_PKT_POOL_SIZE /
+ SHM_PKT_POOL_BUF_SIZE;
+ pool_params.type = ODP_POOL_PACKET;
+
+ snprintf(pool_name, sizeof(pool_name), "%sPool%d",
+ args->stats[i].cos_name, i);
+ stats->pool = odp_pool_create(pool_name, &pool_params);
+
+ if (stats->pool == ODP_POOL_INVALID) {
+ EXAMPLE_ERR("Error: default pool create failed.\n");
exit(EXIT_FAILURE);
}
+ snprintf(cos_name, sizeof(cos_name), "CoS%s",
+ stats->cos_name);
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = stats->pool;
+ cls_param.queue = stats->queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ stats->cos = odp_cls_cos_create(cos_name, &cls_param);
+
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);
+ odp_atomic_init_u64(&stats->queue_pkt_count, 0);
+ odp_atomic_init_u64(&stats->pool_pkt_count, 0);
}
}
@@ -440,6 +504,7 @@ int main(int argc, char *argv[])
odp_pool_param_t params;
odp_pktio_t pktio;
appl_args_t *args;
+ odp_queue_t inq;
odp_shm_t shm;
/* Init ODP before calling anything else */
@@ -494,7 +559,7 @@ int main(int argc, char *argv[])
odp_pool_param_init(&params);
params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
- params.pkt.num = SHM_PKT_POOL_SIZE/SHM_PKT_POOL_BUF_SIZE;
+ params.pkt.num = SHM_PKT_POOL_SIZE / SHM_PKT_POOL_BUF_SIZE;
params.type = ODP_POOL_PACKET;
pool = odp_pool_create("packet_pool", &params);
@@ -510,10 +575,10 @@ int main(int argc, char *argv[])
/* create pktio per interface */
pktio = create_pktio(args->if_name, pool);
- configure_cos_queue(pktio, args);
+ configure_cos(pktio, args);
- /* configure default Cos and default queue */
- configure_default_queue(pktio, args);
+ /* configure default Cos */
+ configure_default_cos(pktio, args);
if (odp_pktio_start(pktio)) {
EXAMPLE_ERR("Error: unable to start pktio.\n");
@@ -541,11 +606,18 @@ int main(int argc, char *argv[])
for (i = 0; i < args->policy_count; i++) {
odp_cos_destroy(args->stats[i].cos);
+ odp_pool_destroy(args->stats[i].pool);
odp_queue_destroy(args->stats[i].queue);
+ odp_pool_destroy(args->stats[i].pool);
}
free(args->if_name);
odp_shm_free(shm);
+ odp_pool_destroy(pool);
+ inq = odp_pktio_inq_getdef(pktio);
+ odp_pktio_inq_remdef(pktio);
+ odp_queue_destroy(inq);
+ odp_pktio_close(pktio);
printf("Exit\n\n");
return 0;
@@ -706,7 +778,7 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *argv[], char *optarg)
/* Queue Name */
token = strtok(NULL, ":");
- strncpy(stats[policy_count].queue_name, token, ODP_QUEUE_NAME_LEN - 1);
+ strncpy(stats[policy_count].cos_name, token, ODP_QUEUE_NAME_LEN - 1);
appl_args->policy_count++;
free(pmr_str);
return 0;
diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
index f15649726..cdbc76168 100644
--- a/example/generator/odp_generator.c
+++ b/example/generator/odp_generator.c
@@ -586,7 +586,7 @@ static void *gen_recv_thread(void *arg)
*/
static void print_global_stats(int num_workers)
{
- odp_time_t start, wait, diff;
+ odp_time_t cur, wait, next;
uint64_t pkts, pkts_prev = 0, pps, maximum_pps = 0;
int verbose_interval = 20;
odp_thrmask_t thrd_mask;
@@ -595,7 +595,7 @@ static void print_global_stats(int num_workers)
continue;
wait = odp_time_local_from_ns(verbose_interval * ODP_TIME_SEC_IN_NS);
- start = odp_time_local();
+ next = odp_time_sum(odp_time_local(), wait);
while (odp_thrmask_worker(&thrd_mask) == num_workers) {
if (args->appl.number != -1 &&
@@ -604,11 +604,11 @@ static void print_global_stats(int num_workers)
break;
}
- diff = odp_time_diff(odp_time_local(), start);
- if (odp_time_cmp(wait, diff) > 0)
+ cur = odp_time_local();
+ if (odp_time_cmp(next, cur) > 0)
continue;
- start = odp_time_local();
+ next = odp_time_sum(cur, wait);
if (args->appl.mode == APPL_MODE_RCV) {
pkts = odp_atomic_load_u64(&counters.udp);
diff --git a/include/odp.h b/include/odp.h
index fe1dc7459..2adcb8b74 100644
--- a/include/odp.h
+++ b/include/odp.h
@@ -24,6 +24,7 @@ extern "C" {
#include <odp/std_types.h>
#include <odp/compiler.h>
#include <odp/align.h>
+#include <odp/hash.h>
#include <odp/hints.h>
#include <odp/debug.h>
#include <odp/byteorder.h>
@@ -54,6 +55,9 @@ extern "C" {
#include <odp/random.h>
#include <odp/errno.h>
#include <odp/thrmask.h>
+#include <odp/spinlock_recursive.h>
+#include <odp/rwlock_recursive.h>
+#include <odp/std_clib.h>
#ifdef __cplusplus
}
diff --git a/include/odp/api/atomic.h b/include/odp/api/atomic.h
index ba5c354e2..97e86392b 100644
--- a/include/odp/api/atomic.h
+++ b/include/odp/api/atomic.h
@@ -18,10 +18,20 @@
extern "C" {
#endif
-/** @addtogroup odp_synchronizers
- * Atomic types and relaxed operations. These operations cannot be used for
- * synchronization.
- * @{
+/**
+ * @defgroup odp_atomic ODP ATOMIC
+ * @details
+ * <b> Atomic integers </b>
+ *
+ * Atomic integer types (odp_atomic_u32_t and odp_atomic_u64_t) can be used to
+ * implement e.g. shared counters. If not otherwise documented, operations in
+ * this API are implemented using <b> RELAXED memory ordering </b> (see memory
+ * order descriptions in the C11 specification). Relaxed operations do not
+ * provide synchronization or ordering for other memory accesses (initiated
+ * before or after the operation), only atomicity of the operation itself is
+ * guaranteed.
+ *
+ * @{
*/
/**
@@ -34,19 +44,16 @@ extern "C" {
/**
* Initialize atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[out] atom Pointer to an atomic uint32 variable
- * @param val Value to initialize the variable with
+ * @param atom Pointer to atomic variable
+ * @param val Value to initialize the variable with
*/
void odp_atomic_init_u32(odp_atomic_u32_t *atom, uint32_t val);
-
/**
* Load value of atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param atom Pointer to an atomic uint32 variable
+ * @param atom Pointer to atomic variable
*
* @return Value of the variable
*/
@@ -54,19 +61,17 @@ uint32_t odp_atomic_load_u32(odp_atomic_u32_t *atom);
/**
* Store value to atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[out] atom Pointer to an atomic uint32 variable
- * @param val Value to store in the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to store in the variable
*/
void odp_atomic_store_u32(odp_atomic_u32_t *atom, uint32_t val);
/**
* Fetch and add to atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint32 variable
- * @param val Value to be added to the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to be added to the variable
*
* @return Value of the variable before the addition
*/
@@ -74,19 +79,17 @@ uint32_t odp_atomic_fetch_add_u32(odp_atomic_u32_t *atom, uint32_t val);
/**
* Add to atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint32 variable
- * @param val A value to be added to the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to be added to the variable
*/
void odp_atomic_add_u32(odp_atomic_u32_t *atom, uint32_t val);
/**
* Fetch and subtract from atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint32 variable
- * @param val A value to be subracted from the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to be subracted from the variable
*
* @return Value of the variable before the subtraction
*/
@@ -94,37 +97,32 @@ uint32_t odp_atomic_fetch_sub_u32(odp_atomic_u32_t *atom, uint32_t val);
/**
* Subtract from atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint32 variable
- * @param val Value to be subtracted from the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to be subtracted from the variable
*/
void odp_atomic_sub_u32(odp_atomic_u32_t *atom, uint32_t val);
/**
* Fetch and increment atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint32 variable
+ * @param atom Pointer to atomic variable
*
* @return Value of the variable before the increment
*/
-
uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *atom);
/**
* Increment atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint32 variable
+ * @param atom Pointer to atomic variable
*/
void odp_atomic_inc_u32(odp_atomic_u32_t *atom);
/**
* Fetch and decrement atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint32 variable
+ * @param atom Pointer to atomic variable
*
* @return Value of the variable before the subtraction
*/
@@ -132,26 +130,23 @@ uint32_t odp_atomic_fetch_dec_u32(odp_atomic_u32_t *atom);
/**
* Decrement atomic uint32 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint32 variable
+ * @param atom Pointer to atomic variable
*/
void odp_atomic_dec_u32(odp_atomic_u32_t *atom);
/**
* Initialize atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[out] atom Pointer to an atomic uint64 variable
- * @param val Value to initialize the variable with
+ * @param atom Pointer to atomic variable
+ * @param val Value to initialize the variable with
*/
void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val);
/**
* Load value of atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param atom Pointer to an atomic uint64 variable
+ * @param atom Pointer to atomic variable
*
* @return Value of the variable
*/
@@ -159,41 +154,35 @@ uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom);
/**
* Store value to atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[out] atom Pointer to an atomic uint64 variable
- * @param val Value to store in the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to store in the variable
*/
void odp_atomic_store_u64(odp_atomic_u64_t *atom, uint64_t val);
/**
* Fetch and add to atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint64 variable
- * @param val Value to be added to the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to be added to the variable
*
* @return Value of the variable before the addition
*/
-
uint64_t odp_atomic_fetch_add_u64(odp_atomic_u64_t *atom, uint64_t val);
/**
* Add to atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
- *
- * @param[in,out] atom Pointer to an atomic uint64 variable
- * @param val Value to be added to the variable
*
+ * @param atom Pointer to atomic variable
+ * @param val Value to be added to the variable
*/
void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val);
/**
* Fetch and subtract from atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint64 variable
- * @param val Value to be subtracted from the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to be subtracted from the variable
*
* @return Value of the variable before the subtraction
*/
@@ -201,18 +190,16 @@ uint64_t odp_atomic_fetch_sub_u64(odp_atomic_u64_t *atom, uint64_t val);
/**
* Subtract from atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint64 variable
- * @param val Value to be subtracted from the variable
+ * @param atom Pointer to atomic variable
+ * @param val Value to be subtracted from the variable
*/
void odp_atomic_sub_u64(odp_atomic_u64_t *atom, uint64_t val);
/**
* Fetch and increment atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint64 variable
+ * @param atom Pointer to atomic variable
*
* @return Value of the variable before the increment
*/
@@ -220,17 +207,15 @@ uint64_t odp_atomic_fetch_inc_u64(odp_atomic_u64_t *atom);
/**
* Increment atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint64 variable
+ * @param atom Pointer to atomic variable
*/
void odp_atomic_inc_u64(odp_atomic_u64_t *atom);
/**
* Fetch and decrement atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint64 variable
+ * @param atom Pointer to atomic variable
*
* @return Value of the variable before the decrement
*/
@@ -238,9 +223,8 @@ uint64_t odp_atomic_fetch_dec_u64(odp_atomic_u64_t *atom);
/**
* Decrement atomic uint64 variable
- * @note Relaxed memory order, cannot be used for synchronization
*
- * @param[in,out] atom Pointer to an atomic uint64 variable
+ * @param atom Pointer to atomic variable
*/
void odp_atomic_dec_u64(odp_atomic_u64_t *atom);
diff --git a/include/odp/api/barrier.h b/include/odp/api/barrier.h
index 28310ba34..823eae66c 100644
--- a/include/odp/api/barrier.h
+++ b/include/odp/api/barrier.h
@@ -18,8 +18,15 @@
extern "C" {
#endif
-/** @addtogroup odp_synchronizers
- * Synchronize threads.
+/**
+ * @defgroup odp_barrier ODP BARRIER
+ * Thread excution and memory ordering barriers.
+ *
+ * @details
+ * <b> Thread execution barrier (odp_barrier_t) </b>
+ *
+ * Thread execution barrier synchronizes a group of threads to wait on the
+ * barrier until the entire group has reached the barrier.
* @{
*/
diff --git a/include/odp/api/classification.h b/include/odp/api/classification.h
index 380d91b15..c9493c2e2 100644
--- a/include/odp/api/classification.h
+++ b/include/odp/api/classification.h
@@ -37,7 +37,7 @@ extern "C" {
/**
* @def ODP_COS_INVALID
- * This value is returned from odp_cos_create() on failure,
+ * This value is returned from odp_cls_cos_create() on failure,
* May also be used as a sink class of service that
* results in packets being discarded.
*/
@@ -60,12 +60,12 @@ extern "C" {
*/
/**
- * Class-of-service packet drop policies
+ * class of service packet drop policies
*/
-typedef enum odp_cos_drop {
+typedef enum odp_cls_drop {
ODP_COS_DROP_POOL, /**< Follow buffer pool drop policy */
ODP_COS_DROP_NEVER, /**< Never drop, ignoring buffer pool policy */
-} odp_drop_e;
+} odp_cls_drop_t;
/**
* Packet header field enumeration
@@ -89,14 +89,39 @@ typedef enum odp_cos_hdr_flow_fields {
} odp_cos_hdr_flow_fields_e;
/**
+ * Class of service parameters
+ * Used to communicate class of service creation options
+ */
+typedef struct odp_cls_cos_param {
+ odp_queue_t queue; /**< Queue associated with CoS */
+ odp_pool_t pool; /**< Pool associated with CoS */
+ odp_cls_drop_t drop_policy; /**< Drop policy associated with CoS */
+} odp_cls_cos_param_t;
+
+/**
+ * Initialize class of service parameters
+ *
+ * Initialize an odp_cls_cos_param_t to its default value for all fields
+ *
+ * @param param Address of the odp_cls_cos_param_t to be initialized
+ */
+void odp_cls_cos_param_init(odp_cls_cos_param_t *param);
+
+/**
* Create a class-of-service
*
- * @param[in] name String intended for debugging purposes.
+ * @param name String intended for debugging purposes.
*
- * @return Class of service instance identifier
+ * @param param class of service parameters
+ *
+ * @retval class of service handle
* @retval ODP_COS_INVALID on failure.
+ *
+ * @note ODP_QUEUE_INVALID and ODP_POOL_INVALID are valid values for queue
+ * and pool associated with a class of service and when any one of these values
+ * are configured as INVALID then the packets assigned to the CoS gets dropped.
*/
-odp_cos_t odp_cos_create(const char *name);
+odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param);
/**
* Discard a class-of-service along with all its associated resources
@@ -145,7 +170,7 @@ odp_queue_t odp_cos_queue(odp_cos_t cos_id);
*
* @note Optional.
*/
-int odp_cos_drop_set(odp_cos_t cos_id, odp_drop_e drop_policy);
+int odp_cos_drop_set(odp_cos_t cos_id, odp_cls_drop_t drop_policy);
/**
* Get the drop policy configured for a specific class-of-service instance.
@@ -155,7 +180,7 @@ int odp_cos_drop_set(odp_cos_t cos_id, odp_drop_e drop_policy);
* @retval Drop policy configured with the given
* class-of-service
*/
-odp_drop_e odp_cos_drop(odp_cos_t cos_id);
+odp_cls_drop_t odp_cos_drop(odp_cos_t cos_id);
/**
* Request to override per-port class of service
@@ -379,6 +404,32 @@ int odp_pktio_pmr_match_set_cos(odp_pmr_set_t pmr_set_id, odp_pktio_t src_pktio,
odp_cos_t dst_cos);
/**
+* Assigns a packet pool for a specific class of service.
+* All the packets belonging to the given class of service will
+* be allocated from the assigned packet pool.
+* The packet pool associated with class of service will supersede the
+* packet pool associated with the pktio interface.
+*
+* @param cos_id class of service handle
+* @param pool_id packet pool handle
+*
+* @retval 0 on success
+* @retval <0 on failure
+*/
+int odp_cls_cos_pool_set(odp_cos_t cos_id, odp_pool_t pool_id);
+
+/**
+* Get the pool associated with the given class of service
+*
+* @param cos_id class of service handle
+*
+* @retval pool handle of the associated pool
+* @retval ODP_POOL_INVALID if no associated pool found or
+* incase of an error
+*/
+odp_pool_t odp_cls_cos_pool(odp_cos_t cos_id);
+
+/**
* Get printable value for an odp_cos_t
*
* @param hdl odp_cos_t handle to be printed
diff --git a/include/odp/api/crypto.h b/include/odp/api/crypto.h
index c62021e04..41beedbf5 100644
--- a/include/odp/api/crypto.h
+++ b/include/odp/api/crypto.h
@@ -70,6 +70,8 @@ typedef enum {
ODP_CIPHER_ALG_3DES_CBC,
/** AES128 with cipher block chaining */
ODP_CIPHER_ALG_AES128_CBC,
+ /** AES128 in Galois/Counter Mode */
+ ODP_CIPHER_ALG_AES128_GCM,
} odp_cipher_alg_t;
/**
@@ -82,6 +84,8 @@ typedef enum {
ODP_AUTH_ALG_MD5_96,
/** SHA256 with 128 bit key */
ODP_AUTH_ALG_SHA256_128,
+ /** AES128 in Galois/Counter Mode */
+ ODP_AUTH_ALG_AES128_GCM,
} odp_auth_alg_t;
/**
diff --git a/include/odp/api/hash.h b/include/odp/api/hash.h
new file mode 100644
index 000000000..1b2a580ea
--- /dev/null
+++ b/include/odp/api/hash.h
@@ -0,0 +1,98 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP Hash functions
+ */
+
+#ifndef ODP_API_HASH_H_
+#define ODP_API_HASH_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/std_types.h>
+
+/** @defgroup odp_hash ODP HASH FUNCTIONS
+ * ODP Hash functions
+ * @{
+ */
+
+/**
+* Calculate CRC-32
+*
+* Calculates CRC-32 over the data. The polynomial is 0x04c11db7.
+*
+* @param data Pointer to data
+* @param data_len Data length in bytes
+* @param init_val CRC generator initialization value
+*
+* @return CRC32 value
+*/
+uint32_t odp_hash_crc32(const void *data, uint32_t data_len, uint32_t init_val);
+
+/**
+* Calculate CRC-32C
+*
+* Calculates CRC-32C (a.k.a. CRC-32 Castagnoli) over the data.
+* The polynomial is 0x1edc6f41.
+*
+* @param data Pointer to data
+* @param data_len Data length in bytes
+* @param init_val CRC generator initialization value
+*
+* @return CRC32C value
+*/
+uint32_t odp_hash_crc32c(const void *data, uint32_t data_len,
+ uint32_t init_val);
+
+/**
+* CRC parameters
+*
+* Supports CRCs up to 64 bits
+*/
+typedef struct odp_hash_crc_param_t {
+ /** CRC width in bits */
+ uint32_t width;
+ /** Polynomial (stored in 'width' LSB bits) */
+ uint64_t poly;
+ /** 0: don't reflect, 1: reflect bits in input bytes */
+ odp_bool_t reflect_in;
+ /** 0: don't reflect, 1: reflect bits in output bytes */
+ odp_bool_t reflect_out;
+ /** XOR this value to CRC output (stored in 'width' LSB bits) */
+ uint64_t xor_out;
+} odp_hash_crc_param_t;
+
+/**
+* Calculate up to 64 bit CRC using the given parameters
+*
+* Calculates CRC over the data using the given parameters.
+*
+* @param data Pointer to data
+* @param data_len Data length in bytes
+* @param init_val CRC generator initialization value
+* @param crc_param CRC parameters
+* @param crc Pointer for CRC output
+*
+* @return 0 on success, <0 on failure (e.g. not supported algorithm)
+*/
+int odp_hash_crc_gen64(const void *data, uint32_t data_len,
+ uint64_t init_val, odp_hash_crc_param_t *crc_param,
+ uint64_t *crc);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/odp/api/init.h b/include/odp/api/init.h
index 737ff6d69..4ac521671 100644
--- a/include/odp/api/init.h
+++ b/include/odp/api/init.h
@@ -141,6 +141,10 @@ typedef struct odp_platform_init_t {
*
* This function must be called once before calling any other ODP API
* functions.
+ * The underlying implementation may have another way to get configuration
+ * related to platform_params (e.g. environmental variable, configuration
+ * file), but if the application passes platform_params, it should always
+ * supersede any other configuration data the platform has.
*
* @param params Those parameters that are interpreted by the ODP API.
* Use NULL to set all parameters to their defaults.
diff --git a/include/odp/api/packet_io.h b/include/odp/api/packet_io.h
index 003861017..cf9275191 100644
--- a/include/odp/api/packet_io.h
+++ b/include/odp/api/packet_io.h
@@ -386,6 +386,15 @@ uint64_t odp_pktio_to_u64(odp_pktio_t pktio);
void odp_pktio_param_init(odp_pktio_param_t *param);
/**
+ * Print pktio info to the console
+ *
+ * Print implementation-defined pktio debug information to the console.
+ *
+ * @param pktio Packet IO handle
+ */
+void odp_pktio_print(odp_pktio_t pktio);
+
+/**
* @}
*/
diff --git a/include/odp/api/rwlock.h b/include/odp/api/rwlock.h
index d730a7014..54f426fe7 100644
--- a/include/odp/api/rwlock.h
+++ b/include/odp/api/rwlock.h
@@ -17,18 +17,21 @@
extern "C" {
#endif
-/** @defgroup odp_synchronizers ODP SYNCRONIZERS
- * Operations on reader/writer locks.
- * A reader/writer lock allows multiple simultaneous readers but only one
- * writer at a time.
- * A thread that wants write access will have to wait until there are no
- * threads that want read access. This casues a risk for starvation.
- * @{
+/**
+ * @defgroup odp_locks ODP LOCKS
+ * @details
+ * <b> Reader / writer lock (odp_rwlock_t) </b>
+ *
+ * A reader/writer lock allows multiple simultaneous readers but only one
+ * writer at a time. A thread that wants write access will have to wait until
+ * there are no threads that want read access. This casues a risk for
+ * starvation.
+ * @{
*/
/**
* @typedef odp_rwlock_t
- * ODP rwlock
+ * ODP reader/writer lock
*/
diff --git a/include/odp/api/rwlock_recursive.h b/include/odp/api/rwlock_recursive.h
new file mode 100644
index 000000000..10b2f79ba
--- /dev/null
+++ b/include/odp/api/rwlock_recursive.h
@@ -0,0 +1,97 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive read/write lock
+ */
+
+#ifndef ODP_API_RWLOCK_RECURSIVE_H_
+#define ODP_API_RWLOCK_RECURSIVE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup odp_locks
+ * @details
+ * <b> Recursive reader/writer lock (odp_rwlock_recursive_t) </b>
+ *
+ * This is recursive version of the reader/writer lock.
+ * A thread can read- or write-acquire a recursive read-write lock multiple
+ * times without a deadlock. To release the lock, the thread must unlock it
+ * the same number of times. Recursion is supported only for a pure series of
+ * read or write lock calls. Read and write lock calls must not be mixed when
+ * recursing.
+ *
+ * For example, these are supported...
+ * * read_lock(); read_lock(); read_unlock(); read_unlock();
+ * * write_lock(); write_lock(); write_unlock(); write_unlock();
+ *
+ * ... but this is not supported.
+ * * read_lock(); write_lock(); write_unlock(); read_unlock();
+ * @{
+ */
+
+/**
+ * @typedef odp_rwlock_recursive_t
+ * Recursive rwlock
+ */
+
+/**
+ * Initialize recursive rwlock
+ *
+ * @param lock Pointer to a lock
+ */
+void odp_rwlock_recursive_init(odp_rwlock_recursive_t *lock);
+
+/**
+ * Acquire recursive rwlock for reading
+ *
+ * This call allows the thread to acquire the same lock multiple times for
+ * reading. The lock cannot be acquired for writing while holding it
+ * for reading.
+ *
+ * @param lock Pointer to a lock
+ */
+void odp_rwlock_recursive_read_lock(odp_rwlock_recursive_t *lock);
+
+/**
+ * Release recursive rwlock after reading
+ *
+ * @param lock Pointer to a lock
+ */
+void odp_rwlock_recursive_read_unlock(odp_rwlock_recursive_t *lock);
+
+/**
+ * Acquire recursive rwlock for writing
+ *
+ * This call allows the thread to acquire the same lock multiple times for
+ * writing. The lock cannot be acquired for reading while holding it
+ * for writing.
+ *
+ * @param lock Pointer to a lock
+ */
+void odp_rwlock_recursive_write_lock(odp_rwlock_recursive_t *lock);
+
+/**
+ * Release recursive rwlock after writing
+ *
+ * @param lock Pointer to a lock
+ */
+void odp_rwlock_recursive_write_unlock(odp_rwlock_recursive_t *lock);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/odp/api/spinlock.h b/include/odp/api/spinlock.h
index 9a5a9290a..154d0258a 100644
--- a/include/odp/api/spinlock.h
+++ b/include/odp/api/spinlock.h
@@ -18,9 +18,14 @@
extern "C" {
#endif
-/** @addtogroup odp_synchronizers
- * Operations on spin locks.
- * @{
+/**
+ * @addtogroup odp_locks
+ * @details
+ * <b> Spin lock (odp_spinlock_t) </b>
+ *
+ * Spinlock simply re-tries to acquire the lock as long as takes to succeed.
+ * Spinlock is not fair since some threads may succeed more often than others.
+ * @{
*/
/**
diff --git a/include/odp/api/spinlock_recursive.h b/include/odp/api/spinlock_recursive.h
new file mode 100644
index 000000000..d98f2bbb6
--- /dev/null
+++ b/include/odp/api/spinlock_recursive.h
@@ -0,0 +1,85 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive spinlock
+ */
+
+#ifndef ODP_API_SPINLOCK_RECURSIVE_H_
+#define ODP_API_SPINLOCK_RECURSIVE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup odp_locks
+ * @details
+ * <b> Recursive spin lock (odp_spinlock_recursive_t) </b>
+ *
+ * This is recursive version of the spin lock. A thread can acquire the lock
+ * multiple times without a deadlock. To release the lock, the thread must
+ * unlock it the same number of times.
+ * @{
+ */
+
+/**
+ * @typedef odp_spinlock_recursive_t
+ * Recursive spinlock
+ */
+
+/**
+ * Initialize recursive spinlock.
+ *
+ * @param lock Pointer to a lock
+ */
+void odp_spinlock_recursive_init(odp_spinlock_recursive_t *lock);
+
+/**
+ * Acquire recursive spinlock.
+ *
+ * @param lock Pointer to a lock
+ */
+void odp_spinlock_recursive_lock(odp_spinlock_recursive_t *lock);
+
+/**
+ * Try to acquire recursive spinlock.
+ *
+ * @param lock Pointer to a lock
+ *
+ * @retval 1 lock acquired
+ * @retval 0 lock not acquired
+ */
+int odp_spinlock_recursive_trylock(odp_spinlock_recursive_t *lock);
+
+/**
+ * Release recursive spinlock.
+ *
+ * @param lock Pointer to a lock
+ */
+void odp_spinlock_recursive_unlock(odp_spinlock_recursive_t *lock);
+
+/**
+ * Check if recursive spinlock is locked.
+ *
+ * @param lock Pointer to a lock
+ *
+ * @retval 1 lock is locked
+ * @retval 0 lock is not locked
+ */
+int odp_spinlock_recursive_is_locked(odp_spinlock_recursive_t *lock);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/odp/api/std_clib.h b/include/odp/api/std_clib.h
new file mode 100644
index 000000000..2119ec481
--- /dev/null
+++ b/include/odp/api/std_clib.h
@@ -0,0 +1,64 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP version of often used C library calls
+ */
+
+#ifndef ODP_API_STD_CLIB_H_
+#define ODP_API_STD_CLIB_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup odp_std_clib ODP STD CLIB
+ * @details
+ * ODP version of often used C library calls
+ * @{
+ */
+
+/**
+ * Memcpy
+ *
+ * ODP version of C library memcpy function. It copies 'num' bytes from source
+ * to destination address. Source and destination memory blocks must not
+ * overlap.
+ *
+ * @param dst Pointer to destination memory block
+ * @param src Pointer to source memory block
+ * @param num Number of bytes to copy
+ *
+ * @return 'dst' address
+ */
+void *odp_memcpy(void *dst, const void *src, size_t num);
+
+/**
+ * Memset
+ *
+ * ODP version of C library memset function. It sets 'value' to first 'num'
+ * bytes of memory block pointed by 'ptr'.
+ *
+ * @param ptr Pointer to the memory block
+ * @param value Value to be set
+ * @param num Number of bytes to set
+ *
+ * @return 'ptr' address
+ */
+void *odp_memset(void *ptr, int value, size_t num);
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/odp/api/sync.h b/include/odp/api/sync.h
index b338a98a8..c6f790c6f 100644
--- a/include/odp/api/sync.h
+++ b/include/odp/api/sync.h
@@ -8,7 +8,7 @@
/**
* @file
*
- * ODP synchronisation
+ * ODP memory barriers
*/
#ifndef ODP_API_SYNC_H_
@@ -18,42 +18,66 @@
extern "C" {
#endif
-/** @addtogroup odp_synchronizers
+/**
+ * @addtogroup odp_barrier
+ * @details
+ * <b> Memory barriers </b>
+ *
+ * Memory barriers enforce ordering of memory load and store operations
+ * specified before and after the barrier. These barriers may affect both
+ * compiler optimizations and CPU out-of-order execution. All ODP
+ * synchronization mechanisms (e.g. execution barriers, locks, queues, etc )
+ * include all necessary memory barriers, so these calls are not needed when
+ * using those. Also ODP atomic operations have memory ordered versions. These
+ * explicit barriers may be needed when thread synchronization is based on
+ * a non-ODP defined mechanism. Depending on the HW platform, heavy usage of
+ * memory barriers may cause significant performance degradation.
+ *
* @{
*/
/**
- * Synchronise stores
+ * Memory barrier for release operations
*
- * Ensures that all CPU store operations that precede the odp_sync_stores()
- * call are globally visible before any store operation that follows it.
+ * This memory barrier has release semantics. It synchronizes with a pairing
+ * barrier for acquire operations. The releasing and acquiring threads
+ * synchronize through shared memory. The releasing thread must call this
+ * barrier before signaling the acquiring thread. After the acquiring thread
+ * receives the signal, it must call odp_mb_acquire() before it reads the
+ * memory written by the releasing thread.
+ *
+ * This call is not needed when using ODP defined synchronization mechanisms.
+ *
+ * @see odp_mb_acquire()
*/
-static inline void odp_sync_stores(void)
-{
-#if defined __x86_64__ || defined __i386__
-
- __asm__ __volatile__ ("sfence\n" : : : "memory");
-
-#elif defined(__arm__)
-#if __ARM_ARCH == 6
- __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
- : : "r" (0) : "memory");
-#elif __ARM_ARCH >= 7 || defined __aarch64__
-
- __asm__ __volatile__ ("dmb st" : : : "memory");
-#else
- __asm__ __volatile__ ("" : : : "memory");
-#endif
-
-#elif defined __OCTEON__
-
- __asm__ __volatile__ ("syncws\n" : : : "memory");
+void odp_mb_release(void);
-#else
- __sync_synchronize();
-#endif
-}
+/**
+ * Memory barrier for acquire operations
+ *
+ * This memory barrier has acquire semantics. It synchronizes with a pairing
+ * barrier for release operations. The releasing and acquiring threads
+ * synchronize through shared memory. The releasing thread must call
+ * odp_mb_release() before signaling the acquiring thread. After the acquiring
+ * thread receives the signal, it must call this barrier before it reads the
+ * memory written by the releasing thread.
+ *
+ * This call is not needed when using ODP defined synchronization mechanisms.
+ *
+ * @see odp_mb_release()
+ */
+void odp_mb_acquire(void);
+/**
+ * Full memory barrier
+ *
+ * This is a full memory barrier. It guarantees that all load and store
+ * operations specified before it are visible to other threads before
+ * all load and store operations specified after it.
+ *
+ * This call is not needed when using ODP defined synchronization mechanisms.
+ */
+void odp_mb_full(void);
/**
* @}
diff --git a/include/odp/api/thread.h b/include/odp/api/thread.h
index 3029342c2..37202497a 100644
--- a/include/odp/api/thread.h
+++ b/include/odp/api/thread.h
@@ -23,6 +23,13 @@ extern "C" {
*/
/**
+ * @def ODP_THREAD_COUNT_MAX
+ * Maximum number of threads supported in build time. Use
+ * odp_thread_count_max() for maximum number of threads supported in run time,
+ * which depend on system configuration and may be lower than this number.
+ */
+
+/**
* Thread type
*/
typedef enum odp_thread_type_e {
@@ -78,7 +85,7 @@ int odp_thread_count(void);
* Maximum thread count
*
* Returns the maximum thread count, which is a constant value and set in
- * ODP initialization phase.
+ * ODP initialization phase. This may be lower than ODP_THREAD_COUNT_MAX.
*
* @return Maximum thread count
*/
diff --git a/include/odp/api/thrmask.h b/include/odp/api/thrmask.h
index ebc31f2f6..8666166e0 100644
--- a/include/odp/api/thrmask.h
+++ b/include/odp/api/thrmask.h
@@ -67,7 +67,7 @@ void odp_thrmask_set(odp_thrmask_t *mask, int thr);
* Set all threads in mask
*
* Set all possible threads in the mask. All threads from 0 to
- * odp_thrmask_count() minus one are set, regardless of which threads are
+ * odp_thread_count_max() minus one are set, regardless of which threads are
* actually active.
*
* @param mask Thread mask to set
diff --git a/include/odp/api/ticketlock.h b/include/odp/api/ticketlock.h
index e395ac4ca..3f0e3f556 100644
--- a/include/odp/api/ticketlock.h
+++ b/include/odp/api/ticketlock.h
@@ -18,13 +18,17 @@
extern "C" {
#endif
-/** @addtogroup odp_synchronizers
- * Operations on ticket locks.
+/**
+ * @addtogroup odp_locks
+ * @details
+ * <b> Ticket lock (odp_ticketlock_t) </b>
+ *
* Acquiring a ticket lock happens in two phases. First the threads takes a
- * ticket. Second it waits (spins) until it is its turn.
- * Ticket locks are believed to be more fair than spin locks.
- * Ticket locks shall not be used in the presence of preemption.
- * @{
+ * ticket. Second it waits (spins) until it is its turn. Ticket locks are
+ * believed to be more fair than spin locks. Ticket locks shall not be used
+ * if a thread may be preempted, since other threads cannot acquire the lock
+ * while the thread in turn is stalled.
+ * @{
*/
/**
diff --git a/include/odp/api/time.h b/include/odp/api/time.h
index 50a0bf55d..efc547802 100644
--- a/include/odp/api/time.h
+++ b/include/odp/api/time.h
@@ -45,13 +45,28 @@ extern "C" {
* Current local time
*
* Returns current local time stamp value. The local time source provides high
- * resolution time.
+ * resolution time, it is initialized to zero during ODP startup and will not
+ * wrap around in at least 10 years.
+ * Local time stamps are local to the calling thread and must not be shared
+ * with other threads.
*
* @return Local time stamp.
*/
odp_time_t odp_time_local(void);
/**
+ * Current global time
+ *
+ * Returns current global time stamp value. The global time source provides high
+ * resolution time, it is initialized to zero during ODP startup and will not
+ * wrap around in at least 10 years.
+ * Global time stamps can be shared between threads.
+ *
+ * @return Global time stamp.
+ */
+odp_time_t odp_time_global(void);
+
+/**
* Time difference
*
* @param t2 Second time stamp
@@ -90,6 +105,15 @@ uint64_t odp_time_to_ns(odp_time_t time);
odp_time_t odp_time_local_from_ns(uint64_t ns);
/**
+ * Convert nanoseconds to global time
+ *
+ * @param ns Time in nanoseconds
+ *
+ * @return Global time stamp
+ */
+odp_time_t odp_time_global_from_ns(uint64_t ns);
+
+/**
* Compare two times
*
* @param t2 Second time
@@ -100,6 +124,38 @@ odp_time_t odp_time_local_from_ns(uint64_t ns);
int odp_time_cmp(odp_time_t t2, odp_time_t t1);
/**
+ * Local time resolution in hertz
+ *
+ * @return Local time resolution in hertz
+ */
+uint64_t odp_time_local_res(void);
+
+/**
+ * Global time resolution in hertz
+ *
+ * @return Global time resolution in hertz
+ */
+uint64_t odp_time_global_res(void);
+
+/**
+ * Wait until the specified (wall clock) time has been reached
+ *
+ * The thread potentially busy loop the entire wait time.
+ *
+ * @param time Time to reach before continue
+ */
+void odp_time_wait_until(odp_time_t time);
+
+/**
+ * Wait the specified number of nanoseconds
+ *
+ * The thread potentially busy loop the entire wait time.
+ *
+ * @param ns Time in nanoseconds to wait
+ */
+void odp_time_wait_ns(uint64_t ns);
+
+/**
* Get printable value for an odp_time_t
*
* @param time time to be printed
diff --git a/include/odp/api/version.h b/include/odp/api/version.h
index 58bb7ecfe..95fac3cf2 100644
--- a/include/odp/api/version.h
+++ b/include/odp/api/version.h
@@ -18,8 +18,15 @@
extern "C" {
#endif
-/** @defgroup odp_version ODP VERSION
- * @{
+/**
+ * @defgroup odp_version ODP VERSION
+ * @details
+ * <b> ODP API and implementation versions </b>
+ *
+ * ODP API version is identified by ODP_VERSION_API_XXX pre-processor macros.
+ * In addition to these macros, API calls can be used to identify implementation
+ * and API version information at run time.
+ * @{
*/
/**
@@ -37,7 +44,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 5
+#define ODP_VERSION_API_MAJOR 6
/**
* ODP API minor version
@@ -49,20 +56,42 @@ extern "C" {
#define ODP_VERSION_API_MINOR 0
/**
- * Returns ODP API version string
+ * ODP API version string
+ *
+ * The API version string defines ODP API version in this format:
+ * @verbatim <generation>.<major>.<minor> @endverbatim
+ *
+ * The string is null terminated.
+ *
+ * @return Pointer to API version string
*/
const char *odp_version_api_str(void);
+/**
+ * Implementation name string
+ *
+ * This is a free format string which identifies the implementation with a
+ * unique name. The string should be compact and remain constant over multiple
+ * API and implementation versions. Application can use this to identify the
+ * underlying implementation at run time. The string is null terminated.
+ *
+ * @return Pointer to implementation name string
+ */
+const char *odp_version_impl_name(void);
/**
- * Returns ODP implementation version string
+ * Implementation version string
+ *
+ * This is a free format string which identifies the implementation with
+ * detailed version information. The string may include information about
+ * implementation version, bug fix level, version control tags, build number,
+ * etc details which exactly identify the implementation code base.
+ * User may include this information e.g. to bug reports. The string is null
+ * terminated.
*
- * Every implementation of ODP may receive bug fixes independent of the version
- * of the API changing, this function returns that indication string.
- * @note This string is implementation specific.
- * @sa odp_version_api_str()
+ * @see odp_version_api_str(), odp_version_impl_name()
*
- * @return null terminated implementation specific version identifier string
+ * @return Pointer to implementation specific version identifier string
*/
const char *odp_version_impl_str(void);
/**
diff --git a/pkg/debian/changelog b/pkg/debian/changelog
index 7680cf1ee..1a0b23c83 100644
--- a/pkg/debian/changelog
+++ b/pkg/debian/changelog
@@ -1,3 +1,8 @@
+opendataplane (1.6.0.0-1) unstable; urgency=low
+ * ODP release v1.6
+
+ -- Maxim Uvarov <maxim.uvarov@linaro.org> Mon, 28 Dec 2015 17:01:58 +0300
+
opendataplane (1.5.0.0-1) unstable; urgency=low
* ODP release v1.5
diff --git a/pkg/rpm/odp.spec b/pkg/rpm/odp.spec
index e76fe58a1..6c675a754 100644
--- a/pkg/rpm/odp.spec
+++ b/pkg/rpm/odp.spec
@@ -68,6 +68,8 @@ and guides in HTMLformats.
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%changelog
+* Mon Dec 28 2015 - maxim.uvarov (at) linaro.org
+- ODP release v1.6
* Mon Nov 30 2015 - mike.holmes (at) linaro.org
- ODP release v1.5
* Tue Nov 10 2015 - anders.roxell (at) linaro.org
diff --git a/platform/Makefile.inc b/platform/Makefile.inc
index 5d589b1b0..ef9724baa 100644
--- a/platform/Makefile.inc
+++ b/platform/Makefile.inc
@@ -32,6 +32,7 @@ odpapiinclude_HEADERS = \
$(top_srcdir)/include/odp/api/debug.h \
$(top_srcdir)/include/odp/api/errno.h \
$(top_srcdir)/include/odp/api/event.h \
+ $(top_srcdir)/include/odp/api/hash.h \
$(top_srcdir)/include/odp/api/hints.h \
$(top_srcdir)/include/odp/api/init.h \
$(top_srcdir)/include/odp/api/packet.h \
@@ -41,10 +42,13 @@ odpapiinclude_HEADERS = \
$(top_srcdir)/include/odp/api/queue.h \
$(top_srcdir)/include/odp/api/random.h \
$(top_srcdir)/include/odp/api/rwlock.h \
+ $(top_srcdir)/include/odp/api/rwlock_recursive.h \
$(top_srcdir)/include/odp/api/schedule.h \
$(top_srcdir)/include/odp/api/schedule_types.h \
$(top_srcdir)/include/odp/api/shared_memory.h \
$(top_srcdir)/include/odp/api/spinlock.h \
+ $(top_srcdir)/include/odp/api/spinlock_recursive.h \
+ $(top_srcdir)/include/odp/api/std_clib.h \
$(top_srcdir)/include/odp/api/std_types.h \
$(top_srcdir)/include/odp/api/sync.h \
$(top_srcdir)/include/odp/api/system_info.h \
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 4639ebcc0..806419359 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -26,6 +26,7 @@ odpinclude_HEADERS = \
$(srcdir)/include/odp/debug.h \
$(srcdir)/include/odp/errno.h \
$(srcdir)/include/odp/event.h \
+ $(srcdir)/include/odp/hash.h \
$(srcdir)/include/odp/hints.h \
$(srcdir)/include/odp/init.h \
$(srcdir)/include/odp/packet_flags.h \
@@ -35,10 +36,13 @@ odpinclude_HEADERS = \
$(srcdir)/include/odp/queue.h \
$(srcdir)/include/odp/random.h \
$(srcdir)/include/odp/rwlock.h \
+ $(srcdir)/include/odp/rwlock_recursive.h \
$(srcdir)/include/odp/schedule.h \
$(srcdir)/include/odp/schedule_types.h \
$(srcdir)/include/odp/shared_memory.h \
$(srcdir)/include/odp/spinlock.h \
+ $(srcdir)/include/odp/spinlock_recursive.h \
+ $(srcdir)/include/odp/std_clib.h \
$(srcdir)/include/odp/std_types.h \
$(srcdir)/include/odp/sync.h \
$(srcdir)/include/odp/system_info.h \
@@ -64,10 +68,13 @@ odpplatinclude_HEADERS = \
$(srcdir)/include/odp/plat/pool_types.h \
$(srcdir)/include/odp/plat/queue_types.h \
$(srcdir)/include/odp/plat/rwlock_types.h \
+ $(srcdir)/include/odp/plat/rwlock_recursive_types.h \
$(srcdir)/include/odp/plat/schedule_types.h \
$(srcdir)/include/odp/plat/shared_memory_types.h \
$(srcdir)/include/odp/plat/spinlock_types.h \
+ $(srcdir)/include/odp/plat/spinlock_recursive_types.h \
$(srcdir)/include/odp/plat/strong_types.h \
+ $(srcdir)/include/odp/plat/thread_types.h \
$(srcdir)/include/odp/plat/thrmask_types.h \
$(srcdir)/include/odp/plat/ticketlock_types.h \
$(srcdir)/include/odp/plat/time_types.h \
@@ -82,7 +89,6 @@ 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 \
@@ -98,7 +104,6 @@ noinst_HEADERS = \
${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 = \
@@ -111,12 +116,14 @@ __LIB__libodp_la_SOURCES = \
odp_crypto.c \
odp_errno.c \
odp_event.c \
+ odp_hash.c \
odp_init.c \
odp_impl.c \
odp_packet.c \
odp_packet_flags.c \
odp_packet_io.c \
pktio/io_ops.c \
+ pktio/pktio_common.c \
pktio/loop.c \
pktio/netmap.c \
pktio/socket.c \
@@ -125,9 +132,11 @@ __LIB__libodp_la_SOURCES = \
odp_pool.c \
odp_queue.c \
odp_rwlock.c \
+ odp_rwlock_recursive.c \
odp_schedule.c \
odp_shared_memory.c \
odp_spinlock.c \
+ odp_spinlock_recursive.c \
odp_system_info.c \
odp_thread.c \
odp_thrmask.c \
diff --git a/platform/linux-generic/include/odp/atomic.h b/platform/linux-generic/include/odp/atomic.h
index e47a280bf..deb4039b3 100644
--- a/platform/linux-generic/include/odp/atomic.h
+++ b/platform/linux-generic/include/odp/atomic.h
@@ -21,7 +21,7 @@ extern "C" {
#include <odp/align.h>
#include <odp/plat/atomic_types.h>
-/** @ingroup odp_synchronizers
+/** @ingroup odp_atomic
* @{
*/
diff --git a/platform/linux-generic/include/odp/barrier.h b/platform/linux-generic/include/odp/barrier.h
index 7ea5a6b99..42df8595a 100644
--- a/platform/linux-generic/include/odp/barrier.h
+++ b/platform/linux-generic/include/odp/barrier.h
@@ -21,14 +21,6 @@ extern "C" {
#include <odp/plat/shared_memory_types.h>
#include <odp/plat/barrier_types.h>
-/** @ingroup odp_synchronizers
- * @{
- */
-
-/**
- * @}
- */
-
#include <odp/api/barrier.h>
#ifdef __cplusplus
diff --git a/platform/linux-generic/include/odp_config_internal.h b/platform/linux-generic/include/odp/hash.h
index 4f20ff8e0..df8add002 100644
--- a/platform/linux-generic/include/odp_config_internal.h
+++ b/platform/linux-generic/include/odp/hash.h
@@ -7,20 +7,25 @@
/**
* @file
*
- * Linux-generic platform internal configuration
+ * ODP Hash function
*/
-#ifndef ODP_CONFIG_INTERNAL_H_
-#define ODP_CONFIG_INTERNAL_H_
+#ifndef ODP_PLAT_HASH_H_
+#define ODP_PLAT_HASH_H_
#ifdef __cplusplus
extern "C" {
#endif
+/** @ingroup odp_hash
+ * @{
+ */
+
/**
- * Maximum number of threads
+ * @}
*/
-#define _ODP_INTERNAL_MAX_THREADS 128
+
+#include <odp/api/hash.h>
#ifdef __cplusplus
}
diff --git a/platform/linux-generic/include/odp/plat/atomic_types.h b/platform/linux-generic/include/odp/plat/atomic_types.h
index 3cdcab8bd..0f6c353a1 100644
--- a/platform/linux-generic/include/odp/plat/atomic_types.h
+++ b/platform/linux-generic/include/odp/plat/atomic_types.h
@@ -62,18 +62,10 @@ struct odp_atomic_u32_s {
})
#endif
-/** @addtogroup odp_synchronizers
- * @{
- */
-
typedef struct odp_atomic_u64_s odp_atomic_u64_t;
typedef struct odp_atomic_u32_s odp_atomic_u32_t;
-/**
- * @}
- */
-
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp/plat/barrier_types.h b/platform/linux-generic/include/odp/plat/barrier_types.h
index c8c978dca..b8e1d97bb 100644
--- a/platform/linux-generic/include/odp/plat/barrier_types.h
+++ b/platform/linux-generic/include/odp/plat/barrier_types.h
@@ -30,16 +30,8 @@ struct odp_barrier_s {
odp_atomic_u32_t bar; /**< Barrier counter */
};
-/** @addtogroup odp_synchronizers
- * @{
- */
-
typedef struct odp_barrier_s odp_barrier_t;
-/**
- * @}
- */
-
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp/plat/rwlock_recursive_types.h b/platform/linux-generic/include/odp/plat/rwlock_recursive_types.h
new file mode 100644
index 000000000..474751cf0
--- /dev/null
+++ b/platform/linux-generic/include/odp/plat/rwlock_recursive_types.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive read/write lock
+ */
+
+#ifndef ODP_RWLOCK_RECURSIVE_TYPES_H_
+#define ODP_RWLOCK_RECURSIVE_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/rwlock.h>
+#include <odp/std_types.h>
+#include <odp/thread.h>
+
+/** @internal */
+struct odp_rwlock_recursive_s {
+ odp_rwlock_t lock; /**< the lock */
+ int wr_owner; /**< write owner thread */
+ uint32_t wr_cnt; /**< write recursion count */
+ uint8_t rd_cnt[ODP_THREAD_COUNT_MAX]; /**< read recursion count */
+};
+
+typedef struct odp_rwlock_recursive_s odp_rwlock_recursive_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/plat/rwlock_types.h b/platform/linux-generic/include/odp/plat/rwlock_types.h
index bd46e5722..35d65decb 100644
--- a/platform/linux-generic/include/odp/plat/rwlock_types.h
+++ b/platform/linux-generic/include/odp/plat/rwlock_types.h
@@ -20,10 +20,7 @@ extern "C" {
#include <odp/atomic.h>
-/**
- * @internal
- * ODP rwlock
- */
+/** @internal */
struct odp_rwlock_s {
odp_atomic_u32_t cnt; /**< lock count
0 lock not taken
@@ -31,16 +28,8 @@ struct odp_rwlock_s {
>0 read lock(s) taken */
};
-/** @addtogroup odp_synchronizers
- * @{
- */
-
typedef struct odp_rwlock_s odp_rwlock_t;
-/**
- * @}
- */
-
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp/plat/spinlock_recursive_types.h b/platform/linux-generic/include/odp/plat/spinlock_recursive_types.h
new file mode 100644
index 000000000..2809277bd
--- /dev/null
+++ b/platform/linux-generic/include/odp/plat/spinlock_recursive_types.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP recursive spinlock
+ */
+
+#ifndef ODP_SPINLOCK_RECURSIVE_TYPES_H_
+#define ODP_SPINLOCK_RECURSIVE_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/spinlock.h>
+#include <odp/std_types.h>
+
+/** @internal */
+struct odp_spinlock_recursive_s {
+ odp_spinlock_t lock; /**< the lock */
+ int owner; /**< thread owning the lock */
+ uint32_t cnt; /**< recursion count */
+};
+
+typedef struct odp_spinlock_recursive_s odp_spinlock_recursive_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/plat/spinlock_types.h b/platform/linux-generic/include/odp/plat/spinlock_types.h
index 83d306b5b..3e0231d1d 100644
--- a/platform/linux-generic/include/odp/plat/spinlock_types.h
+++ b/platform/linux-generic/include/odp/plat/spinlock_types.h
@@ -20,25 +20,13 @@ extern "C" {
#include <odp/std_types.h>
-/**
- * @internal
- * ODP spinlock
- */
+/** @internal */
struct odp_spinlock_s {
char lock; /**< lock flag, should match odp_atomic_flag_t */
};
-
-/** @addtogroup odp_synchronizers
- * @{
- */
-
typedef struct odp_spinlock_s odp_spinlock_t;
-/**
- * @}
- */
-
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp/plat/thread_types.h b/platform/linux-generic/include/odp/plat/thread_types.h
new file mode 100644
index 000000000..33af45983
--- /dev/null
+++ b/platform/linux-generic/include/odp/plat/thread_types.h
@@ -0,0 +1,34 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP thread
+ */
+
+#ifndef ODP_THREAD_TYPES_H_
+#define ODP_THREAD_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @addtogroup odp_thread
+ * @{
+ */
+
+#define ODP_THREAD_COUNT_MAX 128
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/plat/ticketlock_types.h b/platform/linux-generic/include/odp/plat/ticketlock_types.h
index be9308556..73f970542 100644
--- a/platform/linux-generic/include/odp/plat/ticketlock_types.h
+++ b/platform/linux-generic/include/odp/plat/ticketlock_types.h
@@ -20,25 +20,14 @@ extern "C" {
#include <odp/atomic.h>
-/**
- * @internal
- * ODP ticketlock
- */
+/** @internal */
struct odp_ticketlock_s {
odp_atomic_u32_t next_ticket; /**< Next ticket */
odp_atomic_u32_t cur_ticket; /**< Current ticket */
};
-/** @addtogroup odp_synchronizers
- * @{
- */
-
typedef struct odp_ticketlock_s odp_ticketlock_t;
-/**
- * @}
- */
-
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp/plat/time_types.h b/platform/linux-generic/include/odp/plat/time_types.h
index 9ba1508c7..14c35f0bf 100644
--- a/platform/linux-generic/include/odp/plat/time_types.h
+++ b/platform/linux-generic/include/odp/plat/time_types.h
@@ -21,9 +21,16 @@ extern "C" {
* @{
**/
-typedef uint64_t odp_time_t;
+/**
+ * @internal Time structure used to isolate linux-generic implementation from
+ * the linux timespec structure, which is dependent on _POSIX_C_SOURCE level.
+ */
+typedef struct odp_time_t {
+ int64_t tv_sec; /**< @internal Seconds */
+ int64_t tv_nsec; /**< @internal Nanoseconds */
+} odp_time_t;
-#define ODP_TIME_NULL ((odp_time_t)0)
+#define ODP_TIME_NULL ((odp_time_t){0, 0})
/**
* @}
diff --git a/platform/linux-generic/include/odp/rwlock.h b/platform/linux-generic/include/odp/rwlock.h
index ca88ff7db..f9d8f5fd4 100644
--- a/platform/linux-generic/include/odp/rwlock.h
+++ b/platform/linux-generic/include/odp/rwlock.h
@@ -19,14 +19,6 @@ extern "C" {
#include <odp/plat/rwlock_types.h>
-/** @ingroup odp_synchronizers
- * @{
- */
-
-/**
- * @}
- */
-
#include <odp/api/rwlock.h>
#ifdef __cplusplus
diff --git a/platform/linux-generic/include/odp/rwlock_recursive.h b/platform/linux-generic/include/odp/rwlock_recursive.h
new file mode 100644
index 000000000..e9dadc878
--- /dev/null
+++ b/platform/linux-generic/include/odp/rwlock_recursive.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP resursive read/write lock
+ */
+
+#ifndef ODP_PLAT_RWLOCK_RECURSIVE_H_
+#define ODP_PLAT_RWLOCK_RECURSIVE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/plat/rwlock_recursive_types.h>
+
+#include <odp/api/rwlock_recursive.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/spinlock.h b/platform/linux-generic/include/odp/spinlock.h
index 7dbb1c4bf..046fcfada 100644
--- a/platform/linux-generic/include/odp/spinlock.h
+++ b/platform/linux-generic/include/odp/spinlock.h
@@ -19,14 +19,6 @@ extern "C" {
#include <odp/plat/spinlock_types.h>
-/** @ingroup odp_synchronizers
- * @{
- */
-
-/**
- * @}
- */
-
#include <odp/api/spinlock.h>
#ifdef __cplusplus
diff --git a/platform/linux-generic/include/odp/spinlock_recursive.h b/platform/linux-generic/include/odp/spinlock_recursive.h
new file mode 100644
index 000000000..e8a996837
--- /dev/null
+++ b/platform/linux-generic/include/odp/spinlock_recursive.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP resursive spinlock
+ */
+
+#ifndef ODP_PLAT_SPINLOCK_RECURSIVE_H_
+#define ODP_PLAT_SPINLOCK_RECURSIVE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/plat/spinlock_recursive_types.h>
+
+#include <odp/api/spinlock_recursive.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/std_clib.h b/platform/linux-generic/include/odp/std_clib.h
new file mode 100644
index 000000000..c939c48e9
--- /dev/null
+++ b/platform/linux-generic/include/odp/std_clib.h
@@ -0,0 +1,30 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_PLAT_STD_CLIB_H_
+#define ODP_PLAT_STD_CLIB_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/api/std_types.h>
+
+static inline void *odp_memcpy(void *dst, const void *src, size_t num)
+{
+ return memcpy(dst, src, num);
+}
+
+static inline void *odp_memset(void *ptr, int value, size_t num)
+{
+ return memset(ptr, value, num);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/sync.h b/platform/linux-generic/include/odp/sync.h
index 8cdab21ef..b2995e19c 100644
--- a/platform/linux-generic/include/odp/sync.h
+++ b/platform/linux-generic/include/odp/sync.h
@@ -17,10 +17,25 @@
extern "C" {
#endif
-/** @ingroup odp_synchronizers
+/** @ingroup odp_barrier
* @{
*/
+static inline void odp_mb_release(void)
+{
+ __atomic_thread_fence(__ATOMIC_RELEASE);
+}
+
+static inline void odp_mb_acquire(void)
+{
+ __atomic_thread_fence(__ATOMIC_ACQUIRE);
+}
+
+static inline void odp_mb_full(void)
+{
+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
+}
+
/**
* @}
*/
diff --git a/platform/linux-generic/include/odp/thread.h b/platform/linux-generic/include/odp/thread.h
index e5215852a..522ca2599 100644
--- a/platform/linux-generic/include/odp/thread.h
+++ b/platform/linux-generic/include/odp/thread.h
@@ -17,13 +17,7 @@
extern "C" {
#endif
-/** @ingroup odp_thread ODP THREAD
- * @{
- */
-
-/**
- * @}
- */
+#include <odp/plat/thread_types.h>
#include <odp/api/thread.h>
diff --git a/platform/linux-generic/include/odp/ticketlock.h b/platform/linux-generic/include/odp/ticketlock.h
index 658e27fe4..d3491519a 100644
--- a/platform/linux-generic/include/odp/ticketlock.h
+++ b/platform/linux-generic/include/odp/ticketlock.h
@@ -19,15 +19,6 @@ extern "C" {
#include <odp/plat/ticketlock_types.h>
-/** @ingroup odp_synchronizers
- * Operations on ticket locks.
- * @{
- */
-
-/**
- * @}
- */
-
#include <odp/api/ticketlock.h>
#ifdef __cplusplus
diff --git a/platform/linux-generic/include/odp_atomic_internal.h b/platform/linux-generic/include/odp_atomic_internal.h
index 06fc16b1b..ce62368e1 100644
--- a/platform/linux-generic/include/odp_atomic_internal.h
+++ b/platform/linux-generic/include/odp_atomic_internal.h
@@ -25,11 +25,6 @@
extern "C" {
#endif
-/** @addtogroup odp_synchronizers
- * Atomic operations.
- * @{
- */
-
/**
* Pointer atomic type
*/
@@ -598,10 +593,6 @@ static inline void _odp_atomic_flag_clear(_odp_atomic_flag_t *flag)
__atomic_clear(flag, __ATOMIC_RELEASE);
}
-/**
- * @}
- */
-
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp_buffer_internal.h b/platform/linux-generic/include/odp_buffer_internal.h
index 74a0b5c4f..abdd320b4 100644
--- a/platform/linux-generic/include/odp_buffer_internal.h
+++ b/platform/linux-generic/include/odp_buffer_internal.h
@@ -30,7 +30,6 @@ 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 : \
@@ -144,7 +143,7 @@ struct odp_buffer_hdr_t {
/** @internal Compile time assert that the
* allocator field can handle any allocator id*/
-_ODP_STATIC_ASSERT(INT16_MAX >= _ODP_INTERNAL_MAX_THREADS,
+_ODP_STATIC_ASSERT(INT16_MAX >= ODP_THREAD_COUNT_MAX,
"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 4358fcaed..5b6520266 100644
--- a/platform/linux-generic/include/odp_classification_datamodel.h
+++ b/platform/linux-generic/include/odp_classification_datamodel.h
@@ -70,9 +70,8 @@ struct cos_s {
union pmr_u *pmr; /* Chained PMR */
union cos_u *linked_cos; /* CoS linked with the PMR */
uint32_t valid; /* validity Flag */
- odp_drop_e drop_policy; /* Associated Drop Policy */
+ odp_cls_drop_t 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 7f13530c0..e9739aafb 100644
--- a/platform/linux-generic/include/odp_classification_inlines.h
+++ b/platform/linux-generic/include/odp_classification_inlines.h
@@ -39,15 +39,16 @@ static inline int verify_pmr_packet_len(odp_packet_hdr_t *pkt_hdr,
return 0;
}
-static inline int verify_pmr_ip_proto(uint8_t *pkt_addr,
+
+static inline int verify_pmr_ip_proto(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
- odph_ipv4hdr_t *ip;
+ const odph_ipv4hdr_t *ip;
uint8_t proto;
if (!pkt_hdr->input_flags.ipv4)
return 0;
- ip = (odph_ipv4hdr_t *)(pkt_addr + pkt_hdr->l3_offset);
+ ip = (const odph_ipv4hdr_t *)(pkt_addr + pkt_hdr->l3_offset);
proto = ip->proto;
if (term_value->val == (proto & term_value->mask))
return 1;
@@ -55,15 +56,15 @@ static inline int verify_pmr_ip_proto(uint8_t *pkt_addr,
return 0;
}
-static inline int verify_pmr_ipv4_saddr(uint8_t *pkt_addr,
+static inline int verify_pmr_ipv4_saddr(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
- odph_ipv4hdr_t *ip;
+ const odph_ipv4hdr_t *ip;
uint32_t ipaddr;
if (!pkt_hdr->input_flags.ipv4)
return 0;
- ip = (odph_ipv4hdr_t *)(pkt_addr + pkt_hdr->l3_offset);
+ ip = (const odph_ipv4hdr_t *)(pkt_addr + pkt_hdr->l3_offset);
ipaddr = odp_be_to_cpu_32(ip->src_addr);
if (term_value->val == (ipaddr & term_value->mask))
return 1;
@@ -71,15 +72,15 @@ static inline int verify_pmr_ipv4_saddr(uint8_t *pkt_addr,
return 0;
}
-static inline int verify_pmr_ipv4_daddr(uint8_t *pkt_addr,
+static inline int verify_pmr_ipv4_daddr(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
- odph_ipv4hdr_t *ip;
+ const odph_ipv4hdr_t *ip;
uint32_t ipaddr;
if (!pkt_hdr->input_flags.ipv4)
return 0;
- ip = (odph_ipv4hdr_t *)(pkt_addr + pkt_hdr->l3_offset);
+ ip = (const odph_ipv4hdr_t *)(pkt_addr + pkt_hdr->l3_offset);
ipaddr = odp_be_to_cpu_32(ip->dst_addr);
if (term_value->val == (ipaddr & term_value->mask))
return 1;
@@ -87,15 +88,15 @@ static inline int verify_pmr_ipv4_daddr(uint8_t *pkt_addr,
return 0;
}
-static inline int verify_pmr_tcp_sport(uint8_t *pkt_addr,
+static inline int verify_pmr_tcp_sport(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
uint16_t sport;
- odph_tcphdr_t *tcp;
+ const odph_tcphdr_t *tcp;
if (!pkt_hdr->input_flags.tcp)
return 0;
- tcp = (odph_tcphdr_t *)(pkt_addr + pkt_hdr->l4_offset);
+ tcp = (const odph_tcphdr_t *)(pkt_addr + pkt_hdr->l4_offset);
sport = odp_be_to_cpu_16(tcp->src_port);
if (term_value->val == (sport & term_value->mask))
return 1;
@@ -103,15 +104,15 @@ static inline int verify_pmr_tcp_sport(uint8_t *pkt_addr,
return 0;
}
-static inline int verify_pmr_tcp_dport(uint8_t *pkt_addr,
+static inline int verify_pmr_tcp_dport(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
uint16_t dport;
- odph_tcphdr_t *tcp;
+ const odph_tcphdr_t *tcp;
if (!pkt_hdr->input_flags.tcp)
return 0;
- tcp = (odph_tcphdr_t *)(pkt_addr + pkt_hdr->l4_offset);
+ tcp = (const odph_tcphdr_t *)(pkt_addr + pkt_hdr->l4_offset);
dport = odp_be_to_cpu_16(tcp->dst_port);
if (term_value->val == (dport & term_value->mask))
return 1;
@@ -119,30 +120,32 @@ static inline int verify_pmr_tcp_dport(uint8_t *pkt_addr,
return 0;
}
-static inline int verify_pmr_udp_dport(uint8_t *pkt_addr,
+static inline int verify_pmr_udp_dport(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
uint16_t dport;
- odph_udphdr_t *udp;
+ const odph_udphdr_t *udp;
if (!pkt_hdr->input_flags.udp)
return 0;
- udp = (odph_udphdr_t *)(pkt_addr + pkt_hdr->l4_offset);
+ udp = (const odph_udphdr_t *)(pkt_addr + pkt_hdr->l4_offset);
dport = odp_be_to_cpu_16(udp->dst_port);
if (term_value->val == (dport & term_value->mask))
return 1;
return 0;
}
-static inline int verify_pmr_udp_sport(uint8_t *pkt_addr,
+
+static inline int verify_pmr_udp_sport(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
uint16_t sport;
- odph_udphdr_t *udp;
+ const odph_udphdr_t *udp;
+
if (!pkt_hdr->input_flags.udp)
return 0;
- udp = (odph_udphdr_t *)(pkt_addr + pkt_hdr->l4_offset);
+ udp = (const odph_udphdr_t *)(pkt_addr + pkt_hdr->l4_offset);
sport = odp_be_to_cpu_16(udp->src_port);
if (term_value->val == (sport & term_value->mask))
return 1;
@@ -150,7 +153,7 @@ static inline int verify_pmr_udp_sport(uint8_t *pkt_addr,
return 0;
}
-static inline int verify_pmr_dmac(uint8_t *pkt_addr ODP_UNUSED,
+static inline int verify_pmr_dmac(const uint8_t *pkt_addr ODP_UNUSED,
odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
pmr_term_value_t *term_value ODP_UNUSED)
{
@@ -158,28 +161,31 @@ static inline int verify_pmr_dmac(uint8_t *pkt_addr ODP_UNUSED,
return 0;
}
-static inline int verify_pmr_ipv6_saddr(uint8_t *pkt_addr ODP_UNUSED,
+static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr ODP_UNUSED,
odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
pmr_term_value_t *term_value ODP_UNUSED)
{
ODP_UNIMPLEMENTED();
return 0;
}
-static inline int verify_pmr_ipv6_daddr(uint8_t *pkt_addr ODP_UNUSED,
+
+static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr ODP_UNUSED,
odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
pmr_term_value_t *term_value ODP_UNUSED)
{
ODP_UNIMPLEMENTED();
return 0;
}
-static inline int verify_pmr_vlan_id_0(uint8_t *pkt_addr ODP_UNUSED,
+
+static inline int verify_pmr_vlan_id_0(const uint8_t *pkt_addr ODP_UNUSED,
odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
pmr_term_value_t *term_value ODP_UNUSED)
{
ODP_UNIMPLEMENTED();
return 0;
}
-static inline int verify_pmr_vlan_id_x(uint8_t *pkt_addr ODP_UNUSED,
+
+static inline int verify_pmr_vlan_id_x(const uint8_t *pkt_addr ODP_UNUSED,
odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
pmr_term_value_t *term_value ODP_UNUSED)
{
@@ -187,7 +193,7 @@ static inline int verify_pmr_vlan_id_x(uint8_t *pkt_addr ODP_UNUSED,
return 0;
}
-static inline int verify_pmr_ipsec_spi(uint8_t *pkt_addr,
+static inline int verify_pmr_ipsec_spi(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
@@ -199,11 +205,11 @@ static inline int verify_pmr_ipsec_spi(uint8_t *pkt_addr,
pkt_addr += pkt_hdr->l4_offset;
if (pkt_hdr->l4_protocol == ODPH_IPPROTO_AH) {
- odph_ahhdr_t *ahhdr = (odph_ahhdr_t *)pkt_addr;
+ const odph_ahhdr_t *ahhdr = (const odph_ahhdr_t *)pkt_addr;
spi = odp_be_to_cpu_32(ahhdr->spi);
} else if (pkt_hdr->l4_protocol == ODPH_IPPROTO_ESP) {
- odph_esphdr_t *esphdr = (odph_esphdr_t *)pkt_addr;
+ const odph_esphdr_t *esphdr = (const odph_esphdr_t *)pkt_addr;
spi = odp_be_to_cpu_32(esphdr->spi);
} else {
@@ -216,7 +222,7 @@ static inline int verify_pmr_ipsec_spi(uint8_t *pkt_addr,
return 0;
}
-static inline int verify_pmr_ld_vni(uint8_t *pkt_addr ODP_UNUSED,
+static inline int verify_pmr_ld_vni(const uint8_t *pkt_addr ODP_UNUSED,
odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
pmr_term_value_t *term_value ODP_UNUSED)
{
@@ -224,7 +230,7 @@ static inline int verify_pmr_ld_vni(uint8_t *pkt_addr ODP_UNUSED,
return 0;
}
-static inline int verify_pmr_custom_frame(uint8_t *pkt_addr,
+static inline int verify_pmr_custom_frame(const uint8_t *pkt_addr,
odp_packet_hdr_t *pkt_hdr,
pmr_term_value_t *term_value)
{
@@ -244,14 +250,15 @@ static inline int verify_pmr_custom_frame(uint8_t *pkt_addr,
return 0;
}
-static inline int verify_pmr_eth_type_0(uint8_t *pkt_addr ODP_UNUSED,
+static inline int verify_pmr_eth_type_0(const uint8_t *pkt_addr ODP_UNUSED,
odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
pmr_term_value_t *term_value ODP_UNUSED)
{
ODP_UNIMPLEMENTED();
return 0;
}
-static inline int verify_pmr_eth_type_x(uint8_t *pkt_addr ODP_UNUSED,
+
+static inline int verify_pmr_eth_type_x(const 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_classification_internal.h b/platform/linux-generic/include/odp_classification_internal.h
index 55932802c..1e8f291a6 100644
--- a/platform/linux-generic/include/odp_classification_internal.h
+++ b/platform/linux-generic/include/odp_classification_internal.h
@@ -40,8 +40,8 @@ with the PKTIO interface.
Returns the default cos if the packet does not match any PMR
Returns the error_cos if the packet has an error
**/
-cos_t *pktio_select_cos(pktio_entry_t *pktio, uint8_t *pkt_addr,
- odp_packet_hdr_t *pkt_hdr);
+cos_t *pktio_select_cos(pktio_entry_t *pktio, const uint8_t *pkt_addr,
+ odp_packet_hdr_t *pkt_hdr);
/**
@internal
@@ -51,7 +51,7 @@ Select a CoS for the given Packet based on QoS values
This function returns the COS object matching the L2 and L3 QoS
based on the l3_preference value of the pktio
**/
-cos_t *match_qos_cos(pktio_entry_t *entry, uint8_t *pkt_addr,
+cos_t *match_qos_cos(pktio_entry_t *entry, const uint8_t *pkt_addr,
odp_packet_hdr_t *hdr);
/**
Packet Classifier
@@ -59,8 +59,17 @@ Packet Classifier
Start function for Packet Classifier
This function calls Classifier module internal functions for a given packet and
enqueues the packet to specific Queue based on PMR and CoS selected.
+The packet is allocated from the pool associated with the CoS
**/
int packet_classifier(odp_pktio_t pktio, odp_packet_t pkt);
+
+/**
+@internal
+
+Same as packet classifier uses linux-generic internal pktio struct
+**/
+int _odp_packet_classifier(pktio_entry_t *entry, odp_packet_t pkt);
+
/**
Packet IO classifier init
@@ -78,7 +87,7 @@ This function gets called recursively to check the chained PMR Term value
with the packet.
**/
-cos_t *match_pmr_cos(cos_t *cos, uint8_t *pkt_addr, pmr_t *pmr,
+cos_t *match_pmr_cos(cos_t *cos, const uint8_t *pkt_addr, pmr_t *pmr,
odp_packet_hdr_t *hdr);
/**
@internal
@@ -86,7 +95,7 @@ CoS associated with L3 QoS value
This function returns the CoS associated with L3 QoS value
**/
-cos_t *match_qos_l3_cos(pmr_l3_cos_t *l3_cos, uint8_t *pkt_addr,
+cos_t *match_qos_l3_cos(pmr_l3_cos_t *l3_cos, const uint8_t *pkt_addr,
odp_packet_hdr_t *hdr);
/**
@@ -95,7 +104,7 @@ CoS associated with L2 QoS value
This function returns the CoS associated with L2 QoS value
**/
-cos_t *match_qos_l2_cos(pmr_l2_cos_t *l2_cos, uint8_t *pkt_addr,
+cos_t *match_qos_l2_cos(pmr_l2_cos_t *l2_cos, const uint8_t *pkt_addr,
odp_packet_hdr_t *hdr);
/**
@internal
@@ -165,7 +174,7 @@ This function goes through each PMR_TERM value in pmr_t structure and
calls verification function for each term.Returns 1 if PMR matches or 0
Otherwise.
**/
-int verify_pmr(pmr_t *pmr, uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr);
+int verify_pmr(pmr_t *pmr, const uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr);
#ifdef __cplusplus
}
diff --git a/platform/linux-generic/include/odp_cpu_internal.h b/platform/linux-generic/include/odp_cpu_internal.h
deleted file mode 100644
index 664e2df5d..000000000
--- a/platform/linux-generic/include/odp_cpu_internal.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* 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 c2, uint64_t c1)
-{
- 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_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h
index b9128a426..7b104afa8 100644
--- a/platform/linux-generic/include/odp_crypto_internal.h
+++ b/platform/linux-generic/include/odp_crypto_internal.h
@@ -50,6 +50,9 @@ struct odp_crypto_generic_session {
struct {
AES_KEY key;
} aes;
+ struct {
+ EVP_CIPHER_CTX *ctx;
+ } aes_gcm;
} data;
crypto_func_t func;
} cipher;
diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h
index 010b82f1f..113b7004d 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -77,6 +77,8 @@ int odp_schedule_term_local(void);
int odp_timer_init_global(void);
int odp_timer_disarm_all(void);
+int odp_time_global_init(void);
+
void _odp_flush_caches(void);
#ifdef __cplusplus
diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h
index 6f1521ca3..12e9cca10 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -28,6 +28,8 @@ extern "C" {
#include <odp/crypto.h>
#include <odp_crypto_internal.h>
+#define PACKET_JUMBO_LEN (9 * 1024)
+
/**
* Packet input & protocol flags
*/
@@ -243,7 +245,7 @@ void packet_parse_l2(odp_packet_hdr_t *pkt_hdr);
int packet_parse_full(odp_packet_hdr_t *pkt_hdr);
/* Reset parser metadata for a new parse */
-void packet_parse_reset(odp_packet_t pkt);
+void packet_parse_reset(odp_packet_hdr_t *pkt_hdr);
/* Convert a packet handle to a buffer handle */
odp_buffer_t _odp_packet_to_buffer(odp_packet_t pkt);
@@ -251,6 +253,10 @@ odp_buffer_t _odp_packet_to_buffer(odp_packet_t pkt);
/* Convert a buffer handle to a packet handle */
odp_packet_t _odp_packet_from_buffer(odp_buffer_t buf);
+int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr);
+
+int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr);
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h
index de295578f..4d739528d 100644
--- a/platform/linux-generic/include/odp_packet_io_internal.h
+++ b/platform/linux-generic/include/odp_packet_io_internal.h
@@ -88,6 +88,7 @@ struct pktio_entry {
classifier_t cls; /**< classifier linked with this pktio*/
char name[PKTIO_NAME_LEN]; /**< name of pktio provided to
pktio_open() */
+ odp_pktio_t id;
odp_pktio_param_t param;
};
@@ -119,6 +120,9 @@ typedef struct pktio_if_ops {
int (*mac_get)(pktio_entry_t *pktio_entry, void *mac_addr);
} pktio_if_ops_t;
+int _odp_packet_cls_enq(pktio_entry_t *pktio_entry, const uint8_t *base,
+ uint16_t buf_len, odp_packet_t *pkt_ret);
+
extern void *pktio_entry_ptr[];
static inline int pktio_to_id(odp_pktio_t pktio)
diff --git a/platform/linux-generic/include/odp_packet_socket.h b/platform/linux-generic/include/odp_packet_socket.h
index a5e0eb381..1eaafb7e5 100644
--- a/platform/linux-generic/include/odp_packet_socket.h
+++ b/platform/linux-generic/include/odp_packet_socket.h
@@ -44,6 +44,8 @@ typedef struct {
int sockfd; /**< socket descriptor */
odp_pool_t pool; /**< pool to alloc packets from */
unsigned char if_mac[ETH_ALEN]; /**< IF eth mac addr */
+ uint8_t *cache_ptr[ODP_PACKET_SOCKET_MAX_BURST_RX];
+ odp_shm_t shm;
} pkt_sock_t;
/** packet mmap ring */
diff --git a/platform/linux-generic/include/odp_pool_internal.h b/platform/linux-generic/include/odp_pool_internal.h
index 94bf1faee..b12bca8f6 100644
--- a/platform/linux-generic/include/odp_pool_internal.h
+++ b/platform/linux-generic/include/odp_pool_internal.h
@@ -29,6 +29,7 @@ extern "C" {
#include <odp/shared_memory.h>
#include <odp/atomic.h>
#include <odp_atomic_internal.h>
+#include <odp/thread.h>
#include <string.h>
/**
@@ -139,7 +140,7 @@ struct pool_entry_s {
uint32_t headroom;
uint32_t tailroom;
- local_cache_t local_cache[_ODP_INTERNAL_MAX_THREADS] ODP_ALIGNED_CACHE;
+ local_cache_t local_cache[ODP_THREAD_COUNT_MAX] ODP_ALIGNED_CACHE;
};
typedef union pool_entry_u {
diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c
index 1b6d5931a..da195ad8b 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -154,9 +154,32 @@ int odp_classification_term_global(void)
return rc;
}
-odp_cos_t odp_cos_create(const char *name)
+void odp_cls_cos_param_init(odp_cls_cos_param_t *param)
+{
+ param->queue = ODP_QUEUE_INVALID;
+ param->pool = ODP_POOL_INVALID;
+ param->drop_policy = ODP_COS_DROP_NEVER;
+}
+
+odp_cos_t odp_cls_cos_create(const char *name, odp_cls_cos_param_t *param)
{
int i;
+ queue_entry_t *queue;
+ pool_entry_t *pool;
+ odp_cls_drop_t drop_policy;
+
+ /* Packets are dropped if Queue or Pool is invalid*/
+ if (param->queue == ODP_QUEUE_INVALID)
+ queue = NULL;
+ else
+ queue = queue_to_qentry(param->queue);
+
+ if (param->pool == ODP_POOL_INVALID)
+ pool = NULL;
+ else
+ pool = odp_pool_to_entry(param->pool);
+
+ drop_policy = param->drop_policy;
for (i = 0; i < ODP_COS_MAX_ENTRY; i++) {
LOCK(&cos_tbl->cos_entry[i].s.lock);
@@ -166,16 +189,18 @@ odp_cos_t odp_cos_create(const char *name)
cos_tbl->cos_entry[i].s.name[ODP_COS_NAME_LEN - 1] = 0;
cos_tbl->cos_entry[i].s.pmr = NULL;
cos_tbl->cos_entry[i].s.linked_cos = NULL;
- cos_tbl->cos_entry[i].s.queue = NULL;
- cos_tbl->cos_entry[i].s.pool = NULL;
+ cos_tbl->cos_entry[i].s.queue = queue;
+ cos_tbl->cos_entry[i].s.pool = pool;
cos_tbl->cos_entry[i].s.flow_set = 0;
cos_tbl->cos_entry[i].s.headroom = 0;
cos_tbl->cos_entry[i].s.valid = 1;
+ cos_tbl->cos_entry[i].s.drop_policy = drop_policy;
UNLOCK(&cos_tbl->cos_entry[i].s.lock);
return _odp_cast_scalar(odp_cos_t, i);
}
UNLOCK(&cos_tbl->cos_entry[i].s.lock);
}
+
ODP_ERR("ODP_COS_MAX_ENTRY reached");
return ODP_COS_INVALID;
}
@@ -274,8 +299,10 @@ int odp_cos_queue_set(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;
+ if (queue_id == ODP_QUEUE_INVALID)
+ cos->s.queue = NULL;
+ else
+ cos->s.queue = queue_to_qentry(queue_id);
return 0;
}
@@ -288,10 +315,13 @@ odp_queue_t odp_cos_queue(odp_cos_t cos_id)
return ODP_QUEUE_INVALID;
}
- return cos->s.queue_id;
+ if (!cos->s.queue)
+ return ODP_QUEUE_INVALID;
+
+ return cos->s.queue->s.handle;
}
-int odp_cos_drop_set(odp_cos_t cos_id, odp_drop_e drop_policy)
+int odp_cos_drop_set(odp_cos_t cos_id, odp_cls_drop_t drop_policy)
{
cos_t *cos = get_cos_entry(cos_id);
@@ -305,7 +335,7 @@ int odp_cos_drop_set(odp_cos_t cos_id, odp_drop_e drop_policy)
return 0;
}
-odp_drop_e odp_cos_drop(odp_cos_t cos_id)
+odp_cls_drop_t odp_cos_drop(odp_cos_t cos_id)
{
cos_t *cos = get_cos_entry(cos_id);
@@ -661,7 +691,41 @@ int odp_pktio_pmr_match_set_cos(odp_pmr_set_t pmr_set_id, odp_pktio_t src_pktio,
return 0;
}
-int verify_pmr(pmr_t *pmr, uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr)
+int odp_cls_cos_pool_set(odp_cos_t cos_id, odp_pool_t pool_id)
+{
+ cos_t *cos;
+
+ cos = get_cos_entry(cos_id);
+ if (cos == NULL) {
+ ODP_ERR("Invalid odp_cos_t handle");
+ return -1;
+ }
+
+ if (pool_id == ODP_POOL_INVALID)
+ cos->s.pool = NULL;
+ else
+ cos->s.pool = odp_pool_to_entry(pool_id);
+
+ return 0;
+}
+
+odp_pool_t odp_cls_cos_pool(odp_cos_t cos_id)
+{
+ cos_t *cos;
+
+ cos = get_cos_entry(cos_id);
+ if (cos == NULL) {
+ ODP_ERR("Invalid odp_cos_t handle");
+ return ODP_POOL_INVALID;
+ }
+
+ if (!cos->s.pool)
+ return ODP_POOL_INVALID;
+
+ return cos->s.pool->s.pool_hdl;
+}
+
+int verify_pmr(pmr_t *pmr, const uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr)
{
int pmr_failure = 0;
int num_pmr;
@@ -779,7 +843,7 @@ int verify_pmr(pmr_t *pmr, uint8_t *pkt_addr, odp_packet_hdr_t *pkt_hdr)
return true;
}
-cos_t *match_pmr_cos(cos_t *cos, uint8_t *pkt_addr, pmr_t *pmr,
+cos_t *match_pmr_cos(cos_t *cos, const uint8_t *pkt_addr, pmr_t *pmr,
odp_packet_hdr_t *hdr)
{
cos_t *retcos = NULL;
@@ -824,15 +888,14 @@ int pktio_classifier_init(pktio_entry_t *entry)
return 0;
}
-int packet_classifier(odp_pktio_t pktio, odp_packet_t pkt)
+int _odp_packet_classifier(pktio_entry_t *entry, odp_packet_t pkt)
{
- pktio_entry_t *entry;
queue_entry_t *queue;
cos_t *cos;
odp_packet_hdr_t *pkt_hdr;
+ odp_packet_t new_pkt;
uint8_t *pkt_addr;
- entry = get_pktio_entry(pktio);
if (entry == NULL)
return -1;
@@ -844,13 +907,42 @@ int packet_classifier(odp_pktio_t pktio, odp_packet_t pkt)
if (cos == NULL)
return -1;
+ if (cos->s.pool == NULL) {
+ odp_packet_free(pkt);
+ return -1;
+ }
+
+ if (cos->s.queue == NULL) {
+ odp_packet_free(pkt);
+ return -1;
+ }
+
+ if (odp_packet_pool(pkt) != cos->s.pool->s.pool_hdl) {
+ new_pkt = odp_packet_copy(pkt, cos->s.pool->s.pool_hdl);
+ odp_packet_free(pkt);
+ if (new_pkt == ODP_PACKET_INVALID)
+ return -1;
+ } else {
+ new_pkt = pkt;
+ }
+
/* Enqueuing the Packet based on the CoS */
queue = cos->s.queue;
- return queue_enq(queue, odp_buf_to_hdr((odp_buffer_t)pkt), 0);
+ return queue_enq(queue, odp_buf_to_hdr((odp_buffer_t)new_pkt), 0);
+}
+
+int packet_classifier(odp_pktio_t pktio, odp_packet_t pkt)
+{
+ pktio_entry_t *entry;
+
+ entry = get_pktio_entry(pktio);
+ if (entry == NULL)
+ return -1;
+ return _odp_packet_classifier(entry, pkt);
}
-cos_t *pktio_select_cos(pktio_entry_t *entry, uint8_t *pkt_addr,
- odp_packet_hdr_t *pkt_hdr)
+cos_t *pktio_select_cos(pktio_entry_t *entry, const uint8_t *pkt_addr,
+ odp_packet_hdr_t *pkt_hdr)
{
pmr_t *pmr;
cos_t *cos;
@@ -882,20 +974,20 @@ cos_t *pktio_select_cos(pktio_entry_t *entry, uint8_t *pkt_addr,
return cls->default_cos;
}
-cos_t *match_qos_l3_cos(pmr_l3_cos_t *l3_cos, uint8_t *pkt_addr,
+cos_t *match_qos_l3_cos(pmr_l3_cos_t *l3_cos, const uint8_t *pkt_addr,
odp_packet_hdr_t *hdr)
{
uint8_t dscp;
cos_t *cos = NULL;
- odph_ipv4hdr_t *ipv4;
- odph_ipv6hdr_t *ipv6;
+ const odph_ipv4hdr_t *ipv4;
+ const odph_ipv6hdr_t *ipv6;
if (hdr->input_flags.l3 && hdr->input_flags.ipv4) {
- ipv4 = (odph_ipv4hdr_t *)(pkt_addr + hdr->l3_offset);
+ ipv4 = (const odph_ipv4hdr_t *)(pkt_addr + hdr->l3_offset);
dscp = ODPH_IPV4HDR_DSCP(ipv4->tos);
cos = l3_cos->cos[dscp];
} else if (hdr->input_flags.l3 && hdr->input_flags.ipv6) {
- ipv6 = (odph_ipv6hdr_t *)(pkt_addr + hdr->l3_offset);
+ ipv6 = (const odph_ipv6hdr_t *)(pkt_addr + hdr->l3_offset);
dscp = ODPH_IPV6HDR_DSCP(ipv6->ver_tc_flow);
cos = l3_cos->cos[dscp];
}
@@ -903,18 +995,18 @@ cos_t *match_qos_l3_cos(pmr_l3_cos_t *l3_cos, uint8_t *pkt_addr,
return cos;
}
-cos_t *match_qos_l2_cos(pmr_l2_cos_t *l2_cos, uint8_t *pkt_addr,
+cos_t *match_qos_l2_cos(pmr_l2_cos_t *l2_cos, const uint8_t *pkt_addr,
odp_packet_hdr_t *hdr)
{
cos_t *cos = NULL;
- odph_ethhdr_t *eth;
- odph_vlanhdr_t *vlan;
+ const odph_ethhdr_t *eth;
+ const odph_vlanhdr_t *vlan;
uint16_t qos;
if (hdr->input_flags.l2 && hdr->input_flags.vlan &&
hdr->input_flags.eth) {
- eth = (odph_ethhdr_t *)(pkt_addr + hdr->l2_offset);
- vlan = (odph_vlanhdr_t *)(&eth->type);
+ eth = (const odph_ethhdr_t *)(pkt_addr + hdr->l2_offset);
+ vlan = (const odph_vlanhdr_t *)(&eth->type);
qos = odp_be_to_cpu_16(vlan->tci);
qos = ((qos >> 13) & 0x07);
cos = l2_cos->cos[qos];
@@ -922,7 +1014,7 @@ cos_t *match_qos_l2_cos(pmr_l2_cos_t *l2_cos, uint8_t *pkt_addr,
return cos;
}
-cos_t *match_qos_cos(pktio_entry_t *entry, uint8_t *pkt_addr,
+cos_t *match_qos_cos(pktio_entry_t *entry, const uint8_t *pkt_addr,
odp_packet_hdr_t *hdr)
{
classifier_t *cls = &entry->s.cls;
diff --git a/platform/linux-generic/odp_cpu.c b/platform/linux-generic/odp_cpu.c
index 636f811f8..4bd6a9a07 100644
--- a/platform/linux-generic/odp_cpu.c
+++ b/platform/linux-generic/odp_cpu.c
@@ -6,9 +6,11 @@
#include <odp/cpu.h>
#include <odp/hints.h>
-#include <odp_cpu_internal.h>
uint64_t odp_cpu_cycles_diff(uint64_t c2, uint64_t c1)
{
- return _odp_cpu_cycles_diff(c2, c1);
+ if (odp_likely(c2 >= c1))
+ return c2 - c1;
+
+ return c2 + (odp_cpu_cycles_max() - c1) + 1;
}
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index 17fced930..65e850343 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -292,6 +292,170 @@ int process_aes_params(odp_crypto_generic_session_t *session,
}
static
+odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_params_t *params,
+ odp_crypto_generic_session_t *session)
+{
+ uint8_t *data = odp_packet_data(params->out_pkt);
+ uint32_t plain_len = params->cipher_range.length;
+ uint8_t *aad_head = data + params->auth_range.offset;
+ uint8_t *aad_tail = data + params->cipher_range.offset +
+ params->cipher_range.length;
+ uint32_t auth_len = params->auth_range.length;
+ unsigned char iv_enc[AES_BLOCK_SIZE];
+ void *iv_ptr;
+ uint8_t *tag = data + params->hash_result_offset;
+
+ if (params->override_iv_ptr)
+ iv_ptr = params->override_iv_ptr;
+ else if (session->cipher.iv.data)
+ iv_ptr = session->cipher.iv.data;
+ else
+ return ODP_CRYPTO_ALG_ERR_IV_INVALID;
+
+ /* All cipher data must be part of the authentication */
+ if (params->auth_range.offset > params->cipher_range.offset ||
+ params->auth_range.offset + auth_len <
+ params->cipher_range.offset + plain_len)
+ return ODP_CRYPTO_ALG_ERR_DATA_SIZE;
+
+ /*
+ * Create a copy of the IV. The DES library modifies IV
+ * and if we are processing packets on parallel threads
+ * we could get corruption.
+ */
+ memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE);
+
+ /* Adjust pointer for beginning of area to cipher/auth */
+ uint8_t *plaindata = data + params->cipher_range.offset;
+
+ /* Encrypt it */
+ EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx;
+ int cipher_len = 0;
+
+ EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_enc);
+
+ /* Authenticate header data (if any) without encrypting them */
+ if (aad_head < plaindata) {
+ EVP_EncryptUpdate(ctx, NULL, &cipher_len,
+ aad_head, plaindata - aad_head);
+ }
+
+ EVP_EncryptUpdate(ctx, plaindata, &cipher_len,
+ plaindata, plain_len);
+ cipher_len = plain_len;
+
+ /* Authenticate footer data (if any) without encrypting them */
+ if (aad_head + auth_len > plaindata + plain_len) {
+ EVP_EncryptUpdate(ctx, NULL, NULL, aad_tail,
+ auth_len - (aad_tail - aad_head));
+ }
+
+ EVP_EncryptFinal_ex(ctx, plaindata + cipher_len, &cipher_len);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag);
+
+ return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_params_t *params,
+ odp_crypto_generic_session_t *session)
+{
+ uint8_t *data = odp_packet_data(params->out_pkt);
+ uint32_t cipher_len = params->cipher_range.length;
+ uint8_t *aad_head = data + params->auth_range.offset;
+ uint8_t *aad_tail = data + params->cipher_range.offset +
+ params->cipher_range.length;
+ uint32_t auth_len = params->auth_range.length;
+ unsigned char iv_enc[AES_BLOCK_SIZE];
+ void *iv_ptr;
+ uint8_t *tag = data + params->hash_result_offset;
+
+ if (params->override_iv_ptr)
+ iv_ptr = params->override_iv_ptr;
+ else if (session->cipher.iv.data)
+ iv_ptr = session->cipher.iv.data;
+ else
+ return ODP_CRYPTO_ALG_ERR_IV_INVALID;
+
+ /* All cipher data must be part of the authentication */
+ if (params->auth_range.offset > params->cipher_range.offset ||
+ params->auth_range.offset + auth_len <
+ params->cipher_range.offset + cipher_len)
+ return ODP_CRYPTO_ALG_ERR_DATA_SIZE;
+
+ /*
+ * Create a copy of the IV. The DES library modifies IV
+ * and if we are processing packets on parallel threads
+ * we could get corruption.
+ */
+ memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE);
+
+ /* Adjust pointer for beginning of area to cipher/auth */
+ uint8_t *cipherdata = data + params->cipher_range.offset;
+ /* Encrypt it */
+ EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx;
+ int plain_len = 0;
+
+ EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_enc);
+
+ /* Authenticate header data (if any) without encrypting them */
+ if (aad_head < cipherdata) {
+ EVP_DecryptUpdate(ctx, NULL, &plain_len,
+ aad_head, cipherdata - aad_head);
+ }
+
+ EVP_DecryptUpdate(ctx, cipherdata, &plain_len,
+ cipherdata, cipher_len);
+ plain_len = cipher_len;
+
+ /* Authenticate footer data (if any) without encrypting them */
+ if (aad_head + auth_len > cipherdata + cipher_len) {
+ EVP_DecryptUpdate(ctx, NULL, NULL, aad_tail,
+ auth_len - (aad_tail - aad_head));
+ }
+
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag);
+
+ if (EVP_DecryptFinal_ex(ctx, cipherdata + cipher_len, &plain_len) < 0)
+ return ODP_CRYPTO_ALG_ERR_ICV_CHECK;
+
+ return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+int process_aes_gcm_params(odp_crypto_generic_session_t *session,
+ odp_crypto_session_params_t *params)
+{
+ /* Verify Key len is 16 */
+ if (params->cipher_key.length != 16)
+ return -1;
+
+ /* Set function */
+ EVP_CIPHER_CTX *ctx =
+ session->cipher.data.aes_gcm.ctx = EVP_CIPHER_CTX_new();
+
+ if (ODP_CRYPTO_OP_ENCODE == params->op) {
+ session->cipher.func = aes_gcm_encrypt;
+ EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
+ } else {
+ session->cipher.func = aes_gcm_decrypt;
+ EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
+ }
+
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
+ params->iv.length, NULL);
+ if (ODP_CRYPTO_OP_ENCODE == params->op) {
+ EVP_EncryptInit_ex(ctx, NULL, NULL,
+ params->cipher_key.data, NULL);
+ } else {
+ EVP_DecryptInit_ex(ctx, NULL, NULL,
+ params->cipher_key.data, NULL);
+ }
+
+ return 0;
+}
+
+static
odp_crypto_alg_err_t des_encrypt(odp_crypto_op_params_t *params,
odp_crypto_generic_session_t *session)
{
@@ -479,6 +643,15 @@ odp_crypto_session_create(odp_crypto_session_params_t *params,
case ODP_CIPHER_ALG_AES128_CBC:
rc = process_aes_params(session, params);
break;
+ case ODP_CIPHER_ALG_AES128_GCM:
+ /* AES-GCM requires to do both auth and
+ * cipher at the same time */
+ if (params->auth_alg != ODP_AUTH_ALG_AES128_GCM) {
+ rc = -1;
+ break;
+ }
+ rc = process_aes_gcm_params(session, params);
+ break;
default:
rc = -1;
}
@@ -501,6 +674,16 @@ odp_crypto_session_create(odp_crypto_session_params_t *params,
case ODP_AUTH_ALG_SHA256_128:
rc = process_sha256_params(session, params, 128);
break;
+ case ODP_AUTH_ALG_AES128_GCM:
+ /* AES-GCM requires to do both auth and
+ * cipher at the same time */
+ if (params->cipher_alg != ODP_CIPHER_ALG_AES128_GCM) {
+ rc = -1;
+ break;
+ }
+ session->auth.func = null_crypto_routine;
+ rc = 0;
+ break;
default:
rc = -1;
}
diff --git a/platform/linux-generic/odp_hash.c b/platform/linux-generic/odp_hash.c
new file mode 100644
index 000000000..6bee4ef6c
--- /dev/null
+++ b/platform/linux-generic/odp_hash.c
@@ -0,0 +1,487 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <odp/hash.h>
+#include <odp/std_types.h>
+
+static const uint32_t crc32c_tables[8][256] = {{
+ 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C,
+ 0x26A1E7E8, 0xD4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
+ 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 0x105EC76F, 0xE235446C,
+ 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
+ 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC,
+ 0xBC267848, 0x4E4DFB4B, 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
+ 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 0xAA64D611, 0x580F5512,
+ 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
+ 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD,
+ 0x1642AE59, 0xE4292D5A, 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
+ 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, 0xB3109EBF,
+ 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
+ 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F,
+ 0xED03A29B, 0x1F682198, 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
+ 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0xDBFC821C, 0x2997011F,
+ 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
+ 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E,
+ 0x4767748A, 0xB50CF789, 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
+ 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E,
+ 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
+ 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE,
+ 0xDDE0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
+ 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 0x082F63B7, 0xFA44E0B4,
+ 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
+ 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B,
+ 0xB4091BFF, 0x466298FC, 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
+ 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 0xA24BB5A6, 0x502036A5,
+ 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
+ 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975,
+ 0x0E330A81, 0xFC588982, 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
+ 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0xCAA7A905,
+ 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
+ 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8,
+ 0xE52CC12C, 0x1747422F, 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
+ 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0xD3D3E1AB, 0x21B862A8,
+ 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
+ 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78,
+ 0x7FAB5E8C, 0x8DC0DD8F, 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
+ 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6,
+ 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
+ 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69,
+ 0xD5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
+ 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
+},
+{
+ 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB,
+ 0x69CF5132, 0x7A6DC945, 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21,
+ 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, 0x3FC5F181, 0x2C6769F6,
+ 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4,
+ 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92,
+ 0xCB1E630B, 0xD8BCFB7C, 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B,
+ 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, 0xE29F20BA, 0xF13DB8CD,
+ 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF,
+ 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28,
+ 0x298143B1, 0x3A23DBC6, 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2,
+ 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, 0xFF17C604, 0xECB55E73,
+ 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41,
+ 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17,
+ 0x0BCC548E, 0x186ECCF9, 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C,
+ 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, 0x5DC6F43D, 0x4E646C4A,
+ 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78,
+ 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD,
+ 0xE9537434, 0xFAF1EC43, 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27,
+ 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, 0xBF59D487, 0xACFB4CF0,
+ 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2,
+ 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94,
+ 0x4B82460D, 0x5820DE7A, 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260,
+ 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, 0x66D73941, 0x7575A136,
+ 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004,
+ 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3,
+ 0xADC95A4A, 0xBE6BC23D, 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059,
+ 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, 0x844819FB, 0x97EA818C,
+ 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE,
+ 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8,
+ 0x70938B71, 0x63311306, 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3,
+ 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, 0x26992BC2, 0x353BB3B5,
+ 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287,
+ 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556,
+ 0x6D1B6DCF, 0x7EB9F5B8, 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC,
+ 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, 0x3B11CD7C, 0x28B3550B,
+ 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439,
+ 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F,
+ 0xCFCA5FF6, 0xDC68C781, 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766,
+ 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, 0xE64B1C47, 0xF5E98430,
+ 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502,
+ 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5,
+ 0x2D557F4C, 0x3EF7E73B, 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F,
+ 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483,
+},
+{
+ 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664,
+ 0xD1B1F617, 0x74F06469, 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6,
+ 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, 0x70A27D8A, 0xD5E3EFF4,
+ 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3,
+ 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, 0x736C752B,
+ 0x9942B558, 0x3C032726, 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67,
+ 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, 0xD915C5D1, 0x7C5457AF,
+ 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8,
+ 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, 0xAA79B0FA,
+ 0x40577089, 0xE516E2F7, 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828,
+ 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, 0xC76580D9, 0x622412A7,
+ 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0,
+ 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, 0xC4AB8878,
+ 0x2E85480B, 0x8BC4DA75, 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20,
+ 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, 0x8F96C396, 0x2AD751E8,
+ 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF,
+ 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, 0x1DBE4DA9,
+ 0xF7908DDA, 0x52D11FA4, 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B,
+ 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, 0x56830647, 0xF3C29439,
+ 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E,
+ 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, 0x554D0EE6,
+ 0xBF63CE95, 0x1A225CEB, 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730,
+ 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, 0xB3764986, 0x1637DBF8,
+ 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF,
+ 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, 0xC01A3CAD,
+ 0x2A34FCDE, 0x8F756EA0, 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F,
+ 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, 0x6A638C57, 0xCF221E29,
+ 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E,
+ 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, 0x69AD84F6,
+ 0x83834485, 0x26C2D6FB, 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE,
+ 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, 0x2290CF18, 0x87D15D66,
+ 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71,
+ 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, 0x77DDC1FE,
+ 0x9DF3018D, 0x38B293F3, 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C,
+ 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, 0x3CE08A10, 0x99A1186E,
+ 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79,
+ 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, 0x3F2E82B1,
+ 0xD50042C2, 0x7041D0BC, 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD,
+ 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, 0x9557324B, 0x3016A035,
+ 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622,
+ 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, 0xE63B4760,
+ 0x0C158713, 0xA954156D, 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2,
+ 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8,
+},
+{
+ 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B,
+ 0xC4451272, 0x1900B8CA, 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF,
+ 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, 0xE964B13D, 0x34211B85,
+ 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7,
+ 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, 0xB9474990,
+ 0xDB65C0A9, 0x06206A11, 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2,
+ 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, 0x2161776D, 0xFC24DDD5,
+ 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7,
+ 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, 0x98263EFD,
+ 0xFA04B7C4, 0x27411D7C, 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69,
+ 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, 0xABA65FE7, 0x76E3F55F,
+ 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D,
+ 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, 0xFB85A74A,
+ 0x99A72E73, 0x44E284CB, 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3,
+ 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, 0xB4868D3C, 0x69C32784,
+ 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6,
+ 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, 0xDAE4D027,
+ 0xB8C6591E, 0x6583F3A6, 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3,
+ 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, 0x95E7FA51, 0x48A250E9,
+ 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B,
+ 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, 0xC5C402FC,
+ 0xA7E68BC5, 0x7AA3217D, 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006,
+ 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, 0xA4E4AAD9, 0x79A10061,
+ 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213,
+ 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, 0x1DA3E349,
+ 0x7F816A70, 0xA2C4C0C8, 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD,
+ 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, 0x8585DDB4, 0x58C0770C,
+ 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E,
+ 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, 0xD5A62519,
+ 0xB784AC20, 0x6AC10698, 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0,
+ 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, 0x9AA50F6F, 0x47E0A5D7,
+ 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5,
+ 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, 0x5F610D93,
+ 0x3D4384AA, 0xE0062E12, 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07,
+ 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, 0x106227E5, 0xCD278D5D,
+ 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F,
+ 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, 0x4041DF48,
+ 0x22635671, 0xFF26FCC9, 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A,
+ 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, 0xD867E1B5, 0x05224B0D,
+ 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F,
+ 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, 0x6120A825,
+ 0x0302211C, 0xDE478BA4, 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1,
+ 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842,
+},
+{
+ 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, 0xD854D11C,
+ 0x906761E8, 0xA8760E44, 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65,
+ 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5, 0x8F2261D3, 0xB7330E7F,
+ 0xFF00BE8B, 0xC711D127, 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97,
+ 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, 0xAA00D4F2, 0x9211BB5E,
+ 0xDA220BAA, 0xE2336406, 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3,
+ 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13, 0xDECFBEC6, 0xE6DED16A,
+ 0xAEED619E, 0x96FC0E32, 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082,
+ 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, 0x74CF6A34, 0x4CDE0598,
+ 0x04EDB56C, 0x3CFCDAC0, 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1,
+ 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151, 0x37516AAE, 0x0F400502,
+ 0x4773B5F6, 0x7F62DA5A, 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA,
+ 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, 0x1273DF8F, 0x2A62B023,
+ 0x625100D7, 0x5A406F7B, 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89,
+ 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539, 0x7D1400EC, 0x45056F40,
+ 0x0D36DFB4, 0x3527B018, 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8,
+ 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, 0xCCBC6149, 0xF4AD0EE5,
+ 0xBC9EBE11, 0x848FD1BD, 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C,
+ 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C, 0xA3DBBE2A, 0x9BCAD186,
+ 0xD3F96172, 0xEBE80EDE, 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E,
+ 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, 0x86F90B0B, 0xBEE864A7,
+ 0xF6DBD453, 0xCECABBFF, 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8,
+ 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18, 0xABC5DECD, 0x93D4B161,
+ 0xDBE70195, 0xE3F66E39, 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089,
+ 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, 0x01C50A3F, 0x39D46593,
+ 0x71E7D567, 0x49F6BACB, 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA,
+ 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A, 0x750A600B, 0x4D1B0FA7,
+ 0x0528BF53, 0x3D39D0FF, 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F,
+ 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, 0x5028D52A, 0x6839BA86,
+ 0x200A0A72, 0x181B65DE, 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C,
+ 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C, 0x3F4F0A49, 0x075E65E5,
+ 0x4F6DD511, 0x777CBABD, 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D,
+ 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, 0xB9B60142, 0x81A76EEE,
+ 0xC994DE1A, 0xF185B1B6, 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497,
+ 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27, 0xD6D1DE21, 0xEEC0B18D,
+ 0xA6F30179, 0x9EE26ED5, 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065,
+ 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, 0xF3F36B00, 0xCBE204AC,
+ 0x83D1B458, 0xBBC0DBF4, 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51,
+ 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1, 0x873C0134, 0xBF2D6E98,
+ 0xF71EDE6C, 0xCF0FB1C0, 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70,
+ 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, 0x2D3CD5C6, 0x152DBA6A,
+ 0x5D1E0A9E, 0x650F6532, 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013,
+ 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3,
+},
+{
+ 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, 0x5DC55C6E,
+ 0x697997B4, 0x8649FCAD, 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5,
+ 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2, 0xC00C303E, 0x2F3C5B27,
+ 0x1B8090FD, 0xF4B0FBE4, 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93,
+ 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, 0x12FF1F56, 0xFDCF744F,
+ 0xC973BF95, 0x2643D48C, 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57,
+ 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20, 0xE5F20E92, 0x0AC2658B,
+ 0x3E7EAE51, 0xD14EC548, 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F,
+ 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, 0xF70D11C4, 0x183D7ADD,
+ 0x2C81B107, 0xC3B1DA1E, 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576,
+ 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201, 0x0E045BEB, 0xE13430F2,
+ 0xD588FB28, 0x3AB89031, 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746,
+ 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, 0xDCF77483, 0x33C71F9A,
+ 0x077BD440, 0xE84BBF59, 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F,
+ 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778, 0xAE0E73CA, 0x413E18D3,
+ 0x7582D309, 0x9AB2B810, 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67,
+ 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, 0x39057A11, 0xD6351108,
+ 0xE289DAD2, 0x0DB9B1CB, 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3,
+ 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4, 0x4BFC7D58, 0xA4CC1641,
+ 0x9070DD9B, 0x7F40B682, 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5,
+ 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, 0x990F5230, 0x763F3929,
+ 0x4283F2F3, 0xADB399EA, 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C,
+ 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B, 0x7C0EAFC9, 0x933EC4D0,
+ 0xA7820F0A, 0x48B26413, 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364,
+ 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, 0x6EF1B09F, 0x81C1DB86,
+ 0xB57D105C, 0x5A4D7B45, 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D,
+ 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A, 0x99FCA15B, 0x76CCCA42,
+ 0x42700198, 0xAD406A81, 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6,
+ 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, 0x4B0F8E33, 0xA43FE52A,
+ 0x90832EF0, 0x7FB345E9, 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF,
+ 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8, 0x39F6897A, 0xD6C6E263,
+ 0xE27A29B9, 0x0D4A42A0, 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7,
+ 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, 0xA0F9DB4A, 0x4FC9B053,
+ 0x7B757B89, 0x94451090, 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8,
+ 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F, 0xD200DC03, 0x3D30B71A,
+ 0x098C7CC0, 0xE6BC17D9, 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE,
+ 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, 0x00F3F36B, 0xEFC39872,
+ 0xDB7F53A8, 0x344F38B1, 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A,
+ 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D, 0xF7FEE2AF, 0x18CE89B6,
+ 0x2C72426C, 0xC3422975, 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02,
+ 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, 0xE501FDF9, 0x0A3196E0,
+ 0x3E8D5D3A, 0xD1BD3623, 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B,
+ 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C,
+},
+{
+ 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, 0xCDE3E919,
+ 0x75E69C41, 0x1DE5B089, 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B,
+ 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA, 0x9C5BFAA6, 0xF458D66E,
+ 0x4C5DA336, 0x245E8FFE, 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F,
+ 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, 0x7796C224, 0x1F95EEEC,
+ 0xA7909BB4, 0xCF93B77C, 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5,
+ 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334, 0x73767EEE, 0x1B755226,
+ 0xA370277E, 0xCB730BB6, 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67,
+ 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, 0x04E0BCCA, 0x6CE39002,
+ 0xD4E6E55A, 0xBCE5C992, 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110,
+ 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1, 0x7AB7077A, 0x12B42BB2,
+ 0xAAB15EEA, 0xC2B27222, 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3,
+ 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, 0x917A3FF8, 0xF9791330,
+ 0x417C6668, 0x297F4AA0, 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884,
+ 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55, 0xA8C1008F, 0xC0C22C47,
+ 0x78C7591F, 0x10C475D7, 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006,
+ 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, 0xE20C4116, 0x8A0F6DDE,
+ 0x320A1886, 0x5A09344E, 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC,
+ 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D, 0xDBB77E61, 0xB3B452A9,
+ 0x0BB127F1, 0x63B20B39, 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8,
+ 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, 0x307A46E3, 0x58796A2B,
+ 0xE07C1F73, 0x887F33BB, 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC,
+ 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D, 0xBB43F3A7, 0xD340DF6F,
+ 0x6B45AA37, 0x034686FF, 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E,
+ 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, 0xCCD53183, 0xA4D61D4B,
+ 0x1CD36813, 0x74D044DB, 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59,
+ 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988, 0xC8358D49, 0xA036A181,
+ 0x1833D4D9, 0x7030F811, 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0,
+ 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, 0x23F8B5CB, 0x4BFB9903,
+ 0xF3FEEC5B, 0x9BFDC093, 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7,
+ 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766, 0x1A438ABC, 0x7240A674,
+ 0xCA45D32C, 0xA246FFE4, 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35,
+ 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, 0x2A39CC5F, 0x423AE097,
+ 0xFA3F95CF, 0x923CB907, 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185,
+ 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454, 0x1382F328, 0x7B81DFE0,
+ 0xC384AAB8, 0xAB878670, 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1,
+ 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, 0xF84FCBAA, 0x904CE762,
+ 0x2849923A, 0x404ABEF2, 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B,
+ 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA, 0xFCAF7760, 0x94AC5BA8,
+ 0x2CA92EF0, 0x44AA0238, 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9,
+ 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, 0x8B39B544, 0xE33A998C,
+ 0x5B3FECD4, 0x333CC01C, 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E,
+ 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F,
+},
+{
+ 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, 0x6821FF4A,
+ 0xB3657823, 0xFA590504, 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3,
+ 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE, 0x847609B4, 0xCD4A7493,
+ 0x160EF3FA, 0x5F328EDD, 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0,
+ 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, 0xE7508F03, 0xAE6CF224,
+ 0x7528754D, 0x3C14086A, 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0,
+ 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D, 0x4F3B6143, 0x06071C64,
+ 0xDD439B0D, 0x947FE62A, 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447,
+ 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, 0xA86BEE40, 0xE1579367,
+ 0x3A13140E, 0x732F6929, 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E,
+ 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3, 0x1A00CB32, 0x533CB615,
+ 0x8878317C, 0xC1444C5B, 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36,
+ 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, 0x79264D85, 0x301A30A2,
+ 0xEB5EB7CB, 0xA262CAEC, 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF,
+ 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782, 0xDC4DC65C, 0x9571BB7B,
+ 0x4E353C12, 0x07094135, 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358,
+ 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, 0x361D2CC6, 0x7F2151E1,
+ 0xA465D688, 0xED59ABAF, 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18,
+ 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75, 0x9376A71F, 0xDA4ADA38,
+ 0x010E5D51, 0x48322076, 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B,
+ 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, 0xF05021A8, 0xB96C5C8F,
+ 0x6228DBE6, 0x2B14A6C1, 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D,
+ 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360, 0x763A92BE, 0x3F06EF99,
+ 0xE44268F0, 0xAD7E15D7, 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA,
+ 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, 0x916A1DBD, 0xD856609A,
+ 0x0312E7F3, 0x4A2E9AD4, 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63,
+ 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E, 0x3901F3FD, 0x703D8EDA,
+ 0xAB7909B3, 0xE2457494, 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9,
+ 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, 0x5A27754A, 0x131B086D,
+ 0xC85F8F04, 0x8163F223, 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20,
+ 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D, 0xFF4CFE93, 0xB67083B4,
+ 0x6D3404DD, 0x240879FA, 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97,
+ 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, 0x0F1CDF3B, 0x4620A21C,
+ 0x9D642575, 0xD4585852, 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5,
+ 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88, 0xAA7754E2, 0xE34B29C5,
+ 0x380FAEAC, 0x7133D38B, 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6,
+ 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, 0xC951D255, 0x806DAF72,
+ 0x5B29281B, 0x1215553C, 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6,
+ 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB, 0x613A3C15, 0x28064132,
+ 0xF342C65B, 0xBA7EBB7C, 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911,
+ 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, 0x866AB316, 0xCF56CE31,
+ 0x14124958, 0x5D2E347F, 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8,
+ 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5,
+} };
+
+#define CRC32_UPD(crc, n) \
+ (crc32c_tables[(n)][(crc) & 0xff] ^ \
+ crc32c_tables[(n) - 1][((crc) >> 8) & 0xff])
+
+static inline uint32_t crc32c_u32(uint32_t data, uint32_t init_val)
+{
+ uint32_t crc, term1, term2;
+
+ crc = init_val;
+ crc ^= data;
+
+ term1 = CRC32_UPD(crc, 3);
+ term2 = crc >> 16;
+ crc = term1 ^ CRC32_UPD(term2, 1);
+
+ return crc;
+}
+
+static inline uint32_t crc32c_u64(uint64_t data, uint32_t init_val)
+{
+ union {
+ uint64_t u64;
+ uint32_t u32[2];
+ } d;
+ d.u64 = data;
+
+ uint32_t crc, term1, term2;
+
+ crc = init_val;
+ crc ^= d.u32[0];
+
+ term1 = CRC32_UPD(crc, 7);
+ term2 = crc >> 16;
+ crc = term1 ^ CRC32_UPD(term2, 5);
+ term1 = CRC32_UPD(d.u32[1], 3);
+ term2 = d.u32[1] >> 16;
+ crc ^= term1 ^ CRC32_UPD(term2, 1);
+
+ return crc;
+}
+
+uint32_t odp_hash_crc32c(const void *data, uint32_t data_len,
+ uint32_t init_val)
+{
+ size_t i;
+ uint64_t temp = 0;
+ uintptr_t pd = (uintptr_t)data;
+
+ for (i = 0; i < data_len / 8; i++) {
+ init_val = crc32c_u64(*(const uint64_t *)pd, init_val);
+ pd += 8;
+ }
+
+ switch (7 - (data_len & 0x07)) {
+ case 0:
+ temp |= (uint64_t)*((const uint8_t *)pd + 6) << 48;
+ /* Fallthrough */
+ case 1:
+ temp |= (uint64_t)*((const uint8_t *)pd + 5) << 40;
+ /* Fallthrough */
+ case 2:
+ temp |= (uint64_t)*((const uint8_t *)pd + 4) << 32;
+ temp |= *(const uint32_t *)pd;
+ init_val = crc32c_u64(temp, init_val);
+ break;
+ case 3:
+ init_val = crc32c_u32(*(const uint32_t *)pd, init_val);
+ break;
+ case 4:
+ temp |= *((const uint8_t *)pd + 2) << 16;
+ /* Fallthrough */
+ case 5:
+ temp |= *((const uint8_t *)pd + 1) << 8;
+ /* Fallthrough */
+ case 6:
+ temp |= *(const uint8_t *)pd;
+ init_val = crc32c_u32(temp, init_val);
+ /* Fallthrough */
+ default:
+ break;
+ }
+
+ return init_val;
+}
diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c
index 4616e0342..ea9974287 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -24,6 +24,10 @@ int odp_init_global(const odp_init_t *params,
odp_global_data.abort_fn = params->abort_fn;
}
+ if (odp_time_global_init()) {
+ ODP_ERR("ODP time init failed.\n");
+ return -1;
+ }
if (odp_system_info_init()) {
ODP_ERR("ODP system_info init failed.\n");
diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c
index 07c740cfa..db85b5e5e 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -32,10 +32,8 @@ static inline void packet_parse_disable(odp_packet_hdr_t *pkt_hdr)
pkt_hdr->input_flags.parsed_all = 1;
}
-void packet_parse_reset(odp_packet_t pkt)
+void packet_parse_reset(odp_packet_hdr_t *pkt_hdr)
{
- 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;
@@ -780,9 +778,9 @@ int _odp_packet_copy_to_packet(odp_packet_t srcpkt, uint32_t srcoffset,
* Parser helper function for IPv4
*/
static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
- uint8_t **parseptr, uint32_t *offset)
+ const uint8_t **parseptr, uint32_t *offset)
{
- odph_ipv4hdr_t *ipv4 = (odph_ipv4hdr_t *)*parseptr;
+ const odph_ipv4hdr_t *ipv4 = (const odph_ipv4hdr_t *)*parseptr;
uint8_t ver = ODPH_IPV4HDR_VER(ipv4->ver_ihl);
uint8_t ihl = ODPH_IPV4HDR_IHL(ipv4->ver_ihl);
uint16_t frag_offset;
@@ -818,10 +816,10 @@ static inline uint8_t parse_ipv4(odp_packet_hdr_t *pkt_hdr,
* Parser helper function for IPv6
*/
static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
- uint8_t **parseptr, uint32_t *offset)
+ const uint8_t **parseptr, uint32_t *offset)
{
- odph_ipv6hdr_t *ipv6 = (odph_ipv6hdr_t *)*parseptr;
- odph_ipv6hdr_ext_t *ipv6ext;
+ const odph_ipv6hdr_t *ipv6 = (const odph_ipv6hdr_t *)*parseptr;
+ const odph_ipv6hdr_ext_t *ipv6ext;
pkt_hdr->l3_len = odp_be_to_cpu_16(ipv6->payload_len);
@@ -843,7 +841,7 @@ static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
pkt_hdr->input_flags.ipopt = 1;
do {
- ipv6ext = (odph_ipv6hdr_ext_t *)*parseptr;
+ ipv6ext = (const odph_ipv6hdr_ext_t *)*parseptr;
uint16_t extlen = 8 + ipv6ext->ext_len * 8;
*offset += extlen;
@@ -875,9 +873,9 @@ static inline uint8_t parse_ipv6(odp_packet_hdr_t *pkt_hdr,
* Parser helper function for TCP
*/
static inline void parse_tcp(odp_packet_hdr_t *pkt_hdr,
- uint8_t **parseptr, uint32_t *offset)
+ const uint8_t **parseptr, uint32_t *offset)
{
- odph_tcphdr_t *tcp = (odph_tcphdr_t *)*parseptr;
+ const odph_tcphdr_t *tcp = (const odph_tcphdr_t *)*parseptr;
if (tcp->hl < sizeof(odph_tcphdr_t)/sizeof(uint32_t))
pkt_hdr->error_flags.tcp_err = 1;
@@ -895,9 +893,9 @@ static inline void parse_tcp(odp_packet_hdr_t *pkt_hdr,
* Parser helper function for UDP
*/
static inline void parse_udp(odp_packet_hdr_t *pkt_hdr,
- uint8_t **parseptr, uint32_t *offset)
+ const uint8_t **parseptr, uint32_t *offset)
{
- odph_udphdr_t *udp = (odph_udphdr_t *)*parseptr;
+ const odph_udphdr_t *udp = (const odph_udphdr_t *)*parseptr;
uint32_t udplen = odp_be_to_cpu_16(udp->length);
if (udplen < sizeof(odph_udphdr_t) ||
@@ -932,46 +930,55 @@ void packet_parse_l2(odp_packet_hdr_t *pkt_hdr)
pkt_hdr->input_flags.parsed_l2 = 1;
}
-/**
- * Simple packet parser
- */
-int packet_parse_full(odp_packet_hdr_t *pkt_hdr)
+int _odp_parse_common(odp_packet_hdr_t *pkt_hdr, const uint8_t *ptr)
{
- odph_ethhdr_t *eth;
- odph_vlanhdr_t *vlan;
+ const odph_ethhdr_t *eth;
+ const odph_vlanhdr_t *vlan;
uint16_t ethtype;
- uint8_t *parseptr;
uint32_t offset, seglen;
uint8_t ip_proto = 0;
+ const uint8_t *parseptr;
+ offset = sizeof(odph_ethhdr_t);
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;
- ethtype = odp_be_to_cpu_16(*((uint16_t *)(void *)parseptr));
+ if (ptr == NULL) {
+ eth = (odph_ethhdr_t *)packet_map(pkt_hdr, 0, &seglen);
+ parseptr = (const uint8_t *)&eth->type;
+ ethtype = odp_be_to_cpu_16(*((const uint16_t *)
+ (const void *)parseptr));
+ } else {
+ eth = (const odph_ethhdr_t *)ptr;
+ parseptr = (const uint8_t *)&eth->type;
+ ethtype = odp_be_to_cpu_16(*((const uint16_t *)
+ (const void *)parseptr));
+ }
+
/* Parse the VLAN header(s), if present */
if (ethtype == ODPH_ETHTYPE_VLAN_OUTER) {
pkt_hdr->input_flags.vlan_qinq = 1;
pkt_hdr->input_flags.vlan = 1;
- vlan = (odph_vlanhdr_t *)(void *)parseptr;
+
+ vlan = (const odph_vlanhdr_t *)(const void *)parseptr;
pkt_hdr->vlan_s_tag = ((ethtype << 16) |
odp_be_to_cpu_16(vlan->tci));
offset += sizeof(odph_vlanhdr_t);
parseptr += sizeof(odph_vlanhdr_t);
- ethtype = odp_be_to_cpu_16(*((uint16_t *)(void *)parseptr));
+ ethtype = odp_be_to_cpu_16(*((const uint16_t *)
+ (const void *)parseptr));
}
if (ethtype == ODPH_ETHTYPE_VLAN) {
pkt_hdr->input_flags.vlan = 1;
- vlan = (odph_vlanhdr_t *)(void *)parseptr;
+ vlan = (const odph_vlanhdr_t *)(const void *)parseptr;
pkt_hdr->vlan_c_tag = ((ethtype << 16) |
odp_be_to_cpu_16(vlan->tci));
offset += sizeof(odph_vlanhdr_t);
parseptr += sizeof(odph_vlanhdr_t);
- ethtype = odp_be_to_cpu_16(*((uint16_t *)(void *)parseptr));
+ ethtype = odp_be_to_cpu_16(*((const uint16_t *)
+ (const void *)parseptr));
}
/* Check for SNAP vs. DIX */
@@ -983,7 +990,8 @@ int packet_parse_full(odp_packet_hdr_t *pkt_hdr)
}
offset += 8;
parseptr += 8;
- ethtype = odp_be_to_cpu_16(*((uint16_t *)(void *)parseptr));
+ ethtype = odp_be_to_cpu_16(*((const uint16_t *)
+ (const void *)parseptr));
}
/* Consume Ethertype for Layer 3 parse */
@@ -1061,3 +1069,16 @@ parse_exit:
pkt_hdr->input_flags.parsed_all = 1;
return pkt_hdr->error_flags.all != 0;
}
+
+int _odp_cls_parse(odp_packet_hdr_t *pkt_hdr, const uint8_t *parseptr)
+{
+ return _odp_parse_common(pkt_hdr, parseptr);
+}
+
+/**
+ * Simple packet parser
+ */
+int packet_parse_full(odp_packet_hdr_t *pkt_hdr)
+{
+ return _odp_parse_common(pkt_hdr, NULL);
+}
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c
index 1e9d08c02..267aa0137 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -196,6 +196,7 @@ static odp_pktio_t setup_pktio_entry(const char *dev, odp_pool_t pool,
return ODP_PKTIO_INVALID;
memcpy(&pktio_entry->s.param, param, sizeof(odp_pktio_param_t));
+ pktio_entry->s.id = id;
for (pktio_if = 0; pktio_if_ops[pktio_if]; ++pktio_if) {
ret = pktio_if_ops[pktio_if]->open(id, pktio_entry, dev, pool);
@@ -568,7 +569,7 @@ odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
odp_buffer_t buf;
odp_packet_t pkt_tbl[QUEUE_MULTI_MAX];
odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
- int pkts, i, j;
+ int pkts, i;
odp_pktio_t pktio;
buf_hdr = queue_deq(qentry);
@@ -581,27 +582,13 @@ odp_buffer_hdr_t *pktin_dequeue(queue_entry_t *qentry)
if (pkts <= 0)
return NULL;
- 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;
+ for (i = 0; i < pkts; i++) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ hdr_tbl[i] = odp_buf_to_hdr(buf);
}
- if (0 == j)
- return NULL;
-
- if (j > 1)
- queue_enq_multi(qentry, &hdr_tbl[1], j - 1, 0);
+ if (pkts > 1)
+ queue_enq_multi(qentry, &hdr_tbl[1], pkts - 1, 0);
buf_hdr = hdr_tbl[0];
return buf_hdr;
}
@@ -640,27 +627,15 @@ int pktin_deq_multi(queue_entry_t *qentry, odp_buffer_hdr_t *buf_hdr[], int num)
if (pkts <= 0)
return nbr;
- 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);
- }
+ /* 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)
@@ -672,7 +647,7 @@ 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;
+ int num, i;
odp_buffer_t buf;
odp_pktio_t pktio;
@@ -697,26 +672,15 @@ int pktin_poll(pktio_entry_t *entry)
return -1;
}
- 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;
+ for (i = 0; i < num; i++) {
+ buf = _odp_packet_to_buffer(pkt_tbl[i]);
+ hdr_tbl[i] = odp_buf_to_hdr(buf);
}
- if (num_enq) {
+ if (num) {
queue_entry_t *qentry;
qentry = queue_to_qentry(entry->s.inq_default);
- queue_enq_multi(qentry, hdr_tbl, num_enq, 0);
+ queue_enq_multi(qentry, hdr_tbl, num, 0);
}
return 0;
@@ -882,3 +846,43 @@ int odp_pktio_term_global(void)
return ret;
}
+
+void odp_pktio_print(odp_pktio_t id)
+{
+ pktio_entry_t *entry;
+ uint8_t addr[ETH_ALEN];
+ int max_len = 512;
+ char str[max_len];
+ int len = 0;
+ int n = max_len - 1;
+
+ entry = get_pktio_entry(id);
+ if (entry == NULL) {
+ ODP_DBG("pktio entry %d does not exist\n", id);
+ return;
+ }
+
+ len += snprintf(&str[len], n - len,
+ "pktio\n");
+ len += snprintf(&str[len], n - len,
+ " handle %" PRIu64 "\n", odp_pktio_to_u64(id));
+ len += snprintf(&str[len], n - len,
+ " name %s\n", entry->s.name);
+ len += snprintf(&str[len], n - len,
+ " state %s\n",
+ entry->s.state == STATE_START ? "start" :
+ (entry->s.state == STATE_STOP ? "stop" : "unknown"));
+ memset(addr, 0, sizeof(addr));
+ odp_pktio_mac_addr(id, addr, ETH_ALEN);
+ len += snprintf(&str[len], n - len,
+ " mac %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+ len += snprintf(&str[len], n - len,
+ " mtu %d\n", odp_pktio_mtu(id));
+ len += snprintf(&str[len], n - len,
+ " promisc %s\n",
+ odp_pktio_promisc_mode(id) ? "yes" : "no");
+ str[len] = '\0';
+
+ ODP_PRINT("\n%s\n", str);
+}
diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
index 9859ff6d9..84d35bfba 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -17,6 +17,7 @@
#include <odp_internal.h>
#include <odp/config.h>
#include <odp/hints.h>
+#include <odp/thread.h>
#include <odp_debug_internal.h>
#include <odp_atomic_internal.h>
@@ -463,7 +464,7 @@ int odp_pool_destroy(odp_pool_t pool_hdl)
}
/* Make sure local caches are empty */
- for (i = 0; i < _ODP_INTERNAL_MAX_THREADS; i++)
+ for (i = 0; i < ODP_THREAD_COUNT_MAX; i++)
flush_cache(&pool->s.local_cache[i], &pool->s);
/* Call fails if pool has allocated buffers */
diff --git a/platform/linux-generic/odp_queue.c b/platform/linux-generic/odp_queue.c
index db3399ce3..e39176c65 100644
--- a/platform/linux-generic/odp_queue.c
+++ b/platform/linux-generic/odp_queue.c
@@ -355,9 +355,9 @@ int odp_queue_context_set(odp_queue_t handle, void *context)
{
queue_entry_t *queue;
queue = queue_to_qentry(handle);
- odp_sync_stores();
+ odp_mb_full();
queue->s.param.context = context;
- odp_sync_stores();
+ odp_mb_full();
return 0;
}
diff --git a/platform/linux-generic/odp_rwlock_recursive.c b/platform/linux-generic/odp_rwlock_recursive.c
new file mode 100644
index 000000000..e3a383caf
--- /dev/null
+++ b/platform/linux-generic/odp_rwlock_recursive.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/rwlock_recursive.h>
+#include <odp/thread.h>
+#include <string.h>
+
+#define NO_OWNER (-1)
+
+void odp_rwlock_recursive_init(odp_rwlock_recursive_t *rlock)
+{
+ memset(rlock, 0, sizeof(odp_rwlock_recursive_t));
+ odp_rwlock_init(&rlock->lock);
+ rlock->wr_owner = NO_OWNER;
+}
+
+/* Multiple readers can recurse the lock concurrently */
+void odp_rwlock_recursive_read_lock(odp_rwlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ if (rlock->rd_cnt[thr]) {
+ rlock->rd_cnt[thr]++;
+ return;
+ }
+
+ odp_rwlock_read_lock(&rlock->lock);
+ rlock->rd_cnt[thr] = 1;
+}
+
+void odp_rwlock_recursive_read_unlock(odp_rwlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ rlock->rd_cnt[thr]--;
+
+ if (rlock->rd_cnt[thr] > 0)
+ return;
+
+ odp_rwlock_read_unlock(&rlock->lock);
+}
+
+/* Only one writer can recurse the lock */
+void odp_rwlock_recursive_write_lock(odp_rwlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ if (rlock->wr_owner == thr) {
+ rlock->wr_cnt++;
+ return;
+ }
+
+ odp_rwlock_write_lock(&rlock->lock);
+ rlock->wr_owner = thr;
+ rlock->wr_cnt = 1;
+}
+
+void odp_rwlock_recursive_write_unlock(odp_rwlock_recursive_t *rlock)
+{
+ rlock->wr_cnt--;
+
+ if (rlock->wr_cnt > 0)
+ return;
+
+ rlock->wr_owner = NO_OWNER;
+ odp_rwlock_write_unlock(&rlock->lock);
+}
diff --git a/platform/linux-generic/odp_schedule.c b/platform/linux-generic/odp_schedule.c
index 9b7cd57ff..58f1b1b37 100644
--- a/platform/linux-generic/odp_schedule.c
+++ b/platform/linux-generic/odp_schedule.c
@@ -588,11 +588,10 @@ static int schedule_loop(odp_queue_t *out_queue, uint64_t wait,
odp_event_t out_ev[],
unsigned int max_num, unsigned int max_deq)
{
- odp_time_t start_time, time, diff;
+ odp_time_t next, wtime;
+ int first = 1;
int ret;
- start_time = ODP_TIME_NULL;
-
while (1) {
ret = schedule(out_queue, out_ev, max_num, max_deq);
@@ -605,15 +604,14 @@ static int schedule_loop(odp_queue_t *out_queue, uint64_t wait,
if (wait == ODP_SCHED_NO_WAIT)
break;
- if (!odp_time_cmp(ODP_TIME_NULL, start_time)) {
- start_time = odp_time_local();
+ if (first) {
+ wtime = odp_time_local_from_ns(wait);
+ next = odp_time_sum(odp_time_local(), wtime);
+ first = 0;
continue;
}
- time = odp_time_local();
- diff = odp_time_diff(time, start_time);
-
- if (odp_time_cmp(wait, diff) < 0)
+ if (odp_time_cmp(next, odp_time_local()) < 0)
break;
}
@@ -654,7 +652,7 @@ void odp_schedule_resume(void)
uint64_t odp_schedule_wait_time(uint64_t ns)
{
- return odp_time_to_u64(odp_time_local_from_ns(ns));
+ return ns;
}
diff --git a/platform/linux-generic/odp_spinlock_recursive.c b/platform/linux-generic/odp_spinlock_recursive.c
new file mode 100644
index 000000000..8ffe6b3dd
--- /dev/null
+++ b/platform/linux-generic/odp_spinlock_recursive.c
@@ -0,0 +1,70 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/spinlock_recursive.h>
+#include <odp/thread.h>
+
+#define NO_OWNER (-1)
+
+void odp_spinlock_recursive_init(odp_spinlock_recursive_t *rlock)
+{
+ odp_spinlock_init(&rlock->lock);
+ rlock->owner = NO_OWNER;
+ rlock->cnt = 0;
+}
+
+void odp_spinlock_recursive_lock(odp_spinlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ if (rlock->owner == thr) {
+ rlock->cnt++;
+ return;
+ }
+
+ odp_spinlock_lock(&rlock->lock);
+ rlock->owner = thr;
+ rlock->cnt = 1;
+}
+
+int odp_spinlock_recursive_trylock(odp_spinlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ if (rlock->owner == thr) {
+ rlock->cnt++;
+ return 1;
+ }
+
+ if (odp_spinlock_trylock(&rlock->lock)) {
+ rlock->owner = thr;
+ rlock->cnt = 1;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void odp_spinlock_recursive_unlock(odp_spinlock_recursive_t *rlock)
+{
+ rlock->cnt--;
+
+ if (rlock->cnt > 0)
+ return;
+
+ rlock->owner = NO_OWNER;
+ odp_spinlock_unlock(&rlock->lock);
+}
+
+int odp_spinlock_recursive_is_locked(odp_spinlock_recursive_t *rlock)
+{
+ int thr = odp_thread_id();
+
+ if (rlock->owner == thr)
+ return 1;
+
+ return odp_spinlock_is_locked(&rlock->lock);
+}
diff --git a/platform/linux-generic/odp_thread.c b/platform/linux-generic/odp_thread.c
index 2f3934374..06a5dcd5d 100644
--- a/platform/linux-generic/odp_thread.c
+++ b/platform/linux-generic/odp_thread.c
@@ -18,7 +18,6 @@
#include <odp/shared_memory.h>
#include <odp/align.h>
#include <odp/cpu.h>
-#include <odp_config_internal.h>
#include <string.h>
#include <stdio.h>
@@ -32,7 +31,7 @@ typedef struct {
typedef struct {
- thread_state_t thr[_ODP_INTERNAL_MAX_THREADS];
+ thread_state_t thr[ODP_THREAD_COUNT_MAX];
union {
/* struct order must be kept in sync with schedule_types.h */
struct {
@@ -102,10 +101,10 @@ static int alloc_id(odp_thread_type_t type)
int thr;
odp_thrmask_t *all = &thread_globals->all;
- if (thread_globals->num >= _ODP_INTERNAL_MAX_THREADS)
+ if (thread_globals->num >= ODP_THREAD_COUNT_MAX)
return -1;
- for (thr = 0; thr < _ODP_INTERNAL_MAX_THREADS; thr++) {
+ for (thr = 0; thr < ODP_THREAD_COUNT_MAX; thr++) {
if (odp_thrmask_isset(all, thr) == 0) {
odp_thrmask_set(all, thr);
@@ -129,7 +128,7 @@ static int free_id(int thr)
{
odp_thrmask_t *all = &thread_globals->all;
- if (thr < 0 || thr >= _ODP_INTERNAL_MAX_THREADS)
+ if (thr < 0 || thr >= ODP_THREAD_COUNT_MAX)
return -1;
if (odp_thrmask_isset(all, thr) == 0)
@@ -207,7 +206,7 @@ int odp_thread_count(void)
int odp_thread_count_max(void)
{
- return _ODP_INTERNAL_MAX_THREADS;
+ return ODP_THREAD_COUNT_MAX;
}
odp_thread_type_t odp_thread_type(void)
diff --git a/platform/linux-generic/odp_thrmask.c b/platform/linux-generic/odp_thrmask.c
index b62d03c7a..154ae81b6 100644
--- a/platform/linux-generic/odp_thrmask.c
+++ b/platform/linux-generic/odp_thrmask.c
@@ -8,7 +8,6 @@
#define _GNU_SOURCE
#endif
-#include <odp_config_internal.h>
#include <odp/thrmask.h>
#include <odp/cpumask.h>
diff --git a/platform/linux-generic/odp_time.c b/platform/linux-generic/odp_time.c
index 181d7323e..2cb84f2ab 100644
--- a/platform/linux-generic/odp_time.c
+++ b/platform/linux-generic/odp_time.c
@@ -6,81 +6,199 @@
#define _POSIX_C_SOURCE 200809L
+#include <time.h>
#include <odp/time.h>
#include <odp/hints.h>
-#include <odp/system_info.h>
-#include <odp/cpu.h>
-#include <odp_cpu_internal.h>
+#include <odp_debug_internal.h>
-#define GIGA 1000000000
+typedef union {
+ odp_time_t ex;
+ struct timespec in;
+} _odp_time_t;
+
+static odp_time_t start_time;
static inline
-uint64_t time_to_tick(odp_time_t time)
+uint64_t time_to_ns(odp_time_t time)
{
- return (uint64_t)time;
+ uint64_t ns;
+
+ ns = time.tv_sec * ODP_TIME_SEC_IN_NS;
+ ns += time.tv_nsec;
+
+ return ns;
}
-static inline
-odp_time_t tick_to_time(uint64_t tick)
+static inline odp_time_t time_diff(odp_time_t t2, odp_time_t t1)
+{
+ odp_time_t time;
+
+ time.tv_sec = t2.tv_sec - t1.tv_sec;
+ time.tv_nsec = t2.tv_nsec - t1.tv_nsec;
+
+ if (time.tv_nsec < 0) {
+ time.tv_nsec += ODP_TIME_SEC_IN_NS;
+ --time.tv_sec;
+ }
+
+ return time;
+}
+
+static inline odp_time_t time_local(void)
+{
+ int ret;
+ _odp_time_t time;
+
+ ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time.in);
+ if (odp_unlikely(ret != 0))
+ ODP_ABORT("clock_gettime failed\n");
+
+ return time_diff(time.ex, start_time);
+}
+
+static inline int time_cmp(odp_time_t t2, odp_time_t t1)
+{
+ if (t2.tv_sec < t1.tv_sec)
+ return -1;
+
+ if (t2.tv_sec > t1.tv_sec)
+ return 1;
+
+ return t2.tv_nsec - t1.tv_nsec;
+}
+
+static inline odp_time_t time_sum(odp_time_t t1, odp_time_t t2)
{
- return (odp_time_t)tick;
+ odp_time_t time;
+
+ time.tv_sec = t2.tv_sec + t1.tv_sec;
+ time.tv_nsec = t2.tv_nsec + t1.tv_nsec;
+
+ if (time.tv_nsec >= (long)ODP_TIME_SEC_IN_NS) {
+ time.tv_nsec -= ODP_TIME_SEC_IN_NS;
+ ++time.tv_sec;
+ }
+
+ return time;
+}
+
+static inline odp_time_t time_local_from_ns(uint64_t ns)
+{
+ odp_time_t time;
+
+ time.tv_sec = ns / ODP_TIME_SEC_IN_NS;
+ time.tv_nsec = ns - time.tv_sec * ODP_TIME_SEC_IN_NS;
+
+ return time;
+}
+
+static inline void time_wait_until(odp_time_t time)
+{
+ odp_time_t cur;
+
+ do {
+ cur = time_local();
+ } while (time_cmp(time, cur) > 0);
+}
+
+static inline uint64_t time_local_res(void)
+{
+ int ret;
+ struct timespec tres;
+
+ ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres);
+ if (odp_unlikely(ret != 0))
+ ODP_ABORT("clock_getres failed\n");
+
+ return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec;
}
odp_time_t odp_time_local(void)
{
- return tick_to_time(odp_cpu_cycles());
+ return time_local();
+}
+
+odp_time_t odp_time_global(void)
+{
+ return time_local();
}
odp_time_t odp_time_diff(odp_time_t t2, odp_time_t t1)
{
- return tick_to_time(_odp_cpu_cycles_diff(t2, t1));
+ return time_diff(t2, t1);
}
uint64_t odp_time_to_ns(odp_time_t time)
{
- uint64_t hz = odp_sys_cpu_hz();
- uint64_t tick = time_to_tick(time);
-
- if (tick > (UINT64_MAX / GIGA))
- return (tick / hz) * GIGA;
+ return time_to_ns(time);
+}
- return (tick * GIGA) / hz;
+odp_time_t odp_time_local_from_ns(uint64_t ns)
+{
+ return time_local_from_ns(ns);
}
+odp_time_t odp_time_global_from_ns(uint64_t ns)
+{
+ return time_local_from_ns(ns);
+}
-odp_time_t odp_time_local_from_ns(uint64_t ns)
+int odp_time_cmp(odp_time_t t2, odp_time_t t1)
{
- uint64_t hz = odp_sys_cpu_hz();
+ return time_cmp(t2, t1);
+}
- if (ns > (UINT64_MAX / hz))
- return tick_to_time((ns / GIGA) * hz);
+odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2)
+{
+ return time_sum(t1, t2);
+}
- return tick_to_time((ns * hz) / GIGA);
+uint64_t odp_time_local_res(void)
+{
+ return time_local_res();
}
-int odp_time_cmp(odp_time_t t2, odp_time_t t1)
+uint64_t odp_time_global_res(void)
{
- uint64_t tick1 = time_to_tick(t1);
- uint64_t tick2 = time_to_tick(t2);
+ return time_local_res();
+}
- if (tick1 < tick2)
- return 1;
+void odp_time_wait_ns(uint64_t ns)
+{
+ odp_time_t cur = time_local();
+ odp_time_t wait = time_local_from_ns(ns);
+ odp_time_t end_time = time_sum(cur, wait);
- if (tick1 > tick2)
- return -1;
+ time_wait_until(end_time);
+}
- return 0;
+void odp_time_wait_until(odp_time_t time)
+{
+ return time_wait_until(time);
}
-odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2)
+uint64_t odp_time_to_u64(odp_time_t time)
{
- uint64_t tick1 = time_to_tick(t1);
- uint64_t tick2 = time_to_tick(t2);
+ int ret;
+ struct timespec tres;
+ uint64_t resolution;
- return tick_to_time(tick1 + tick2);
+ ret = clock_getres(CLOCK_MONOTONIC_RAW, &tres);
+ if (odp_unlikely(ret != 0))
+ ODP_ABORT("clock_getres failed\n");
+
+ resolution = (uint64_t)tres.tv_nsec;
+
+ return time_to_ns(time) / resolution;
}
-uint64_t odp_time_to_u64(odp_time_t hdl)
+int odp_time_global_init(void)
{
- return time_to_tick(hdl);
+ int ret;
+ _odp_time_t time;
+
+ ret = clock_gettime(CLOCK_MONOTONIC_RAW, &time.in);
+ start_time = ret ? ODP_TIME_NULL : time.ex;
+
+ return ret;
}
diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c
index ce19add2b..47745ad83 100644
--- a/platform/linux-generic/pktio/loop.c
+++ b/platform/linux-generic/pktio/loop.c
@@ -12,6 +12,7 @@
#include <odp.h>
#include <odp_packet_internal.h>
#include <odp_packet_io_internal.h>
+#include <odp_classification_internal.h>
#include <odp_debug_internal.h>
#include <odp/hints.h>
@@ -50,19 +51,35 @@ static int loopback_close(pktio_entry_t *pktio_entry)
static int loopback_recv(pktio_entry_t *pktio_entry, odp_packet_t pkts[],
unsigned len)
{
- int nbr, i;
+ int nbr, i, j;
odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
queue_entry_t *qentry;
odp_packet_hdr_t *pkt_hdr;
+ odp_packet_t pkt;
+ nbr = 0;
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]));
- pkt_hdr = odp_packet_hdr(pkts[i]);
- packet_parse_reset(pkts[i]);
- packet_parse_l2(pkt_hdr);
+ if (pktio_cls_enabled(pktio_entry)) {
+ for (i = 0, j = 0; i < nbr; i++) {
+ pkt = _odp_packet_from_buffer(odp_hdr_to_buf
+ (hdr_tbl[i]));
+ pkt_hdr = odp_packet_hdr(pkt);
+ packet_parse_reset(pkt_hdr);
+ packet_parse_l2(pkt_hdr);
+ if (0 > _odp_packet_classifier(pktio_entry, pkt))
+ pkts[j++] = pkt;
+ }
+ nbr = j;
+ } else {
+ for (i = 0; i < nbr; ++i) {
+ pkts[i] = _odp_packet_from_buffer(odp_hdr_to_buf
+ (hdr_tbl[i]));
+ pkt_hdr = odp_packet_hdr(pkts[i]);
+ packet_parse_reset(pkt_hdr);
+ packet_parse_l2(pkt_hdr);
+ }
}
return nbr;
diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c
index d0643230b..11ebd5581 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -20,6 +20,9 @@
#include <poll.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
+#include <odp_classification_datamodel.h>
+#include <odp_classification_inlines.h>
+#include <odp_classification_internal.h>
#define NETMAP_WITH_LIBS
#include <net/netmap_user.h>
@@ -197,7 +200,7 @@ static inline int netmap_pkt_to_odp(pktio_entry_t *pktio_entry,
uint16_t len)
{
odp_packet_t pkt;
- odp_packet_hdr_t *pkt_hdr;
+ int ret;
if (odp_unlikely(len > pktio_entry->s.pkt_nm.max_frame_len)) {
ODP_ERR("RX: frame too big %" PRIu16 " %zu!\n", len,
@@ -210,21 +213,32 @@ static inline int netmap_pkt_to_odp(pktio_entry_t *pktio_entry,
return -1;
}
- pkt = packet_alloc(pktio_entry->s.pkt_nm.pool, len, 1);
- if (pkt == ODP_PACKET_INVALID)
+ if (pktio_cls_enabled(pktio_entry)) {
+ ret = _odp_packet_cls_enq(pktio_entry, (const uint8_t *)buf,
+ len, pkt_out);
+ if (ret)
+ return 0;
return -1;
+ } else {
+ odp_packet_hdr_t *pkt_hdr;
- pkt_hdr = odp_packet_hdr(pkt);
+ pkt = packet_alloc(pktio_entry->s.pkt_nm.pool, len, 1);
+ if (pkt == ODP_PACKET_INVALID)
+ return -1;
- /* For now copy the data in the mbuf,
- worry about zero-copy later */
- if (odp_packet_copydata_in(pkt, 0, len, buf) != 0) {
- odp_packet_free(pkt);
- return -1;
+ 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, len, buf) != 0) {
+ odp_packet_free(pkt);
+ return -1;
+ }
+
+ packet_parse_l2(pkt_hdr);
+ *pkt_out = pkt;
}
- packet_parse_l2(pkt_hdr);
- *pkt_out = pkt;
return 0;
}
diff --git a/platform/linux-generic/pktio/pktio_common.c b/platform/linux-generic/pktio/pktio_common.c
new file mode 100644
index 000000000..5729db6eb
--- /dev/null
+++ b/platform/linux-generic/pktio/pktio_common.c
@@ -0,0 +1,57 @@
+/* Copyright (c) 2013, Linaro Limited
+ * Copyright (c) 2013, Nokia Solutions and Networks
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <odp_packet_io_internal.h>
+#include <odp_classification_internal.h>
+
+int _odp_packet_cls_enq(pktio_entry_t *pktio_entry,
+ const uint8_t *base, uint16_t buf_len,
+ odp_packet_t *pkt_ret)
+{
+ cos_t *cos;
+ odp_packet_t pkt;
+ odp_packet_hdr_t pkt_hdr;
+ int ret;
+ odp_pool_t pool;
+
+ packet_parse_reset(&pkt_hdr);
+
+ _odp_cls_parse(&pkt_hdr, base);
+ cos = pktio_select_cos(pktio_entry, base, &pkt_hdr);
+
+ /* if No CoS found then drop the packet */
+ if (cos == NULL || cos->s.queue == NULL || cos->s.pool == NULL)
+ return 0;
+
+ pool = cos->s.pool->s.pool_hdl;
+
+ pkt = odp_packet_alloc(pool, buf_len);
+ if (odp_unlikely(pkt == ODP_PACKET_INVALID))
+ return 0;
+
+ copy_packet_parser_metadata(&pkt_hdr, odp_packet_hdr(pkt));
+ odp_packet_hdr(pkt)->input = pktio_entry->s.id;
+
+ if (odp_packet_copydata_in(pkt, 0, buf_len, base) != 0) {
+ odp_packet_free(pkt);
+ return 0;
+ }
+
+ /* Parse and set packet header data */
+ odp_packet_pull_tail(pkt, odp_packet_len(pkt) - buf_len);
+ ret = queue_enq(cos->s.queue, odp_buf_to_hdr((odp_buffer_t)pkt), 0);
+ if (ret < 0) {
+ *pkt_ret = pkt;
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c
index ef2e031db..dfdab18d7 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -38,6 +38,9 @@
#include <odp_packet_io_internal.h>
#include <odp_align_internal.h>
#include <odp_debug_internal.h>
+#include <odp_classification_datamodel.h>
+#include <odp_classification_inlines.h>
+#include <odp_classification_internal.h>
#include <odp/hints.h>
#include <odp/helper/eth.h>
@@ -202,6 +205,8 @@ static int sock_close(pktio_entry_t *pktio_entry)
return -1;
}
+ odp_shm_free(pkt_sock->shm);
+
return 0;
}
@@ -213,10 +218,13 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev,
{
int sockfd;
int err;
+ int i;
unsigned int if_idx;
struct ifreq ethreq;
struct sockaddr_ll sa_ll;
+ char shm_name[ODP_SHM_NAME_LEN];
pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock;
+ uint8_t *addr;
/* Init pktio entry */
memset(pkt_sock, 0, sizeof(*pkt_sock));
@@ -226,6 +234,20 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev,
if (pool == ODP_POOL_INVALID)
return -1;
pkt_sock->pool = pool;
+ snprintf(shm_name, ODP_SHM_NAME_LEN, "%s-%s", "pktio", netdev);
+ shm_name[ODP_SHM_NAME_LEN - 1] = '\0';
+
+ pkt_sock->shm = odp_shm_reserve(shm_name, PACKET_JUMBO_LEN,
+ PACKET_JUMBO_LEN *
+ ODP_PACKET_SOCKET_MAX_BURST_RX, 0);
+ if (pkt_sock->shm == ODP_SHM_INVALID)
+ return -1;
+
+ addr = odp_shm_addr(pkt_sock->shm);
+ for (i = 0; i < ODP_PACKET_SOCKET_MAX_BURST_RX; i++) {
+ pkt_sock->cache_ptr[i] = addr;
+ addr += PACKET_JUMBO_LEN;
+ }
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd == -1) {
@@ -261,7 +283,6 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev,
ODP_ERR("bind(to IF): %s\n", strerror(errno));
goto error;
}
-
return 0;
error:
@@ -319,58 +340,95 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
const int sockfd = pkt_sock->sockfd;
int msgvec_len;
struct mmsghdr msgvec[ODP_PACKET_SOCKET_MAX_BURST_RX];
- struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_RX][ODP_BUFFER_MAX_SEG];
int nb_rx = 0;
int recv_msgs;
+ int ret;
+ uint8_t **recv_cache;
int i;
if (odp_unlikely(len > ODP_PACKET_SOCKET_MAX_BURST_RX))
return -1;
memset(msgvec, 0, sizeof(msgvec));
+ recv_cache = pkt_sock->cache_ptr;
- for (i = 0; i < (int)len; i++) {
- pkt_table[i] = packet_alloc(pkt_sock->pool, 0 /*default*/, 1);
- if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID))
- break;
+ if (pktio_cls_enabled(pktio_entry)) {
+ struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_RX];
- msgvec[i].msg_hdr.msg_iovlen =
- _rx_pkt_to_iovec(pkt_table[i], iovecs[i]);
-
- msgvec[i].msg_hdr.msg_iov = iovecs[i];
- }
- msgvec_len = i; /* number of successfully allocated pkt buffers */
+ for (i = 0; i < (int)len; i++) {
+ msgvec[i].msg_hdr.msg_iovlen = 1;
+ iovecs[i].iov_base = recv_cache[i];
+ iovecs[i].iov_len = PACKET_JUMBO_LEN;
+ msgvec[i].msg_hdr.msg_iov = &iovecs[i];
+ }
+ /* number of successfully allocated pkt buffers */
+ msgvec_len = i;
+
+ recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len,
+ MSG_DONTWAIT, NULL);
+ for (i = 0; i < recv_msgs; i++) {
+ void *base = msgvec[i].msg_hdr.msg_iov->iov_base;
+ struct ethhdr *eth_hdr = base;
+ uint16_t pkt_len = msgvec[i].msg_len;
+
+ /* Don't receive packets sent by ourselves */
+ if (odp_unlikely(ethaddrs_equal(pkt_sock->if_mac,
+ eth_hdr->h_source)))
+ continue;
+
+ ret = _odp_packet_cls_enq(pktio_entry, base,
+ pkt_len, &pkt_table[nb_rx]);
+ if (ret)
+ nb_rx++;
+ }
+ } else {
+ struct iovec iovecs[ODP_PACKET_SOCKET_MAX_BURST_RX]
+ [ODP_BUFFER_MAX_SEG];
- recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len, MSG_DONTWAIT, NULL);
+ for (i = 0; i < (int)len; i++) {
+ pkt_table[i] = packet_alloc(pkt_sock->pool,
+ 0 /*default*/, 1);
+ if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID))
+ break;
- 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;
+ msgvec[i].msg_hdr.msg_iovlen =
+ _rx_pkt_to_iovec(pkt_table[i], iovecs[i]);
- /* Don't receive packets sent by ourselves */
- if (odp_unlikely(ethaddrs_equal(pkt_sock->if_mac,
- eth_hdr->h_source))) {
- odp_packet_free(pkt_table[i]);
- continue;
+ msgvec[i].msg_hdr.msg_iov = iovecs[i];
}
- 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);
+ /* number of successfully allocated pkt buffers */
+ msgvec_len = i;
- packet_parse_l2(pkt_hdr);
+ recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len,
+ MSG_DONTWAIT, NULL);
- pkt_table[nb_rx] = pkt_table[i];
- nb_rx++;
- }
+ for (i = 0; i < recv_msgs; i++) {
+ void *base = msgvec[i].msg_hdr.msg_iov->iov_base;
+ struct ethhdr *eth_hdr = base;
+ odp_packet_hdr_t *pkt_hdr;
- /* Free unused pkt buffers */
- for (; i < msgvec_len; i++)
- odp_packet_free(pkt_table[i]);
+ /* Don't receive packets sent by ourselves */
+ if (odp_unlikely(ethaddrs_equal(pkt_sock->if_mac,
+ eth_hdr->h_source))) {
+ odp_packet_free(pkt_table[i]);
+ continue;
+ }
+ pkt_hdr = odp_packet_hdr(pkt_table[i]);
+ /* Parse and set packet header data */
+ odp_packet_pull_tail(pkt_table[i],
+ odp_packet_len(pkt_table[i]) -
+ msgvec[i].msg_len);
+
+ packet_parse_l2(pkt_hdr);
+ pkt_table[nb_rx] = pkt_table[i];
+ nb_rx++;
+ }
+ /* Free unused pkt buffers */
+ for (; i < msgvec_len; i++)
+ odp_packet_free(pkt_table[i]);
+ }
return nb_rx;
}
@@ -385,7 +443,7 @@ static uint32_t _tx_pkt_to_iovec(odp_packet_t pkt,
uint32_t seglen;
iovecs[iov_count].iov_base = odp_packet_offset(pkt, offset,
- &seglen, NULL);
+ &seglen, NULL);
iovecs[iov_count].iov_len = seglen;
iov_count++;
offset += seglen;
@@ -415,7 +473,7 @@ static int sock_mmsg_send(pktio_entry_t *pktio_entry,
for (i = 0; i < len; i++) {
msgvec[i].msg_hdr.msg_iov = iovecs[i];
msgvec[i].msg_hdr.msg_iovlen = _tx_pkt_to_iovec(pkt_table[i],
- iovecs[i]);
+ iovecs[i]);
}
for (i = 0; i < len; ) {
@@ -423,7 +481,7 @@ static int sock_mmsg_send(pktio_entry_t *pktio_entry,
if (odp_unlikely(ret <= -1)) {
if (i == 0 && SOCK_ERR_REPORT(errno)) {
__odp_errno = errno;
- ODP_ERR("sendmmsg(): %s\n", strerror(errno));
+ ODP_ERR("sendmmsg(): %s\n", strerror(errno));
return -1;
}
break;
diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c
index 2bdb72b35..fcaaaf63f 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -28,6 +28,9 @@
#include <odp_packet_internal.h>
#include <odp_packet_io_internal.h>
#include <odp_debug_internal.h>
+#include <odp_classification_datamodel.h>
+#include <odp_classification_inlines.h>
+#include <odp_classification_internal.h>
#include <odp/hints.h>
#include <odp/helper/eth.h>
@@ -108,9 +111,9 @@ static inline void mmap_tx_user_ready(struct tpacket2_hdr *hdr)
__sync_synchronize();
}
-static inline unsigned pkt_mmap_v2_rx(int sock, struct ring *ring,
+static inline unsigned pkt_mmap_v2_rx(pktio_entry_t *pktio_entry,
+ pkt_sock_mmap_t *pkt_sock,
odp_packet_t pkt_table[], unsigned len,
- odp_pool_t pool,
unsigned char if_mac[])
{
union frame_map ppd;
@@ -118,57 +121,68 @@ 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;
+ uint8_t nb_rx = 0;
+ struct ring *ring;
+ int ret;
- (void)sock;
-
+ ring = &pkt_sock->rx_ring;
frame_num = ring->frame_num;
while (i < len) {
- if (mmap_rx_kernel_ready(ring->rd[frame_num].iov_base)) {
- ppd.raw = ring->rd[frame_num].iov_base;
+ if (!mmap_rx_kernel_ready(ring->rd[frame_num].iov_base))
+ break;
+
+ ppd.raw = ring->rd[frame_num].iov_base;
+ next_frame_num = (frame_num + 1) % ring->rd_num;
+
+ pkt_buf = (uint8_t *)ppd.raw + ppd.v2->tp_h.tp_mac;
+ pkt_len = ppd.v2->tp_h.tp_snaplen;
- next_frame_num = (frame_num + 1) % ring->rd_num;
+ /* Don't receive packets sent by ourselves */
+ eth_hdr = (struct ethhdr *)pkt_buf;
+ if (odp_unlikely(ethaddrs_equal(if_mac,
+ eth_hdr->h_source))) {
+ mmap_rx_user_ready(ppd.raw); /* drop */
+ frame_num = next_frame_num;
+ continue;
+ }
- pkt_buf = (uint8_t *)ppd.raw + ppd.v2->tp_h.tp_mac;
- pkt_len = ppd.v2->tp_h.tp_snaplen;
+ if (pktio_cls_enabled(pktio_entry)) {
+ ret = _odp_packet_cls_enq(pktio_entry, pkt_buf,
+ pkt_len, &pkt_table[nb_rx]);
+ if (ret)
+ nb_rx++;
+ } else {
+ odp_packet_hdr_t *hdr;
- /* Don't receive packets sent by ourselves */
- eth_hdr = (struct ethhdr *)pkt_buf;
- if (odp_unlikely(ethaddrs_equal(if_mac,
- eth_hdr->h_source))) {
+ pkt_table[i] = packet_alloc(pkt_sock->pool, pkt_len, 1);
+ if (odp_unlikely(pkt_table[i] == ODP_PACKET_INVALID)) {
mmap_rx_user_ready(ppd.raw); /* drop */
frame_num = next_frame_num;
continue;
}
-
- 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) {
+ hdr = odp_packet_hdr(pkt_table[i]);
+ ret = odp_packet_copydata_in(pkt_table[i], 0,
+ pkt_len, pkt_buf);
+ if (ret != 0) {
odp_packet_free(pkt_table[i]);
- break;
+ mmap_rx_user_ready(ppd.raw); /* drop */
+ frame_num = next_frame_num;
+ continue;
}
- packet_parse_l2(pkt_hdr);
-
- mmap_rx_user_ready(ppd.raw);
-
- frame_num = next_frame_num;
- i++;
- } else {
- break;
+ packet_parse_l2(hdr);
+ nb_rx++;
}
+
+ mmap_rx_user_ready(ppd.raw);
+ frame_num = next_frame_num;
+ i++;
}
ring->frame_num = frame_num;
-
- return i;
+ return nb_rx;
}
static inline unsigned pkt_mmap_v2_tx(int sock, struct ring *ring,
@@ -502,9 +516,8 @@ static int sock_mmap_recv(pktio_entry_t *pktio_entry,
{
pkt_sock_mmap_t *const pkt_sock = &pktio_entry->s.pkt_sock_mmap;
- return pkt_mmap_v2_rx(pkt_sock->rx_ring.sock, &pkt_sock->rx_ring,
- pkt_table, len, pkt_sock->pool,
- pkt_sock->if_mac);
+ return pkt_mmap_v2_rx(pktio_entry, pkt_sock,
+ pkt_table, len, pkt_sock->if_mac);
}
static int sock_mmap_send(pktio_entry_t *pktio_entry,
diff --git a/platform/linux-generic/test/Makefile.am b/platform/linux-generic/test/Makefile.am
index 594aa11eb..e62987297 100644
--- a/platform/linux-generic/test/Makefile.am
+++ b/platform/linux-generic/test/Makefile.am
@@ -12,6 +12,7 @@ TESTS = pktio/pktio_run \
${top_builddir}/test/validation/cpumask/cpumask_main$(EXEEXT) \
${top_builddir}/test/validation/crypto/crypto_main$(EXEEXT) \
${top_builddir}/test/validation/errno/errno_main$(EXEEXT) \
+ ${top_builddir}/test/validation/hash/hash_main$(EXEEXT) \
${top_builddir}/test/validation/init/init_main_ok$(EXEEXT) \
${top_builddir}/test/validation/init/init_main_abort$(EXEEXT) \
${top_builddir}/test/validation/init/init_main_log$(EXEEXT) \
@@ -20,6 +21,7 @@ TESTS = pktio/pktio_run \
${top_builddir}/test/validation/queue/queue_main$(EXEEXT) \
${top_builddir}/test/validation/random/random_main$(EXEEXT) \
${top_builddir}/test/validation/scheduler/scheduler_main$(EXEEXT) \
+ ${top_builddir}/test/validation/std_clib/std_clib_main$(EXEEXT) \
${top_builddir}/test/validation/synchronizers/synchronizers_main$(EXEEXT) \
${top_builddir}/test/validation/thread/thread_main$(EXEEXT) \
${top_builddir}/test/validation/time/time_main$(EXEEXT) \
diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
index 481fb01d2..a85b8309b 100644
--- a/test/performance/odp_l2fwd.c
+++ b/test/performance/odp_l2fwd.c
@@ -208,8 +208,8 @@ static void *pktio_queue_thread(void *arg)
stats->s.packets += pkts;
}
- /* Make sure that the last stats write is visible to readers */
- odp_sync_stores();
+ /* Make sure that latest stat writes are visible to other threads */
+ odp_mb_full();
return NULL;
}
@@ -326,8 +326,8 @@ static void *pktio_direct_recv_thread(void *arg)
stats->s.packets += pkts;
}
- /* Make sure that the last stats write is visible to readers */
- odp_sync_stores();
+ /* Make sure that latest stat writes are visible to other threads */
+ odp_mb_full();
return NULL;
}
diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
index 82dcf19c1..4cc1affc3 100644
--- a/test/performance/odp_pktio_perf.c
+++ b/test/performance/odp_pktio_perf.c
@@ -305,8 +305,8 @@ static void *run_thread_tx(void *arg)
int thr_id;
odp_queue_t outq;
pkt_tx_stats_t *stats;
- odp_time_t start_time, cur_time, send_duration;
- odp_time_t burst_start_time, burst_gap;
+ odp_time_t cur_time, send_time_end, send_duration;
+ odp_time_t burst_gap_end, burst_gap;
uint32_t batch_len;
int unsent_pkts = 0;
odp_event_t tx_event[BATCH_LEN_MAX];
@@ -336,19 +336,19 @@ static void *run_thread_tx(void *arg)
odp_barrier_wait(&globals->tx_barrier);
cur_time = odp_time_local();
- start_time = cur_time;
- burst_start_time = odp_time_diff(cur_time, burst_gap);
- while (odp_time_diff(cur_time, start_time) < send_duration) {
+ send_time_end = odp_time_sum(cur_time, send_duration);
+ burst_gap_end = cur_time;
+ while (odp_time_cmp(send_time_end, cur_time) > 0) {
unsigned alloc_cnt = 0, tx_cnt;
- if (odp_time_diff(cur_time, burst_start_time) < burst_gap) {
+ if (odp_time_cmp(burst_gap_end, cur_time) > 0) {
cur_time = odp_time_local();
if (!odp_time_cmp(idle_start, ODP_TIME_NULL))
idle_start = cur_time;
continue;
}
- if (odp_time_cmp(idle_start, ODP_TIME_NULL)) {
+ if (odp_time_cmp(idle_start, ODP_TIME_NULL) > 0) {
odp_time_t diff = odp_time_diff(cur_time, idle_start);
stats->s.idle_ticks =
@@ -357,7 +357,7 @@ static void *run_thread_tx(void *arg)
idle_start = ODP_TIME_NULL;
}
- burst_start_time += burst_gap;
+ burst_gap_end = odp_time_sum(burst_gap_end, burst_gap);
alloc_cnt = alloc_packets(tx_event, batch_len - unsent_pkts);
if (alloc_cnt != batch_len)
@@ -591,20 +591,6 @@ static int setup_txrx_masks(odp_cpumask_t *thd_mask_tx,
}
/*
- * Busy loop for specified length of time.
- */
-static void busy_loop_ns(uint64_t wait_ns)
-{
- odp_time_t diff;
- odp_time_t start_time = odp_time_local();
- odp_time_t wait = odp_time_local_from_ns(wait_ns);
-
- do {
- diff = odp_time_diff(odp_time_local(), start_time);
- } while (odp_time_cmp(wait, diff) > 0);
-}
-
-/*
* Run a single instance of the throughput test. When attempting to determine
* the maximum packet rate this will be invoked multiple times with the only
* difference between runs being the target PPS rate.
@@ -647,7 +633,7 @@ static int run_test_single(odp_cpumask_t *thd_mask_tx,
num_tx_workers);
/* delay to allow transmitted packets to reach the receivers */
- busy_loop_ns(SHUTDOWN_DELAY_NS);
+ odp_time_wait_ns(SHUTDOWN_DELAY_NS);
/* indicate to the receivers to exit */
odp_atomic_store_u32(&shutdown, 1);
diff --git a/test/performance/odp_scheduling.c b/test/performance/odp_scheduling.c
index 971d19b05..fc6ccdc2a 100644
--- a/test/performance/odp_scheduling.c
+++ b/test/performance/odp_scheduling.c
@@ -702,7 +702,7 @@ static void *run_thread(void *arg)
*/
static void test_cpu_freq(void)
{
- struct timespec tp1, tp2;
+ odp_time_t cur_time, test_time, start_time, end_time;
uint64_t c1, c2, cycles;
uint64_t nsec;
double diff_max_hz, max_cycles;
@@ -710,40 +710,21 @@ static void test_cpu_freq(void)
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;
- }
-
- /* 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");
- return;
- }
-
- } while (tp1.tv_sec == tp2.tv_sec);
+ test_time = odp_time_local_from_ns(TEST_SEC * ODP_TIME_SEC_IN_NS);
+ start_time = odp_time_local();
+ end_time = odp_time_sum(start_time, test_time);
/* Start the measurement */
c1 = odp_cpu_cycles();
do {
- if (clock_gettime(CLOCK_MONOTONIC, &tp2)) {
- LOG_ERR("clock_gettime failed.\n");
- return;
- }
-
- } while ((tp2.tv_sec - tp1.tv_sec) < TEST_SEC);
+ cur_time = odp_time_local();
+ } while (odp_time_cmp(end_time, cur_time) > 0);
c2 = odp_cpu_cycles();
- nsec = (tp2.tv_sec - tp1.tv_sec) * 1000000000;
-
- if (tp2.tv_nsec > tp1.tv_nsec)
- nsec += tp2.tv_nsec - tp1.tv_nsec;
- else
- nsec -= tp1.tv_nsec - tp2.tv_nsec;
+ test_time = odp_time_diff(cur_time, start_time);
+ nsec = odp_time_to_ns(test_time);
cycles = odp_cpu_cycles_diff(c2, c1);
max_cycles = (nsec * odp_sys_cpu_hz()) / 1000000000.0;
@@ -751,7 +732,7 @@ static void test_cpu_freq(void)
/* 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", nsec);
+ printf("odp_time %" 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);
diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am
index 4e364944a..1711b93e7 100644
--- a/test/validation/Makefile.am
+++ b/test/validation/Makefile.am
@@ -4,6 +4,7 @@ ODP_MODULES = buffer \
cpumask \
crypto \
errno \
+ hash \
init \
queue \
packet \
@@ -11,6 +12,7 @@ ODP_MODULES = buffer \
pool \
random \
scheduler \
+ std_clib \
synchronizers \
thread \
time \
diff --git a/test/validation/classification/classification.h b/test/validation/classification/classification.h
index 99dbd65cf..a186339ff 100644
--- a/test/validation/classification/classification.h
+++ b/test/validation/classification/classification.h
@@ -59,6 +59,7 @@ void classification_test_destroy_cos(void);
void classification_test_create_pmr_match(void);
void classification_test_destroy_pmr(void);
void classification_test_cos_set_queue(void);
+void classification_test_cos_set_pool(void);
void classification_test_cos_set_drop(void);
void classification_test_pmr_match_set_create(void);
void classification_test_pmr_match_set_destroy(void);
diff --git a/test/validation/classification/odp_classification_basic.c b/test/validation/classification/odp_classification_basic.c
index 20c157f4e..f0b7a4243 100644
--- a/test/validation/classification/odp_classification_basic.c
+++ b/test/validation/classification/odp_classification_basic.c
@@ -13,26 +13,60 @@
void classification_test_create_cos(void)
{
odp_cos_t cos;
- char name[ODP_COS_NAME_LEN];
- sprintf(name, "ClassOfService");
- cos = odp_cos_create(name);
- CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+ odp_cls_cos_param_t cls_param;
+ odp_pool_t pool;
+ odp_queue_t queue;
+ char cosname[ODP_COS_NAME_LEN];
+
+ pool = pool_create("cls_basic_pool");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ queue = queue_create("cls_basic_queue", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ sprintf(cosname, "ClassOfService");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+
+ cos = odp_cls_cos_create(cosname, &cls_param);
CU_ASSERT(odp_cos_to_u64(cos) != odp_cos_to_u64(ODP_COS_INVALID));
odp_cos_destroy(cos);
+ odp_pool_destroy(pool);
+ odp_queue_destroy(queue);
}
void classification_test_destroy_cos(void)
{
odp_cos_t cos;
char name[ODP_COS_NAME_LEN];
+ odp_pool_t pool;
+ odp_queue_t queue;
+ odp_cls_cos_param_t cls_param;
int retval;
+
+ pool = pool_create("cls_basic_pool");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ queue = queue_create("cls_basic_queue", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
sprintf(name, "ClassOfService");
- cos = odp_cos_create(name);
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+
+ cos = odp_cls_cos_create(name, &cls_param);
CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
retval = odp_cos_destroy(cos);
CU_ASSERT(retval == 0);
retval = odp_cos_destroy(ODP_COS_INVALID);
CU_ASSERT(retval < 0);
+
+ odp_pool_destroy(pool);
+ odp_queue_destroy(queue);
}
void classification_test_create_pmr_match(void)
@@ -82,35 +116,101 @@ void classification_test_cos_set_queue(void)
{
int retval;
char cosname[ODP_COS_NAME_LEN];
- char queuename[ODP_QUEUE_NAME_LEN];
- odp_queue_param_t qparam;
+ odp_cls_cos_param_t cls_param;
+ odp_pool_t pool;
+ odp_queue_t queue;
odp_queue_t queue_cos;
odp_cos_t cos_queue;
+ odp_queue_t recvqueue;
+
+ pool = pool_create("cls_basic_pool");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ queue = queue_create("cls_basic_queue", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
sprintf(cosname, "CoSQueue");
- cos_queue = odp_cos_create(cosname);
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_queue = odp_cls_cos_create(cosname, &cls_param);
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;
- sprintf(queuename, "%s", "QueueCoS");
+ queue_cos = queue_create("QueueCoS", true);
+ CU_ASSERT_FATAL(queue_cos != ODP_QUEUE_INVALID);
- queue_cos = odp_queue_create(queuename,
- ODP_QUEUE_TYPE_SCHED, &qparam);
retval = odp_cos_queue_set(cos_queue, queue_cos);
CU_ASSERT(retval == 0);
+ recvqueue = odp_cos_queue(cos_queue);
+ CU_ASSERT(recvqueue == queue_cos);
+
odp_cos_destroy(cos_queue);
odp_queue_destroy(queue_cos);
+ odp_queue_destroy(queue);
+ odp_pool_destroy(pool);
+}
+
+void classification_test_cos_set_pool(void)
+{
+ int retval;
+ char cosname[ODP_COS_NAME_LEN];
+ odp_cls_cos_param_t cls_param;
+ odp_pool_t pool;
+ odp_queue_t queue;
+ odp_pool_t cos_pool;
+ odp_cos_t cos;
+ odp_pool_t recvpool;
+
+ pool = pool_create("cls_basic_pool");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ queue = queue_create("cls_basic_queue", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ sprintf(cosname, "CoSQueue");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+ cos_pool = pool_create("PoolCoS");
+ CU_ASSERT_FATAL(cos_pool != ODP_POOL_INVALID);
+
+ retval = odp_cls_cos_pool_set(cos, cos_pool);
+ CU_ASSERT(retval == 0);
+ recvpool = odp_cls_cos_pool(cos);
+ CU_ASSERT(recvpool == cos_pool);
+
+ odp_cos_destroy(cos);
+ odp_queue_destroy(queue);
+ odp_pool_destroy(pool);
+ odp_pool_destroy(cos_pool);
}
void classification_test_cos_set_drop(void)
{
int retval;
char cosname[ODP_COS_NAME_LEN];
- sprintf(cosname, "CoSDrop");
odp_cos_t cos_drop;
- cos_drop = odp_cos_create(cosname);
+ odp_queue_t queue;
+ odp_pool_t pool;
+ odp_cls_cos_param_t cls_param;
+
+ pool = pool_create("cls_basic_pool");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ queue = queue_create("cls_basic_queue", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ sprintf(cosname, "CoSDrop");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_drop = odp_cls_cos_create(cosname, &cls_param);
CU_ASSERT_FATAL(cos_drop != ODP_COS_INVALID);
retval = odp_cos_drop_set(cos_drop, ODP_COS_DROP_POOL);
@@ -118,6 +218,8 @@ void classification_test_cos_set_drop(void)
retval = odp_cos_drop_set(cos_drop, ODP_COS_DROP_NEVER);
CU_ASSERT(retval == 0);
odp_cos_destroy(cos_drop);
+ odp_pool_destroy(pool);
+ odp_queue_destroy(queue);
}
void classification_test_pmr_match_set_create(void)
@@ -177,6 +279,7 @@ odp_testinfo_t classification_suite_basic[] = {
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_cos_set_pool),
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
index a56c017fb..afcea4546 100644
--- a/test/validation/classification/odp_classification_common.c
+++ b/test/validation/classification/odp_classification_common.c
@@ -154,7 +154,7 @@ odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns)
return odp_packet_from_event(ev);
}
-odp_queue_t queue_create(char *queuename, bool sched)
+odp_queue_t queue_create(const char *queuename, bool sched)
{
odp_queue_t queue;
odp_queue_param_t qparam;
@@ -177,6 +177,19 @@ odp_queue_t queue_create(char *queuename, bool sched)
return queue;
}
+odp_pool_t pool_create(const char *poolname)
+{
+ 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;
+
+ return odp_pool_create(poolname, &param);
+}
+
odp_packet_t create_packet(odp_pool_t pool, bool vlan,
odp_atomic_u32_t *seq, bool flag_udp)
{
diff --git a/test/validation/classification/odp_classification_test_pmr.c b/test/validation/classification/odp_classification_test_pmr.c
index 5a6272e8f..6644b53a4 100644
--- a/test/validation/classification/odp_classification_test_pmr.c
+++ b/test/validation/classification/odp_classification_test_pmr.c
@@ -12,23 +12,15 @@
#include <odp/helper/udp.h>
#include <odp/helper/tcp.h>
-static odp_pool_t pool_default;
+static odp_pool_t pkt_pool;
/** 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) {
+ pkt_pool = pool_create("classification_pmr_pool");
+ if (ODP_POOL_INVALID == pkt_pool) {
fprintf(stderr, "Packet pool creation failed.\n");
return -1;
}
@@ -43,7 +35,7 @@ odp_pktio_t create_pktio(odp_queue_type_t q_type)
odp_pktio_param_t pktio_param;
int ret;
- if (pool_default == ODP_POOL_INVALID)
+ if (pkt_pool == ODP_POOL_INVALID)
return ODP_PKTIO_INVALID;
odp_pktio_param_init(&pktio_param);
@@ -52,9 +44,9 @@ odp_pktio_t create_pktio(odp_queue_type_t q_type)
else
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
- pktio = odp_pktio_open("loop", pool_default, &pktio_param);
+ pktio = odp_pktio_open("loop", pkt_pool, &pktio_param);
if (pktio == ODP_PKTIO_INVALID) {
- ret = odp_pool_destroy(pool_default);
+ ret = odp_pool_destroy(pkt_pool);
if (ret)
fprintf(stderr, "unable to destroy pool.\n");
return ODP_PKTIO_INVALID;
@@ -63,7 +55,7 @@ odp_pktio_t create_pktio(odp_queue_type_t q_type)
return pktio;
}
-odp_queue_t create_default_inq(odp_pktio_t pktio, odp_queue_type_t qtype)
+int create_default_inq(odp_pktio_t pktio, odp_queue_type_t qtype)
{
odp_queue_param_t qparam;
odp_queue_t inq_def;
@@ -86,22 +78,56 @@ odp_queue_t create_default_inq(odp_pktio_t pktio, odp_queue_type_t qtype)
CU_ASSERT_FATAL(inq_def != ODP_QUEUE_INVALID);
if (0 > odp_pktio_inq_setdef(pktio, inq_def))
- return ODP_QUEUE_INVALID;
+ return -1;
if (odp_pktio_start(pktio)) {
fprintf(stderr, "unable to start loop\n");
- return ODP_QUEUE_INVALID;
+ return -1;
}
- return inq_def;
+ return 0;
+}
+
+void configure_default_cos(odp_pktio_t pktio, odp_cos_t *cos,
+ odp_queue_t *queue, odp_pool_t *pool)
+{
+ odp_cls_cos_param_t cls_param;
+ odp_pool_t default_pool;
+ odp_cos_t default_cos;
+ odp_queue_t default_queue;
+ int retval;
+ char cosname[ODP_COS_NAME_LEN];
+
+ default_pool = pool_create("DefaultPool");
+ CU_ASSERT(default_pool != ODP_POOL_INVALID);
+
+ default_queue = queue_create("DefaultQueue", true);
+ CU_ASSERT(default_queue != ODP_QUEUE_INVALID);
+
+ sprintf(cosname, "DefaultCos");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = default_pool;
+ cls_param.queue = default_queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+
+ default_cos = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT(default_cos != ODP_COS_INVALID);
+
+ retval = odp_pktio_default_cos_set(pktio, default_cos);
+ CU_ASSERT(retval == 0);
+
+ *cos = default_cos;
+ *queue = default_queue;
+ *pool = default_pool;
+ return;
}
int classification_suite_pmr_term(void)
{
int retcode = 0;
- if (0 != odp_pool_destroy(pool_default)) {
- fprintf(stderr, "pool_default destroy failed.\n");
+ if (0 != odp_pool_destroy(pkt_pool)) {
+ fprintf(stderr, "pkt_pool destroy failed.\n");
retcode = -1;
}
@@ -119,11 +145,16 @@ void classification_test_pmr_term_tcp_dport(void)
odp_pktio_t pktio;
odp_queue_t queue;
odp_queue_t retqueue;
- odp_queue_t defqueue;
+ odp_queue_t default_queue;
+ odp_cos_t default_cos;
+ odp_pool_t default_pool;
+ odp_pool_t recvpool;
odp_pmr_t pmr;
odp_cos_t cos;
- char cosname[ODP_QUEUE_NAME_LEN];
- char queuename[ODP_QUEUE_NAME_LEN];
+ char cosname[ODP_COS_NAME_LEN];
+ odp_cls_cos_param_t cls_param;
+ odp_pool_t pool;
+ odp_pool_t pool_recv;
odp_pmr_match_t match;
val = CLS_DEFAULT_DPORT;
@@ -132,8 +163,8 @@ void classification_test_pmr_term_tcp_dport(void)
pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
- defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
- CU_ASSERT_FATAL(defqueue != ODP_QUEUE_INVALID);
+ retval = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(retval == 0);
match.term = ODP_PMR_TCP_DPORT;
match.val = &val;
@@ -143,22 +174,29 @@ void classification_test_pmr_term_tcp_dport(void)
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);
+ queue = queue_create("tcp_dport1", true);
CU_ASSERT(queue != ODP_QUEUE_INVALID);
- retval = odp_cos_queue_set(cos, queue);
- CU_ASSERT(retval == 0);
+ pool = pool_create("tcp_dport1");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ sprintf(cosname, "tcp_dport");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+
+ cos = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT(cos != ODP_COS_INVALID);
retval = odp_pktio_pmr_cos(pmr, pktio, cos);
CU_ASSERT(retval == 0);
- pkt = create_packet(pool_default, false, &seq, false);
+ configure_default_cos(pktio, &default_cos,
+ &default_queue, &default_pool);
+ pkt = create_packet(pkt_pool, false, &seq, false);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -168,14 +206,17 @@ void classification_test_pmr_term_tcp_dport(void)
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
+ pool_recv = odp_packet_pool(pkt);
+ CU_ASSERT(pool == pool_recv);
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);
+ pkt = create_packet(pkt_pool, false, &seq, false);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -185,15 +226,21 @@ void classification_test_pmr_term_tcp_dport(void)
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
- CU_ASSERT(retqueue == defqueue);
+ CU_ASSERT(retqueue == default_queue);
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == default_pool);
odp_packet_free(pkt);
odp_cos_destroy(cos);
+ odp_cos_destroy(default_cos);
odp_pmr_destroy(pmr);
destroy_inq(pktio);
odp_queue_destroy(queue);
+ odp_queue_destroy(default_queue);
+ odp_pool_destroy(pool);
+ odp_pool_destroy(default_pool);
odp_pktio_close(pktio);
}
@@ -208,11 +255,15 @@ void classification_test_pmr_term_tcp_sport(void)
odp_pktio_t pktio;
odp_queue_t queue;
odp_queue_t retqueue;
- odp_queue_t defqueue;
+ odp_queue_t default_queue;
+ odp_cos_t default_cos;
+ odp_pool_t default_pool;
+ odp_pool_t pool;
+ odp_pool_t recvpool;
odp_pmr_t pmr;
odp_cos_t cos;
- char cosname[ODP_QUEUE_NAME_LEN];
- char queuename[ODP_QUEUE_NAME_LEN];
+ char cosname[ODP_COS_NAME_LEN];
+ odp_cls_cos_param_t cls_param;
odp_pmr_match_t match;
val = CLS_DEFAULT_SPORT;
@@ -221,8 +272,8 @@ void classification_test_pmr_term_tcp_sport(void)
pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
- defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
- CU_ASSERT_FATAL(defqueue != ODP_QUEUE_INVALID);
+ retval = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(retval == 0);
match.term = ODP_PMR_TCP_SPORT;
match.val = &val;
@@ -232,22 +283,28 @@ void classification_test_pmr_term_tcp_sport(void)
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);
+ queue = queue_create("tcp_sport", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
- sprintf(queuename, "%s", "tcp_sport");
+ pool = pool_create("tcp_sport");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
- queue = queue_create(queuename, true);
- CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+ sprintf(cosname, "tcp_sport");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
- retval = odp_cos_queue_set(cos, queue);
- CU_ASSERT(retval == 0);
+ cos = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
retval = odp_pktio_pmr_cos(pmr, pktio, cos);
CU_ASSERT(retval == 0);
- pkt = create_packet(pool_default, false, &seq, false);
+ configure_default_cos(pktio, &default_cos,
+ &default_queue, &default_pool);
+ pkt = create_packet(pkt_pool, false, &seq, false);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -257,12 +314,15 @@ void classification_test_pmr_term_tcp_sport(void)
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
CU_ASSERT(retqueue == queue);
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == pool);
odp_packet_free(pkt);
- pkt = create_packet(pool_default, false, &seq, false);
+ pkt = create_packet(pkt_pool, false, &seq, false);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -272,15 +332,21 @@ void classification_test_pmr_term_tcp_sport(void)
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
- CU_ASSERT(retqueue == defqueue);
+ CU_ASSERT(retqueue == default_queue);
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == default_pool);
odp_packet_free(pkt);
odp_cos_destroy(cos);
+ odp_cos_destroy(default_cos);
odp_pmr_destroy(pmr);
destroy_inq(pktio);
+ odp_pool_destroy(default_pool);
+ odp_pool_destroy(pool);
odp_queue_destroy(queue);
+ odp_queue_destroy(default_queue);
odp_pktio_close(pktio);
}
@@ -293,14 +359,18 @@ void classification_test_pmr_term_udp_dport(void)
uint16_t mask;
int retval;
odp_pktio_t pktio;
+ odp_pool_t pool;
+ odp_pool_t recvpool;
odp_queue_t queue;
odp_queue_t retqueue;
- odp_queue_t defqueue;
+ odp_queue_t default_queue;
+ odp_cos_t default_cos;
+ odp_pool_t default_pool;
odp_pmr_t pmr;
odp_cos_t cos;
- char cosname[ODP_QUEUE_NAME_LEN];
- char queuename[ODP_QUEUE_NAME_LEN];
+ char cosname[ODP_COS_NAME_LEN];
odp_pmr_match_t match;
+ odp_cls_cos_param_t cls_param;
val = CLS_DEFAULT_DPORT;
mask = 0xffff;
@@ -308,8 +378,8 @@ void classification_test_pmr_term_udp_dport(void)
pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
- defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
- CU_ASSERT_FATAL(defqueue != ODP_QUEUE_INVALID);
+ retval = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(retval == 0);
match.term = ODP_PMR_UDP_DPORT;
match.val = &val;
@@ -319,22 +389,28 @@ void classification_test_pmr_term_udp_dport(void)
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);
+ queue = queue_create("udp_dport", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
- sprintf(queuename, "%s", "udp_dport");
+ pool = pool_create("udp_dport");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
- queue = queue_create(queuename, true);
- CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+ sprintf(cosname, "udp_dport");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
- retval = odp_cos_queue_set(cos, queue);
- CU_ASSERT(retval == 0);
+ cos = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
retval = odp_pktio_pmr_cos(pmr, pktio, cos);
CU_ASSERT(retval == 0);
- pkt = create_packet(pool_default, false, &seq, true);
+ configure_default_cos(pktio, &default_cos,
+ &default_queue, &default_pool);
+ pkt = create_packet(pkt_pool, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -344,13 +420,16 @@ void classification_test_pmr_term_udp_dport(void)
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
CU_ASSERT(retqueue == queue);
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == pool);
odp_packet_free(pkt);
/* Other packets received in default queue */
- pkt = create_packet(pool_default, false, &seq, true);
+ pkt = create_packet(pkt_pool, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -360,15 +439,21 @@ void classification_test_pmr_term_udp_dport(void)
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
- CU_ASSERT(retqueue == defqueue);
+ CU_ASSERT(retqueue == default_queue);
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == default_pool);
odp_packet_free(pkt);
odp_cos_destroy(cos);
+ odp_cos_destroy(default_cos);
odp_pmr_destroy(pmr);
destroy_inq(pktio);
odp_queue_destroy(queue);
+ odp_queue_destroy(default_queue);
+ odp_pool_destroy(default_pool);
+ odp_pool_destroy(pool);
odp_pktio_close(pktio);
}
@@ -383,12 +468,16 @@ void classification_test_pmr_term_udp_sport(void)
odp_pktio_t pktio;
odp_queue_t queue;
odp_queue_t retqueue;
- odp_queue_t defqueue;
+ odp_queue_t default_queue;
+ odp_cos_t default_cos;
+ odp_pool_t default_pool;
+ odp_pool_t pool;
+ odp_pool_t recvpool;
odp_pmr_t pmr;
odp_cos_t cos;
- char cosname[ODP_QUEUE_NAME_LEN];
- char queuename[ODP_QUEUE_NAME_LEN];
+ char cosname[ODP_COS_NAME_LEN];
odp_pmr_match_t match;
+ odp_cls_cos_param_t cls_param;
val = CLS_DEFAULT_SPORT;
mask = 0xffff;
@@ -396,8 +485,8 @@ void classification_test_pmr_term_udp_sport(void)
pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
- defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
- CU_ASSERT_FATAL(defqueue != ODP_QUEUE_INVALID);
+ retval = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(retval == 0);
match.term = ODP_PMR_UDP_SPORT;
match.val = &val;
@@ -407,22 +496,28 @@ void classification_test_pmr_term_udp_sport(void)
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);
+ queue = queue_create("udp_sport", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
- sprintf(queuename, "%s", "udp_sport");
+ pool = pool_create("udp_sport");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
- queue = queue_create(queuename, true);
- CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+ sprintf(cosname, "udp_sport");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
- retval = odp_cos_queue_set(cos, queue);
- CU_ASSERT(retval == 0);
+ cos = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
retval = odp_pktio_pmr_cos(pmr, pktio, cos);
CU_ASSERT(retval == 0);
- pkt = create_packet(pool_default, false, &seq, true);
+ configure_default_cos(pktio, &default_cos,
+ &default_queue, &default_pool);
+ pkt = create_packet(pkt_pool, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -432,12 +527,15 @@ void classification_test_pmr_term_udp_sport(void)
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
CU_ASSERT(retqueue == queue);
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == pool);
odp_packet_free(pkt);
- pkt = create_packet(pool_default, false, &seq, true);
+ pkt = create_packet(pkt_pool, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -447,15 +545,21 @@ void classification_test_pmr_term_udp_sport(void)
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
- CU_ASSERT(retqueue == defqueue);
+ CU_ASSERT(retqueue == default_queue);
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == default_pool);
odp_packet_free(pkt);
odp_cos_destroy(cos);
+ odp_cos_destroy(default_cos);
odp_pmr_destroy(pmr);
destroy_inq(pktio);
+ odp_pool_destroy(default_pool);
+ odp_pool_destroy(pool);
odp_queue_destroy(queue);
+ odp_queue_destroy(default_queue);
odp_pktio_close(pktio);
}
@@ -469,11 +573,15 @@ void classification_test_pmr_term_ipproto(void)
odp_pktio_t pktio;
odp_queue_t queue;
odp_queue_t retqueue;
- odp_queue_t defqueue;
+ odp_queue_t default_queue;
+ odp_cos_t default_cos;
+ odp_pool_t default_pool;
+ odp_pool_t pool;
+ odp_pool_t recvpool;
odp_pmr_t pmr;
odp_cos_t cos;
- char cosname[ODP_QUEUE_NAME_LEN];
- char queuename[ODP_QUEUE_NAME_LEN];
+ char cosname[ODP_COS_NAME_LEN];
+ odp_cls_cos_param_t cls_param;
odp_pmr_match_t match;
val = ODPH_IPPROTO_UDP;
@@ -482,8 +590,8 @@ void classification_test_pmr_term_ipproto(void)
pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
- defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
- CU_ASSERT_FATAL(defqueue != ODP_QUEUE_INVALID);
+ retval = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(retval == 0);
match.term = ODP_PMR_IPPROTO;
match.val = &val;
@@ -493,50 +601,253 @@ void classification_test_pmr_term_ipproto(void)
pmr = odp_pmr_create(&match);
CU_ASSERT(pmr != ODP_PMR_INVAL);
+ queue = queue_create("ipproto", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ pool = pool_create("ipproto");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
sprintf(cosname, "ipproto");
- cos = odp_cos_create(cosname);
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+
+ cos = odp_cls_cos_create(cosname, &cls_param);
CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
- sprintf(queuename, "%s", "ipproto");
+ retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+ CU_ASSERT(retval == 0);
+
+ configure_default_cos(pktio, &default_cos,
+ &default_queue, &default_pool);
+ pkt = create_packet(pkt_pool, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == pool);
+ CU_ASSERT(retqueue == queue);
+ odp_packet_free(pkt);
+
+ /* Other packets delivered to default queue */
+ pkt = create_packet(pkt_pool, false, &seq, false);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
+ seqno = cls_pkt_get_seq(pkt);
+ CU_ASSERT(seqno != TEST_SEQ_INVALID);
+
+ enqueue_pktio_interface(pkt, pktio);
+
+ pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == default_pool);
+ CU_ASSERT(retqueue == default_queue);
+
+ odp_cos_destroy(cos);
+ odp_cos_destroy(default_cos);
+ odp_pmr_destroy(pmr);
+ odp_packet_free(pkt);
+ destroy_inq(pktio);
+ odp_pool_destroy(default_pool);
+ odp_pool_destroy(pool);
+ odp_queue_destroy(queue);
+ odp_queue_destroy(default_queue);
+ odp_pktio_close(pktio);
+}
+
+static void classification_test_pmr_pool_set(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 default_queue;
+ odp_cos_t default_cos;
+ odp_pool_t default_pool;
+ odp_pool_t pool;
+ odp_pool_t pool_new;
+ odp_pool_t recvpool;
+ odp_pmr_t pmr;
+ odp_cos_t cos;
+ char cosname[ODP_COS_NAME_LEN];
+ odp_cls_cos_param_t cls_param;
+ odp_pmr_match_t match;
+
+ val = ODPH_IPPROTO_UDP;
+ mask = 0xff;
+ seqno = 0;
+
+ pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
+ retval = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(retval == 0);
+
+ match.term = ODP_PMR_IPPROTO;
+ match.val = &val;
+ match.mask = &mask;
+ match.val_sz = sizeof(val);
- queue = queue_create(queuename, true);
+ pmr = odp_pmr_create(&match);
+ CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+ queue = queue_create("ipproto1", true);
CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
- retval = odp_cos_queue_set(cos, queue);
+ pool = pool_create("ipproto1");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ sprintf(cosname, "ipproto1");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+
+ cos = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+ pool_new = pool_create("ipproto2");
+ CU_ASSERT_FATAL(pool_new != ODP_POOL_INVALID);
+
+ /* new pool is set on CoS */
+ retval = odp_cls_cos_pool_set(cos, pool_new);
CU_ASSERT(retval == 0);
retval = odp_pktio_pmr_cos(pmr, pktio, cos);
CU_ASSERT(retval == 0);
- pkt = create_packet(pool_default, false, &seq, true);
+ configure_default_cos(pktio, &default_cos,
+ &default_queue, &default_pool);
+ pkt = create_packet(pkt_pool, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == pool_new);
CU_ASSERT(retqueue == queue);
odp_packet_free(pkt);
- /* Other packets delivered to default queue */
- pkt = create_packet(pool_default, false, &seq, false);
+ odp_cos_destroy(cos);
+ odp_cos_destroy(default_cos);
+ odp_pmr_destroy(pmr);
+ odp_packet_free(pkt);
+ destroy_inq(pktio);
+ odp_pool_destroy(default_pool);
+ odp_pool_destroy(pool);
+ odp_pool_destroy(pool_new);
+ odp_queue_destroy(queue);
+ odp_queue_destroy(default_queue);
+ odp_pktio_close(pktio);
+}
+
+static void classification_test_pmr_queue_set(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 default_queue;
+ odp_cos_t default_cos;
+ odp_pool_t default_pool;
+ odp_pool_t pool;
+ odp_queue_t queue_new;
+ odp_pool_t recvpool;
+ odp_pmr_t pmr;
+ odp_cos_t cos;
+ char cosname[ODP_COS_NAME_LEN];
+ odp_cls_cos_param_t cls_param;
+ odp_pmr_match_t match;
+
+ val = ODPH_IPPROTO_UDP;
+ mask = 0xff;
+ seqno = 0;
+
+ pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
+ retval = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+ CU_ASSERT(retval == 0);
+
+ 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);
+
+ queue = queue_create("ipproto1", true);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ pool = pool_create("ipproto1");
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ sprintf(cosname, "ipproto1");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue;
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+
+ cos = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+ queue_new = queue_create("ipproto2", true);
+ CU_ASSERT_FATAL(queue_new != ODP_QUEUE_INVALID);
+
+ /* new queue is set on CoS */
+ retval = odp_cos_queue_set(cos, queue_new);
+ CU_ASSERT(retval == 0);
+
+ retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+ CU_ASSERT(retval == 0);
+
+ configure_default_cos(pktio, &default_cos,
+ &default_queue, &default_pool);
+ pkt = create_packet(pkt_pool, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
enqueue_pktio_interface(pkt, pktio);
pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
- CU_ASSERT(retqueue == defqueue);
+ recvpool = odp_packet_pool(pkt);
+ CU_ASSERT(recvpool == pool);
+ CU_ASSERT(retqueue == queue_new);
+ odp_packet_free(pkt);
odp_cos_destroy(cos);
+ odp_cos_destroy(default_cos);
odp_pmr_destroy(pmr);
odp_packet_free(pkt);
destroy_inq(pktio);
+ odp_pool_destroy(default_pool);
+ odp_pool_destroy(pool);
+ odp_queue_destroy(queue_new);
odp_queue_destroy(queue);
+ odp_queue_destroy(default_queue);
odp_pktio_close(pktio);
}
@@ -546,5 +857,7 @@ odp_testinfo_t classification_suite_pmr[] = {
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(classification_test_pmr_pool_set),
+ ODP_TEST_INFO(classification_test_pmr_queue_set),
ODP_TEST_INFO_NULL,
};
diff --git a/test/validation/classification/odp_classification_tests.c b/test/validation/classification/odp_classification_tests.c
index 3944d9456..e11c3d8b6 100644
--- a/test/validation/classification/odp_classification_tests.c
+++ b/test/validation/classification/odp_classification_tests.c
@@ -14,6 +14,7 @@
static odp_cos_t cos_list[CLS_ENTRIES];
static odp_pmr_t pmr_list[CLS_ENTRIES];
static odp_queue_t queue_list[CLS_ENTRIES];
+static odp_pool_t pool_list[CLS_ENTRIES];
static odp_pmr_set_t pmr_set;
static odp_pool_t pool_default;
@@ -24,7 +25,6 @@ odp_atomic_u32_t seq;
int classification_suite_init(void)
{
- odp_pool_param_t param;
odp_queue_t inq_def;
odp_queue_param_t qparam;
char queuename[ODP_QUEUE_NAME_LEN];
@@ -32,13 +32,7 @@ int classification_suite_init(void)
int ret;
odp_pktio_param_t pktio_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_pool", &param);
+ pool_default = pool_create("classification_pool");
if (ODP_POOL_INVALID == pool_default) {
fprintf(stderr, "Packet pool creation failed.\n");
return -1;
@@ -54,6 +48,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;
@@ -73,6 +68,9 @@ int classification_suite_init(void)
for (i = 0; i < CLS_ENTRIES; i++)
queue_list[i] = ODP_QUEUE_INVALID;
+ for (i = 0; i < CLS_ENTRIES; i++)
+ pool_list[i] = ODP_POOL_INVALID;
+
odp_atomic_init_u32(&seq, 0);
ret = odp_pktio_start(pktio_loop);
@@ -113,6 +111,9 @@ int classification_suite_term(void)
for (i = 0; i < CLS_ENTRIES; i++)
odp_queue_destroy(queue_list[i]);
+ for (i = 0; i < CLS_ENTRIES; i++)
+ odp_pool_destroy(pool_list[i]);
+
return retcode;
}
@@ -129,14 +130,13 @@ void configure_cls_pmr_chain(void)
int retval;
char cosname[ODP_QUEUE_NAME_LEN];
odp_queue_param_t qparam;
+ odp_cls_cos_param_t cls_param;
char queuename[ODP_QUEUE_NAME_LEN];
+ char poolname[ODP_POOL_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);
odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_NORMAL;
@@ -150,13 +150,19 @@ void configure_cls_pmr_chain(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_SRC] != ODP_QUEUE_INVALID);
- retval = odp_cos_queue_set(cos_list[CLS_PMR_CHAIN_SRC],
- queue_list[CLS_PMR_CHAIN_SRC]);
- CU_ASSERT(retval == 0);
- sprintf(cosname, "DstCos");
- cos_list[CLS_PMR_CHAIN_DST] = odp_cos_create(cosname);
- CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_DST] != ODP_COS_INVALID);
+ sprintf(poolname, "%s", "SrcPool");
+ pool_list[CLS_PMR_CHAIN_SRC] = pool_create(poolname);
+ CU_ASSERT_FATAL(pool_list[CLS_PMR_CHAIN_SRC] != ODP_POOL_INVALID);
+
+ sprintf(cosname, "SrcCos");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool_list[CLS_PMR_CHAIN_SRC];
+ cls_param.queue = queue_list[CLS_PMR_CHAIN_SRC];
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_list[CLS_PMR_CHAIN_SRC] = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_SRC] != ODP_COS_INVALID);
+
odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_NORMAL;
@@ -169,9 +175,17 @@ void configure_cls_pmr_chain(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_DST] != ODP_QUEUE_INVALID);
- retval = odp_cos_queue_set(cos_list[CLS_PMR_CHAIN_DST],
- queue_list[CLS_PMR_CHAIN_DST]);
- CU_ASSERT(retval == 0);
+ sprintf(poolname, "%s", "DstPool");
+ pool_list[CLS_PMR_CHAIN_DST] = pool_create(poolname);
+ CU_ASSERT_FATAL(pool_list[CLS_PMR_CHAIN_DST] != ODP_POOL_INVALID);
+
+ sprintf(cosname, "DstCos");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool_list[CLS_PMR_CHAIN_DST];
+ cls_param.queue = queue_list[CLS_PMR_CHAIN_DST];
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_list[CLS_PMR_CHAIN_DST] = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_DST] != ODP_COS_INVALID);
parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
match.term = ODP_PMR_SIP_ADDR;
@@ -206,11 +220,13 @@ void test_cls_pmr_chain(void)
odph_ipv4hdr_t *ip;
odph_udphdr_t *udp;
odp_queue_t queue;
+ odp_pool_t pool;
uint32_t addr = 0;
uint32_t mask;
uint32_t seqno = 0;
pkt = create_packet(pool_default, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -226,12 +242,15 @@ void test_cls_pmr_chain(void)
enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ pool = odp_packet_pool(pkt);
+ CU_ASSERT(pool == pool_list[CLS_PMR_CHAIN_DST]);
odp_packet_free(pkt);
pkt = create_packet(pool_default, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -243,9 +262,11 @@ void test_cls_pmr_chain(void)
enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ pool = odp_packet_pool(pkt);
+ CU_ASSERT(pool == pool_list[CLS_PMR_CHAIN_SRC]);
odp_packet_free(pkt);
}
@@ -253,12 +274,10 @@ void configure_pktio_default_cos(void)
{
int retval;
odp_queue_param_t qparam;
+ odp_cls_cos_param_t cls_param;
char cosname[ODP_COS_NAME_LEN];
char queuename[ODP_QUEUE_NAME_LEN];
-
- sprintf(cosname, "DefaultCoS");
- cos_list[CLS_DEFAULT] = odp_cos_create(cosname);
- CU_ASSERT_FATAL(cos_list[CLS_DEFAULT] != ODP_COS_INVALID);
+ char poolname[ODP_POOL_NAME_LEN];
odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
@@ -269,9 +288,17 @@ void configure_pktio_default_cos(void)
ODP_QUEUE_TYPE_SCHED, &qparam);
CU_ASSERT_FATAL(queue_list[CLS_DEFAULT] != ODP_QUEUE_INVALID);
- retval = odp_cos_queue_set(cos_list[CLS_DEFAULT],
- queue_list[CLS_DEFAULT]);
- CU_ASSERT(retval == 0);
+ sprintf(poolname, "DefaultPool");
+ pool_list[CLS_DEFAULT] = pool_create(poolname);
+ CU_ASSERT_FATAL(pool_list[CLS_DEFAULT] != ODP_POOL_INVALID);
+
+ sprintf(cosname, "DefaultCoS");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool_list[CLS_DEFAULT];
+ cls_param.queue = queue_list[CLS_DEFAULT];
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_list[CLS_DEFAULT] = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos_list[CLS_DEFAULT] != ODP_COS_INVALID);
retval = odp_pktio_default_cos_set(pktio_loop, cos_list[CLS_DEFAULT]);
CU_ASSERT(retval == 0);
@@ -282,18 +309,22 @@ void test_pktio_default_cos(void)
odp_packet_t pkt;
odp_queue_t queue;
uint32_t seqno = 0;
+ odp_pool_t pool;
/* create a default packet */
pkt = create_packet(pool_default, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
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_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
/* Default packet should be received in default queue */
CU_ASSERT(queue == queue_list[CLS_DEFAULT]);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
+ pool = odp_packet_pool(pkt);
+ CU_ASSERT(pool == pool_list[CLS_DEFAULT]);
odp_packet_free(pkt);
}
@@ -302,8 +333,10 @@ void configure_pktio_error_cos(void)
{
int retval;
odp_queue_param_t qparam;
+ odp_cls_cos_param_t cls_param;
char queuename[ODP_QUEUE_NAME_LEN];
char cosname[ODP_COS_NAME_LEN];
+ char poolname[ODP_POOL_NAME_LEN];
odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_LOWEST;
@@ -316,13 +349,18 @@ void configure_pktio_error_cos(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_ERROR] != ODP_QUEUE_INVALID);
+ sprintf(poolname, "ErrorPool");
+ pool_list[CLS_ERROR] = pool_create(poolname);
+ CU_ASSERT_FATAL(pool_list[CLS_ERROR] != ODP_POOL_INVALID);
+
sprintf(cosname, "%s", "ErrorCos");
- cos_list[CLS_ERROR] = odp_cos_create(cosname);
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool_list[CLS_ERROR];
+ cls_param.queue = queue_list[CLS_ERROR];
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_list[CLS_ERROR] = odp_cls_cos_create(cosname, &cls_param);
CU_ASSERT_FATAL(cos_list[CLS_ERROR] != ODP_COS_INVALID);
- 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]);
CU_ASSERT(retval == 0);
}
@@ -331,9 +369,11 @@ void test_pktio_error_cos(void)
{
odp_queue_t queue;
odp_packet_t pkt;
+ odp_pool_t pool;
/*Create an error packet */
pkt = create_packet(pool_default, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
/* Incorrect IpV4 version */
@@ -342,9 +382,11 @@ void test_pktio_error_cos(void)
enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
/* Error packet should be received in error queue */
CU_ASSERT(queue == queue_list[CLS_ERROR]);
+ pool = odp_packet_pool(pkt);
+ CU_ASSERT(pool == pool_list[CLS_ERROR]);
odp_packet_free(pkt);
}
@@ -382,12 +424,15 @@ void configure_cos_with_l2_priority(void)
uint8_t num_qos = CLS_L2_QOS_MAX;
odp_cos_t cos_tbl[CLS_L2_QOS_MAX];
odp_queue_t queue_tbl[CLS_L2_QOS_MAX];
+ odp_pool_t pool;
uint8_t qos_tbl[CLS_L2_QOS_MAX];
char cosname[ODP_COS_NAME_LEN];
char queuename[ODP_QUEUE_NAME_LEN];
+ char poolname[ODP_POOL_NAME_LEN];
int retval;
int i;
odp_queue_param_t qparam;
+ odp_cls_cos_param_t cls_param;
/** Initialize scalar variable qos_tbl **/
for (i = 0; i < CLS_L2_QOS_MAX; i++)
@@ -398,23 +443,31 @@ void configure_cos_with_l2_priority(void)
qparam.sched.group = ODP_SCHED_GROUP_ALL;
for (i = 0; i < num_qos; i++) {
qparam.sched.prio = ODP_SCHED_PRIO_LOWEST - i;
- sprintf(cosname, "%s_%d", "L2_Cos", i);
- cos_tbl[i] = odp_cos_create(cosname);
- if (cos_tbl[i] == ODP_COS_INVALID)
- break;
-
- cos_list[CLS_L2_QOS_0 + i] = cos_tbl[i];
sprintf(queuename, "%s_%d", "L2_Queue", i);
queue_tbl[i] = odp_queue_create(queuename, ODP_QUEUE_TYPE_SCHED,
&qparam);
CU_ASSERT_FATAL(queue_tbl[i] != ODP_QUEUE_INVALID);
queue_list[CLS_L2_QOS_0 + i] = queue_tbl[i];
- retval = odp_cos_queue_set(cos_tbl[i], queue_tbl[i]);
- CU_ASSERT(retval == 0);
+
+ sprintf(poolname, "%s_%d", "L2_Pool", i);
+ pool = pool_create(poolname);
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+ pool_list[CLS_L2_QOS_0 + i] = pool;
+
+ sprintf(cosname, "%s_%d", "L2_Cos", i);
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool;
+ cls_param.queue = queue_tbl[i];
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_tbl[i] = odp_cls_cos_create(cosname, &cls_param);
+ if (cos_tbl[i] == ODP_COS_INVALID)
+ break;
+
+ cos_list[CLS_L2_QOS_0 + i] = cos_tbl[i];
qos_tbl[i] = i;
}
/* count 'i' is passed instead of num_qos to handle the rare scenario
- if the odp_cos_create() failed in the middle*/
+ if the odp_cls_cos_create() failed in the middle*/
retval = odp_cos_with_l2_priority(pktio_loop, i, qos_tbl, cos_tbl);
CU_ASSERT(retval == 0);
}
@@ -425,11 +478,13 @@ void test_cos_with_l2_priority(void)
odph_ethhdr_t *ethhdr;
odph_vlanhdr_t *vlan;
odp_queue_t queue;
+ odp_pool_t pool;
uint32_t seqno = 0;
uint8_t i;
for (i = 0; i < CLS_L2_QOS_MAX; i++) {
pkt = create_packet(pool_default, true, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
@@ -437,8 +492,10 @@ void test_cos_with_l2_priority(void)
vlan->tci = odp_cpu_to_be_16(i << 13);
enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]);
+ pool = odp_packet_pool(pkt);
+ CU_ASSERT(pool == pool_list[CLS_L2_QOS_0 + i]);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
}
@@ -451,8 +508,10 @@ void configure_pmr_cos(void)
int retval;
odp_pmr_match_t match;
odp_queue_param_t qparam;
+ odp_cls_cos_param_t cls_param;
char cosname[ODP_COS_NAME_LEN];
char queuename[ODP_QUEUE_NAME_LEN];
+ char poolname[ODP_POOL_NAME_LEN];
val = CLS_PMR_SPORT;
mask = 0xffff;
@@ -462,11 +521,7 @@ void configure_pmr_cos(void)
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);
+ CU_ASSERT_FATAL(pmr_list[CLS_PMR] != ODP_PMR_INVAL);
odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST;
@@ -479,9 +534,17 @@ void configure_pmr_cos(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_PMR] != ODP_QUEUE_INVALID);
- retval = odp_cos_queue_set(cos_list[CLS_PMR],
- queue_list[CLS_PMR]);
- CU_ASSERT(retval == 0);
+ sprintf(poolname, "PMR_Pool");
+ pool_list[CLS_PMR] = pool_create(poolname);
+ CU_ASSERT_FATAL(pool_list[CLS_PMR] != ODP_POOL_INVALID);
+
+ sprintf(cosname, "PMR_CoS");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool_list[CLS_PMR];
+ cls_param.queue = queue_list[CLS_PMR];
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_list[CLS_PMR] = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos_list[CLS_PMR] != ODP_COS_INVALID);
retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR], pktio_loop,
cos_list[CLS_PMR]);
@@ -493,17 +556,21 @@ void test_pmr_cos(void)
odp_packet_t pkt;
odph_udphdr_t *udp;
odp_queue_t queue;
+ odp_pool_t pool;
uint32_t seqno = 0;
pkt = create_packet(pool_default, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
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_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_PMR]);
+ pool = odp_packet_pool(pkt);
+ CU_ASSERT(pool == pool_list[CLS_PMR]);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
}
@@ -516,8 +583,10 @@ void configure_pktio_pmr_match_set_cos(void)
uint16_t maskport;
int num_terms = 2; /* one pmr for each L3 and L4 */
odp_queue_param_t qparam;
+ odp_cls_cos_param_t cls_param;
char cosname[ODP_COS_NAME_LEN];
char queuename[ODP_QUEUE_NAME_LEN];
+ char poolname[ODP_POOL_NAME_LEN];
uint32_t addr = 0;
uint32_t mask;
@@ -538,10 +607,6 @@ void configure_pktio_pmr_match_set_cos(void)
retval = odp_pmr_match_set_create(num_terms, pmr_terms, &pmr_set);
CU_ASSERT(retval > 0);
- 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);
-
odp_queue_param_init(&qparam);
qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST;
qparam.sched.sync = ODP_SCHED_SYNC_NONE;
@@ -553,9 +618,17 @@ void configure_pktio_pmr_match_set_cos(void)
&qparam);
CU_ASSERT_FATAL(queue_list[CLS_PMR_SET] != ODP_QUEUE_INVALID);
- retval = odp_cos_queue_set(cos_list[CLS_PMR_SET],
- queue_list[CLS_PMR_SET]);
- CU_ASSERT(retval == 0);
+ sprintf(poolname, "cos_pmr_set_pool");
+ pool_list[CLS_PMR_SET] = pool_create(poolname);
+ CU_ASSERT_FATAL(pool_list[CLS_PMR_SET] != ODP_POOL_INVALID);
+
+ sprintf(cosname, "cos_pmr_set");
+ odp_cls_cos_param_init(&cls_param);
+ cls_param.pool = pool_list[CLS_PMR_SET];
+ cls_param.queue = queue_list[CLS_PMR_SET];
+ cls_param.drop_policy = ODP_COS_DROP_POOL;
+ cos_list[CLS_PMR_SET] = odp_cls_cos_create(cosname, &cls_param);
+ CU_ASSERT_FATAL(cos_list[CLS_PMR_SET] != ODP_COS_INVALID);
retval = odp_pktio_pmr_match_set_cos(pmr_set, pktio_loop,
cos_list[CLS_PMR_SET]);
@@ -569,10 +642,12 @@ void test_pktio_pmr_match_set_cos(void)
odph_ipv4hdr_t *ip;
odph_udphdr_t *udp;
odp_packet_t pkt;
+ odp_pool_t pool;
odp_queue_t queue;
uint32_t seqno = 0;
pkt = create_packet(pool_default, false, &seq, true);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
seqno = cls_pkt_get_seq(pkt);
CU_ASSERT(seqno != TEST_SEQ_INVALID);
@@ -586,8 +661,10 @@ void test_pktio_pmr_match_set_cos(void)
udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT);
enqueue_pktio_interface(pkt, pktio_loop);
pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(pkt != ODP_PACKET_INVALID);
+ CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID);
CU_ASSERT(queue == queue_list[CLS_PMR_SET]);
+ pool = odp_packet_pool(pkt);
+ CU_ASSERT(pool == pool_list[CLS_PMR_SET]);
CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
odp_packet_free(pkt);
}
diff --git a/test/validation/classification/odp_classification_testsuites.h b/test/validation/classification/odp_classification_testsuites.h
index 7d27d95b5..02828e125 100644
--- a/test/validation/classification/odp_classification_testsuites.h
+++ b/test/validation/classification/odp_classification_testsuites.h
@@ -25,11 +25,14 @@ odp_packet_t create_packet(odp_pool_t pool, bool vlan,
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 create_default_inq(odp_pktio_t pktio, odp_queue_type_t qtype);
+void configure_default_cos(odp_pktio_t pktio, odp_cos_t *cos,
+ odp_queue_t *queue, odp_pool_t *pool);
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);
+odp_pool_t pool_create(const char *poolname);
+odp_queue_t queue_create(const char *queuename, bool sched);
void configure_pktio_default_cos(void);
void test_pktio_default_cos(void);
void configure_pktio_error_cos(void);
diff --git a/test/validation/crypto/crypto.h b/test/validation/crypto/crypto.h
index 4769fad1f..5224e4763 100644
--- a/test/validation/crypto/crypto.h
+++ b/test/validation/crypto/crypto.h
@@ -18,6 +18,10 @@ void crypto_test_enc_alg_aes128_cbc(void);
void crypto_test_enc_alg_aes128_cbc_ovr_iv(void);
void crypto_test_dec_alg_aes128_cbc(void);
void crypto_test_dec_alg_aes128_cbc_ovr_iv(void);
+void crypto_test_enc_alg_aes128_gcm(void);
+void crypto_test_enc_alg_aes128_gcm_ovr_iv(void);
+void crypto_test_dec_alg_aes128_gcm(void);
+void crypto_test_dec_alg_aes128_gcm_ovr_iv(void);
void crypto_test_alg_hmac_md5(void);
void crypto_test_alg_hmac_sha256(void);
diff --git a/test/validation/crypto/odp_crypto_test_inp.c b/test/validation/crypto/odp_crypto_test_inp.c
index 5295c6329..b6fcb1272 100644
--- a/test/validation/crypto/odp_crypto_test_inp.c
+++ b/test/validation/crypto/odp_crypto_test_inp.c
@@ -35,10 +35,15 @@ static void alg_test(odp_crypto_op_t op,
odp_crypto_key_t cipher_key,
odp_auth_alg_t auth_alg,
odp_crypto_key_t auth_key,
- uint8_t *input_vec,
- unsigned int input_vec_len,
- uint8_t *output_vec,
- unsigned int output_vec_len)
+ odp_crypto_data_range_t *cipher_range,
+ odp_crypto_data_range_t *auth_range,
+ const uint8_t *plaintext,
+ unsigned int plaintext_len,
+ const uint8_t *ciphertext,
+ unsigned int ciphertext_len,
+ const uint8_t *digest,
+ unsigned int digest_len
+ )
{
odp_crypto_session_t session;
int rc;
@@ -69,11 +74,12 @@ static void alg_test(odp_crypto_op_t op,
odp_crypto_session_to_u64(ODP_CRYPTO_SESSION_INVALID));
/* Prepare input data */
- odp_packet_t pkt = odp_packet_alloc(suite_context.pool, input_vec_len);
+ odp_packet_t pkt = odp_packet_alloc(suite_context.pool,
+ plaintext_len + digest_len);
CU_ASSERT(pkt != ODP_PACKET_INVALID);
uint8_t *data_addr = odp_packet_data(pkt);
- memcpy(data_addr, input_vec, input_vec_len);
- const int data_off = 0;
+ memcpy(data_addr, plaintext, plaintext_len);
+ int data_off = 0;
/* Prepare input/output params */
odp_crypto_op_params_t op_params;
@@ -82,20 +88,24 @@ static void alg_test(odp_crypto_op_t op,
op_params.pkt = pkt;
op_params.out_pkt = pkt;
op_params.ctx = (void *)0xdeadbeef;
- if (cipher_alg != ODP_CIPHER_ALG_NULL &&
- auth_alg == ODP_AUTH_ALG_NULL) {
+
+ if (cipher_range) {
+ op_params.cipher_range = *cipher_range;
+ data_off = cipher_range->offset;
+ } else {
op_params.cipher_range.offset = data_off;
- op_params.cipher_range.length = input_vec_len;
- if (op_iv_ptr)
- op_params.override_iv_ptr = op_iv_ptr;
- } else if (cipher_alg == ODP_CIPHER_ALG_NULL &&
- auth_alg != ODP_AUTH_ALG_NULL) {
- op_params.auth_range.offset = data_off;
- op_params.auth_range.length = input_vec_len;
- op_params.hash_result_offset = data_off;
+ op_params.cipher_range.length = plaintext_len;
+ }
+ if (auth_range) {
+ op_params.auth_range = *auth_range;
} else {
- CU_FAIL("%s : not implemented for combined alg mode\n");
+ op_params.auth_range.offset = data_off;
+ op_params.auth_range.length = plaintext_len;
}
+ if (op_iv_ptr)
+ op_params.override_iv_ptr = op_iv_ptr;
+
+ op_params.hash_result_offset = plaintext_len;
rc = odp_crypto_operation(&op_params, &posted, &result);
if (rc < 0) {
@@ -119,7 +129,12 @@ static void alg_test(odp_crypto_op_t op,
CU_ASSERT(result.ok);
CU_ASSERT(result.pkt == pkt);
- CU_ASSERT(!memcmp(data_addr, output_vec, output_vec_len));
+ if (cipher_alg != ODP_CIPHER_ALG_NULL)
+ CU_ASSERT(!memcmp(data_addr, ciphertext, ciphertext_len));
+
+ if (op == ODP_CRYPTO_OP_ENCODE && auth_alg != ODP_AUTH_ALG_NULL)
+ CU_ASSERT(!memcmp(data_addr + op_params.hash_result_offset,
+ digest, digest_len));
CU_ASSERT(result.ctx == (void *)0xdeadbeef);
cleanup:
@@ -155,10 +170,11 @@ void crypto_test_enc_alg_3des_cbc(void)
cipher_key,
ODP_AUTH_ALG_NULL,
auth_key,
+ NULL, NULL,
tdes_cbc_reference_plaintext[i],
tdes_cbc_reference_length[i],
tdes_cbc_reference_ciphertext[i],
- tdes_cbc_reference_length[i]);
+ tdes_cbc_reference_length[i], NULL, 0);
}
}
@@ -185,10 +201,11 @@ void crypto_test_enc_alg_3des_cbc_ovr_iv(void)
cipher_key,
ODP_AUTH_ALG_NULL,
auth_key,
+ NULL, NULL,
tdes_cbc_reference_plaintext[i],
tdes_cbc_reference_length[i],
tdes_cbc_reference_ciphertext[i],
- tdes_cbc_reference_length[i]);
+ tdes_cbc_reference_length[i], NULL, 0);
}
}
@@ -220,10 +237,11 @@ void crypto_test_dec_alg_3des_cbc(void)
cipher_key,
ODP_AUTH_ALG_NULL,
auth_key,
+ NULL, NULL,
tdes_cbc_reference_ciphertext[i],
tdes_cbc_reference_length[i],
tdes_cbc_reference_plaintext[i],
- tdes_cbc_reference_length[i]);
+ tdes_cbc_reference_length[i], NULL, 0);
}
}
@@ -252,10 +270,161 @@ void crypto_test_dec_alg_3des_cbc_ovr_iv(void)
cipher_key,
ODP_AUTH_ALG_NULL,
auth_key,
+ NULL, NULL,
tdes_cbc_reference_ciphertext[i],
tdes_cbc_reference_length[i],
tdes_cbc_reference_plaintext[i],
- tdes_cbc_reference_length[i]);
+ tdes_cbc_reference_length[i], NULL, 0);
+ }
+}
+
+/* This test verifies the correctness of encode (plaintext -> ciphertext)
+ * operation for AES128_GCM algorithm. IV for the operation is the session IV.
+ * In addition the test verifies if the implementation can use the
+ * packet buffer as completion event buffer.*/
+void crypto_test_enc_alg_aes128_gcm(void)
+{
+ odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+ auth_key = { .data = NULL, .length = 0 };
+ odp_crypto_iv_t iv = { .data = NULL, .length = AES128_GCM_IV_LEN };
+ unsigned int test_vec_num = (sizeof(aes128_gcm_reference_length) /
+ sizeof(aes128_gcm_reference_length[0]));
+ unsigned int i;
+
+ for (i = 0; i < test_vec_num; i++) {
+ cipher_key.data = aes128_gcm_reference_key[i];
+ cipher_key.length = sizeof(aes128_gcm_reference_key[i]);
+ iv.data = aes128_gcm_reference_iv[i];
+ iv.length = sizeof(aes128_gcm_reference_iv[i]);
+
+ alg_test(ODP_CRYPTO_OP_ENCODE,
+ ODP_CIPHER_ALG_AES128_GCM,
+ iv,
+ NULL,
+ cipher_key,
+ ODP_AUTH_ALG_AES128_GCM,
+ auth_key,
+ &aes128_gcm_cipher_range[i],
+ &aes128_gcm_auth_range[i],
+ aes128_gcm_reference_plaintext[i],
+ aes128_gcm_reference_length[i],
+ aes128_gcm_reference_ciphertext[i],
+ aes128_gcm_reference_length[i],
+ aes128_gcm_reference_ciphertext[i] +
+ aes128_gcm_reference_length[i],
+ AES128_GCM_CHECK_LEN);
+ }
+}
+
+/* This test verifies the correctness of encode (plaintext -> ciphertext)
+ * operation for AES128_GCM algorithm. IV for the operation is the session IV.
+ * In addition the test verifies if the implementation can use the
+ * packet buffer as completion event buffer.*/
+void crypto_test_enc_alg_aes128_gcm_ovr_iv(void)
+{
+ odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+ auth_key = { .data = NULL, .length = 0 };
+ odp_crypto_iv_t iv = { .data = NULL, .length = AES128_GCM_IV_LEN };
+ unsigned int test_vec_num = (sizeof(aes128_gcm_reference_length) /
+ sizeof(aes128_gcm_reference_length[0]));
+ unsigned int i;
+
+ for (i = 0; i < test_vec_num; i++) {
+ cipher_key.data = aes128_gcm_reference_key[i];
+ cipher_key.length = sizeof(aes128_gcm_reference_key[i]);
+
+ alg_test(ODP_CRYPTO_OP_ENCODE,
+ ODP_CIPHER_ALG_AES128_GCM,
+ iv,
+ aes128_gcm_reference_iv[i],
+ cipher_key,
+ ODP_AUTH_ALG_AES128_GCM,
+ auth_key,
+ &aes128_gcm_cipher_range[i],
+ &aes128_gcm_auth_range[i],
+ aes128_gcm_reference_plaintext[i],
+ aes128_gcm_reference_length[i],
+ aes128_gcm_reference_ciphertext[i],
+ aes128_gcm_reference_length[i],
+ aes128_gcm_reference_ciphertext[i] +
+ aes128_gcm_reference_length[i],
+ AES128_GCM_CHECK_LEN);
+ }
+}
+
+/* This test verifies the correctness of decode (ciphertext -> plaintext)
+ * operation for 3DES_CBC algorithm. IV for the operation is the session IV
+ * In addition the test verifies if the implementation can use the
+ * packet buffer as completion event buffer.
+ * */
+void crypto_test_dec_alg_aes128_gcm(void)
+{
+ odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+ auth_key = { .data = NULL, .length = 0 };
+ odp_crypto_iv_t iv = { .data = NULL, .length = AES128_GCM_IV_LEN };
+ unsigned int test_vec_num = (sizeof(aes128_gcm_reference_length) /
+ sizeof(aes128_gcm_reference_length[0]));
+ unsigned int i;
+
+ for (i = 0; i < test_vec_num; i++) {
+ cipher_key.data = aes128_gcm_reference_key[i];
+ cipher_key.length = sizeof(aes128_gcm_reference_key[i]);
+ iv.data = aes128_gcm_reference_iv[i];
+ iv.length = sizeof(aes128_gcm_reference_iv[i]);
+
+ alg_test(ODP_CRYPTO_OP_DECODE,
+ ODP_CIPHER_ALG_AES128_GCM,
+ iv,
+ NULL,
+ cipher_key,
+ ODP_AUTH_ALG_AES128_GCM,
+ auth_key,
+ &aes128_gcm_cipher_range[i],
+ &aes128_gcm_auth_range[i],
+ aes128_gcm_reference_ciphertext[i],
+ aes128_gcm_reference_length[i] + AES128_GCM_CHECK_LEN,
+ aes128_gcm_reference_plaintext[i],
+ aes128_gcm_reference_length[i],
+ aes128_gcm_reference_ciphertext[i] +
+ aes128_gcm_reference_length[i],
+ AES128_GCM_CHECK_LEN);
+ }
+}
+
+/* This test verifies the correctness of decode (ciphertext -> plaintext)
+ * operation for 3DES_CBC algorithm. IV for the operation is the session IV
+ * In addition the test verifies if the implementation can use the
+ * packet buffer as completion event buffer.
+ * */
+void crypto_test_dec_alg_aes128_gcm_ovr_iv(void)
+{
+ odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+ auth_key = { .data = NULL, .length = 0 };
+ odp_crypto_iv_t iv = { .data = NULL, .length = AES128_GCM_IV_LEN };
+ unsigned int test_vec_num = (sizeof(aes128_gcm_reference_length) /
+ sizeof(aes128_gcm_reference_length[0]));
+ unsigned int i;
+
+ for (i = 0; i < test_vec_num; i++) {
+ cipher_key.data = aes128_gcm_reference_key[i];
+ cipher_key.length = sizeof(aes128_gcm_reference_key[i]);
+
+ alg_test(ODP_CRYPTO_OP_DECODE,
+ ODP_CIPHER_ALG_AES128_GCM,
+ iv,
+ aes128_gcm_reference_iv[i],
+ cipher_key,
+ ODP_AUTH_ALG_AES128_GCM,
+ auth_key,
+ &aes128_gcm_cipher_range[i],
+ &aes128_gcm_auth_range[i],
+ aes128_gcm_reference_ciphertext[i],
+ aes128_gcm_reference_length[i] + AES128_GCM_CHECK_LEN,
+ aes128_gcm_reference_plaintext[i],
+ aes128_gcm_reference_length[i],
+ aes128_gcm_reference_ciphertext[i] +
+ aes128_gcm_reference_length[i],
+ AES128_GCM_CHECK_LEN);
}
}
@@ -285,10 +454,11 @@ void crypto_test_enc_alg_aes128_cbc(void)
cipher_key,
ODP_AUTH_ALG_NULL,
auth_key,
+ NULL, NULL,
aes128_cbc_reference_plaintext[i],
aes128_cbc_reference_length[i],
aes128_cbc_reference_ciphertext[i],
- aes128_cbc_reference_length[i]);
+ aes128_cbc_reference_length[i], NULL, 0);
}
}
@@ -315,10 +485,11 @@ void crypto_test_enc_alg_aes128_cbc_ovr_iv(void)
cipher_key,
ODP_AUTH_ALG_NULL,
auth_key,
+ NULL, NULL,
aes128_cbc_reference_plaintext[i],
aes128_cbc_reference_length[i],
aes128_cbc_reference_ciphertext[i],
- aes128_cbc_reference_length[i]);
+ aes128_cbc_reference_length[i], NULL, 0);
}
}
@@ -349,10 +520,11 @@ void crypto_test_dec_alg_aes128_cbc(void)
cipher_key,
ODP_AUTH_ALG_NULL,
auth_key,
+ NULL, NULL,
aes128_cbc_reference_ciphertext[i],
aes128_cbc_reference_length[i],
aes128_cbc_reference_plaintext[i],
- aes128_cbc_reference_length[i]);
+ aes128_cbc_reference_length[i], NULL, 0);
}
}
@@ -381,10 +553,11 @@ void crypto_test_dec_alg_aes128_cbc_ovr_iv(void)
cipher_key,
ODP_AUTH_ALG_NULL,
auth_key,
+ NULL, NULL,
aes128_cbc_reference_ciphertext[i],
aes128_cbc_reference_length[i],
aes128_cbc_reference_plaintext[i],
- aes128_cbc_reference_length[i]);
+ aes128_cbc_reference_length[i], NULL, 0);
}
}
@@ -417,8 +590,10 @@ void crypto_test_alg_hmac_md5(void)
cipher_key,
ODP_AUTH_ALG_MD5_96,
auth_key,
+ NULL, NULL,
hmac_md5_reference_plaintext[i],
hmac_md5_reference_length[i],
+ NULL, 0,
hmac_md5_reference_digest[i],
HMAC_MD5_96_CHECK_LEN);
}
@@ -453,8 +628,10 @@ void crypto_test_alg_hmac_sha256(void)
cipher_key,
ODP_AUTH_ALG_SHA256_128,
auth_key,
+ NULL, NULL,
hmac_sha256_reference_plaintext[i],
hmac_sha256_reference_length[i],
+ NULL, 0,
hmac_sha256_reference_digest[i],
HMAC_SHA256_128_CHECK_LEN);
}
@@ -493,6 +670,10 @@ odp_testinfo_t crypto_suite[] = {
ODP_TEST_INFO(crypto_test_dec_alg_aes128_cbc),
ODP_TEST_INFO(crypto_test_enc_alg_aes128_cbc_ovr_iv),
ODP_TEST_INFO(crypto_test_dec_alg_aes128_cbc_ovr_iv),
+ ODP_TEST_INFO(crypto_test_enc_alg_aes128_gcm),
+ ODP_TEST_INFO(crypto_test_enc_alg_aes128_gcm_ovr_iv),
+ ODP_TEST_INFO(crypto_test_dec_alg_aes128_gcm),
+ ODP_TEST_INFO(crypto_test_dec_alg_aes128_gcm_ovr_iv),
ODP_TEST_INFO(crypto_test_alg_hmac_md5),
ODP_TEST_INFO(crypto_test_alg_hmac_sha256),
ODP_TEST_INFO_NULL,
diff --git a/test/validation/crypto/test_vectors.h b/test/validation/crypto/test_vectors.h
index 73f54b5b3..1b760a24e 100644
--- a/test/validation/crypto/test_vectors.h
+++ b/test/validation/crypto/test_vectors.h
@@ -112,6 +112,158 @@ aes128_cbc_reference_ciphertext[][AES128_CBC_MAX_DATA_LEN] = {
0x49, 0xa5, 0x3e, 0x87, 0xf4, 0xc3, 0xda, 0x55 }
};
+/* AES-GCM test vectors extracted from
+ * https://tools.ietf.org/html/draft-mcgrew-gcm-test-01#section-2
+ */
+static uint8_t aes128_gcm_reference_key[][AES128_GCM_KEY_LEN] = {
+ { 0x4c, 0x80, 0xcd, 0xef, 0xbb, 0x5d, 0x10, 0xda,
+ 0x90, 0x6a, 0xc7, 0x3c, 0x36, 0x13, 0xa6, 0x34 },
+ { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
+ 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x3d, 0xe0, 0x98, 0x74, 0xb3, 0x88, 0xe6, 0x49,
+ 0x19, 0x88, 0xd0, 0xc3, 0x60, 0x7e, 0xae, 0x1f }
+};
+
+static uint8_t aes128_gcm_reference_iv[][AES128_GCM_IV_LEN] = {
+ { 0x2e, 0x44, 0x3b, 0x68, 0x49, 0x56, 0xed, 0x7e,
+ 0x3b, 0x24, 0x4c, 0xfe },
+ { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
+ 0xde, 0xca, 0xf8, 0x88 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 },
+ { 0x57, 0x69, 0x0e, 0x43, 0x4e, 0x28, 0x00, 0x00,
+ 0xa2, 0xfc, 0xa1, 0xa3 }
+};
+
+static uint32_t aes128_gcm_reference_length[] = { 84, 72, 72, 40};
+
+static odp_crypto_data_range_t aes128_gcm_cipher_range[] = {
+ { .offset = 12, .length = 72 },
+ { .offset = 8, .length = 64 },
+ { .offset = 8, .length = 64 },
+ { .offset = 12, .length = 28 },
+};
+
+static odp_crypto_data_range_t aes128_gcm_auth_range[] = {
+ { .offset = 0, .length = 84 },
+ { .offset = 0, .length = 72 },
+ { .offset = 0, .length = 72 },
+ { .offset = 0, .length = 40 },
+};
+
+static uint8_t
+aes128_gcm_reference_plaintext[][AES128_GCM_MAX_DATA_LEN] = {
+ { /* Aad */
+ 0x00, 0x00, 0x43, 0x21, 0x87, 0x65, 0x43, 0x21,
+ 0x00, 0x00, 0x00, 0x00,
+ /* Plain */
+ 0x45, 0x00, 0x00, 0x48, 0x69, 0x9a, 0x00, 0x00,
+ 0x80, 0x11, 0x4d, 0xb7, 0xc0, 0xa8, 0x01, 0x02,
+ 0xc0, 0xa8, 0x01, 0x01, 0x0a, 0x9b, 0xf1, 0x56,
+ 0x38, 0xd3, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x5f, 0x73, 0x69,
+ 0x70, 0x04, 0x5f, 0x75, 0x64, 0x70, 0x03, 0x73,
+ 0x69, 0x70, 0x09, 0x63, 0x79, 0x62, 0x65, 0x72,
+ 0x63, 0x69, 0x74, 0x79, 0x02, 0x64, 0x6b, 0x00,
+ 0x00, 0x21, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01 },
+
+ { /* Aad */
+ 0x00, 0x00, 0xa5, 0xf8, 0x00, 0x00, 0x00, 0x0a,
+ /* Plain */
+ 0x45, 0x00, 0x00, 0x3e, 0x69, 0x8f, 0x00, 0x00,
+ 0x80, 0x11, 0x4d, 0xcc, 0xc0, 0xa8, 0x01, 0x02,
+ 0xc0, 0xa8, 0x01, 0x01, 0x0a, 0x98, 0x00, 0x35,
+ 0x00, 0x2a, 0x23, 0x43, 0xb2, 0xd0, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x73, 0x69, 0x70, 0x09, 0x63, 0x79, 0x62,
+ 0x65, 0x72, 0x63, 0x69, 0x74, 0x79, 0x02, 0x64,
+ 0x6b, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01 },
+
+ { /* Aad */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ /* Plain */
+ 0x45, 0x00, 0x00, 0x3c, 0x99, 0xc5, 0x00, 0x00,
+ 0x80, 0x01, 0xcb, 0x7a, 0x40, 0x67, 0x93, 0x18,
+ 0x01, 0x01, 0x01, 0x01, 0x08, 0x00, 0x07, 0x5c,
+ 0x02, 0x00, 0x44, 0x00, 0x61, 0x62, 0x63, 0x64,
+ 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
+ 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74,
+ 0x75, 0x76, 0x77, 0x61, 0x62, 0x63, 0x64, 0x65,
+ 0x66, 0x67, 0x68, 0x69, 0x01, 0x02, 0x02, 0x01 },
+
+ { /* Aad */
+ 0x42, 0xf6, 0x7e, 0x3f, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10,
+ /* Plain */
+ 0x45, 0x00, 0x00, 0x1c, 0x42, 0xa2, 0x00, 0x00,
+ 0x80, 0x01, 0x44, 0x1f, 0x40, 0x67, 0x93, 0xb6,
+ 0xe0, 0x00, 0x00, 0x02, 0x0a, 0x00, 0xf5, 0xff,
+ 0x01, 0x02, 0x02, 0x01 }
+};
+
+static uint8_t
+aes128_gcm_reference_ciphertext[][AES128_GCM_MAX_DATA_LEN] = {
+ { /* Aad */
+ 0x00, 0x00, 0x43, 0x21, 0x87, 0x65, 0x43, 0x21,
+ 0x00, 0x00, 0x00, 0x00,
+ /* Plain */
+ 0xfe, 0xcf, 0x53, 0x7e, 0x72, 0x9d, 0x5b, 0x07,
+ 0xdc, 0x30, 0xdf, 0x52, 0x8d, 0xd2, 0x2b, 0x76,
+ 0x8d, 0x1b, 0x98, 0x73, 0x66, 0x96, 0xa6, 0xfd,
+ 0x34, 0x85, 0x09, 0xfa, 0x13, 0xce, 0xac, 0x34,
+ 0xcf, 0xa2, 0x43, 0x6f, 0x14, 0xa3, 0xf3, 0xcf,
+ 0x65, 0x92, 0x5b, 0xf1, 0xf4, 0xa1, 0x3c, 0x5d,
+ 0x15, 0xb2, 0x1e, 0x18, 0x84, 0xf5, 0xff, 0x62,
+ 0x47, 0xae, 0xab, 0xb7, 0x86, 0xb9, 0x3b, 0xce,
+ 0x61, 0xbc, 0x17, 0xd7, 0x68, 0xfd, 0x97, 0x32,
+ /* Digest */
+ 0x45, 0x90, 0x18, 0x14, 0x8f, 0x6c, 0xbe, 0x72,
+ 0x2f, 0xd0, 0x47, 0x96, 0x56, 0x2d, 0xfd, 0xb4 },
+
+ { /* Aad */
+ 0x00, 0x00, 0xa5, 0xf8, 0x00, 0x00, 0x00, 0x0a,
+ /* Plain */
+ 0xde, 0xb2, 0x2c, 0xd9, 0xb0, 0x7c, 0x72, 0xc1,
+ 0x6e, 0x3a, 0x65, 0xbe, 0xeb, 0x8d, 0xf3, 0x04,
+ 0xa5, 0xa5, 0x89, 0x7d, 0x33, 0xae, 0x53, 0x0f,
+ 0x1b, 0xa7, 0x6d, 0x5d, 0x11, 0x4d, 0x2a, 0x5c,
+ 0x3d, 0xe8, 0x18, 0x27, 0xc1, 0x0e, 0x9a, 0x4f,
+ 0x51, 0x33, 0x0d, 0x0e, 0xec, 0x41, 0x66, 0x42,
+ 0xcf, 0xbb, 0x85, 0xa5, 0xb4, 0x7e, 0x48, 0xa4,
+ 0xec, 0x3b, 0x9b, 0xa9, 0x5d, 0x91, 0x8b, 0xd1,
+ /* Digest */
+ 0x83, 0xb7, 0x0d, 0x3a, 0xa8, 0xbc, 0x6e, 0xe4,
+ 0xc3, 0x09, 0xe9, 0xd8, 0x5a, 0x41, 0xad, 0x4a },
+ { /* Aad */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ /* Plain */
+ 0x46, 0x88, 0xda, 0xf2, 0xf9, 0x73, 0xa3, 0x92,
+ 0x73, 0x29, 0x09, 0xc3, 0x31, 0xd5, 0x6d, 0x60,
+ 0xf6, 0x94, 0xab, 0xaa, 0x41, 0x4b, 0x5e, 0x7f,
+ 0xf5, 0xfd, 0xcd, 0xff, 0xf5, 0xe9, 0xa2, 0x84,
+ 0x45, 0x64, 0x76, 0x49, 0x27, 0x19, 0xff, 0xb6,
+ 0x4d, 0xe7, 0xd9, 0xdc, 0xa1, 0xe1, 0xd8, 0x94,
+ 0xbc, 0x3b, 0xd5, 0x78, 0x73, 0xed, 0x4d, 0x18,
+ 0x1d, 0x19, 0xd4, 0xd5, 0xc8, 0xc1, 0x8a, 0xf3,
+ /* Digest */
+ 0xf8, 0x21, 0xd4, 0x96, 0xee, 0xb0, 0x96, 0xe9,
+ 0x8a, 0xd2, 0xb6, 0x9e, 0x47, 0x99, 0xc7, 0x1d },
+
+ { /* Aad */
+ 0x42, 0xf6, 0x7e, 0x3f, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10,
+ /* Plain */
+ 0xfb, 0xa2, 0xca, 0x84, 0x5e, 0x5d, 0xf9, 0xf0,
+ 0xf2, 0x2c, 0x3e, 0x6e, 0x86, 0xdd, 0x83, 0x1e,
+ 0x1f, 0xc6, 0x57, 0x92, 0xcd, 0x1a, 0xf9, 0x13,
+ 0x0e, 0x13, 0x79, 0xed,
+ /* Digest */
+ 0x36, 0x9f, 0x07, 0x1f, 0x35, 0xe0, 0x34, 0xbe,
+ 0x95, 0xf1, 0x12, 0xe4, 0xe7, 0xd0, 0x5d, 0x35 }
+};
+
static uint8_t hmac_md5_reference_key[][HMAC_MD5_KEY_LEN] = {
{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b } ,
diff --git a/test/validation/crypto/test_vectors_len.h b/test/validation/crypto/test_vectors_len.h
index 5bc6f4b50..4fbb5cd70 100644
--- a/test/validation/crypto/test_vectors_len.h
+++ b/test/validation/crypto/test_vectors_len.h
@@ -16,6 +16,13 @@
#define AES128_CBC_IV_LEN 16
#define AES128_CBC_MAX_DATA_LEN 64
+/* AES128-CBC */
+#define AES128_GCM_KEY_LEN 16
+#define AES128_GCM_IV_LEN 12
+#define AES128_GCM_MAX_DATA_LEN 106
+#define AES128_GCM_DIGEST_LEN 16
+#define AES128_GCM_CHECK_LEN 16
+
/* HMAC-MD5 */
#define HMAC_MD5_KEY_LEN 16
#define HMAC_MD5_MAX_DATA_LEN 128
diff --git a/test/validation/hash/.gitignore b/test/validation/hash/.gitignore
new file mode 100644
index 000000000..6d0bc9314
--- /dev/null
+++ b/test/validation/hash/.gitignore
@@ -0,0 +1 @@
+hash_main
diff --git a/test/validation/hash/Makefile.am b/test/validation/hash/Makefile.am
new file mode 100644
index 000000000..b899b8bd3
--- /dev/null
+++ b/test/validation/hash/Makefile.am
@@ -0,0 +1,10 @@
+include ../Makefile.inc
+
+noinst_LTLIBRARIES = libtesthash.la
+libtesthash_la_SOURCES = hash.c
+
+test_PROGRAMS = hash_main$(EXEEXT)
+dist_hash_main_SOURCES = hash_main.c
+hash_main_LDADD = libtesthash.la $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST = hash.h
diff --git a/test/validation/hash/hash.c b/test/validation/hash/hash.c
new file mode 100644
index 000000000..11b331e28
--- /dev/null
+++ b/test/validation/hash/hash.c
@@ -0,0 +1,49 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp.h>
+#include <odp_cunit_common.h>
+#include "hash.h"
+
+void hash_test_crc32c(void)
+{
+ uint32_t test_value = 0x12345678;
+ uint32_t ret = odp_hash_crc32c(&test_value, 4, 0);
+
+ CU_ASSERT(ret == 0xfa745634);
+
+ test_value = 0x87654321;
+ ret = odp_hash_crc32c(&test_value, 4, 0);
+
+ CU_ASSERT(ret == 0xaca37da7);
+
+ uint32_t test_values[] = {0x12345678, 0x87654321};
+
+ ret = odp_hash_crc32c(test_values, 8, 0);
+
+ CU_ASSERT(ret == 0xe6e910b0);
+}
+
+odp_testinfo_t hash_suite[] = {
+ ODP_TEST_INFO(hash_test_crc32c),
+ ODP_TEST_INFO_NULL,
+};
+
+odp_suiteinfo_t hash_suites[] = {
+ {"Hash", NULL, NULL, hash_suite},
+ ODP_SUITE_INFO_NULL
+};
+
+int hash_main(void)
+{
+ int ret = odp_cunit_register(hash_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
+
+}
diff --git a/test/validation/hash/hash.h b/test/validation/hash/hash.h
new file mode 100644
index 000000000..46c74660d
--- /dev/null
+++ b/test/validation/hash/hash.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _ODP_TEST_HASH_H_
+#define _ODP_TEST_HASH_H_
+
+#include <odp_cunit_common.h>
+
+/* test functions: */
+void hash_test_crc32c(void);
+
+/* test arrays: */
+extern odp_testinfo_t hash_suite[];
+
+/* test registry: */
+extern odp_suiteinfo_t hash_suites[];
+
+/* main test program: */
+int hash_main(void);
+
+#endif
diff --git a/test/validation/hash/hash_main.c b/test/validation/hash/hash_main.c
new file mode 100644
index 000000000..4f7765ca2
--- /dev/null
+++ b/test/validation/hash/hash_main.c
@@ -0,0 +1,12 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "hash.h"
+
+int main(void)
+{
+ return hash_main();
+}
diff --git a/test/validation/pktio/pktio.c b/test/validation/pktio/pktio.c
index c85bce78d..e473a1d1c 100644
--- a/test/validation/pktio/pktio.c
+++ b/test/validation/pktio/pktio.c
@@ -288,6 +288,10 @@ static odp_pktio_t create_pktio(int iface_idx, odp_pktio_input_mode_t imode,
CU_ASSERT(pktio != ODP_PKTIO_INVALID);
CU_ASSERT(odp_pktio_to_u64(pktio) !=
odp_pktio_to_u64(ODP_PKTIO_INVALID));
+ /* Print pktio debug info and test that the odp_pktio_print() function
+ * is implemented. */
+ if (pktio != ODP_PKTIO_INVALID)
+ odp_pktio_print(pktio);
if (wait_for_network)
spin_wait(ODP_TIME_SEC_IN_NS / 4);
@@ -355,18 +359,16 @@ static int destroy_inq(odp_pktio_t pktio)
static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
{
- odp_time_t start, now, diff;
+ odp_time_t wait, end;
odp_event_t ev;
- start = odp_time_local();
-
+ wait = odp_time_local_from_ns(ns);
+ end = odp_time_sum(odp_time_local(), wait);
do {
ev = odp_queue_deq(queue);
if (ev != ODP_EVENT_INVALID)
return ev;
- now = odp_time_local();
- diff = odp_time_diff(now, start);
- } while (odp_time_to_ns(diff) < ns);
+ } while (odp_time_cmp(end, odp_time_local()) > 0);
return ODP_EVENT_INVALID;
}
@@ -374,14 +376,14 @@ static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
uint32_t seq, uint64_t ns)
{
- odp_time_t start, now, diff;
+ odp_time_t wait_time, end;
odp_event_t ev;
odp_packet_t pkt;
uint64_t wait;
- start = odp_time_local();
wait = odp_schedule_wait_time(ns);
-
+ wait_time = odp_time_local_from_ns(ns);
+ end = odp_time_sum(odp_time_local(), wait_time);
do {
pkt = ODP_PACKET_INVALID;
@@ -407,10 +409,7 @@ static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
odp_packet_free(pkt);
}
-
- now = odp_time_local();
- diff = odp_time_diff(now, start);
- } while (odp_time_to_ns(diff) < ns);
+ } while (odp_time_cmp(end, odp_time_local()) > 0);
CU_FAIL("failed to receive transmitted packet");
diff --git a/test/validation/scheduler/scheduler.c b/test/validation/scheduler/scheduler.c
index 2e157a520..7ba6a0693 100644
--- a/test/validation/scheduler/scheduler.c
+++ b/test/validation/scheduler/scheduler.c
@@ -48,6 +48,8 @@
#define CHAOS_NDX_TO_PTR(n) ((void *)(uintptr_t)n)
#define CHAOS_WAIT_FAIL (5 * ODP_TIME_SEC_IN_NS)
+#define ODP_WAIT_TOLERANCE (20 * ODP_TIME_MSEC_IN_NS)
+
/* Test global variables */
typedef struct {
int num_workers;
@@ -114,13 +116,52 @@ static int exit_schedule_loop(void)
void scheduler_test_wait_time(void)
{
+ int i;
+ odp_queue_t queue;
uint64_t wait_time;
+ odp_queue_param_t qp;
+ odp_time_t lower_limit, upper_limit;
+ odp_time_t start_time, end_time, diff;
+ /* check on read */
wait_time = odp_schedule_wait_time(0);
wait_time = odp_schedule_wait_time(1);
- wait_time = odp_schedule_wait_time((uint64_t)-1LL);
- CU_ASSERT(wait_time > 0);
+ /* check ODP_SCHED_NO_WAIT */
+ odp_queue_param_init(&qp);
+ queue = odp_queue_create("dummy_queue", ODP_QUEUE_TYPE_SCHED, &qp);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ wait_time = odp_schedule_wait_time(ODP_TIME_SEC_IN_NS);
+ start_time = odp_time_local();
+ odp_schedule(&queue, ODP_SCHED_NO_WAIT);
+ end_time = odp_time_local();
+
+ diff = odp_time_diff(end_time, start_time);
+ lower_limit = ODP_TIME_NULL;
+ upper_limit = odp_time_local_from_ns(ODP_WAIT_TOLERANCE);
+
+ CU_ASSERT(odp_time_cmp(diff, lower_limit) >= 0);
+ CU_ASSERT(odp_time_cmp(diff, upper_limit) <= 0);
+
+ /* check time correctness */
+ start_time = odp_time_local();
+ for (i = 1; i < 6; i++) {
+ odp_schedule(&queue, wait_time);
+ printf("%d..", i);
+ }
+ end_time = odp_time_local();
+
+ diff = odp_time_diff(end_time, start_time);
+ lower_limit = odp_time_local_from_ns(5 * ODP_TIME_SEC_IN_NS -
+ ODP_WAIT_TOLERANCE);
+ upper_limit = odp_time_local_from_ns(5 * ODP_TIME_SEC_IN_NS +
+ ODP_WAIT_TOLERANCE);
+
+ CU_ASSERT(odp_time_cmp(diff, lower_limit) >= 0);
+ CU_ASSERT(odp_time_cmp(diff, upper_limit) <= 0);
+
+ CU_ASSERT_FATAL(odp_queue_destroy(queue) == 0);
}
void scheduler_test_num_prio(void)
diff --git a/test/validation/std_clib/.gitignore b/test/validation/std_clib/.gitignore
new file mode 100644
index 000000000..37828330a
--- /dev/null
+++ b/test/validation/std_clib/.gitignore
@@ -0,0 +1 @@
+std_clib_main
diff --git a/test/validation/std_clib/Makefile.am b/test/validation/std_clib/Makefile.am
new file mode 100644
index 000000000..e2fc0ccf3
--- /dev/null
+++ b/test/validation/std_clib/Makefile.am
@@ -0,0 +1,10 @@
+include ../Makefile.inc
+
+noinst_LTLIBRARIES = libteststd_clib.la
+libteststd_clib_la_SOURCES = std_clib.c
+
+test_PROGRAMS = std_clib_main$(EXEEXT)
+dist_std_clib_main_SOURCES = std_clib_main.c
+std_clib_main_LDADD = libteststd_clib.la $(LIBCUNIT_COMMON) $(LIBODP)
+
+EXTRA_DIST = std_clib.h
diff --git a/test/validation/std_clib/std_clib.c b/test/validation/std_clib/std_clib.c
new file mode 100644
index 000000000..e53ad3946
--- /dev/null
+++ b/test/validation/std_clib/std_clib.c
@@ -0,0 +1,66 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp.h>
+#include <odp_cunit_common.h>
+#include "std_clib.h"
+
+#include <string.h>
+
+#define PATTERN 0x5e
+
+static void std_clib_test_memcpy(void)
+{
+ uint8_t src[] = {0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15};
+ uint8_t dst[16];
+ int ret;
+
+ memset(dst, 0, sizeof(dst));
+
+ odp_memcpy(dst, src, sizeof(dst));
+
+ ret = memcmp(dst, src, sizeof(dst));
+
+ CU_ASSERT(ret == 0);
+}
+
+static void std_clib_test_memset(void)
+{
+ uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15};
+ uint8_t ref[16];
+ int ret;
+
+ odp_memset(data, PATTERN, sizeof(data));
+
+ memset(ref, PATTERN, sizeof(ref));
+
+ ret = memcmp(data, ref, sizeof(data));
+
+ CU_ASSERT(ret == 0);
+}
+
+odp_testinfo_t std_clib_suite[] = {
+ ODP_TEST_INFO(std_clib_test_memcpy),
+ ODP_TEST_INFO(std_clib_test_memset),
+ ODP_TEST_INFO_NULL,
+};
+
+odp_suiteinfo_t std_clib_suites[] = {
+ {"Std C library", NULL, NULL, std_clib_suite},
+ ODP_SUITE_INFO_NULL
+};
+
+int std_clib_main(void)
+{
+ int ret = odp_cunit_register(std_clib_suites);
+
+ if (ret == 0)
+ ret = odp_cunit_run();
+
+ return ret;
+}
diff --git a/test/validation/std_clib/std_clib.h b/test/validation/std_clib/std_clib.h
new file mode 100644
index 000000000..eab6872f1
--- /dev/null
+++ b/test/validation/std_clib/std_clib.h
@@ -0,0 +1,21 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _ODP_TEST_STD_CLIB_H_
+#define _ODP_TEST_STD_CLIB_H_
+
+#include <odp_cunit_common.h>
+
+/* test arrays: */
+extern odp_testinfo_t std_clib_suite[];
+
+/* test registry: */
+extern odp_suiteinfo_t std_clib_suites[];
+
+/* main test program: */
+int std_clib_main(void);
+
+#endif
diff --git a/test/validation/std_clib/std_clib_main.c b/test/validation/std_clib/std_clib_main.c
new file mode 100644
index 000000000..010c1c6f4
--- /dev/null
+++ b/test/validation/std_clib/std_clib_main.c
@@ -0,0 +1,12 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "std_clib.h"
+
+int main(void)
+{
+ return std_clib_main();
+}
diff --git a/test/validation/synchronizers/synchronizers.c b/test/validation/synchronizers/synchronizers.c
index 2406c7706..0302069b8 100644
--- a/test/validation/synchronizers/synchronizers.c
+++ b/test/validation/synchronizers/synchronizers.c
@@ -36,6 +36,8 @@
static odp_atomic_u32_t a32u;
static odp_atomic_u64_t a64u;
+static volatile int temp_result;
+
typedef __volatile uint32_t volatile_u32_t;
typedef __volatile uint64_t volatile_u64_t;
@@ -63,8 +65,10 @@ typedef struct {
/* Locks */
odp_spinlock_t global_spinlock;
+ odp_spinlock_recursive_t global_recursive_spinlock;
odp_ticketlock_t global_ticketlock;
odp_rwlock_t global_rwlock;
+ odp_rwlock_recursive_t global_recursive_rwlock;
volatile_u32_t global_lock_owner;
} global_shared_mem_t;
@@ -77,8 +81,10 @@ typedef struct {
int thread_core;
odp_spinlock_t per_thread_spinlock;
+ odp_spinlock_recursive_t per_thread_recursive_spinlock;
odp_ticketlock_t per_thread_ticketlock;
odp_rwlock_t per_thread_rwlock;
+ odp_rwlock_recursive_t per_thread_recursive_rwlock;
volatile_u64_t delay_counter;
} per_thread_mem_t;
@@ -220,12 +226,12 @@ static uint32_t barrier_test(per_thread_mem_t *per_thread_mem,
odp_barrier_wait(&global_mem->test_barriers[cnt]);
global_mem->barrier_cnt1 = cnt + 1;
- odp_sync_stores();
+ odp_mb_full();
if (i_am_slow_thread) {
global_mem->slow_thread_num = next_slow_thread;
global_mem->barrier_cnt2 = cnt + 1;
- odp_sync_stores();
+ odp_mb_full();
} else {
while (global_mem->barrier_cnt2 != (cnt + 1))
thread_delay(per_thread_mem, BASE_DELAY);
@@ -314,6 +320,56 @@ static void *spinlock_api_tests(void *arg UNUSED)
return NULL;
}
+static void spinlock_recursive_api_test(odp_spinlock_recursive_t *spinlock)
+{
+ odp_spinlock_recursive_init(spinlock);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);
+
+ odp_spinlock_recursive_lock(spinlock);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+ odp_spinlock_recursive_lock(spinlock);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+ odp_spinlock_recursive_unlock(spinlock);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+ odp_spinlock_recursive_unlock(spinlock);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);
+
+ CU_ASSERT(odp_spinlock_recursive_trylock(spinlock) == 1);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+ CU_ASSERT(odp_spinlock_recursive_trylock(spinlock) == 1);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+ odp_spinlock_recursive_unlock(spinlock);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 1);
+
+ odp_spinlock_recursive_unlock(spinlock);
+ CU_ASSERT(odp_spinlock_recursive_is_locked(spinlock) == 0);
+}
+
+static void *spinlock_recursive_api_tests(void *arg UNUSED)
+{
+ global_shared_mem_t *global_mem;
+ per_thread_mem_t *per_thread_mem;
+ odp_spinlock_recursive_t local_recursive_spin_lock;
+
+ per_thread_mem = thread_init();
+ global_mem = per_thread_mem->global_mem;
+
+ odp_barrier_wait(&global_mem->global_barrier);
+
+ spinlock_recursive_api_test(&local_recursive_spin_lock);
+ spinlock_recursive_api_test(
+ &per_thread_mem->per_thread_recursive_spinlock);
+
+ thread_finalize(per_thread_mem);
+
+ return NULL;
+}
+
static void ticketlock_api_test(odp_ticketlock_t *ticketlock)
{
odp_ticketlock_init(ticketlock);
@@ -386,6 +442,45 @@ static void *rwlock_api_tests(void *arg UNUSED)
return NULL;
}
+static void rwlock_recursive_api_test(odp_rwlock_recursive_t *rw_lock)
+{
+ odp_rwlock_recursive_init(rw_lock);
+ /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */
+
+ odp_rwlock_recursive_read_lock(rw_lock);
+ odp_rwlock_recursive_read_lock(rw_lock);
+
+ odp_rwlock_recursive_read_unlock(rw_lock);
+ odp_rwlock_recursive_read_unlock(rw_lock);
+
+ odp_rwlock_recursive_write_lock(rw_lock);
+ odp_rwlock_recursive_write_lock(rw_lock);
+ /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 1); */
+
+ odp_rwlock_recursive_write_unlock(rw_lock);
+ odp_rwlock_recursive_write_unlock(rw_lock);
+ /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */
+}
+
+static void *rwlock_recursive_api_tests(void *arg UNUSED)
+{
+ global_shared_mem_t *global_mem;
+ per_thread_mem_t *per_thread_mem;
+ odp_rwlock_recursive_t local_recursive_rwlock;
+
+ per_thread_mem = thread_init();
+ global_mem = per_thread_mem->global_mem;
+
+ odp_barrier_wait(&global_mem->global_barrier);
+
+ rwlock_recursive_api_test(&local_recursive_rwlock);
+ rwlock_recursive_api_test(&per_thread_mem->per_thread_recursive_rwlock);
+
+ thread_finalize(per_thread_mem);
+
+ return NULL;
+}
+
static void *no_lock_functional_test(void *arg UNUSED)
{
global_shared_mem_t *global_mem;
@@ -408,7 +503,7 @@ static void *no_lock_functional_test(void *arg UNUSED)
for (cnt = 1; cnt <= iterations; cnt++) {
global_mem->global_lock_owner = thread_num;
- odp_sync_stores();
+ odp_mb_full();
thread_delay(per_thread_mem, lock_owner_delay);
if (global_mem->global_lock_owner != thread_num) {
@@ -417,7 +512,7 @@ static void *no_lock_functional_test(void *arg UNUSED)
}
global_mem->global_lock_owner = 0;
- odp_sync_stores();
+ odp_mb_full();
thread_delay(per_thread_mem, MIN_DELAY);
if (global_mem->global_lock_owner == thread_num) {
@@ -498,7 +593,7 @@ static void *spinlock_functional_test(void *arg UNUSED)
* global_lock_owner to be themselves
*/
global_mem->global_lock_owner = thread_num;
- odp_sync_stores();
+ odp_mb_full();
thread_delay(per_thread_mem, lock_owner_delay);
if (global_mem->global_lock_owner != thread_num) {
current_errs++;
@@ -507,7 +602,7 @@ static void *spinlock_functional_test(void *arg UNUSED)
/* Release shared lock, and make sure we no longer have it */
global_mem->global_lock_owner = 0;
- odp_sync_stores();
+ odp_mb_full();
odp_spinlock_unlock(&global_mem->global_spinlock);
if (global_mem->global_lock_owner == thread_num) {
current_errs++;
@@ -543,6 +638,115 @@ static void *spinlock_functional_test(void *arg UNUSED)
return NULL;
}
+static void *spinlock_recursive_functional_test(void *arg UNUSED)
+{
+ global_shared_mem_t *global_mem;
+ per_thread_mem_t *per_thread_mem;
+ uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;
+ uint32_t sync_failures, recursive_errs, is_locked_errs, current_errs;
+ uint32_t lock_owner_delay;
+
+ thread_num = odp_cpu_id() + 1;
+ per_thread_mem = thread_init();
+ global_mem = per_thread_mem->global_mem;
+ iterations = global_mem->g_iterations;
+
+ odp_barrier_wait(&global_mem->global_barrier);
+
+ sync_failures = 0;
+ recursive_errs = 0;
+ is_locked_errs = 0;
+ current_errs = 0;
+ rs_idx = 0;
+ resync_cnt = iterations / NUM_RESYNC_BARRIERS;
+ lock_owner_delay = BASE_DELAY;
+
+ for (cnt = 1; cnt <= iterations; cnt++) {
+ /* Acquire the shared global lock */
+ odp_spinlock_recursive_lock(
+ &global_mem->global_recursive_spinlock);
+
+ /* Make sure we have the lock AND didn't previously own it */
+ if (odp_spinlock_recursive_is_locked(
+ &global_mem->global_recursive_spinlock) != 1)
+ is_locked_errs++;
+
+ if (global_mem->global_lock_owner != 0) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ /* Now set the global_lock_owner to be us, wait a while, and
+ * then we see if anyone else has snuck in and changed the
+ * global_lock_owner to be themselves
+ */
+ global_mem->global_lock_owner = thread_num;
+ odp_mb_full();
+ thread_delay(per_thread_mem, lock_owner_delay);
+ if (global_mem->global_lock_owner != thread_num) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ /* Verify that we can acquire the lock recursively */
+ odp_spinlock_recursive_lock(
+ &global_mem->global_recursive_spinlock);
+ if (global_mem->global_lock_owner != thread_num) {
+ current_errs++;
+ recursive_errs++;
+ }
+
+ /* Release the lock and verify that we still have it*/
+ odp_spinlock_recursive_unlock(
+ &global_mem->global_recursive_spinlock);
+ thread_delay(per_thread_mem, lock_owner_delay);
+ if (global_mem->global_lock_owner != thread_num) {
+ current_errs++;
+ recursive_errs++;
+ }
+
+ /* Release shared lock, and make sure we no longer have it */
+ global_mem->global_lock_owner = 0;
+ odp_mb_full();
+ odp_spinlock_recursive_unlock(
+ &global_mem->global_recursive_spinlock);
+ if (global_mem->global_lock_owner == thread_num) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ if (current_errs == 0)
+ lock_owner_delay++;
+
+ /* Wait a small amount of time and rerun the test */
+ thread_delay(per_thread_mem, BASE_DELAY);
+
+ /* Try to resync all of the threads to increase contention */
+ if ((rs_idx < NUM_RESYNC_BARRIERS) &&
+ ((cnt % resync_cnt) == (resync_cnt - 1)))
+ odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);
+ }
+
+ if ((global_mem->g_verbose) &&
+ (sync_failures != 0 || recursive_errs != 0 || is_locked_errs != 0))
+ printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+ " sync_failures and %" PRIu32
+ " recursive_errs and %" PRIu32
+ " is_locked_errs in %" PRIu32
+ " iterations\n", thread_num,
+ per_thread_mem->thread_id, per_thread_mem->thread_core,
+ sync_failures, recursive_errs, is_locked_errs,
+ iterations);
+
+ CU_ASSERT(sync_failures == 0);
+ CU_ASSERT(recursive_errs == 0);
+ CU_ASSERT(is_locked_errs == 0);
+
+ thread_finalize(per_thread_mem);
+
+ return NULL;
+}
+
static void *ticketlock_functional_test(void *arg UNUSED)
{
global_shared_mem_t *global_mem;
@@ -585,7 +789,7 @@ static void *ticketlock_functional_test(void *arg UNUSED)
* global_lock_owner to be themselves
*/
global_mem->global_lock_owner = thread_num;
- odp_sync_stores();
+ odp_mb_full();
thread_delay(per_thread_mem, lock_owner_delay);
if (global_mem->global_lock_owner != thread_num) {
current_errs++;
@@ -594,7 +798,7 @@ static void *ticketlock_functional_test(void *arg UNUSED)
/* Release shared lock, and make sure we no longer have it */
global_mem->global_lock_owner = 0;
- odp_sync_stores();
+ odp_mb_full();
odp_ticketlock_unlock(&global_mem->global_ticketlock);
if (global_mem->global_lock_owner == thread_num) {
current_errs++;
@@ -652,6 +856,19 @@ static void *rwlock_functional_test(void *arg UNUSED)
lock_owner_delay = BASE_DELAY;
for (cnt = 1; cnt <= iterations; cnt++) {
+ /* Verify that we can obtain a read lock */
+ odp_rwlock_read_lock(&global_mem->global_rwlock);
+
+ /* Verify lock is unowned (no writer holds it) */
+ thread_delay(per_thread_mem, lock_owner_delay);
+ if (global_mem->global_lock_owner != 0) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ /* Release the read lock */
+ odp_rwlock_read_unlock(&global_mem->global_rwlock);
+
/* Acquire the shared global lock */
odp_rwlock_write_lock(&global_mem->global_rwlock);
@@ -666,7 +883,7 @@ static void *rwlock_functional_test(void *arg UNUSED)
* global_lock_owner to be themselves
*/
global_mem->global_lock_owner = thread_num;
- odp_sync_stores();
+ odp_mb_full();
thread_delay(per_thread_mem, lock_owner_delay);
if (global_mem->global_lock_owner != thread_num) {
current_errs++;
@@ -675,7 +892,7 @@ static void *rwlock_functional_test(void *arg UNUSED)
/* Release shared lock, and make sure we no longer have it */
global_mem->global_lock_owner = 0;
- odp_sync_stores();
+ odp_mb_full();
odp_rwlock_write_unlock(&global_mem->global_rwlock);
if (global_mem->global_lock_owner == thread_num) {
current_errs++;
@@ -708,6 +925,136 @@ static void *rwlock_functional_test(void *arg UNUSED)
return NULL;
}
+static void *rwlock_recursive_functional_test(void *arg UNUSED)
+{
+ global_shared_mem_t *global_mem;
+ per_thread_mem_t *per_thread_mem;
+ uint32_t thread_num, resync_cnt, rs_idx, iterations, cnt;
+ uint32_t sync_failures, recursive_errs, current_errs, lock_owner_delay;
+
+ thread_num = odp_cpu_id() + 1;
+ per_thread_mem = thread_init();
+ global_mem = per_thread_mem->global_mem;
+ iterations = global_mem->g_iterations;
+
+ /* Wait here until all of the threads have also reached this point */
+ odp_barrier_wait(&global_mem->global_barrier);
+
+ sync_failures = 0;
+ recursive_errs = 0;
+ current_errs = 0;
+ rs_idx = 0;
+ resync_cnt = iterations / NUM_RESYNC_BARRIERS;
+ lock_owner_delay = BASE_DELAY;
+
+ for (cnt = 1; cnt <= iterations; cnt++) {
+ /* Verify that we can obtain a read lock */
+ odp_rwlock_recursive_read_lock(
+ &global_mem->global_recursive_rwlock);
+
+ /* Verify lock is unowned (no writer holds it) */
+ thread_delay(per_thread_mem, lock_owner_delay);
+ if (global_mem->global_lock_owner != 0) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ /* Verify we can get read lock recursively */
+ odp_rwlock_recursive_read_lock(
+ &global_mem->global_recursive_rwlock);
+
+ /* Verify lock is unowned (no writer holds it) */
+ thread_delay(per_thread_mem, lock_owner_delay);
+ if (global_mem->global_lock_owner != 0) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ /* Release the read lock */
+ odp_rwlock_recursive_read_unlock(
+ &global_mem->global_recursive_rwlock);
+ odp_rwlock_recursive_read_unlock(
+ &global_mem->global_recursive_rwlock);
+
+ /* Acquire the shared global lock */
+ odp_rwlock_recursive_write_lock(
+ &global_mem->global_recursive_rwlock);
+
+ /* Make sure we have lock now AND didn't previously own it */
+ if (global_mem->global_lock_owner != 0) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ /* Now set the global_lock_owner to be us, wait a while, and
+ * then we see if anyone else has snuck in and changed the
+ * global_lock_owner to be themselves
+ */
+ global_mem->global_lock_owner = thread_num;
+ odp_mb_full();
+ thread_delay(per_thread_mem, lock_owner_delay);
+ if (global_mem->global_lock_owner != thread_num) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ /* Acquire it again and verify we still own it */
+ odp_rwlock_recursive_write_lock(
+ &global_mem->global_recursive_rwlock);
+ thread_delay(per_thread_mem, lock_owner_delay);
+ if (global_mem->global_lock_owner != thread_num) {
+ current_errs++;
+ recursive_errs++;
+ }
+
+ /* Release the recursive lock and make sure we still own it */
+ odp_rwlock_recursive_write_unlock(
+ &global_mem->global_recursive_rwlock);
+ thread_delay(per_thread_mem, lock_owner_delay);
+ if (global_mem->global_lock_owner != thread_num) {
+ current_errs++;
+ recursive_errs++;
+ }
+
+ /* Release shared lock, and make sure we no longer have it */
+ global_mem->global_lock_owner = 0;
+ odp_mb_full();
+ odp_rwlock_recursive_write_unlock(
+ &global_mem->global_recursive_rwlock);
+ if (global_mem->global_lock_owner == thread_num) {
+ current_errs++;
+ sync_failures++;
+ }
+
+ if (current_errs == 0)
+ lock_owner_delay++;
+
+ /* Wait a small amount of time and then rerun the test */
+ thread_delay(per_thread_mem, BASE_DELAY);
+
+ /* Try to resync all of the threads to increase contention */
+ if ((rs_idx < NUM_RESYNC_BARRIERS) &&
+ ((cnt % resync_cnt) == (resync_cnt - 1)))
+ odp_barrier_wait(&global_mem->barrier_array[rs_idx++]);
+ }
+
+ if ((global_mem->g_verbose) && (sync_failures != 0))
+ printf("\nThread %" PRIu32 " (id=%d core=%d) had %" PRIu32
+ " sync_failures and %" PRIu32
+ " recursive_errs in %" PRIu32
+ " iterations\n", thread_num,
+ per_thread_mem->thread_id,
+ per_thread_mem->thread_core,
+ sync_failures, recursive_errs, iterations);
+
+ CU_ASSERT(sync_failures == 0);
+ CU_ASSERT(recursive_errs == 0);
+
+ thread_finalize(per_thread_mem);
+
+ return NULL;
+}
+
static void barrier_test_init(void)
{
uint32_t num_threads, idx;
@@ -922,6 +1269,26 @@ static void test_atomic_validate(void)
}
/* Barrier tests */
+void synchronizers_test_memory_barrier(void)
+{
+ volatile int a = 0;
+ volatile int b = 0;
+ volatile int c = 0;
+ volatile int d = 0;
+
+ /* Call all memory barriers to verify that those are implemented */
+ a = 1;
+ odp_mb_release();
+ b = 1;
+ odp_mb_acquire();
+ c = 1;
+ odp_mb_full();
+ d = 1;
+
+ /* Avoid "variable set but not used" warning */
+ temp_result = a + b + c + d;
+}
+
void synchronizers_test_no_barrier_functional(void)
{
pthrd_arg arg;
@@ -943,6 +1310,7 @@ void synchronizers_test_barrier_functional(void)
}
odp_testinfo_t synchronizers_suite_barrier[] = {
+ ODP_TEST_INFO(synchronizers_test_memory_barrier),
ODP_TEST_INFO(synchronizers_test_no_barrier_functional),
ODP_TEST_INFO(synchronizers_test_barrier_functional),
ODP_TEST_INFO_NULL
@@ -983,12 +1351,37 @@ void synchronizers_test_spinlock_functional(void)
odp_cunit_thread_exit(&arg);
}
+void synchronizers_test_spinlock_recursive_api(void)
+{
+ pthrd_arg arg;
+
+ arg.numthrds = global_mem->g_num_threads;
+ odp_cunit_thread_create(spinlock_recursive_api_tests, &arg);
+ odp_cunit_thread_exit(&arg);
+}
+
+void synchronizers_test_spinlock_recursive_functional(void)
+{
+ pthrd_arg arg;
+
+ arg.numthrds = global_mem->g_num_threads;
+ odp_spinlock_recursive_init(&global_mem->global_recursive_spinlock);
+ odp_cunit_thread_create(spinlock_recursive_functional_test, &arg);
+ odp_cunit_thread_exit(&arg);
+}
+
odp_testinfo_t synchronizers_suite_spinlock[] = {
ODP_TEST_INFO(synchronizers_test_spinlock_api),
ODP_TEST_INFO(synchronizers_test_spinlock_functional),
ODP_TEST_INFO_NULL
};
+odp_testinfo_t synchronizers_suite_spinlock_recursive[] = {
+ ODP_TEST_INFO(synchronizers_test_spinlock_recursive_api),
+ ODP_TEST_INFO(synchronizers_test_spinlock_recursive_functional),
+ ODP_TEST_INFO_NULL
+};
+
/* Ticket lock tests */
void synchronizers_test_ticketlock_api(void)
{
@@ -1042,6 +1435,31 @@ odp_testinfo_t synchronizers_suite_rwlock[] = {
ODP_TEST_INFO_NULL
};
+void synchronizers_test_rwlock_recursive_api(void)
+{
+ pthrd_arg arg;
+
+ arg.numthrds = global_mem->g_num_threads;
+ odp_cunit_thread_create(rwlock_recursive_api_tests, &arg);
+ odp_cunit_thread_exit(&arg);
+}
+
+void synchronizers_test_rwlock_recursive_functional(void)
+{
+ pthrd_arg arg;
+
+ arg.numthrds = global_mem->g_num_threads;
+ odp_rwlock_recursive_init(&global_mem->global_recursive_rwlock);
+ odp_cunit_thread_create(rwlock_recursive_functional_test, &arg);
+ odp_cunit_thread_exit(&arg);
+}
+
+odp_testinfo_t synchronizers_suite_rwlock_recursive[] = {
+ ODP_TEST_INFO(synchronizers_test_rwlock_recursive_api),
+ ODP_TEST_INFO(synchronizers_test_rwlock_recursive_functional),
+ ODP_TEST_INFO_NULL
+};
+
int synchronizers_suite_init(void)
{
uint32_t num_threads, idx;
@@ -1203,10 +1621,14 @@ odp_suiteinfo_t synchronizers_suites[] = {
synchronizers_suite_no_locking},
{"spinlock", synchronizers_suite_init, NULL,
synchronizers_suite_spinlock},
+ {"spinlock_recursive", synchronizers_suite_init, NULL,
+ synchronizers_suite_spinlock_recursive},
{"ticketlock", synchronizers_suite_init, NULL,
synchronizers_suite_ticketlock},
{"rwlock", synchronizers_suite_init, NULL,
synchronizers_suite_rwlock},
+ {"rwlock_recursive", synchronizers_suite_init, NULL,
+ synchronizers_suite_rwlock_recursive},
{"atomic", NULL, NULL,
synchronizers_suite_atomic},
ODP_SUITE_INFO_NULL
diff --git a/test/validation/synchronizers/synchronizers.h b/test/validation/synchronizers/synchronizers.h
index f16477cb9..ad8db0b2e 100644
--- a/test/validation/synchronizers/synchronizers.h
+++ b/test/validation/synchronizers/synchronizers.h
@@ -10,15 +10,20 @@
#include <odp_cunit_common.h>
/* test functions: */
+void synchronizers_test_memory_barrier(void);
void synchronizers_test_no_barrier_functional(void);
void synchronizers_test_barrier_functional(void);
void synchronizers_test_no_lock_functional(void);
void synchronizers_test_spinlock_api(void);
void synchronizers_test_spinlock_functional(void);
+void synchronizers_test_spinlock_recursive_api(void);
+void synchronizers_test_spinlock_recursive_functional(void);
void synchronizers_test_ticketlock_api(void);
void synchronizers_test_ticketlock_functional(void);
void synchronizers_test_rwlock_api(void);
void synchronizers_test_rwlock_functional(void);
+void synchronizers_test_rwlock_recursive_api(void);
+void synchronizers_test_rwlock_recursive_functional(void);
void synchronizers_test_atomic_inc_dec(void);
void synchronizers_test_atomic_add_sub(void);
void synchronizers_test_atomic_fetch_inc_dec(void);
@@ -28,8 +33,10 @@ void synchronizers_test_atomic_fetch_add_sub(void);
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_spinlock_recursive[];
extern odp_testinfo_t synchronizers_suite_ticketlock[];
extern odp_testinfo_t synchronizers_suite_rwlock[];
+extern odp_testinfo_t synchronizers_suite_rwlock_recursive[];
extern odp_testinfo_t synchronizers_suite_atomic[];
/* test array init/term functions: */
diff --git a/test/validation/time/time.c b/test/validation/time/time.c
index f70c7768a..8b469b02c 100644
--- a/test/validation/time/time.c
+++ b/test/validation/time/time.c
@@ -8,64 +8,424 @@
#include "odp_cunit_common.h"
#include "time.h"
-#define TOLERANCE 1
-#define BUSY_LOOP_CNT 100
+#define BUSY_LOOP_CNT 30000000 /* used for t > min resolution */
+#define BUSY_LOOP_CNT_LONG 12000000000 /* used for t > 4 sec */
+#define MIN_TIME_RATE 32000
+#define MAX_TIME_RATE 15000000000
+#define DELAY_TOLERANCE 20000000 /* deviation for delay */
+
+static uint64_t local_res;
+static uint64_t global_res;
+
+typedef odp_time_t time_cb(void);
+typedef uint64_t time_res_cb(void);
+typedef odp_time_t time_from_ns_cb(uint64_t ns);
+
+void time_test_constants(void)
+{
+ uint64_t ns;
+
+ ns = ODP_TIME_SEC_IN_NS / 1000;
+ CU_ASSERT(ns == ODP_TIME_MSEC_IN_NS);
+ ns /= 1000;
+ CU_ASSERT(ns == ODP_TIME_USEC_IN_NS);
+}
+
+static void time_test_res(time_res_cb time_res, uint64_t res)
+{
+ uint64_t rate;
+
+ rate = time_res();
+ CU_ASSERT(rate > MIN_TIME_RATE);
+ CU_ASSERT(rate < MAX_TIME_RATE);
+
+ res = ODP_TIME_SEC_IN_NS / rate;
+ res = res ? res : 1;
+}
+
+void time_test_local_res(void)
+{
+ time_test_res(odp_time_local_res, local_res);
+}
+
+void time_test_global_res(void)
+{
+ time_test_res(odp_time_global_res, global_res);
+}
+
+/* check that related conversions come back to the same value */
+static void time_test_conversion(time_from_ns_cb time_from_ns, uint64_t res)
+{
+ uint64_t ns1, ns2;
+ odp_time_t time;
+ uint64_t upper_limit, lower_limit;
+
+ ns1 = 100;
+ time = time_from_ns(ns1);
+
+ ns2 = odp_time_to_ns(time);
+
+ /* need to check within arithmetic tolerance that the same
+ * value in ns is returned after conversions */
+ upper_limit = ns1 + res;
+ lower_limit = ns1 - res;
+ CU_ASSERT((ns2 <= upper_limit) && (ns2 >= lower_limit));
+
+ ns1 = 60 * 11 * ODP_TIME_SEC_IN_NS;
+ time = time_from_ns(ns1);
+
+ ns2 = odp_time_to_ns(time);
+
+ /* need to check within arithmetic tolerance that the same
+ * value in ns is returned after conversions */
+ upper_limit = ns1 + res;
+ lower_limit = ns1 - res;
+ CU_ASSERT((ns2 <= upper_limit) && (ns2 >= lower_limit));
+
+ /* test on 0 */
+ ns1 = odp_time_to_ns(ODP_TIME_NULL);
+ CU_ASSERT(ns1 == 0);
+}
+
+void time_test_local_conversion(void)
+{
+ time_test_conversion(odp_time_local_from_ns, local_res);
+}
+
+void time_test_global_conversion(void)
+{
+ time_test_conversion(odp_time_global_from_ns, global_res);
+}
+
+static void time_test_monotony(time_cb time)
+{
+ volatile uint64_t count = 0;
+ odp_time_t t1, t2, t3;
+ uint64_t ns1, ns2, ns3;
+
+ t1 = time();
+
+ while (count < BUSY_LOOP_CNT) {
+ count++;
+ };
+
+ t2 = time();
+
+ while (count < BUSY_LOOP_CNT_LONG) {
+ count++;
+ };
+
+ t3 = time();
+
+ ns1 = odp_time_to_ns(t1);
+ ns2 = odp_time_to_ns(t2);
+ ns3 = odp_time_to_ns(t3);
+
+ CU_ASSERT(ns2 > ns1);
+ CU_ASSERT(ns3 > ns2);
+}
+
+void time_test_local_monotony(void)
+{
+ time_test_monotony(odp_time_local);
+}
+
+void time_test_global_monotony(void)
+{
+ time_test_monotony(odp_time_global);
+}
+
+static void time_test_cmp(time_cb time, time_from_ns_cb time_from_ns)
+{
+ /* volatile to stop optimization of busy loop */
+ volatile int count = 0;
+ odp_time_t t1, t2, t3;
+
+ t1 = time();
+
+ while (count < BUSY_LOOP_CNT) {
+ count++;
+ };
+
+ t2 = time();
+
+ while (count < BUSY_LOOP_CNT * 2) {
+ count++;
+ };
+
+ t3 = time();
+
+ CU_ASSERT(odp_time_cmp(t2, t1) > 0);
+ CU_ASSERT(odp_time_cmp(t3, t2) > 0);
+ CU_ASSERT(odp_time_cmp(t3, t1) > 0);
+ CU_ASSERT(odp_time_cmp(t1, t2) < 0);
+ CU_ASSERT(odp_time_cmp(t2, t3) < 0);
+ CU_ASSERT(odp_time_cmp(t1, t3) < 0);
+ CU_ASSERT(odp_time_cmp(t1, t1) == 0);
+ CU_ASSERT(odp_time_cmp(t2, t2) == 0);
+ CU_ASSERT(odp_time_cmp(t3, t3) == 0);
+
+ t2 = time_from_ns(60 * 10 * ODP_TIME_SEC_IN_NS);
+ t1 = time_from_ns(3);
+
+ CU_ASSERT(odp_time_cmp(t2, t1) > 0);
+ CU_ASSERT(odp_time_cmp(t1, t2) < 0);
+
+ t1 = time_from_ns(0);
+ CU_ASSERT(odp_time_cmp(t1, ODP_TIME_NULL) == 0);
+}
+
+void time_test_local_cmp(void)
+{
+ time_test_cmp(odp_time_local, odp_time_local_from_ns);
+}
+
+void time_test_global_cmp(void)
+{
+ time_test_cmp(odp_time_global, odp_time_global_from_ns);
+}
/* check that a time difference gives a reasonable result */
-void time_test_odp_diff(void)
+static void time_test_diff(time_cb time,
+ time_from_ns_cb time_from_ns,
+ uint64_t res)
{
/* volatile to stop optimization of busy loop */
volatile int count = 0;
odp_time_t diff, t1, t2;
+ uint64_t nsdiff, ns1, ns2, ns;
+ uint64_t upper_limit, lower_limit;
- t1 = odp_time_local();
+ /* test timestamp diff */
+ t1 = time();
while (count < BUSY_LOOP_CNT) {
count++;
};
- t2 = odp_time_local();
+ t2 = time();
CU_ASSERT(odp_time_cmp(t2, t1) > 0);
diff = odp_time_diff(t2, t1);
CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
-}
-/* check that a negative time difference gives a reasonable result */
-void time_test_odp_negative_diff(void)
-{
- odp_time_t diff, t1, t2;
+ ns1 = odp_time_to_ns(t1);
+ ns2 = odp_time_to_ns(t2);
+ ns = ns2 - ns1;
+ nsdiff = odp_time_to_ns(diff);
+
+ upper_limit = ns + res;
+ lower_limit = ns - res;
+ CU_ASSERT((nsdiff <= upper_limit) && (nsdiff >= lower_limit));
+
+ /* test timestamp and interval diff */
+ ns1 = 54;
+ t1 = time_from_ns(ns1);
+ ns = ns2 - ns1;
- t1 = 10;
- t2 = 5;
diff = odp_time_diff(t2, t1);
CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
+ nsdiff = odp_time_to_ns(diff);
+
+ upper_limit = ns + res;
+ lower_limit = ns - res;
+ CU_ASSERT((nsdiff <= upper_limit) && (nsdiff >= lower_limit));
+
+ /* test interval diff */
+ ns2 = 60 * 10 * ODP_TIME_SEC_IN_NS;
+ ns = ns2 - ns1;
+
+ t2 = time_from_ns(ns2);
+ diff = odp_time_diff(t2, t1);
+ CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
+ nsdiff = odp_time_to_ns(diff);
+
+ upper_limit = ns + res;
+ lower_limit = ns - res;
+ CU_ASSERT((nsdiff <= upper_limit) && (nsdiff >= lower_limit));
+
+ /* same time has to diff to 0 */
+ diff = odp_time_diff(t2, t2);
+ CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) == 0);
+
+ diff = odp_time_diff(t2, ODP_TIME_NULL);
+ CU_ASSERT(odp_time_cmp(t2, diff) == 0);
}
-/* check that related conversions come back to the same value */
-void time_test_odp_conversion(void)
+void time_test_local_diff(void)
{
- uint64_t ns1, ns2;
- odp_time_t time;
+ time_test_diff(odp_time_local, odp_time_local_from_ns, local_res);
+}
+
+void time_test_global_diff(void)
+{
+ time_test_diff(odp_time_global, odp_time_global_from_ns, global_res);
+}
+
+/* check that a time sum gives a reasonable result */
+static void time_test_sum(time_cb time,
+ time_from_ns_cb time_from_ns,
+ uint64_t res)
+{
+ odp_time_t sum, t1, t2;
+ uint64_t nssum, ns1, ns2, ns;
uint64_t upper_limit, lower_limit;
- ns1 = 100;
- time = odp_time_local_from_ns(ns1);
- CU_ASSERT(odp_time_cmp(time, ODP_TIME_NULL) > 0);
+ /* sum timestamp and interval */
+ t1 = time();
+ ns2 = 103;
+ t2 = time_from_ns(ns2);
+ ns1 = odp_time_to_ns(t1);
+ ns = ns1 + ns2;
- ns2 = odp_time_to_ns(time);
+ sum = odp_time_sum(t2, t1);
+ CU_ASSERT(odp_time_cmp(sum, ODP_TIME_NULL) > 0);
+ nssum = odp_time_to_ns(sum);
- /* need to check within arithmetic tolerance that the same
- * value in ns is returned after conversions */
- upper_limit = ns1 + TOLERANCE;
- lower_limit = ns1 - TOLERANCE;
- CU_ASSERT((ns2 <= upper_limit) && (ns2 >= lower_limit));
+ upper_limit = ns + res;
+ lower_limit = ns - res;
+ CU_ASSERT((nssum <= upper_limit) && (nssum >= lower_limit));
+
+ /* sum intervals */
+ ns1 = 60 * 13 * ODP_TIME_SEC_IN_NS;
+ t1 = time_from_ns(ns1);
+ ns = ns1 + ns2;
+
+ sum = odp_time_sum(t2, t1);
+ CU_ASSERT(odp_time_cmp(sum, ODP_TIME_NULL) > 0);
+ nssum = odp_time_to_ns(sum);
+
+ upper_limit = ns + res;
+ lower_limit = ns - res;
+ CU_ASSERT((nssum <= upper_limit) && (nssum >= lower_limit));
+
+ /* test on 0 */
+ sum = odp_time_sum(t2, ODP_TIME_NULL);
+ CU_ASSERT(odp_time_cmp(t2, sum) == 0);
+}
+
+void time_test_local_sum(void)
+{
+ time_test_sum(odp_time_local, odp_time_local_from_ns, local_res);
+}
+
+void time_test_global_sum(void)
+{
+ time_test_sum(odp_time_global, odp_time_global_from_ns, global_res);
+}
+
+static void time_test_wait_until(time_cb time, time_from_ns_cb time_from_ns)
+{
+ int i;
+ odp_time_t lower_limit, upper_limit;
+ odp_time_t start_time, end_time, wait;
+ odp_time_t second = time_from_ns(ODP_TIME_SEC_IN_NS);
+
+ start_time = time();
+ wait = start_time;
+ for (i = 1; i < 6; i++) {
+ wait = odp_time_sum(wait, second);
+ odp_time_wait_until(wait);
+ printf("%d..", i);
+ }
+ end_time = time();
+
+ wait = odp_time_diff(end_time, start_time);
+ lower_limit = time_from_ns(5 * ODP_TIME_SEC_IN_NS - DELAY_TOLERANCE);
+ upper_limit = time_from_ns(5 * ODP_TIME_SEC_IN_NS + DELAY_TOLERANCE);
+
+ CU_ASSERT(odp_time_cmp(wait, lower_limit) >= 0);
+ CU_ASSERT(odp_time_cmp(wait, upper_limit) <= 0);
+}
+
+void time_test_local_wait_until(void)
+{
+ time_test_wait_until(odp_time_local, odp_time_local_from_ns);
+}
+
+void time_test_global_wait_until(void)
+{
+ time_test_wait_until(odp_time_global, odp_time_global_from_ns);
+}
+
+void time_test_wait_ns(void)
+{
+ int i;
+ odp_time_t lower_limit, upper_limit;
+ odp_time_t start_time, end_time, diff;
+
+ start_time = odp_time_local();
+ for (i = 1; i < 6; i++) {
+ odp_time_wait_ns(ODP_TIME_SEC_IN_NS);
+ printf("%d..", i);
+ }
+ end_time = odp_time_local();
+
+ diff = odp_time_diff(end_time, start_time);
+
+ lower_limit = odp_time_local_from_ns(5 * ODP_TIME_SEC_IN_NS -
+ DELAY_TOLERANCE);
+ upper_limit = odp_time_local_from_ns(5 * ODP_TIME_SEC_IN_NS +
+ DELAY_TOLERANCE);
+
+ CU_ASSERT(odp_time_cmp(diff, lower_limit) >= 0);
+ CU_ASSERT(odp_time_cmp(diff, upper_limit) <= 0);
+}
+
+static void time_test_to_u64(time_cb time)
+{
+ volatile int count = 0;
+ uint64_t val1, val2;
+ odp_time_t t1, t2;
+
+ t1 = time();
+
+ val1 = odp_time_to_u64(t1);
+ CU_ASSERT(val1 > 0);
+
+ while (count < BUSY_LOOP_CNT) {
+ count++;
+ };
+
+ t2 = time();
+ val2 = odp_time_to_u64(t2);
+ CU_ASSERT(val2 > 0);
+
+ CU_ASSERT(val2 > val1);
+
+ val1 = odp_time_to_u64(ODP_TIME_NULL);
+ CU_ASSERT(val1 == 0);
+}
+
+void time_test_local_to_u64(void)
+{
+ time_test_to_u64(odp_time_local);
+}
+
+void time_test_global_to_u64(void)
+{
+ time_test_to_u64(odp_time_global);
}
odp_testinfo_t time_suite_time[] = {
- ODP_TEST_INFO(time_test_odp_diff),
- ODP_TEST_INFO(time_test_odp_negative_diff),
- ODP_TEST_INFO(time_test_odp_conversion),
+ ODP_TEST_INFO(time_test_constants),
+ ODP_TEST_INFO(time_test_local_res),
+ ODP_TEST_INFO(time_test_local_conversion),
+ ODP_TEST_INFO(time_test_local_monotony),
+ ODP_TEST_INFO(time_test_local_cmp),
+ ODP_TEST_INFO(time_test_local_diff),
+ ODP_TEST_INFO(time_test_local_sum),
+ ODP_TEST_INFO(time_test_local_wait_until),
+ ODP_TEST_INFO(time_test_wait_ns),
+ ODP_TEST_INFO(time_test_local_to_u64),
+ ODP_TEST_INFO(time_test_global_res),
+ ODP_TEST_INFO(time_test_global_conversion),
+ ODP_TEST_INFO(time_test_global_monotony),
+ ODP_TEST_INFO(time_test_global_cmp),
+ ODP_TEST_INFO(time_test_global_diff),
+ ODP_TEST_INFO(time_test_global_sum),
+ ODP_TEST_INFO(time_test_global_wait_until),
+ ODP_TEST_INFO(time_test_global_to_u64),
ODP_TEST_INFO_NULL
};
diff --git a/test/validation/time/time.h b/test/validation/time/time.h
index b4e613c0b..d75b0f58d 100644
--- a/test/validation/time/time.h
+++ b/test/validation/time/time.h
@@ -10,9 +10,24 @@
#include <odp_cunit_common.h>
/* test functions: */
-void time_test_odp_diff(void);
-void time_test_odp_conversion(void);
-void time_test_odp_negative_diff(void);
+void time_test_constants(void);
+void time_test_local_res(void);
+void time_test_global_res(void);
+void time_test_local_conversion(void);
+void time_test_global_conversion(void);
+void time_test_local_monotony(void);
+void time_test_global_monotony(void);
+void time_test_local_cmp(void);
+void time_test_global_cmp(void);
+void time_test_local_diff(void);
+void time_test_global_diff(void);
+void time_test_local_sum(void);
+void time_test_global_sum(void);
+void time_test_local_wait_until(void);
+void time_test_global_wait_until(void);
+void time_test_wait_ns(void);
+void time_test_local_to_u64(void);
+void time_test_global_to_u64(void);
/* test arrays: */
extern odp_testinfo_t time_suite_time[];