diff options
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(ð->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(ð->src, port_in); + /* Update source address MAC table entry */ + mac_table_update(ð->src, port_in, cur_tick); - /* Lookup destination MAC address */ - ret = mac_table_get(ð->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(ð->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, ð_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(¶ms); @@ -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(¶ms); + + params.type = ODP_POOL_PACKET; + params.pkt.len = len; + params.pkt.num = num; + params.pkt.align = align; + + pool = odp_pool_create("packet_pool_align", ¶ms); + 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), |