aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/odp-linux-generic.conf3
-rw-r--r--configure.ac2
-rw-r--r--example/switch/odp_switch.c166
-rw-r--r--include/odp/api/abi-default/align.h3
-rw-r--r--include/odp/api/spec/align.h13
-rw-r--r--include/odp/api/spec/packet.h16
-rw-r--r--include/odp/api/spec/pool.h19
-rw-r--r--include/odp/api/spec/version.h.in18
-rw-r--r--platform/linux-generic/odp_comp.c2
-rw-r--r--platform/linux-generic/odp_ishm.c16
-rw-r--r--platform/linux-generic/odp_name_table.c5
-rw-r--r--platform/linux-generic/odp_packet.c16
-rw-r--r--platform/linux-generic/odp_pool.c10
-rw-r--r--platform/linux-generic/pktio/dpdk.c103
-rw-r--r--platform/linux-generic/pktio/ipc.c6
-rw-r--r--test/performance/odp_sched_latency.c46
-rw-r--r--test/performance/odp_sched_perf.c255
-rw-r--r--test/validation/api/ipsec/ipsec.c2
-rw-r--r--test/validation/api/ipsec/ipsec_test_out.c4
-rw-r--r--test/validation/api/ipsec/test_vectors.h4
-rw-r--r--test/validation/api/packet/packet.c56
-rw-r--r--test/validation/api/scheduler/scheduler.c14
-rw-r--r--test/validation/api/shmem/shmem.c17
-rw-r--r--test/validation/api/system/system.c47
24 files changed, 680 insertions, 163 deletions
diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf
index 5a3ca72ff..b1f0e9009 100644
--- a/config/odp-linux-generic.conf
+++ b/config/odp-linux-generic.conf
@@ -62,7 +62,8 @@ pool: {
max_num = 262143
# Base alignment for segment data. When set to zero,
- # cache line size is used. Use power of two values.
+ # cache line size is used. Use power of two values. This is
+ # also the maximum value for the packet pool alignment param.
base_align = 0
}
diff --git a/configure.ac b/configure.ac
index 3d7604a98..ed91971ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ AC_PREREQ([2.5])
##########################################################################
m4_define([odpapi_generation_version], [1])
m4_define([odpapi_major_version], [23])
-m4_define([odpapi_minor_version], [1])
+m4_define([odpapi_minor_version], [3])
m4_define([odpapi_point_version], [0])
m4_define([odpapi_version],
[odpapi_generation_version.odpapi_major_version.odpapi_minor_version.odpapi_point_version])
diff --git a/example/switch/odp_switch.c b/example/switch/odp_switch.c
index b73d8a50c..ccb975f6c 100644
--- a/example/switch/odp_switch.c
+++ b/example/switch/odp_switch.c
@@ -1,4 +1,5 @@
/* Copyright (c) 2016-2018, Linaro Limited
+ * Copyright (c) 2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -9,6 +10,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
+#include <signal.h>
#include <odp_api.h>
#include <odp/helper/odph_api.h>
@@ -34,6 +36,9 @@
/** Number of MAC table entries. Must match to hash length. */
#define MAC_TBL_SIZE UINT16_MAX
+/** Aging time for MAC table entries in minutes. Must be <= UINT8_MAX. */
+#define AGING_TIME 5
+
/** Get rid of path in filename - only for unix-type paths using '/' */
#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
strrchr((file_name), '/') + 1 : (file_name))
@@ -43,6 +48,7 @@ typedef union {
struct {
odph_ethaddr_t mac; /**< Ethernet MAC address */
uint8_t port; /**< Port index */
+ uint8_t tick; /**< Tick of the latest received packet */
} s;
uint64_t u64;
@@ -61,6 +67,12 @@ typedef struct {
char *if_str; /**< Storage for interface names */
} appl_args_t;
+typedef enum frame_type_t {
+ FRAME_UNICAST,
+ FRAME_BROADCAST,
+ FRAME_INVALID
+} frame_type_t;
+
/**
* Statistics
*/
@@ -138,6 +150,13 @@ typedef struct {
/** Global pointer to args */
static args_t *gbl_args;
+static void sig_handler(int signo ODP_UNUSED)
+{
+ if (gbl_args == NULL)
+ return;
+ gbl_args->exit_threads = 1;
+}
+
/**
* Calculate MAC table index using Ethernet address hash
*
@@ -155,15 +174,29 @@ static inline uint16_t calc_mac_tbl_idx(odph_ethaddr_t *mac)
}
/**
+ * Calculate diff between ticks and take care of value wrap
+ */
+static inline uint8_t diff_ticks(uint8_t t2, uint8_t t1)
+{
+ if (t1 < t2)
+ return t2 - t1;
+ else if (t1 > t2)
+ return UINT8_MAX + t2 - t1;
+ return 0;
+}
+
+/**
* Get Ethernet address port index from MAC table
*
* @param mac Pointer to Ethernet address
* @param port[out] Pointer to port index for output
+ * @param cur_tick Current tick
*
- * @retval 0 on success
- * @retval -1 on failure
+ * @retval 1 on entry found
+ * @retval 0 on entry not found or expired
*/
-static inline int mac_table_get(odph_ethaddr_t *mac, uint8_t *port)
+static inline int mac_table_get(odph_ethaddr_t *mac, uint8_t *port,
+ uint8_t cur_tick)
{
mac_tbl_entry_t entry;
uint16_t idx;
@@ -173,10 +206,13 @@ static inline int mac_table_get(odph_ethaddr_t *mac, uint8_t *port)
entry.u64 = odp_atomic_load_u64(&gbl_args->mac_tbl[idx]);
if (memcmp(mac->addr, entry.s.mac.addr, ODPH_ETHADDR_LEN))
- return -1;
+ return 0;
+
+ if (odp_unlikely(diff_ticks(cur_tick, entry.s.tick) > AGING_TIME))
+ return 0;
*port = entry.s.port;
- return 0;
+ return 1;
}
/**
@@ -184,18 +220,24 @@ static inline int mac_table_get(odph_ethaddr_t *mac, uint8_t *port)
*
* @param mac Pointer to Ethernet address
* @param port Pointer to port index
+ * @param cur_tick Current tick
*/
-static inline void mac_table_put(odph_ethaddr_t *mac, uint8_t port)
+static inline void mac_table_update(odph_ethaddr_t *mac, uint8_t port,
+ uint8_t cur_tick)
{
mac_tbl_entry_t entry;
uint16_t idx;
idx = calc_mac_tbl_idx(mac);
+ entry.u64 = odp_atomic_load_u64(&gbl_args->mac_tbl[idx]);
- entry.s.mac = *mac;
- entry.s.port = port;
-
- odp_atomic_store_u64(&gbl_args->mac_tbl[idx], entry.u64);
+ if (memcmp(entry.s.mac.addr, mac->addr, ODPH_ETHADDR_LEN) ||
+ entry.s.port != port || entry.s.tick != cur_tick) {
+ entry.s.mac = *mac;
+ entry.s.port = port;
+ entry.s.tick = cur_tick;
+ odp_atomic_store_u64(&gbl_args->mac_tbl[idx], entry.u64);
+ }
}
/**
@@ -318,6 +360,8 @@ static int print_speed_stats(int num_workers, stats_t (*thr_stats)[MAX_PKTIOS],
uint64_t tx_pkts_prev[MAX_PKTIOS] = {0};
uint64_t rx_pkts_tot;
uint64_t tx_pkts_tot;
+ uint64_t rx_drops_tot;
+ uint64_t tx_drops_tot;
uint64_t rx_pps;
uint64_t tx_pps;
int i, j;
@@ -336,11 +380,13 @@ static int print_speed_stats(int num_workers, stats_t (*thr_stats)[MAX_PKTIOS],
do {
uint64_t rx_pkts[MAX_PKTIOS] = {0};
uint64_t tx_pkts[MAX_PKTIOS] = {0};
- uint64_t rx_drops = 0;
- uint64_t tx_drops = 0;
+ uint64_t rx_drops[MAX_PKTIOS] = {0};
+ uint64_t tx_drops[MAX_PKTIOS] = {0};
rx_pkts_tot = 0;
tx_pkts_tot = 0;
+ rx_drops_tot = 0;
+ tx_drops_tot = 0;
sleep(timeout);
elapsed += timeout;
@@ -349,8 +395,8 @@ static int print_speed_stats(int num_workers, stats_t (*thr_stats)[MAX_PKTIOS],
for (j = 0; j < num_ifaces; j++) {
rx_pkts[j] += thr_stats[i][j].s.rx_packets;
tx_pkts[j] += thr_stats[i][j].s.tx_packets;
- rx_drops += thr_stats[i][j].s.rx_drops;
- tx_drops += thr_stats[i][j].s.tx_drops;
+ rx_drops[j] += thr_stats[i][j].s.rx_drops;
+ tx_drops[j] += thr_stats[i][j].s.tx_drops;
}
}
@@ -362,20 +408,24 @@ static int print_speed_stats(int num_workers, stats_t (*thr_stats)[MAX_PKTIOS],
tx_pps = (tx_pkts[j] - tx_pkts_prev[j]) / timeout;
printf(" Port %d: %" PRIu64 " rx pps, %" PRIu64
" tx pps, %" PRIu64 " rx pkts, %" PRIu64
- " tx pkts\n", j, rx_pps, tx_pps, rx_pkts[j],
- tx_pkts[j]);
+ " tx pkts, %" PRIu64 " rx drops, %" PRIu64
+ " tx drops\n", j, rx_pps, tx_pps, rx_pkts[j],
+ tx_pkts[j], rx_drops[j], tx_drops[j]);
rx_pkts_prev[j] = rx_pkts[j];
tx_pkts_prev[j] = tx_pkts[j];
rx_pkts_tot += rx_pkts[j];
tx_pkts_tot += tx_pkts[j];
+ rx_drops_tot += rx_drops[j];
+ tx_drops_tot += tx_drops[j];
}
printf("Total: %" PRIu64 " rx pkts, %" PRIu64 " tx pkts, %"
PRIu64 " rx drops, %" PRIu64 " tx drops\n", rx_pkts_tot,
- tx_pkts_tot, rx_drops, tx_drops);
+ tx_pkts_tot, rx_drops_tot, tx_drops_tot);
- } while (loop_forever || (elapsed < duration));
+ } while (!gbl_args->exit_threads &&
+ (loop_forever || (elapsed < duration)));
return rx_pkts_tot >= 100 ? 0 : -1;
}
@@ -463,6 +513,34 @@ static inline void broadcast_packet(odp_packet_t pkt, thread_args_t *thr_arg,
}
/**
+ * Check Ethernet frame for broadcast/invalid addresses
+ *
+ * @param eth Pointer to an Ethernet header
+ *
+ * @retval Ethernet frame_type_t
+ */
+static frame_type_t check_frame(odph_ethhdr_t *eth)
+{
+ static uint8_t broadcast_addr[ODPH_ETHADDR_LEN] = {0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff};
+ static uint8_t null_addr[ODPH_ETHADDR_LEN] = {0, 0, 0, 0, 0, 0};
+
+ /* Drop invalid frames */
+ if (odp_unlikely(!memcmp(eth->src.addr, broadcast_addr,
+ ODPH_ETHADDR_LEN) ||
+ !memcmp(eth->dst.addr, null_addr,
+ ODPH_ETHADDR_LEN) ||
+ !memcmp(eth->src.addr, null_addr,
+ ODPH_ETHADDR_LEN))) {
+ return FRAME_INVALID;
+ }
+ if (!memcmp(eth->dst.addr, broadcast_addr, ODPH_ETHADDR_LEN))
+ return FRAME_BROADCAST;
+
+ return FRAME_UNICAST;
+}
+
+/**
* Forward packets to correct output buffers
*
* Packets, whose destination MAC address is already known from previously
@@ -474,38 +552,44 @@ static inline void broadcast_packet(odp_packet_t pkt, thread_args_t *thr_arg,
* @param num Number of packets in the array
* @param thr_arg Thread arguments
* @param port_in Input port index
+ * @param cur_tick Current tick
*/
static inline void forward_packets(odp_packet_t pkt_tbl[], unsigned int num,
- thread_args_t *thr_arg, uint8_t port_in)
+ thread_args_t *thr_arg, uint8_t port_in,
+ uint8_t cur_tick)
{
odp_packet_t pkt;
odph_ethhdr_t *eth;
unsigned int i;
unsigned int buf_id;
- int ret;
uint8_t port_out = 0;
+ int frame_type;
for (i = 0; i < num; i++) {
pkt = pkt_tbl[i];
if (!odp_packet_has_eth(pkt)) {
+ thr_arg->stats[port_in]->s.rx_drops++;
odp_packet_free(pkt);
continue;
}
eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
- /* Lookup source MAC address */
- ret = mac_table_get(&eth->src, &port_out);
+ /* Check Ethernet frame type */
+ frame_type = check_frame(eth);
+ if (odp_unlikely(frame_type == FRAME_INVALID)) {
+ thr_arg->stats[port_in]->s.rx_drops++;
+ odp_packet_free(pkt);
+ continue;
+ }
- /* Update for address table if necessary */
- if (ret < 0 || port_out != port_in)
- mac_table_put(&eth->src, port_in);
+ /* Update source address MAC table entry */
+ mac_table_update(&eth->src, port_in, cur_tick);
- /* Lookup destination MAC address */
- ret = mac_table_get(&eth->dst, &port_out);
- if (ret < 0) {
- /* If address was not found, broadcast packet */
+ /* Broadcast frame is necessary */
+ if (frame_type == FRAME_BROADCAST ||
+ !mac_table_get(&eth->dst, &port_out, cur_tick)) {
broadcast_packet(pkt, thr_arg, port_in);
continue;
}
@@ -583,6 +667,9 @@ static int run_worker(void *arg)
odp_packet_t pkt_tbl[MAX_PKT_BURST];
odp_pktin_queue_t pktin;
odp_pktout_queue_t pktout;
+ odp_time_t time_prev;
+ odp_time_t minute;
+ uint8_t cur_tick;
unsigned int num_pktio;
unsigned int pktio = 0;
uint8_t port_in;
@@ -595,7 +682,13 @@ static int run_worker(void *arg)
odp_barrier_wait(&gbl_args->barrier);
+ minute = odp_time_local_from_ns(ODP_TIME_MIN_IN_NS);
+ time_prev = odp_time_local();
+ cur_tick = (odp_time_to_ns(time_prev) / ODP_TIME_MIN_IN_NS) % UINT8_MAX;
+
while (!gbl_args->exit_threads) {
+ odp_time_t time_cur;
+ odp_time_t time_diff;
int sent;
unsigned int drops;
@@ -611,10 +704,20 @@ static int run_worker(void *arg)
if (odp_unlikely(pkts <= 0))
continue;
+ time_cur = odp_time_local();
+ time_diff = odp_time_diff(time_cur, time_prev);
+
+ if (odp_unlikely(odp_time_cmp(time_diff, minute))) {
+ /* Tick stored as 8 bit value */
+ cur_tick = (odp_time_to_ns(time_cur) /
+ ODP_TIME_MIN_IN_NS) % UINT8_MAX;
+ time_prev = time_cur;
+ }
+
thr_args->stats[port_in]->s.rx_packets += pkts;
/* Sort packets to thread local tx buffers */
- forward_packets(pkt_tbl, pkts, thr_args, port_in);
+ forward_packets(pkt_tbl, pkts, thr_args, port_in, cur_tick);
/* Empty all thread local tx buffers */
for (port_out = 0; port_out < gbl_args->appl.if_count;
@@ -882,6 +985,8 @@ int main(int argc, char **argv)
odp_init_t init_param;
odph_odpthread_params_t thr_params;
+ signal(SIGINT, sig_handler);
+
/* Let helper collect its own arguments (e.g. --odph_proc) */
argc = odph_parse_options(argc, argv);
if (odph_options(&helper_options)) {
@@ -1066,6 +1171,5 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
- printf("Exit: %d\n\n", ret);
return ret;
}
diff --git a/include/odp/api/abi-default/align.h b/include/odp/api/abi-default/align.h
index c1150febe..b3bbed199 100644
--- a/include/odp/api/abi-default/align.h
+++ b/include/odp/api/abi-default/align.h
@@ -45,6 +45,9 @@ extern "C" {
#define ODP_ALIGNED_PAGE ODP_ALIGNED(ODP_PAGE_SIZE)
+#define ODP_CACHE_LINE_ROUNDUP(x) \
+((ODP_CACHE_LINE_SIZE) * (((x) + (ODP_CACHE_LINE_SIZE) - 1) / (ODP_CACHE_LINE_SIZE)))
+
/**
* @}
*/
diff --git a/include/odp/api/spec/align.h b/include/odp/api/spec/align.h
index 6e4ef0cd2..99f8f1db0 100644
--- a/include/odp/api/spec/align.h
+++ b/include/odp/api/spec/align.h
@@ -48,12 +48,12 @@ extern "C" {
/**
* @def ODP_CACHE_LINE_SIZE
- * Cache line size
+ * Cache line size in bytes
*/
/**
* @def ODP_PAGE_SIZE
- * Page size
+ * Page size in bytes
*/
/**
@@ -67,6 +67,15 @@ extern "C" {
*/
/**
+ * @def ODP_CACHE_LINE_ROUNDUP
+ * Round up to cache line size
+ *
+ * Rounds up the passed value to the next multiple of cache line size
+ * (ODP_CACHE_LINE_SIZE). Returns the original value if it is already
+ * a multiple of cache line size or zero.
+ */
+
+/**
* @}
*/
diff --git a/include/odp/api/spec/packet.h b/include/odp/api/spec/packet.h
index cbc3c2cbd..ec20371b2 100644
--- a/include/odp/api/spec/packet.h
+++ b/include/odp/api/spec/packet.h
@@ -318,11 +318,10 @@ void odp_packet_free_sp(const odp_packet_t pkt[], int num);
*
* Resets all packet metadata to their default values. Packet length is used
* to initialize pointers and lengths. It must be less than the total buffer
- * length of the packet minus the default headroom length. Packet is not
- * modified on failure.
+ * length of the packet. Packet is not modified on failure.
*
* @param pkt Packet handle
- * @param len Packet data length
+ * @param len Packet data length (1 ... odp_packet_buf_len())
*
* @retval 0 on success
* @retval <0 on failure
@@ -724,7 +723,8 @@ int odp_packet_extend_head(odp_packet_t *pkt, uint32_t len, void **data_ptr,
*
* @param[in, out] pkt Pointer to packet handle. A successful operation outputs
* the new packet handle.
- * @param len Number of bytes to truncate the head (0 ... packet_len)
+ * @param len Number of bytes to truncate the head
+ * (0 ... packet_len - 1)
* @param[out] data_ptr Pointer to output the new data pointer.
* Ignored when NULL.
* @param[out] seg_len Pointer to output segment length at 'data_ptr' above.
@@ -797,7 +797,8 @@ int odp_packet_extend_tail(odp_packet_t *pkt, uint32_t len, void **data_ptr,
*
* @param[in, out] pkt Pointer to packet handle. A successful operation outputs
* the new packet handle.
- * @param len Number of bytes to truncate the tail (0 ... packet_len)
+ * @param len Number of bytes to truncate the tail
+ * (0 ... packet_len - 1)
* @param[out] tail_ptr Pointer to output the new tail pointer.
* Ignored when NULL.
* @param[out] tailroom Pointer to output the new tailroom. Ignored when NULL.
@@ -861,7 +862,9 @@ int odp_packet_add_data(odp_packet_t *pkt, uint32_t offset, uint32_t len);
* @param[in, out] pkt Pointer to packet handle. A successful operation outputs
* the new packet handle.
* @param offset Byte offset into the packet
- * @param len Number of bytes to remove from the offset
+ * @param len Number of bytes to remove from the offset. When offset
+ * is zero: 0 ... packet_len - 1 bytes, otherwise
+ * 0 ... packet_len - offset bytes.
*
* @retval 0 Operation successful, old pointers remain valid
* @retval >0 Operation successful, old pointers need to be updated
@@ -1064,6 +1067,7 @@ int odp_packet_concat(odp_packet_t *dst, odp_packet_t src);
* @param[in, out] pkt Pointer to packet handle. A successful operation
* outputs a new packet handle for the head packet.
* @param len Data length remaining in the head packet
+ * (1 ... packet_len - 1)
* @param tail Pointer to output the tail packet handle
*
* @retval 0 Operation successful, old pointers remain valid
diff --git a/include/odp/api/spec/pool.h b/include/odp/api/spec/pool.h
index 69e99605c..754e2cc04 100644
--- a/include/odp/api/spec/pool.h
+++ b/include/odp/api/spec/pool.h
@@ -92,6 +92,12 @@ typedef struct odp_pool_capability_t {
* memory size for the pool. */
uint32_t max_num;
+ /** Maximum packet data alignment in bytes
+ *
+ * This is the maximum value of packet pool alignment
+ * (pkt.align) parameter. */
+ uint32_t max_align;
+
/** Minimum packet level headroom length in bytes
*
* The minimum number of headroom bytes that newly created
@@ -248,6 +254,19 @@ typedef struct odp_pool_param_t {
*/
uint32_t max_len;
+ /** Minimum packet data alignment in bytes.
+ *
+ * Valid values are powers of two. User allocated packets have
+ * start of data (@see odp_packet_data()) aligned to this or
+ * a higher alignment (power of two value). This parameter
+ * does not apply to packets that ODP allocates internally
+ * (e.g. packets from packet input).
+ *
+ * The maximum value is defined by pool capability
+ * pkt.max_align. Use 0 for default alignment.
+ */
+ uint32_t align;
+
/** Minimum number of packet data bytes that are stored in the
* first segment of a packet. The maximum value is defined by
* pool capability pkt.max_seg_len. Use 0 for default.
diff --git a/include/odp/api/spec/version.h.in b/include/odp/api/spec/version.h.in
index 4c3cbfee8..21a5f9a77 100644
--- a/include/odp/api/spec/version.h.in
+++ b/include/odp/api/spec/version.h.in
@@ -1,4 +1,5 @@
/* Copyright (c) 2013-2018, Linaro Limited
+ * Copyright (c) 2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -56,6 +57,23 @@ extern "C" {
#define ODP_VERSION_API_MINOR @ODP_VERSION_API_MINOR@
/**
+ * ODP API version number macro
+ *
+ * Macro to build a version number for comparisons
+ */
+#define ODP_VERSION_API_NUM(gen, ma, mi) ((gen) << 24 | (ma) << 16 | (mi) << 8)
+
+/**
+ * ODP API version number
+ *
+ * API version number for comparisons against ODP_VERSION_API_NUM()
+ * macro output.
+ */
+#define ODP_VERSION_API ODP_VERSION_API_NUM(ODP_VERSION_API_GENERATION, \
+ ODP_VERSION_API_MAJOR, \
+ ODP_VERSION_API_MINOR)
+
+/**
* ODP API version string
*
* The API version string defines ODP API version in this format:
diff --git a/platform/linux-generic/odp_comp.c b/platform/linux-generic/odp_comp.c
index 0e9ce5a89..8e1de69c2 100644
--- a/platform/linux-generic/odp_comp.c
+++ b/platform/linux-generic/odp_comp.c
@@ -154,7 +154,7 @@ static void process_input(odp_packet_t pkt_out,
streamp->next_out = out_data;
streamp->avail_out = out_len;
- ODP_DBG("next_in 0x%x, avail_in %d next_out 0x%lx"
+ ODP_DBG("next_in %p, avail_in %d next_out %p"
" avail_out %d, sync %d\n",
streamp->next_in, streamp->avail_in,
streamp->next_out,
diff --git a/platform/linux-generic/odp_ishm.c b/platform/linux-generic/odp_ishm.c
index 41f3979bf..8e34feecd 100644
--- a/platform/linux-generic/odp_ishm.c
+++ b/platform/linux-generic/odp_ishm.c
@@ -2037,7 +2037,9 @@ int _odp_ishm_status(const char *title)
entry_fd = ishm_proctable->entry[proc_index].fd;
}
- ODP_PRINT("%2i %-*s %s%c 0x%-08lx-0x%08lx %-08ld %-08ld %-3lu %-3lu %-3d %s\n",
+ ODP_PRINT("%2i %-*s %s%c %p-%p %-08" PRIu64 " "
+ "%-08" PRIu64 " %-3" PRIu64 " %-3" PRIu64 " "
+ "%-3d %s\n",
i, max_name_len, ishm_tbl->block[i].name,
flags, huge, start_addr, end_addr,
ishm_tbl->block[i].user_len,
@@ -2049,10 +2051,10 @@ int _odp_ishm_status(const char *title)
ishm_tbl->block[i].filename :
"(none)");
}
- ODP_PRINT("TOTAL: %58s%-08ld %2s%-08ld\n",
+ ODP_PRINT("TOTAL: %58s%-08" PRIu64 " %2s%-08" PRIu64 "\n",
"", len_total,
"", lost_total);
- ODP_PRINT("%65s(%dMB) %4s(%dMB)\n",
+ ODP_PRINT("%65s(%" PRIu64 "MB) %4s(%" PRIu64 "MB)\n",
"", len_total / 1024 / 1024,
"", lost_total / 1024 / 1024);
@@ -2141,9 +2143,9 @@ void _odp_ishm_print(int block_index)
ODP_PRINT(" expt: %s\n", block->exptname);
ODP_PRINT(" user_flags: 0x%x\n", block->user_flags);
ODP_PRINT(" flags: 0x%x\n", block->flags);
- ODP_PRINT(" user_len: %lu\n", block->user_len);
+ ODP_PRINT(" user_len: %" PRIu64 "\n", block->user_len);
ODP_PRINT(" start: %p\n", block->start);
- ODP_PRINT(" len: %lu\n", block->len);
+ ODP_PRINT(" len: %" PRIu64 "\n", block->len);
switch (block->huge) {
case HUGE:
@@ -2163,8 +2165,8 @@ void _odp_ishm_print(int block_index)
}
ODP_PRINT(" page type: %s\n", str);
- ODP_PRINT(" seq: %lu\n", block->seq);
- ODP_PRINT(" refcnt: %lu\n", block->refcnt);
+ ODP_PRINT(" seq: %" PRIu64 "\n", block->seq);
+ ODP_PRINT(" refcnt: %" PRIu64 "\n", block->refcnt);
ODP_PRINT("\n");
odp_spinlock_unlock(&ishm_tbl->lock);
diff --git a/platform/linux-generic/odp_name_table.c b/platform/linux-generic/odp_name_table.c
index b4825fa18..3697bc877 100644
--- a/platform/linux-generic/odp_name_table.c
+++ b/platform/linux-generic/odp_name_table.c
@@ -10,6 +10,7 @@
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
+#include <inttypes.h>
#include <odp_name_table_internal.h>
#include <odp_debug_internal.h>
#include <odp_macros_internal.h>
@@ -1125,8 +1126,8 @@ void _odp_int_name_tbl_stats_print(void)
uint32_t avg;
ODP_DBG("\nname table stats:\n");
- ODP_DBG(" num_names=%u num_adds=%lu "
- "num_deletes=%lu num_name_tbls=%u\n",
+ ODP_DBG(" num_names=%" PRIu32 " num_adds=%" PRIu64 " "
+ "num_deletes=%" PRIu64 " num_name_tbls=%" PRIu8 "\n",
name_tbls.current_num_names, name_tbls.num_adds,
name_tbls.num_deletes, name_tbls.num_name_tbls);
for (idx = 0; idx < NUM_NAME_TBLS; idx++) {
diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c
index 9e3f3a2b8..430839be6 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -686,7 +686,7 @@ odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len)
return ODP_PACKET_INVALID;
}
- if (odp_unlikely(len > pool->max_len))
+ if (odp_unlikely(len > pool->max_len || len == 0))
return ODP_PACKET_INVALID;
num_seg = num_segments(len, pool->seg_len);
@@ -709,7 +709,7 @@ int odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len,
return -1;
}
- if (odp_unlikely(len > pool->max_len))
+ if (odp_unlikely(len > pool->max_len || len == 0))
return -1;
num_seg = num_segments(len, pool->seg_len);
@@ -771,7 +771,7 @@ int odp_packet_reset(odp_packet_t pkt, uint32_t len)
int num = pkt_hdr->seg_count;
int num_req;
- if (odp_unlikely(len > (pool->seg_len * num)))
+ if (odp_unlikely(len > (pool->seg_len * num)) || len == 0)
return -1;
/* Free possible extra segments */
@@ -887,7 +887,7 @@ void *odp_packet_pull_head(odp_packet_t pkt, uint32_t len)
{
odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt);
- if (len > pkt_hdr->frame_len)
+ if (len >= pkt_hdr->seg_len)
return NULL;
pull_head(pkt_hdr, len);
@@ -900,7 +900,7 @@ int odp_packet_trunc_head(odp_packet_t *pkt, uint32_t len,
odp_packet_hdr_t *pkt_hdr = packet_hdr(*pkt);
uint32_t seg_len = packet_first_seg_len(pkt_hdr);
- if (len > pkt_hdr->frame_len)
+ if (len >= pkt_hdr->frame_len)
return -1;
if (len < seg_len) {
@@ -993,7 +993,7 @@ void *odp_packet_pull_tail(odp_packet_t pkt, uint32_t len)
ODP_ASSERT(odp_packet_has_ref(pkt) == 0);
- if (len > last_seg->seg_len)
+ if (len >= last_seg->seg_len)
return NULL;
pull_tail(pkt_hdr, len);
@@ -1009,7 +1009,7 @@ int odp_packet_trunc_tail(odp_packet_t *pkt, uint32_t len,
odp_packet_hdr_t *last_seg;
odp_packet_hdr_t *pkt_hdr = packet_hdr(*pkt);
- if (len > pkt_hdr->frame_len)
+ if (len >= pkt_hdr->frame_len)
return -1;
ODP_ASSERT(odp_packet_has_ref(*pkt) == 0);
@@ -1234,7 +1234,7 @@ int odp_packet_rem_data(odp_packet_t *pkt_ptr, uint32_t offset, uint32_t len)
pool_t *pool = pkt_hdr->buf_hdr.pool_ptr;
odp_packet_t newpkt;
- if (offset > pktlen || offset + len > pktlen)
+ if (offset + len >= pktlen)
return -1;
newpkt = odp_packet_alloc(pool->pool_hdl, pktlen - len);
diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
index 5d5217aaf..e1964f840 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -503,6 +503,15 @@ static odp_pool_t pool_create(const char *name, odp_pool_param_t *params,
align = 0;
if (params->type == ODP_POOL_PACKET) {
+ uint32_t align_req = params->pkt.align;
+
+ if (align_req &&
+ (!CHECK_IS_POWER2(align_req) ||
+ align_req > _odp_pool_glb->config.pkt_base_align)) {
+ ODP_ERR("Bad align requirement\n");
+ return ODP_POOL_INVALID;
+ }
+
align = _odp_pool_glb->config.pkt_base_align;
} else {
if (params->type == ODP_POOL_BUFFER)
@@ -1106,6 +1115,7 @@ int odp_pool_capability(odp_pool_capability_t *capa)
capa->pkt.max_pools = max_pools;
capa->pkt.max_len = CONFIG_PACKET_MAX_LEN;
capa->pkt.max_num = _odp_pool_glb->config.pkt_max_num;
+ capa->pkt.max_align = _odp_pool_glb->config.pkt_base_align;
capa->pkt.min_headroom = CONFIG_PACKET_HEADROOM;
capa->pkt.max_headroom = CONFIG_PACKET_HEADROOM;
capa->pkt.min_tailroom = CONFIG_PACKET_TAILROOM;
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c
index 4308f0c99..18f583a65 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -1115,6 +1115,8 @@ static int dpdk_setup_eth_dev(pktio_entry_t *pktio_entry,
struct rte_eth_rss_conf rss_conf;
struct rte_eth_conf eth_conf;
uint64_t rss_hf_capa = dev_info->flow_type_rss_offloads;
+ uint64_t rx_offloads = 0;
+ uint64_t tx_offloads = 0;
memset(&rss_conf, 0, sizeof(struct rte_eth_rss_conf));
@@ -1134,6 +1136,36 @@ static int dpdk_setup_eth_dev(pktio_entry_t *pktio_entry,
eth_conf.txmode.mq_mode = ETH_MQ_TX_NONE;
eth_conf.rx_adv_conf.rss_conf = rss_conf;
+ /* Setup RX checksum offloads */
+ if (pktio_entry->s.config.pktin.bit.ipv4_chksum)
+ rx_offloads |= DEV_RX_OFFLOAD_IPV4_CKSUM;
+
+ if (pktio_entry->s.config.pktin.bit.udp_chksum)
+ rx_offloads |= DEV_RX_OFFLOAD_UDP_CKSUM;
+
+ if (pktio_entry->s.config.pktin.bit.tcp_chksum)
+ rx_offloads |= DEV_RX_OFFLOAD_TCP_CKSUM;
+
+ eth_conf.rxmode.offloads = rx_offloads;
+
+ /* Setup TX checksum offloads */
+ if (pktio_entry->s.config.pktout.bit.ipv4_chksum_ena)
+ tx_offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
+
+ if (pktio_entry->s.config.pktout.bit.udp_chksum_ena)
+ tx_offloads |= DEV_TX_OFFLOAD_UDP_CKSUM;
+
+ if (pktio_entry->s.config.pktout.bit.tcp_chksum_ena)
+ tx_offloads |= DEV_TX_OFFLOAD_TCP_CKSUM;
+
+ if (pktio_entry->s.config.pktout.bit.sctp_chksum_ena)
+ tx_offloads |= DEV_TX_OFFLOAD_SCTP_CKSUM;
+
+ eth_conf.txmode.offloads = tx_offloads;
+
+ if (tx_offloads)
+ pktio_entry->s.chksum_insert_ena = 1;
+
ret = rte_eth_dev_configure(pkt_dpdk->port_id,
pktio_entry->s.num_in_queue,
pktio_entry->s.num_out_queue, &eth_conf);
@@ -1441,15 +1473,17 @@ static int dpdk_output_queues_config(pktio_entry_t *pktio_entry,
return 0;
}
-static void dpdk_init_capability(pktio_entry_t *pktio_entry,
- struct rte_eth_dev_info *dev_info)
+static int dpdk_init_capability(pktio_entry_t *pktio_entry,
+ struct rte_eth_dev_info *dev_info)
{
pkt_dpdk_t *pkt_dpdk = pkt_priv(pktio_entry);
odp_pktio_capability_t *capa = &pktio_entry->s.capa;
+ struct rte_ether_addr mac_addr;
int ptype_cnt;
int ptype_l3_ipv4 = 0;
int ptype_l4_tcp = 0;
int ptype_l4_udp = 0;
+ int ret;
uint32_t ptype_mask = RTE_PTYPE_L3_MASK | RTE_PTYPE_L4_MASK;
memset(dev_info, 0, sizeof(struct rte_eth_dev_info));
@@ -1469,6 +1503,16 @@ static void dpdk_init_capability(pktio_entry_t *pktio_entry,
PKTIO_MAX_QUEUES);
capa->set_op.op.promisc_mode = 1;
+ /* Check if setting default MAC address is supporter */
+ rte_eth_macaddr_get(pkt_dpdk->port_id, &mac_addr);
+ ret = rte_eth_dev_default_mac_addr_set(pkt_dpdk->port_id, &mac_addr);
+ if (ret == 0) {
+ capa->set_op.op.mac_addr = 1;
+ } else if (ret != -ENOTSUP && ret != -EPERM) {
+ ODP_ERR("Failed to set interface default MAC: %d\n", ret);
+ return -1;
+ }
+
ptype_cnt = rte_eth_dev_get_supported_ptypes(pkt_dpdk->port_id,
ptype_mask, NULL, 0);
if (ptype_cnt > 0) {
@@ -1528,6 +1572,8 @@ static void dpdk_init_capability(pktio_entry_t *pktio_entry,
capa->config.pktout.bit.udp_chksum;
capa->config.pktout.bit.tcp_chksum_ena =
capa->config.pktout.bit.tcp_chksum;
+
+ return 0;
}
/* Some DPDK PMD virtual devices, like PCAP, do not support promisc
@@ -1606,7 +1652,10 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
return -1;
}
- dpdk_init_capability(pktio_entry, &dev_info);
+ if (dpdk_init_capability(pktio_entry, &dev_info)) {
+ ODP_ERR("Failed to initialize capability\n");
+ return -1;
+ }
/* Initialize runtime options */
if (init_options(pktio_entry, &dev_info)) {
@@ -1680,38 +1729,15 @@ static int dpdk_setup_eth_tx(pktio_entry_t *pktio_entry,
const pkt_dpdk_t *pkt_dpdk,
const struct rte_eth_dev_info *dev_info)
{
- struct rte_eth_txconf txconf;
- uint64_t tx_offloads;
uint32_t i;
int ret;
uint16_t port_id = pkt_dpdk->port_id;
- txconf = dev_info->default_txconf;
-
- tx_offloads = 0;
- if (pktio_entry->s.config.pktout.bit.ipv4_chksum_ena)
- tx_offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
-
- if (pktio_entry->s.config.pktout.bit.udp_chksum_ena)
- tx_offloads |= DEV_TX_OFFLOAD_UDP_CKSUM;
-
- if (pktio_entry->s.config.pktout.bit.tcp_chksum_ena)
- tx_offloads |= DEV_TX_OFFLOAD_TCP_CKSUM;
-
- if (pktio_entry->s.config.pktout.bit.sctp_chksum_ena)
- tx_offloads |= DEV_TX_OFFLOAD_SCTP_CKSUM;
-
- txconf.offloads = tx_offloads;
-
- if (tx_offloads)
- pktio_entry->s.chksum_insert_ena = 1;
-
for (i = 0; i < pktio_entry->s.num_out_queue; i++) {
-
ret = rte_eth_tx_queue_setup(port_id, i,
pkt_dpdk->opt.num_tx_desc,
rte_eth_dev_socket_id(port_id),
- &txconf);
+ &dev_info->default_txconf);
if (ret < 0) {
ODP_ERR("Queue setup failed: err=%d, port=%" PRIu8 "\n",
ret, port_id);
@@ -1727,7 +1753,6 @@ static int dpdk_setup_eth_rx(const pktio_entry_t *pktio_entry,
const struct rte_eth_dev_info *dev_info)
{
struct rte_eth_rxconf rxconf;
- uint64_t rx_offloads;
uint32_t i;
int ret;
uint16_t port_id = pkt_dpdk->port_id;
@@ -1736,18 +1761,6 @@ static int dpdk_setup_eth_rx(const pktio_entry_t *pktio_entry,
rxconf.rx_drop_en = pkt_dpdk->opt.rx_drop_en;
- rx_offloads = 0;
- if (pktio_entry->s.config.pktin.bit.ipv4_chksum)
- rx_offloads |= DEV_RX_OFFLOAD_IPV4_CKSUM;
-
- if (pktio_entry->s.config.pktin.bit.udp_chksum)
- rx_offloads |= DEV_RX_OFFLOAD_UDP_CKSUM;
-
- if (pktio_entry->s.config.pktin.bit.tcp_chksum)
- rx_offloads |= DEV_RX_OFFLOAD_TCP_CKSUM;
-
- rxconf.offloads = rx_offloads;
-
for (i = 0; i < pktio_entry->s.num_in_queue; i++) {
ret = rte_eth_rx_queue_setup(port_id, i,
pkt_dpdk->opt.num_rx_desc,
@@ -1996,6 +2009,14 @@ static int dpdk_mac_addr_get(pktio_entry_t *pktio_entry, void *mac_addr)
return ETH_ALEN;
}
+static int dpdk_mac_addr_set(pktio_entry_t *pktio_entry, const void *mac_addr)
+{
+ struct rte_ether_addr addr = *(const struct rte_ether_addr *)mac_addr;
+
+ return rte_eth_dev_default_mac_addr_set(pkt_priv(pktio_entry)->port_id,
+ &addr);
+}
+
static int dpdk_promisc_mode_set(pktio_entry_t *pktio_entry, odp_bool_t enable)
{
uint16_t port_id = pkt_priv(pktio_entry)->port_id;
@@ -2089,7 +2110,7 @@ const pktio_if_ops_t dpdk_pktio_ops = {
.promisc_mode_set = dpdk_promisc_mode_set,
.promisc_mode_get = dpdk_promisc_mode_get,
.mac_get = dpdk_mac_addr_get,
- .mac_set = NULL,
+ .mac_set = dpdk_mac_addr_set,
.capability = dpdk_capability,
.pktin_ts_res = NULL,
.pktin_ts_from_ns = NULL,
diff --git a/platform/linux-generic/pktio/ipc.c b/platform/linux-generic/pktio/ipc.c
index 7575eb052..d63a77b74 100644
--- a/platform/linux-generic/pktio/ipc.c
+++ b/platform/linux-generic/pktio/ipc.c
@@ -819,9 +819,9 @@ static int ipc_pktio_send_lockless(pktio_entry_t *pktio_entry,
(uint8_t *)odp_shm_addr(pool->shm);
/* compile all function code even if ipc disabled with config */
- IPC_ODP_DBG("%d/%d send packet %llx, pool %llx,"
- "phdr = %p, offset %x, sendoff %x, addr %llx iaddr %llx\n",
- i, num,
+ IPC_ODP_DBG("%d/%d send packet %" PRIu64 ", pool %" PRIu64 ","
+ "phdr = %p, offset %x, sendoff %x, addr %p iaddr "
+ "%p\n", i, num,
odp_packet_to_u64(pkt), odp_pool_to_u64(pool_hdl),
pkt_hdr, (uint8_t *)pkt_hdr->seg_data -
(uint8_t *)odp_shm_addr(pool->shm), offsets[i],
diff --git a/test/performance/odp_sched_latency.c b/test/performance/odp_sched_latency.c
index 2bdc4b356..c726074c5 100644
--- a/test/performance/odp_sched_latency.c
+++ b/test/performance/odp_sched_latency.c
@@ -1,4 +1,5 @@
/* Copyright (c) 2016-2018, Linaro Limited
+ * Copyright (c) 2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -25,8 +26,8 @@
#define MAX_QUEUES 4096 /**< Maximum number of queues */
#define EVENT_POOL_SIZE (1024 * 1024) /**< Event pool size */
-#define TEST_ROUNDS (4 * 1024 * 1024) /**< Test rounds for each thread */
-#define MAIN_THREAD 1 /**< Thread ID performing maintenance tasks */
+#define TEST_ROUNDS 10 /**< Test rounds for each thread (millions) */
+#define MAIN_THREAD 1 /**< Thread ID performing maintenance tasks */
/* Default values for command line arguments */
#define SAMPLE_EVENT_PER_PRIO 0 /**< Allocate a separate sample event for
@@ -35,6 +36,7 @@
#define LO_PRIO_EVENTS 32 /**< Number of low priority events */
#define HI_PRIO_QUEUES 16 /**< Number of high priority queues */
#define LO_PRIO_QUEUES 64 /**< Number of low priority queues */
+#define WARM_UP_ROUNDS 100 /**< Number of warm-up rounds */
#define EVENTS_PER_HI_PRIO_QUEUE 0 /**< Alloc HI_PRIO_QUEUES x HI_PRIO_EVENTS
events */
@@ -54,7 +56,7 @@ ODP_STATIC_ASSERT(LO_PRIO_QUEUES <= MAX_QUEUES, "Too many LO priority queues");
/** Test event types */
typedef enum {
- WARM_UP, /**< Warm up event */
+ WARM_UP, /**< Warm-up event */
COOL_DOWN,/**< Last event on queue */
TRAFFIC, /**< Event used only as traffic load */
SAMPLE /**< Event used to measure latency */
@@ -66,12 +68,15 @@ typedef struct {
event_type_t type; /**< Message type */
int src_idx[NUM_PRIOS]; /**< Source ODP queue */
int prio; /**< Source queue priority */
+ int warm_up_rounds; /**< Number of completed warm-up rounds */
} test_event_t;
/** Test arguments */
typedef struct {
unsigned int cpu_count; /**< CPU count */
odp_schedule_sync_t sync_type; /**< Scheduler sync type */
+ int test_rounds; /**< Number of test rounds (millions) */
+ int warm_up_rounds; /**< Number of warm-up rounds */
struct {
int queues; /**< Number of scheduling queues */
int events; /**< Number of events */
@@ -218,9 +223,10 @@ static int enqueue_events(int prio, int num_queues, int num_events,
memset(event, 0, sizeof(test_event_t));
/* Latency isn't measured from the first processing
- * round. */
+ * rounds. */
if (num_samples > 0) {
event->type = WARM_UP;
+ event->warm_up_rounds = 0;
num_samples--;
} else {
event->type = TRAFFIC;
@@ -329,7 +335,7 @@ static void print_results(test_globals_t *globals)
/**
* Measure latency of scheduled ODP events
*
- * Schedule and enqueue events until 'TEST_ROUNDS' events have been processed.
+ * Schedule and enqueue events until 'test_rounds' events have been processed.
* Scheduling latency is measured only from type 'SAMPLE' events. Other events
* are simply enqueued back to the scheduling queues.
*
@@ -354,12 +360,14 @@ static int test_schedule(int thr, test_globals_t *globals)
test_event_t *event;
test_stat_t *stats;
int dst_idx;
+ int warm_up_rounds = globals->args.warm_up_rounds;
+ uint64_t test_rounds = globals->args.test_rounds * 1000000;
memset(&globals->core_stat[thr], 0, sizeof(core_stat_t));
globals->core_stat[thr].prio[HI_PRIO].min = UINT64_MAX;
globals->core_stat[thr].prio[LO_PRIO].min = UINT64_MAX;
- for (i = 0; i < TEST_ROUNDS; i++) {
+ for (i = 0; i < test_rounds; i++) {
ev = odp_schedule(&src_queue, ODP_SCHED_WAIT);
buf = odp_buffer_from_event(ev);
@@ -383,10 +391,13 @@ static int test_schedule(int thr, test_globals_t *globals)
event->prio = !event->prio;
}
- if (odp_unlikely(event->type == WARM_UP))
- event->type = SAMPLE;
- else
+ if (odp_unlikely(event->type == WARM_UP)) {
+ event->warm_up_rounds++;
+ if (event->warm_up_rounds >= warm_up_rounds)
+ event->type = SAMPLE;
+ } else {
stats->events++;
+ }
/* Move event to next queue */
dst_idx = event->src_idx[event->prio] + 1;
@@ -496,6 +507,7 @@ static void usage(void)
"Usage: ./odp_sched_latency [options]\n"
"Optional OPTIONS:\n"
" -c, --count <number> CPU count, 0=all available, default=1\n"
+ " -d, --duration <number> Test duration in scheduling rounds (millions), default=%d, min=1\n"
" -l, --lo-prio-queues <number> Number of low priority scheduled queues\n"
" -t, --hi-prio-queues <number> Number of high priority scheduled queues\n"
" -m, --lo-prio-events-per-queue <number> Number of events per low priority queue\n"
@@ -511,8 +523,9 @@ static void usage(void)
" 0: ODP_SCHED_SYNC_PARALLEL (default)\n"
" 1: ODP_SCHED_SYNC_ATOMIC\n"
" 2: ODP_SCHED_SYNC_ORDERED\n"
+ " -w, --warm-up <number> Number of warm-up rounds, default=%d, min=1\n"
" -h, --help Display help and exit.\n\n"
- );
+ , TEST_ROUNDS, WARM_UP_ROUNDS);
}
/**
@@ -538,13 +551,16 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
{"hi-prio-events", required_argument, NULL, 'p'},
{"sample-per-prio", no_argument, NULL, 'r'},
{"sync", required_argument, NULL, 's'},
+ {"warm-up", required_argument, NULL, 'w'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
- static const char *shortopts = "+c:s:l:t:m:n:o:p:rh";
+ static const char *shortopts = "+c:d:s:l:t:m:n:o:p:rw:h";
args->cpu_count = 1;
+ args->test_rounds = TEST_ROUNDS;
+ args->warm_up_rounds = WARM_UP_ROUNDS;
args->sync_type = ODP_SCHED_SYNC_PARALLEL;
args->sample_per_prio = SAMPLE_EVENT_PER_PRIO;
args->prio[LO_PRIO].queues = LO_PRIO_QUEUES;
@@ -564,6 +580,9 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
case 'c':
args->cpu_count = atoi(optarg);
break;
+ case 'd':
+ args->test_rounds = atoi(optarg);
+ break;
case 'l':
args->prio[LO_PRIO].queues = atoi(optarg);
break;
@@ -598,6 +617,9 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
case 'r':
args->sample_per_prio = 1;
break;
+ case 'w':
+ args->warm_up_rounds = atoi(optarg);
+ break;
case 'h':
usage();
exit(EXIT_SUCCESS);
@@ -616,6 +638,8 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
args->prio[LO_PRIO].queues = MAX_QUEUES;
if (args->prio[HI_PRIO].queues > MAX_QUEUES)
args->prio[HI_PRIO].queues = MAX_QUEUES;
+ if (args->test_rounds < 1)
+ args->test_rounds = 1;
if (!args->prio[HI_PRIO].queues && !args->prio[LO_PRIO].queues) {
printf("No queues configured\n");
usage();
diff --git a/test/performance/odp_sched_perf.c b/test/performance/odp_sched_perf.c
index 08623d2a7..b0f8f379a 100644
--- a/test/performance/odp_sched_perf.c
+++ b/test/performance/odp_sched_perf.c
@@ -1,4 +1,5 @@
/* Copyright (c) 2018, Linaro Limited
+ * Copyright (c) 2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -17,6 +18,9 @@
#define MAX_QUEUES (256 * 1024)
#define MAX_GROUPS 256
+/* Round up 'X' to a multiple of 'NUM' */
+#define ROUNDUP(X, NUM) ((NUM) * (((X) + (NUM) - 1) / (NUM)))
+
typedef struct test_options_t {
uint32_t num_cpu;
uint32_t num_queue;
@@ -31,6 +35,12 @@ typedef struct test_options_t {
uint32_t queue_size;
uint32_t tot_queue;
uint32_t tot_event;
+ int touch_data;
+ uint32_t rd_words;
+ uint32_t rw_words;
+ uint32_t ctx_size;
+ uint32_t ctx_rd_words;
+ uint32_t ctx_rw_words;
uint64_t wait_ns;
} test_options_t;
@@ -42,6 +52,7 @@ typedef struct test_stat_t {
uint64_t nsec;
uint64_t cycles;
uint64_t waits;
+ uint64_t dummy_sum;
} test_stat_t;
@@ -57,6 +68,7 @@ typedef struct test_global_t {
odp_barrier_t barrier;
odp_pool_t pool;
odp_cpumask_t cpumask;
+ odp_shm_t ctx_shm;
odp_queue_t queue[MAX_QUEUES];
odp_schedule_group_t group[MAX_GROUPS];
odph_thread_t thread_tbl[ODP_THREAD_COUNT_MAX];
@@ -88,6 +100,10 @@ static void print_usage(void)
" -t, --type Queue type. 0: parallel, 1: atomic, 2: ordered. Default: 0.\n"
" -f, --forward 0: Keep event in the original queue, 1: Forward event to the next queue. Default: 0.\n"
" -w, --wait_ns Number of nsec to wait before enqueueing events. Default: 0.\n"
+ " -k, --ctx_rd_words Number of queue context words (uint64_t) to read on every event. Default: 0.\n"
+ " -l, --ctx_rw_words Number of queue context words (uint64_t) to modify on every event. Default: 0.\n"
+ " -n, --rd_words Number of event data words (uint64_t) to read before enqueueing it. Default: 0.\n"
+ " -m, --rw_words Number of event data words (uint64_t) to modify before enqueueing it. Default: 0.\n"
" -h, --help This help\n"
"\n");
}
@@ -96,26 +112,31 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
{
int opt;
int long_index;
- int ret = 0;
uint32_t num_group, num_join;
+ int ret = 0;
+ uint32_t ctx_size = 0;
static const struct option longopts[] = {
- {"num_cpu", required_argument, NULL, 'c'},
- {"num_queue", required_argument, NULL, 'q'},
- {"num_dummy", required_argument, NULL, 'd'},
- {"num_event", required_argument, NULL, 'e'},
- {"num_round", required_argument, NULL, 'r'},
- {"num_group", required_argument, NULL, 'g'},
- {"num_join", required_argument, NULL, 'j'},
- {"burst", required_argument, NULL, 'b'},
- {"type", required_argument, NULL, 't'},
- {"forward", required_argument, NULL, 'f'},
- {"wait_ns", required_argument, NULL, 'w'},
- {"help", no_argument, NULL, 'h'},
+ {"num_cpu", required_argument, NULL, 'c'},
+ {"num_queue", required_argument, NULL, 'q'},
+ {"num_dummy", required_argument, NULL, 'd'},
+ {"num_event", required_argument, NULL, 'e'},
+ {"num_round", required_argument, NULL, 'r'},
+ {"num_group", required_argument, NULL, 'g'},
+ {"num_join", required_argument, NULL, 'j'},
+ {"burst", required_argument, NULL, 'b'},
+ {"type", required_argument, NULL, 't'},
+ {"forward", required_argument, NULL, 'f'},
+ {"wait_ns", required_argument, NULL, 'w'},
+ {"ctx_rd_words", required_argument, NULL, 'k'},
+ {"ctx_rw_words", required_argument, NULL, 'l'},
+ {"rd_words", required_argument, NULL, 'n'},
+ {"rw_words", required_argument, NULL, 'm'},
+ {"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
- static const char *shortopts = "+c:q:d:e:r:g:j:b:t:f:w:h";
+ static const char *shortopts = "+c:q:d:e:r:g:j:b:t:f:w:k:l:n:m:h";
test_options->num_cpu = 1;
test_options->num_queue = 1;
@@ -127,6 +148,10 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
test_options->max_burst = 100;
test_options->queue_type = 0;
test_options->forward = 0;
+ test_options->ctx_rd_words = 0;
+ test_options->ctx_rw_words = 0;
+ test_options->rd_words = 0;
+ test_options->rw_words = 0;
test_options->wait_ns = 0;
while (1) {
@@ -166,6 +191,18 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
case 'f':
test_options->forward = atoi(optarg);
break;
+ case 'k':
+ test_options->ctx_rd_words = atoi(optarg);
+ break;
+ case 'l':
+ test_options->ctx_rw_words = atoi(optarg);
+ break;
+ case 'n':
+ test_options->rd_words = atoi(optarg);
+ break;
+ case 'm':
+ test_options->rw_words = atoi(optarg);
+ break;
case 'w':
test_options->wait_ns = atoll(optarg);
break;
@@ -178,6 +215,9 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
}
}
+ test_options->touch_data = test_options->rd_words ||
+ test_options->rw_words;
+
if ((test_options->num_queue + test_options->num_dummy) > MAX_QUEUES) {
printf("Error: Too many queues. Max supported %i.\n",
MAX_QUEUES);
@@ -216,9 +256,27 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
test_options->queue_size = test_options->num_event;
- /* When forwarding, all events may end up into a single queue. */
- if (test_options->forward)
+ if (test_options->forward) {
+ /* When forwarding, all events may end up into
+ * a single queue */
test_options->queue_size = test_options->tot_event;
+ ctx_size = sizeof(odp_queue_t);
+ }
+
+ if (test_options->ctx_rd_words || test_options->ctx_rw_words) {
+ /* Round up queue handle size to a multiple of 8 for correct
+ * context data alignment */
+ ctx_size = ROUNDUP(ctx_size, 8);
+ ctx_size += 8 * test_options->ctx_rd_words;
+ ctx_size += 8 * test_options->ctx_rw_words;
+ }
+
+ /* When context data is modified, round up to cache line size to avoid
+ * false sharing */
+ if (test_options->ctx_rw_words)
+ ctx_size = ROUNDUP(ctx_size, ODP_CACHE_LINE_SIZE);
+
+ test_options->ctx_size = ctx_size;
return ret;
}
@@ -259,7 +317,7 @@ static int create_pool(test_global_t *global)
odp_pool_capability_t pool_capa;
odp_pool_param_t pool_param;
odp_pool_t pool;
- uint32_t max_num;
+ uint32_t max_num, max_size;
test_options_t *test_options = &global->test_options;
uint32_t num_cpu = test_options->num_cpu;
uint32_t num_queue = test_options->num_queue;
@@ -274,21 +332,46 @@ static int create_pool(test_global_t *global)
uint32_t num_join = test_options->num_join;
int forward = test_options->forward;
uint64_t wait_ns = test_options->wait_ns;
+ uint32_t event_size = 16;
+ int touch_data = test_options->touch_data;
+ uint32_t ctx_size = test_options->ctx_size;
+
+ if (touch_data) {
+ event_size = test_options->rd_words + test_options->rw_words;
+ event_size = 8 * event_size;
+ }
printf("\nScheduler performance test\n");
+ printf(" num rounds %u\n", num_round);
printf(" num cpu %u\n", num_cpu);
printf(" num queues %u\n", num_queue);
printf(" num empty queues %u\n", num_dummy);
printf(" total queues %u\n", tot_queue);
printf(" num groups %u\n", num_group);
printf(" num join %u\n", num_join);
+ printf(" forward events %i\n", forward ? 1 : 0);
+ printf(" wait nsec %" PRIu64 "\n", wait_ns);
printf(" events per queue %u\n", num_event);
printf(" queue size %u\n", queue_size);
printf(" max burst size %u\n", max_burst);
printf(" total events %u\n", tot_event);
- printf(" num rounds %u\n", num_round);
- printf(" forward events %i\n", forward ? 1 : 0);
- printf(" wait nsec %" PRIu64 "\n", wait_ns);
+ printf(" event size %u bytes", event_size);
+ if (touch_data) {
+ printf(" (rd: %u, rw: %u)\n",
+ 8 * test_options->rd_words,
+ 8 * test_options->rw_words);
+ } else {
+ printf("\n");
+ }
+
+ printf(" context size %u bytes", ctx_size);
+ if (test_options->ctx_rd_words || test_options->ctx_rw_words) {
+ printf(" (rd: %u, rw: %u)\n",
+ 8 * test_options->ctx_rd_words,
+ 8 * test_options->ctx_rw_words);
+ } else {
+ printf("\n");
+ }
if (odp_pool_capability(&pool_capa)) {
printf("Error: Pool capa failed.\n");
@@ -296,15 +379,23 @@ static int create_pool(test_global_t *global)
}
max_num = pool_capa.buf.max_num;
+ max_size = pool_capa.buf.max_size;
if (max_num && tot_event > max_num) {
printf("Error: max events supported %u\n", max_num);
return -1;
}
+ if (max_size && event_size > max_size) {
+ printf("Error: max supported event size %u\n", max_size);
+ return -1;
+ }
+
odp_pool_param_init(&pool_param);
pool_param.type = ODP_POOL_BUFFER;
pool_param.buf.num = tot_event;
+ pool_param.buf.size = event_size;
+ pool_param.buf.align = 8;
pool = odp_pool_create("sched perf", &pool_param);
@@ -373,6 +464,8 @@ static int create_queues(test_global_t *global)
uint32_t num_group = test_options->num_group;
int type = test_options->queue_type;
odp_pool_t pool = global->pool;
+ uint8_t *ctx = NULL;
+ uint32_t ctx_size = test_options->ctx_size;
if (type == 0) {
type_str = "parallel";
@@ -400,6 +493,14 @@ static int create_queues(test_global_t *global)
return -1;
}
+ if (ctx_size) {
+ ctx = odp_shm_addr(global->ctx_shm);
+ if (ctx == NULL) {
+ printf("Bad queue context\n");
+ return -1;
+ }
+ }
+
odp_queue_param_init(&queue_param);
queue_param.type = ODP_QUEUE_TYPE_SCHED;
queue_param.sched.prio = ODP_SCHED_PRIO_DEFAULT;
@@ -434,17 +535,24 @@ static int create_queues(test_global_t *global)
for (i = first; i < tot_queue; i++) {
queue = global->queue[i];
- if (test_options->forward) {
- uint32_t next = i + 1;
+ if (ctx_size) {
+ if (test_options->forward) {
+ odp_queue_t *next_queue;
+ uint32_t next = i + 1;
- if (next == tot_queue)
- next = first;
+ if (next == tot_queue)
+ next = first;
- if (odp_queue_context_set(queue, &global->queue[next],
- sizeof(odp_queue_t))) {
+ next_queue = (odp_queue_t *)(uintptr_t)ctx;
+ *next_queue = global->queue[next];
+ }
+
+ if (odp_queue_context_set(queue, ctx, ctx_size)) {
printf("Error: Context set failed %u\n", i);
return -1;
}
+
+ ctx += ctx_size;
}
for (j = 0; j < num_event; j++) {
@@ -553,6 +661,51 @@ static int destroy_groups(test_global_t *global)
return 0;
}
+static inline uint64_t rw_ctx_data(void *ctx, uint32_t offset,
+ uint32_t rd_words, uint32_t rw_words)
+{
+ uint64_t *data;
+ uint32_t i;
+ uint64_t sum = 0;
+
+ data = (uint64_t *)(uintptr_t)((uint8_t *)ctx + offset);
+
+ for (i = 0; i < rd_words; i++)
+ sum += data[i];
+
+ for (; i < rd_words + rw_words; i++) {
+ sum += data[i];
+ data[i] += 1;
+ }
+
+ return sum;
+}
+
+static uint64_t rw_data(odp_event_t ev[], int num,
+ uint32_t rd_words, uint32_t rw_words)
+{
+ odp_buffer_t buf;
+ uint64_t *data;
+ int i;
+ uint32_t j;
+ uint64_t sum = 0;
+
+ for (i = 0; i < num; i++) {
+ buf = odp_buffer_from_event(ev[i]);
+ data = odp_buffer_addr(buf);
+
+ for (j = 0; j < rd_words; j++)
+ sum += data[j];
+
+ for (; j < rd_words + rw_words; j++) {
+ sum += data[j];
+ data[j] += 1;
+ }
+ }
+
+ return sum;
+}
+
static int test_sched(void *arg)
{
int num, num_enq, ret, thr;
@@ -569,11 +722,24 @@ static int test_sched(void *arg)
uint32_t max_burst = test_options->max_burst;
uint32_t num_group = test_options->num_group;
int forward = test_options->forward;
+ int touch_data = test_options->touch_data;
+ uint32_t rd_words = test_options->rd_words;
+ uint32_t rw_words = test_options->rw_words;
+ uint32_t ctx_size = test_options->ctx_size;
+ uint32_t ctx_rd_words = test_options->ctx_rd_words;
+ uint32_t ctx_rw_words = test_options->ctx_rw_words;
+ int touch_ctx = ctx_rd_words || ctx_rw_words;
+ uint32_t ctx_offset = 0;
+ uint64_t data_sum = 0;
+ uint64_t ctx_sum = 0;
uint64_t wait_ns = test_options->wait_ns;
odp_event_t ev[max_burst];
thr = odp_thread_id();
+ if (forward)
+ ctx_offset = ROUNDUP(sizeof(odp_queue_t), 8);
+
if (num_group) {
uint32_t num_join = test_options->num_join;
@@ -626,11 +792,24 @@ static int test_sched(void *arg)
events += num;
i = 0;
- if (odp_unlikely(forward)) {
- next = odp_queue_context(queue);
- queue = *next;
+ if (odp_unlikely(ctx_size)) {
+ void *ctx = odp_queue_context(queue);
+
+ if (forward) {
+ next = ctx;
+ queue = *next;
+ }
+
+ if (odp_unlikely(touch_ctx))
+ ctx_sum += rw_ctx_data(ctx, ctx_offset,
+ ctx_rd_words,
+ ctx_rw_words);
}
+ if (odp_unlikely(touch_data))
+ data_sum += rw_data(ev, num, rd_words,
+ rw_words);
+
if (odp_unlikely(wait_ns)) {
waits++;
odp_time_wait_ns(wait_ns);
@@ -679,6 +858,7 @@ static int test_sched(void *arg)
global->stat[thr].nsec = nsec;
global->stat[thr].cycles = cycles;
global->stat[thr].waits = waits;
+ global->stat[thr].dummy_sum = data_sum + ctx_sum;
/* Pause scheduling before thread exit */
odp_schedule_pause();
@@ -867,6 +1047,7 @@ int main(int argc, char **argv)
global = &test_global;
memset(global, 0, sizeof(test_global_t));
global->pool = ODP_POOL_INVALID;
+ global->ctx_shm = ODP_SHM_INVALID;
if (parse_options(argc, argv, &global->test_options))
return -1;
@@ -892,6 +1073,19 @@ int main(int argc, char **argv)
return -1;
}
+ if (global->test_options.ctx_size) {
+ uint64_t size = global->test_options.ctx_size *
+ global->test_options.tot_queue;
+
+ global->ctx_shm = odp_shm_reserve("queue contexts", size,
+ ODP_CACHE_LINE_SIZE, 0);
+ if (global->ctx_shm == ODP_SHM_INVALID) {
+ printf("Error: SHM reserve %" PRIu64 " bytes failed\n",
+ size);
+ return -1;
+ }
+ }
+
odp_schedule_config_init(&global->schedule_config);
odp_schedule_config(&global->schedule_config);
@@ -926,6 +1120,9 @@ int main(int argc, char **argv)
return -1;
}
+ if (global->ctx_shm != ODP_SHM_INVALID)
+ odp_shm_free(global->ctx_shm);
+
if (odp_term_local()) {
printf("Error: term local failed.\n");
return -1;
diff --git a/test/validation/api/ipsec/ipsec.c b/test/validation/api/ipsec/ipsec.c
index 705fbbabf..5b60fd888 100644
--- a/test/validation/api/ipsec/ipsec.c
+++ b/test/validation/api/ipsec/ipsec.c
@@ -429,7 +429,7 @@ odp_packet_t ipsec_packet(const ipsec_test_packet *itp)
{
odp_packet_t pkt = odp_packet_alloc(suite_context.pool, itp->len);
- CU_ASSERT_NOT_EQUAL(ODP_PACKET_INVALID, pkt);
+ CU_ASSERT_NOT_EQUAL_FATAL(ODP_PACKET_INVALID, pkt);
if (ODP_PACKET_INVALID == pkt)
return pkt;
diff --git a/test/validation/api/ipsec/ipsec_test_out.c b/test/validation/api/ipsec/ipsec_test_out.c
index 0bfb9cff8..6cdbb72f4 100644
--- a/test/validation/api/ipsec/ipsec_test_out.c
+++ b/test/validation/api/ipsec/ipsec_test_out.c
@@ -1036,7 +1036,7 @@ static void test_out_dummy_esp_null_sha256_tun_ipv4(void)
test.out[0].l3_type = ODP_PROTO_L3_TYPE_IPV4;
test.out[0].l4_type = ODP_PROTO_L4_TYPE_NO_NEXT;
- test_empty.pkt_in = &pkt_test_emtpy;
+ test_empty.pkt_in = &pkt_test_empty;
test_empty.num_opt = 1;
test_empty.opt.flag.tfc_dummy = 1;
test_empty.opt.tfc_pad_len = 16;
@@ -1110,7 +1110,7 @@ static void test_out_dummy_esp_null_sha256_tun_ipv6(void)
test.out[0].l3_type = ODP_PROTO_L3_TYPE_IPV4;
test.out[0].l4_type = ODP_PROTO_L4_TYPE_NO_NEXT;
- test_empty.pkt_in = &pkt_test_emtpy;
+ test_empty.pkt_in = &pkt_test_empty;
test_empty.num_opt = 1;
test_empty.opt.flag.tfc_dummy = 1;
test_empty.opt.tfc_pad_len = 16;
diff --git a/test/validation/api/ipsec/test_vectors.h b/test/validation/api/ipsec/test_vectors.h
index 289b8008c..e9b8634f2 100644
--- a/test/validation/api/ipsec/test_vectors.h
+++ b/test/validation/api/ipsec/test_vectors.h
@@ -1865,8 +1865,8 @@ static const ODP_UNUSED ipsec_test_packet
},
};
-static const ipsec_test_packet pkt_test_emtpy = {
- .len = 0,
+static const ipsec_test_packet pkt_test_empty = {
+ .len = 1,
.l2_offset = ODP_PACKET_OFFSET_INVALID,
.l3_offset = ODP_PACKET_OFFSET_INVALID,
.l4_offset = ODP_PACKET_OFFSET_INVALID,
diff --git a/test/validation/api/packet/packet.c b/test/validation/api/packet/packet.c
index 90226819c..b7dfb59f3 100644
--- a/test/validation/api/packet/packet.c
+++ b/test/validation/api/packet/packet.c
@@ -341,7 +341,7 @@ static int packet_alloc_multi(odp_pool_t pool, uint32_t pkt_len,
CU_ASSERT(ret >= 0);
CU_ASSERT(ret <= num - total);
total += ret;
- } while (total < num && ret);
+ } while (total < num && ret > 0);
return total;
}
@@ -430,7 +430,7 @@ static void packet_test_free_sp(void)
odp_pool_param_t params;
uint32_t len = packet_len;
- if (pool_capa.pkt.max_len < len)
+ if (pool_capa.pkt.max_len && pool_capa.pkt.max_len < len)
len = pool_capa.pkt.max_len;
odp_pool_param_init(&params);
@@ -544,6 +544,57 @@ static void packet_test_alloc_segmented(void)
CU_ASSERT(odp_pool_destroy(pool) == 0);
}
+static void packet_test_alloc_align(void)
+{
+ odp_pool_t pool;
+ odp_pool_param_t params;
+ uintptr_t data, mask;
+ uint32_t i;
+ uint32_t error_print = 10;
+ uint32_t len = packet_len;
+ uint32_t align = 256;
+ uint32_t num = 100;
+ odp_packet_t pkt[num];
+
+ CU_ASSERT(pool_capa.pkt.max_align >= 2);
+
+ if (align > pool_capa.pkt.max_align)
+ align = pool_capa.pkt.max_align;
+
+ mask = align - 1;
+
+ odp_pool_param_init(&params);
+
+ params.type = ODP_POOL_PACKET;
+ params.pkt.len = len;
+ params.pkt.num = num;
+ params.pkt.align = align;
+
+ pool = odp_pool_create("packet_pool_align", &params);
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ /* Allocate the only buffer from the pool */
+ for (i = 0; i < num; i++) {
+ pkt[i] = odp_packet_alloc(pool, len);
+ CU_ASSERT_FATAL(pkt[i] != ODP_PACKET_INVALID);
+ CU_ASSERT(odp_packet_len(pkt[i]) == len);
+ data = (uintptr_t)odp_packet_data(pkt[i]);
+
+ if (data & mask) {
+ /* Print only first couple of failures to the log */
+ if (error_print > 0) {
+ CU_ASSERT((data & mask) == 0);
+ printf("\nError: Bad data align. Pointer %p, requested align %u\n",
+ (void *)data, align);
+ error_print--;
+ }
+ }
+ }
+
+ odp_packet_free_multi(pkt, num);
+ CU_ASSERT(odp_pool_destroy(pool) == 0);
+}
+
static void packet_test_event_conversion(void)
{
odp_packet_t pkt0 = test_packet;
@@ -3530,6 +3581,7 @@ odp_testinfo_t packet_suite[] = {
ODP_TEST_INFO(packet_test_alloc_free_multi),
ODP_TEST_INFO(packet_test_free_sp),
ODP_TEST_INFO(packet_test_alloc_segmented),
+ ODP_TEST_INFO(packet_test_alloc_align),
ODP_TEST_INFO(packet_test_basic_metadata),
ODP_TEST_INFO(packet_test_debug),
ODP_TEST_INFO(packet_test_segments),
diff --git a/test/validation/api/scheduler/scheduler.c b/test/validation/api/scheduler/scheduler.c
index ca92a3cf8..90d30ff5b 100644
--- a/test/validation/api/scheduler/scheduler.c
+++ b/test/validation/api/scheduler/scheduler.c
@@ -1831,8 +1831,20 @@ static int sched_and_plain_thread(void *arg)
/* Make sure scheduling context is released */
odp_schedule_pause();
- while ((ev1 = odp_schedule(NULL, wait)) != ODP_EVENT_INVALID)
+ while ((ev1 = odp_schedule(NULL, wait)) != ODP_EVENT_INVALID) {
+ if (sync == ODP_SCHED_SYNC_ORDERED)
+ odp_schedule_order_lock(0);
+
+ ev2 = odp_queue_deq(plain_queue);
+ CU_ASSERT_FATAL(ev2 != ODP_EVENT_INVALID);
+
+ CU_ASSERT_FATAL(!odp_queue_enq(plain_queue, ev2));
+
+ if (sync == ODP_SCHED_SYNC_ORDERED)
+ odp_schedule_order_unlock(0);
+
CU_ASSERT_FATAL(!odp_queue_enq(sched_queue, ev1));
+ }
/* Don't resume scheduling until all threads have finished */
odp_barrier_wait(&globals->barrier);
diff --git a/test/validation/api/shmem/shmem.c b/test/validation/api/shmem/shmem.c
index c5a161319..50b12e736 100644
--- a/test/validation/api/shmem/shmem.c
+++ b/test/validation/api/shmem/shmem.c
@@ -366,8 +366,8 @@ static int run_test_reserve_after_fork(void *arg ODP_UNUSED)
}
/* print block address */
- printf("In thread: Block index: %d mapped at %lx\n",
- thr_index, (long int)odp_shm_addr(shm));
+ printf("In thread: Block index: %d mapped at %p\n",
+ thr_index, odp_shm_addr(shm));
odp_barrier_wait(&glob_data->test_barrier1);
odp_barrier_wait(&glob_data->test_barrier2);
@@ -388,7 +388,6 @@ static void shmem_test_reserve_after_fork(void)
odp_cpumask_t unused;
int thr_index;
int i;
- void *address;
shared_test_data_small_t *pattern_small;
shared_test_data_medium_t *pattern_medium;
shared_test_data_big_t *pattern_big;
@@ -447,11 +446,9 @@ static void shmem_test_reserve_after_fork(void)
/*
* print the mapping address of the blocks
*/
- for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++) {
- address = odp_shm_addr(glob_data->shm[thr_index]);
- printf("In main Block index: %d mapped at %lx\n",
- thr_index, (long int)address);
- }
+ for (thr_index = 0; thr_index < thrdarg.numthrds; thr_index++)
+ printf("In main Block index: %d mapped at %p\n",
+ thr_index, odp_shm_addr(glob_data->shm[thr_index]));
/* unblock the threads and let them terminate (no free is done): */
odp_barrier_wait(&glob_data->test_barrier2);
@@ -541,8 +538,8 @@ static int run_test_singleva_after_fork(void *arg ODP_UNUSED)
}
/* print block address */
- printf("In thread: Block index: %d mapped at %lx\n",
- thr_index, (long int)odp_shm_addr(shm));
+ printf("In thread: Block index: %d mapped at %p\n",
+ thr_index, odp_shm_addr(shm));
odp_barrier_wait(&glob_data->test_barrier1);
odp_barrier_wait(&glob_data->test_barrier2);
diff --git a/test/validation/api/system/system.c b/test/validation/api/system/system.c
index 090999457..ed5949ec3 100644
--- a/test/validation/api/system/system.c
+++ b/test/validation/api/system/system.c
@@ -17,7 +17,7 @@
#define GIGA_HZ 1000000000ULL
#define KILO_HZ 1000ULL
-static void system_test_odp_version_numbers(void)
+static void test_version_api_str(void)
{
int char_ok = 0;
char version_string[128];
@@ -39,6 +39,40 @@ static void system_test_odp_version_numbers(void)
CU_ASSERT(char_ok);
}
+static void test_version_str(void)
+{
+ printf("\nAPI version:\n");
+ printf("%s\n\n", odp_version_api_str());
+
+ printf("Implementation name:\n");
+ printf("%s\n\n", odp_version_impl_name());
+
+ printf("Implementation details:\n");
+ printf("%s\n\n", odp_version_impl_str());
+}
+
+static void test_version_macro(void)
+{
+ CU_ASSERT(ODP_VERSION_API_NUM(0, 0, 0) < ODP_VERSION_API_NUM(0, 0, 1));
+ CU_ASSERT(ODP_VERSION_API_NUM(0, 0, 1) < ODP_VERSION_API_NUM(0, 1, 0));
+ CU_ASSERT(ODP_VERSION_API_NUM(0, 1, 0) < ODP_VERSION_API_NUM(1, 0, 0));
+ CU_ASSERT(ODP_VERSION_API_NUM(1, 90, 0) <
+ ODP_VERSION_API_NUM(1, 90, 1));
+
+ CU_ASSERT(ODP_VERSION_API_NUM(ODP_VERSION_API_GENERATION,
+ ODP_VERSION_API_MAJOR,
+ ODP_VERSION_API_MINOR) ==
+ ODP_VERSION_API);
+
+ CU_ASSERT(ODP_VERSION_API_NUM(ODP_VERSION_API_GENERATION,
+ ODP_VERSION_API_MAJOR, 0) <=
+ ODP_VERSION_API);
+
+ CU_ASSERT(ODP_VERSION_API_NUM(ODP_VERSION_API_GENERATION,
+ ODP_VERSION_API_MAJOR + 1, 0) >
+ ODP_VERSION_API);
+}
+
static void system_test_odp_cpu_count(void)
{
int cpus;
@@ -172,6 +206,13 @@ static void system_test_odp_sys_cache_line_size(void)
cache_size = odp_sys_cache_line_size();
CU_ASSERT(0 < cache_size);
CU_ASSERT(ODP_CACHE_LINE_SIZE == cache_size);
+
+ CU_ASSERT(ODP_CACHE_LINE_ROUNDUP(0) == 0);
+ CU_ASSERT(ODP_CACHE_LINE_ROUNDUP(1) == ODP_CACHE_LINE_SIZE);
+ CU_ASSERT(ODP_CACHE_LINE_ROUNDUP(ODP_CACHE_LINE_SIZE) ==
+ ODP_CACHE_LINE_SIZE);
+ CU_ASSERT(ODP_CACHE_LINE_ROUNDUP(ODP_CACHE_LINE_SIZE + 1) ==
+ 2 * ODP_CACHE_LINE_SIZE);
}
static void system_test_odp_cpu_model_str(void)
@@ -335,7 +376,9 @@ static void system_test_info_print(void)
}
odp_testinfo_t system_suite[] = {
- ODP_TEST_INFO(system_test_odp_version_numbers),
+ ODP_TEST_INFO(test_version_api_str),
+ ODP_TEST_INFO(test_version_str),
+ ODP_TEST_INFO(test_version_macro),
ODP_TEST_INFO(system_test_odp_cpu_count),
ODP_TEST_INFO(system_test_odp_sys_cache_line_size),
ODP_TEST_INFO(system_test_odp_cpu_model_str),