aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatias Elo <matias.elo@nokia.com>2020-07-03 17:03:49 +0300
committerGitHub <noreply@github.com>2020-07-03 17:03:49 +0300
commitaa55e35150da8099ed9f565173993609650010af (patch)
tree90573ee0b4ff53ff2c080f28b4c66a4e90f0f864
parentbd75b10924e6df74089d27482dd68bdef33eaf83 (diff)
parente20ecf15d8af37602a2eb0873d0a91dc5167dd28 (diff)
Merge ODP v1.24.0.0v1.24.0.0_DPDK_18.11
Merge and port ODP linux-generic v1.24.0.0 commits into odp-dpdk.
-rw-r--r--.checkpatch.conf4
-rw-r--r--.travis.yml12
-rw-r--r--CHANGELOG325
-rwxr-xr-xbootstrap2
-rw-r--r--configure.ac9
-rw-r--r--example/Makefile.inc2
-rw-r--r--example/ipsec/odp_ipsec.c5
-rw-r--r--example/ipsec/odp_ipsec_stream.c38
-rw-r--r--example/ipsec/odp_ipsec_stream.h7
-rw-r--r--example/ipsec_api/odp_ipsec.c5
-rw-r--r--example/l2fwd_simple/odp_l2fwd_simple.c7
-rw-r--r--example/l3fwd/odp_l3fwd.c39
-rw-r--r--example/packet/odp_packet_dump.c8
-rw-r--r--example/packet/odp_pktio.c9
-rw-r--r--example/ping/odp_ping.c15
-rw-r--r--example/simple_pipeline/odp_simple_pipeline.c15
-rw-r--r--example/switch/odp_switch.c11
-rw-r--r--example/timer/odp_timer_accuracy.c2
-rw-r--r--example/timer/odp_timer_simple.c1
-rw-r--r--helper/Makefile.am2
-rw-r--r--helper/cuckootable.c8
-rw-r--r--helper/iplookuptable.c2
-rw-r--r--include/Makefile.am16
-rw-r--r--include/odp/api/abi-default/errno.h20
-rw-r--r--include/odp/api/abi-default/hash.h20
-rw-r--r--include/odp/api/errno.h2
-rw-r--r--include/odp/api/hash.h2
-rw-r--r--include/odp/api/spec/packet_io.h121
-rw-r--r--include/odp/api/spec/random.h4
-rw-r--r--include/odp/api/spec/time.h19
-rw-r--r--include/odp/api/spec/timer.h39
-rw-r--r--include/odp/api/spec/traffic_mngr.h112
-rw-r--r--include/odp/arch/arm32-linux/odp/api/abi/errno.h7
-rw-r--r--include/odp/arch/arm32-linux/odp/api/abi/hash.h7
-rw-r--r--include/odp/arch/arm64-linux/odp/api/abi/errno.h7
-rw-r--r--include/odp/arch/arm64-linux/odp/api/abi/hash.h7
-rw-r--r--include/odp/arch/default-linux/odp/api/abi/errno.h7
-rw-r--r--include/odp/arch/default-linux/odp/api/abi/hash.h7
-rw-r--r--include/odp/arch/mips64-linux/odp/api/abi/errno.h7
-rw-r--r--include/odp/arch/mips64-linux/odp/api/abi/hash.h7
-rw-r--r--include/odp/arch/power64-linux/odp/api/abi/errno.h7
-rw-r--r--include/odp/arch/power64-linux/odp/api/abi/hash.h7
-rw-r--r--include/odp/arch/x86_32-linux/odp/api/abi/errno.h7
-rw-r--r--include/odp/arch/x86_32-linux/odp/api/abi/hash.h7
-rw-r--r--include/odp/arch/x86_64-linux/odp/api/abi/errno.h7
-rw-r--r--include/odp/arch/x86_64-linux/odp/api/abi/hash.h7
-rw-r--r--m4/odp_atomic.m411
-rw-r--r--platform/Makefile.inc8
-rw-r--r--platform/linux-dpdk/Makefile.am7
l---------platform/linux-dpdk/include-abi/odp/api/abi/errno.h1
l---------platform/linux-dpdk/include-abi/odp/api/abi/hash.h1
-rw-r--r--platform/linux-dpdk/include/odp/api/plat/time_inlines.h56
-rw-r--r--platform/linux-dpdk/include/odp_packet_io_internal.h1
-rw-r--r--platform/linux-dpdk/libodp-linux.pc.in4
-rw-r--r--platform/linux-dpdk/m4/configure.m41
-rw-r--r--platform/linux-dpdk/m4/odp_libconfig.m49
-rw-r--r--platform/linux-dpdk/odp_packet_dpdk.c60
-rw-r--r--platform/linux-dpdk/odp_time.c37
-rw-r--r--platform/linux-dpdk/odp_timer.c32
-rw-r--r--platform/linux-generic/Makefile.am7
-rw-r--r--platform/linux-generic/include-abi/odp/api/abi/errno.h18
-rw-r--r--platform/linux-generic/include-abi/odp/api/abi/hash.h18
-rw-r--r--platform/linux-generic/include/odp/api/plat/time_inlines.h55
-rw-r--r--platform/linux-generic/include/odp_packet_io_internal.h1
-rw-r--r--platform/linux-generic/include/odp_socket_common.h7
-rw-r--r--platform/linux-generic/libodp-linux.pc.in4
-rw-r--r--platform/linux-generic/m4/configure.m41
-rw-r--r--platform/linux-generic/m4/odp_libconfig.m49
-rw-r--r--platform/linux-generic/odp_crypto_openssl.c3
-rw-r--r--platform/linux-generic/odp_packet_io.c27
-rw-r--r--platform/linux-generic/odp_pool.c4
-rw-r--r--platform/linux-generic/odp_time.c37
-rw-r--r--platform/linux-generic/odp_timer.c35
-rw-r--r--platform/linux-generic/odp_traffic_mngr.c42
-rw-r--r--platform/linux-generic/pktio/dpdk.c60
-rw-r--r--platform/linux-generic/pktio/ipc.c31
-rw-r--r--platform/linux-generic/pktio/loop.c20
-rw-r--r--platform/linux-generic/pktio/netmap.c26
-rw-r--r--platform/linux-generic/pktio/null.c22
-rw-r--r--platform/linux-generic/pktio/pcap.c22
-rw-r--r--platform/linux-generic/pktio/socket.c6
-rw-r--r--platform/linux-generic/pktio/socket_common.c139
-rw-r--r--platform/linux-generic/pktio/socket_mmap.c6
-rw-r--r--platform/linux-generic/pktio/tap.c6
-rw-r--r--platform/linux-generic/test/pktio_ipc/ipc_common.c1
-rw-r--r--platform/linux-generic/test/pktio_ipc/pktio_ipc2.c1
-rwxr-xr-xscripts/checkpatch.pl920
-rw-r--r--test/Makefile.inc2
-rw-r--r--test/common/odp_cunit_common.h23
-rw-r--r--test/performance/odp_bench_packet.c7
-rw-r--r--test/performance/odp_cpu_bench.c11
-rw-r--r--test/performance/odp_l2fwd.c15
-rw-r--r--test/performance/odp_packet_gen.c210
-rw-r--r--test/performance/odp_pktio_ordered.c7
-rw-r--r--test/performance/odp_pktio_perf.c2
-rw-r--r--test/performance/odp_sched_pktio.c2
-rw-r--r--test/validation/api/crypto/odp_crypto_test_inp.c9
-rw-r--r--test/validation/api/packet/packet.c4
-rw-r--r--test/validation/api/pktio/parser.c2
-rw-r--r--test/validation/api/pktio/pktio.c48
-rw-r--r--test/validation/api/pool/pool.c3
-rw-r--r--test/validation/api/queue/queue.c4
-rw-r--r--test/validation/api/random/random.c26
-rw-r--r--test/validation/api/time/time.c64
-rw-r--r--test/validation/api/timer/timer.c108
-rw-r--r--test/validation/api/traffic_mngr/traffic_mngr.c63
106 files changed, 2736 insertions, 611 deletions
diff --git a/.checkpatch.conf b/.checkpatch.conf
index 7195642fc..7c179e3e8 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -15,5 +15,9 @@
--ignore=CONSTANT_COMPARISON
--ignore=BLOCK_COMMENT_STYLE
--ignore=UNNECESSARY_PARENTHESES
+--ignore=SPDX_LICENSE_TAG
+--ignore=PREFER_FALLTHROUGH
+--ignore=LONG_LINE_STRING
+--ignore=EMAIL_SUBJECT
--codespell
--codespellfile=/usr/share/codespell/dictionary.txt
diff --git a/.travis.yml b/.travis.yml
index 1aa85fc96..26b9f1521 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -180,6 +180,16 @@ jobs:
- docker run --privileged -i -t -v `pwd`:/odp --shm-size 8g
-e CC="${CC}"
${DOCKER_NAMESPACE}/travis-odp-ubuntu_20.04-${ARCH} /odp/scripts/ci/build_${ARCH}.sh
+ - stage: test
+ env: TEST=gcc-10_lto
+ compiler: gcc-10
+ script:
+ - if [ -z "${DOCKER_NAMESPACE}" ] ; then export DOCKER_NAMESPACE="opendataplane"; fi
+ - docker run --privileged -i -t -v `pwd`:/odp --shm-size 8g
+ -e CC="${CC}"
+ -e CXX=g++-10
+ -e CONF="--enable-lto"
+ ${DOCKER_NAMESPACE}/travis-odp-ubuntu_20.04-${ARCH} /odp/scripts/ci/build_${ARCH}.sh
- stage: "build only"
env: TEST=documentation
compiler: gcc
@@ -220,8 +230,8 @@ jobs:
-e CC="${CC}"
${DOCKER_NAMESPACE}/travis-odp-${OS}-${ARCH} /odp/scripts/ci/build_${ARCH}.sh
- stage: test
- canfail: yes
env: TEST=checkpatch
+ canfail: yes
compiler: gcc
install:
- true
diff --git a/CHANGELOG b/CHANGELOG
index f3b366d8f..2a7cbefb5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,328 @@
+== OpenDataPlane (1.24.0.0)
+=== Summary of Changes
+
+This release introduces a new stash API module. The other main API additions are
+pool buffer caching configuration and packet IO link information. The release
+also includes several smaller API improvements and clarifications.
+
+=== API
+==== Common
+* Added missing const qualifiers
+
+Some API calls missed const qualifiers on read-only data pointers.
+
+* Improved Doxygen module descriptions
+* Use param_init functions for parameter defaults
+
+When available, parameter init functions must be used to initialize parameters
+into their default values.
+
+=== Align
+* Added `ODP_CACHE_LINE_ROUNDUP` macro
+
+Added macro for rounding up a value to the next multiple of cache line size.
+This round up is needed e.g. when selecting buffer sizes so that false sharing
+is avoided.
+
+==== CPU
+* Make supporting CPU frequency and cycle counter optional
+
+CPU frequencies or CPU cycle counter may not be available on all HW/SW
+platforms. Zero is returned if those cannot be read.
+
+==== Feature
+* Added feature bits `stash` and `compress` into `odp_feature_t`.
+
+==== Packet
+* Clarify packet length function argument definitions
+
+Modify documentations of functions, which decrease packet length, to clearly
+state what are the allowed values for length argument. This is done to avoid
+creating zero length packets which are not allowed by the packet API.
+
+* Added `odp_packet_input_set()` function
+
+An application may use this for testing or other purposes, when perception of
+the packet input interface need to be changed.
+
+==== Packet I/O
+* Added `odp_pktio_link_info()` function for reading link status information
+** Autonegotiation mode (unknown/enabled/disabled)
+** Duplex mode (unknown/half duplex/full duplex)
+** Flow control (unknown/on/off)
+** Link status (unknown/up/down)
+** Media (media type as string)
+** Speed (unknown/Mbps)
+
+* Modified `odp_pktio_link_status()` to return `odp_pktio_link_status_t` enum
+(backward compatible values)
+
+==== Pool
+* Added `cache_size` parameters to `odp_pool_capability_t` and `odp_pool_param_t`
+
+Added thread local cache size parameter and capability. This allows application
+to control thread local caching and prepare large enough pool when
+implementation caches events per thread. The default value is implementation
+specific for backwards compatibility.
+
+* Removed default value of packet `max_len` from `odp_pool_param_t`
+
+The default value is implementation specific and may not be equal to the maximum
+capability.
+
+* Added packet data `align` parameter to `odp_pool_param_t`
+
+Added packet pool parameter to request minimum data alignment for user allocated
+packets. When user allocates a new packet and fills in protocol headers, it's
+convenient that data alignment does not need to be checked (and tuned) on each
+allocated packet.
+
+==== Queue
+* Unify `max_size capa` specification for all plain queue types
+
+Specify queue maximum size capability the same way for all non-blocking levels
+(`ODP_BLOCKING`, `ODP_NONBLOCKING_LF` and `ODP_NONBLOCKING_WF`). Max_size value
+of zero means that there is no size limit.
+
+* Clarify that queue operations include memory barriers
+
+Clarify that queue enqueue operations include memory barrier of release
+semantics and queue dequeue operations include acquire semantics.
+
+==== Random
+* Clarify how much data `odp_random_data()` and `odp_random_test_data()` output on success.
+
+It may not be possible for random generator functions to return requested number
+of bytes. Clarify that implementation is not required to loop until `len` bytes
+are available. Instead application should contain such logic.
+
+==== Scheduler
+* Clarify synchronization of store operations during atomic context
+
+Stores performed while holding an atomic scheduling context are seen correctly
+by other thread when they hold the same context later on. This is guaranteed
+also when queue enqueue is not used in between.
+
+* Clarify that schedule operations include memory barriers
+
+Clarify that event schedule operations include memory barrier of acquire
+semantics.
+
+==== Shared Memory
+* Add `ODP_SHM_HW_ACCESS` flag
+
+This can be used to memory allocations where both CPUs and HW accelerators
+access the same memory area. These HW accelerators may be programmed outside of
+ODP APIs, but the memory is reserved and shared normally inside/between ODP
+applications.
+
+==== Stash
+* Added new stash API module
+
+Application needs often store object handles for later usage. From current APIs,
+e.g. buffers and queues could be used to store these handles, but buffers
+consume more memory than is necessary and event queues are not needed for this
+simple use case. This new API maybe implemented e.g. as a ring of object handles
+in memory, or with a HW buffer manager.
+
+==== Time
+* Added `odp_time_local_ns()` and `odp_time_global_ns()` functions for acquiring
+current time stamp in nanoseconds
+
+Added functions to get the current local/global
+time stamp directly in nanoseconds. For example, `odp_time_local_ns()` is
+equivalent of calling `odp_time_to_ns(odp_time_local())`. This simplifies use
+cases where time will be always converted to nanoseconds. However, when time API
+performance is important conversions to nanoseconds should be avoided or
+minimized.
+
+==== Timer
+* Clarify that `odp_timeout_tick()` returns original expiration time
+
+Specification was open if returned expiration time is the original or actual
+expiration time. HW based implementations will not likely modify timeout event
+with actual expiration time. Also original expiration time is more valuable to
+an application as it can be used to calculate e.g. the next period.
+
+* Add resolution in hertz parameter `res_hz` into `odp_timer_pool_param_t`
+
+Added option to specify timer pool resolution in hertz. High resolution values
+in nanoseconds result small numbers and thus poor granularity. Hertz offers
+better granularity with high resolution values. User gives resolution either in
+nanoseconds or hertz, and sets the other parameter to zero.
+
+==== Traffic Manager
+* Add missing handle debug functions
+
+Traffic Manager API defines all types as platform specific, yet unit tests
+expect to be able to print them. Therefore introduce u64 debug print conversion
+functions for all TM types: `odp_tm_to_u64()`, `odp_tm_queue_to_u64()`,
+`odp_tm_node_to_u64()`, `odp_tm_shaper_to_u64()`, `odp_tm_sched_to_u64()`,
+`odp_tm_threshold_to_u64()`, `odp_tm_wred_to_u64()`
+
+* Info structures are written only on success
+
+Clarify that info structures (`odp_tm_node_info_t`, `odp_tm_node_fanin_info_t`,
+`odp_tm_queue_info_t`, `odp_tm_query_info_t`) are written only on success.
+
+==== Version
+* Added `ODP_VERSION_API` define and `ODP_VERSION_API_NUM` macro
+
+Added a macro and version number defines for easier comparison of API version
+numbers.
+
+=== Validation Tests
+==== Buffer
+* Rewrote buffer tests for improved coverage
+* Allow allocated buffer size to be larger than requested
+
+==== Classification
+* Fix duplicate global variable definition
+* Use `odp_schedule_wait_time()` correctly
+
+==== Crypto
+* Fix var len array scope
+
+==== Init
+* Add tests for new `compress` and `stash` feature bits
+* Improved log prints
+
+==== IPSec
+* Fixed invalid allocation of zero length test packet
+* Fixed invalid test for user pointer value
+
+==== Packet
+* Add max pools test
+* Add packet alloc align test
+* Fix max_num expectations
+* Prevent test trying to allocate zero length packets
+* Remove pools from suite init
+* Remove reset test packet from suite init
+* Rename default pool
+* Use common pool capability
+
+==== Packet I/O
+* Check parser flags on receive
+* Check pktio index
+* Decrease timeout in `odp_pktin_recv_tmo()` test
+* Make `pktio_check_start_stop()` test conditional
+* Remove unnecessary test start-up input flushes
+* Test `odp_packet_input_set()`
+* Test user pointer on receive
+* Do no attempt to continue with invalid queue handle
+
+==== Pool
+* Add pool cache size tests
+* Add test for packet pool seg_len parameter
+
+==== Queue
+* Lockfree queue max_size may be zero
+
+==== Scheduler
+* Add new stress test
+* Fix plain+sched test
+* Test `odp_schedule_group_create()` with non-zero mask
+
+==== Shared Memory
+* Add reserve flag tests
+* Fix printf format types for pointers
+
+==== Stash
+* Add tests for the new API
+
+==== System
+* Add test for `ODP_CACHE_LINE_ROUNDUP`
+* Add version macro test
+* Call version string functions
+* Cpu cycle counter may not be supported
+* Make `odp_cpu_hz_max()` tests conditional
+
+==== Timer
+* Timeout tick equals requested tick
+* Always initialize `odp_timer_pool_param_t` contents
+
+==== Traffic Manager
+* Fix shaper profile parameter check
+* Init structs between tests
+
+=== Example Applications
+==== Bench_packet
+* Added tests for missing packet functions
+
+==== Hello
+* Removed `-c` command line option
+
+==== L2fwd
+* Added number of packets option `-n`
+* Added packet copy option `-p`
+* Added pool per interface option `-y`
+
+==== Packet_dump
+* Added VLAN support
+
+==== Packet_gen
+* Added new simple packet generator test application
+
+==== Sched_latency
+* Added option for selecting event forwarding mode `-f`
+* Increased the number of warm-up and scheduling rounds
+
+==== Sched_perf
+* Added data touch options `-n` and `-m`
+* Added queue context data touch options `-k` and `-l`
+* Improved test reliability
+
+==== Switch
+* Added 5 minute aging time to MAC table entries
+* Added signal handler for SIGINT
+* Added support for detecting invalid and broadcast ethernet addresses
+* Improved packet drop statistics printing
+
+==== Timer_accuracy
+* Added burst gap option `-g`
+* Added mode option `-m`
+* Added option `-e` to retry on too early error
+* Added output file option `-o`
+* Added timer burst option `-b`
+
+=== Implementation Improvements
+==== GCC 10 support
+Fixed issues reported by GCC 10. The code base builds now with GCC 10
+also when LTO is enabled.
+
+==== Add configure option for setting path to the default config file
+Added `--with-config-file=FILE` configuration option for setting path to the
+default configuration file. The default configuration file has to include all
+configuration options.
+
+=== Bug Fixes
+==== Numbered Bugs / Issues
+* Fixed: https://github.com/OpenDataPlane/odp/issues/796[Issue 796]
+seg[0].data MUST return to its initial value on odp_packet_reset
+
+* Fixed: https://github.com/OpenDataPlane/odp/issues/826[Issue 826]
+max_size requires clarification for ODP_NONBLOCKING_LF and ODP_NONBLOCKING_WF
+
+* Fixed: https://github.com/OpenDataPlane/odp/issues/915[Issue 915]
+SIGSEGV: example/sysinfo (raspberry Pi 3B+, arm7, odp-linux, gcc 8.2.0)
+
+* Fixed: https://github.com/OpenDataPlane/odp/issues/930[Issue 930]
+Build failing with GCC 9.2
+
+* Fixed: https://github.com/OpenDataPlane/odp/issues/959[Issue 959]
+ODP build fails with GCC 10.1
+
+==== Unnumbered Bugs / Issues
+* Fixed: crypto: fix session allocation when out of sessions
+* Fixed: dpdk: DPDK renamed protocol structs
+* Fixed: dpdk: fix rx/tx checksum offload
+* Fixed: fix print failures on 32-bit systems
+* Fixed: pool: fix overflow when creating a huge packet pool
+* Fixed: pool: rename pool global variable
+* Fixed: sched scalable: fix pktio ingress queue polling dead lock
+* Fixed: test: fix global variables that are defined multiple times
+* Fixed: timer: fix timer pool create sync with inline timer scan
+
== OpenDataPlane (1.23.0.0)
=== Summary of Changes
The ODP API changes in this release are related to the classifier module.
diff --git a/bootstrap b/bootstrap
index 6fd91c816..095d83c82 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1,7 +1,7 @@
#! /bin/sh
set -x
aclocal -I config -I m4
-libtoolize --copy
+libtoolize --copy --force
autoheader
automake --add-missing --copy --warnings=all
autoconf --force
diff --git a/configure.ac b/configure.ac
index b12001f25..465304d9e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,8 +3,8 @@ AC_PREREQ([2.5])
# ODP API version
##########################################################################
m4_define([odpapi_generation_version], [1])
-m4_define([odpapi_major_version], [23])
-m4_define([odpapi_minor_version], [5])
+m4_define([odpapi_major_version], [24])
+m4_define([odpapi_minor_version], [0])
m4_define([odpapi_point_version], [0])
m4_define([odpapi_version],
[odpapi_generation_version.odpapi_major_version.odpapi_minor_version.odpapi_point_version])
@@ -136,7 +136,7 @@ ODP_CHECK_CFLAG([-Wno-error=address-of-packed-member])
# GCC 10 sometimes gets confused about object sizes and gives bogus warnings.
# Make the affected warnings generate only warnings, not errors.
AS_IF([test "$GCC" == yes],
- AS_IF([test `$CC -dumpversion` -ge 10],
+ AS_IF([test `$CC -dumpversion | cut -d '.' -f 1` -ge 10],
ODP_CHECK_CFLAG([-Wno-error=array-bounds])
ODP_CHECK_CFLAG([-Wno-error=stringop-overflow])
)
@@ -295,6 +295,7 @@ AC_DEFINE_UNQUOTED([_ODP_IMPLEMENTATION_NAME], ["$ODP_IMPLEMENTATION_NAME"],
[Define to the name of the implementation])
AM_CONDITIONAL([ODP_USE_CONFIG], [test "x$odp_use_config" = "xtrue"])
+AC_SUBST([ODP_LIB_NAME])
##########################################################################
# Build examples/tests dynamically
@@ -456,6 +457,7 @@ AC_OUTPUT
AC_MSG_RESULT([
$PACKAGE $VERSION
+ ODP Library name: ${ODP_LIB_NAME}
ODP Library version: ${ODP_LIBSO_VERSION}
Helper Library version: ${ODPHELPER_LIBSO_VERSION}
@@ -499,6 +501,7 @@ AC_MSG_RESULT([
test_example: ${test_example}
user_guides: ${user_guides}
pcapng: ${have_pcapng}
+ default_config_path: ${default_config_path}
])
AS_IF([test "${with_openssl}" = "no"],
diff --git a/example/Makefile.inc b/example/Makefile.inc
index 4668b0ae7..4330431af 100644
--- a/example/Makefile.inc
+++ b/example/Makefile.inc
@@ -4,7 +4,7 @@ include $(top_srcdir)/Makefile.inc
TESTS_ENVIRONMENT = EXEEXT=${EXEEXT}
-LDADD = $(LIB)/libodp-linux.la $(LIB)/libodphelper.la
+LDADD = $(LIB)/libodphelper.la $(LIB)/lib$(ODP_LIB_NAME).la
# Do not link to DPDK twice in case of dynamic linking with ODP
if STATIC_APPS
diff --git a/example/ipsec/odp_ipsec.c b/example/ipsec/odp_ipsec.c
index a50468d6e..2db4c9158 100644
--- a/example/ipsec/odp_ipsec.c
+++ b/example/ipsec/odp_ipsec.c
@@ -1326,6 +1326,10 @@ main(int argc, char *argv[])
/* If we have test streams build them before starting workers */
resolve_stream_db();
stream_count = create_stream_db_inputs();
+ if (stream_count < 0) {
+ ODPH_ERR("Error: creating input packets failed\n");
+ exit(EXIT_FAILURE);
+ }
/*
* Create and init worker threads
@@ -1632,6 +1636,7 @@ static void usage(char *progname)
"\n"
"Optional OPTIONS\n"
" -c, --count <number> CPU count, 0=all available, default=1\n"
+ " -s, --stream SrcIP:DstIP:InIntf:OutIntf:Count:Length\n"
" -h, --help Display help and exit.\n"
" environment variables: ODP_IPSEC_USE_POLL_QUEUES\n"
" to enable use of poll queues instead of scheduled (default)\n"
diff --git a/example/ipsec/odp_ipsec_stream.c b/example/ipsec/odp_ipsec_stream.c
index 9f953e4a9..d689c6198 100644
--- a/example/ipsec/odp_ipsec_stream.c
+++ b/example/ipsec/odp_ipsec_stream.c
@@ -168,7 +168,8 @@ void resolve_stream_db(void)
odp_packet_t create_ipv4_packet(stream_db_entry_t *stream,
uint8_t *dmac,
- odp_pool_t pkt_pool)
+ odp_pool_t pkt_pool,
+ uint32_t max_len)
{
ipsec_cache_entry_t *entry = NULL;
odp_packet_t pkt;
@@ -188,10 +189,18 @@ odp_packet_t create_ipv4_packet(stream_db_entry_t *stream,
else if (stream->output.entry)
entry = stream->output.entry;
+ /* Make sure there is enough space for protocol overhead */
+ if ((stream->length + 200) > max_len) {
+ ODPH_ERR("Error: too large test packet\n");
+ return ODP_PACKET_INVALID;
+ }
+
/* Get packet */
- pkt = odp_packet_alloc(pkt_pool, 0);
- if (ODP_PACKET_INVALID == pkt)
+ pkt = odp_packet_alloc(pkt_pool, max_len);
+ if (ODP_PACKET_INVALID == pkt) {
+ ODPH_ERR("Error: packet alloc failed\n");
return ODP_PACKET_INVALID;
+ }
base = odp_packet_data(pkt);
data = odp_packet_data(pkt);
@@ -358,7 +367,7 @@ odp_packet_t create_ipv4_packet(stream_db_entry_t *stream,
}
/* Correct set packet length offsets */
- odp_packet_push_tail(pkt, data - base);
+ odp_packet_pull_tail(pkt, max_len - (data - base));
odp_packet_l2_offset_set(pkt, (uint8_t *)eth - base);
odp_packet_l3_offset_set(pkt, (uint8_t *)ip - base);
odp_packet_l4_offset_set(pkt, ((uint8_t *)ip - base) + sizeof(*ip));
@@ -545,14 +554,23 @@ int create_stream_db_inputs(void)
{
int created = 0;
odp_pool_t pkt_pool;
+ odp_pool_info_t pool_info;
stream_db_entry_t *stream = NULL;
+ uint32_t max_len;
/* Lookup the packet pool */
pkt_pool = odp_pool_lookup("packet_pool");
if (pkt_pool == ODP_POOL_INVALID) {
ODPH_ERR("Error: pkt_pool not found\n");
- exit(EXIT_FAILURE);
+ return -1;
}
+ if (odp_pool_info(pkt_pool, &pool_info)) {
+ ODPH_ERR("Error: pool info failed\n");
+ return -1;
+ }
+
+ /* Only single segment packets are supported */
+ max_len = pool_info.params.pkt.seg_len;
/* For each stream create corresponding input packets */
for (stream = stream_db->list; NULL != stream; stream = stream->next) {
@@ -579,15 +597,15 @@ int create_stream_db_inputs(void)
for (count = stream->count; count > 0; count--) {
odp_packet_t pkt;
- pkt = create_ipv4_packet(stream, dmac, pkt_pool);
+ pkt = create_ipv4_packet(stream, dmac, pkt_pool, max_len);
if (ODP_PACKET_INVALID == pkt) {
- printf("Packet buffers exhausted\n");
+ ODPH_ERR("Error: packet buffers exhausted\n");
break;
}
stream->created++;
if (odp_pktout_send(queue, &pkt, 1) != 1) {
odp_packet_free(pkt);
- printf("Queue enqueue failed\n");
+ ODPH_ERR("Error: queue enqueue failed\n");
break;
}
@@ -596,6 +614,10 @@ int create_stream_db_inputs(void)
created++;
}
}
+ if ((stream_db->index > 0) && created == 0) {
+ ODPH_ERR("Error: failed to create any input streams\n");
+ return -1;
+ }
return created;
}
diff --git a/example/ipsec/odp_ipsec_stream.h b/example/ipsec/odp_ipsec_stream.h
index 91ccb0be2..b32f1d7cb 100644
--- a/example/ipsec/odp_ipsec_stream.h
+++ b/example/ipsec/odp_ipsec_stream.h
@@ -85,12 +85,14 @@ void resolve_stream_db(void);
* @param stream Stream DB entry
* @param dmac Destination MAC address to use
* @param pkt_pool Packet buffer pool to allocate from
+ * @param max_len Maximum packet length
*
* @return packet else ODP_PACKET_INVALID
*/
odp_packet_t create_ipv4_packet(stream_db_entry_t *stream,
uint8_t *dmac,
- odp_pool_t pkt_pool);
+ odp_pool_t pkt_pool,
+ uint32_t max_len);
/**
* Verify an IPv4 packet received on a loop output queue
@@ -108,10 +110,11 @@ odp_bool_t verify_ipv4_packet(stream_db_entry_t *stream,
*
* Create input packets based on the configured streams and enqueue them
* into loop interface input queues. Once packet processing starts these
- * packets will be remomved and processed as if they had come from a normal
+ * packets will be removed and processed as if they had come from a normal
* packet interface.
*
* @return number of streams successfully processed
+ * @return <0 on failure
*/
int create_stream_db_inputs(void);
diff --git a/example/ipsec_api/odp_ipsec.c b/example/ipsec_api/odp_ipsec.c
index a02343467..c7ae1be4e 100644
--- a/example/ipsec_api/odp_ipsec.c
+++ b/example/ipsec_api/odp_ipsec.c
@@ -1020,6 +1020,10 @@ main(int argc, char *argv[])
/* If we have test streams build them before starting workers */
resolve_stream_db();
stream_count = create_stream_db_inputs();
+ if (stream_count < 0) {
+ ODPH_ERR("Error: creating input packets failed\n");
+ exit(EXIT_FAILURE);
+ }
/*
* Create and init worker threads
@@ -1331,6 +1335,7 @@ static void usage(char *progname)
"\n"
"Optional OPTIONS\n"
" -c, --count <number> CPU count, 0=all available, default=1\n"
+ " -s, --stream SrcIP:DstIP:InIntf:OutIntf:Count:Length\n"
" -h, --help Display help and exit.\n"
" environment variables: ODP_IPSEC_USE_POLL_QUEUES\n"
" to enable use of poll queues instead of scheduled (default)\n"
diff --git a/example/l2fwd_simple/odp_l2fwd_simple.c b/example/l2fwd_simple/odp_l2fwd_simple.c
index 48f1462dd..94f21ddf2 100644
--- a/example/l2fwd_simple/odp_l2fwd_simple.c
+++ b/example/l2fwd_simple/odp_l2fwd_simple.c
@@ -23,7 +23,7 @@ typedef struct {
odp_pktout_queue_t if0out, if1out;
odph_ethaddr_t src, dst;
odp_shm_t shm;
- int exit_thr;
+ odp_atomic_u32_t exit_thr;
int wait_sec;
} global_data_t;
@@ -34,7 +34,7 @@ static void sig_handler(int signo ODP_UNUSED)
printf("sig_handler!\n");
if (global == NULL)
return;
- global->exit_thr = 1;
+ odp_atomic_store_u32(&global->exit_thr, 1);
}
static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,
@@ -105,7 +105,7 @@ static int run_worker(void *arg ODP_UNUSED)
printf("started output interface\n");
printf("started all\n");
- while (!global->exit_thr) {
+ while (!odp_atomic_load_u32(&global->exit_thr)) {
pkts = odp_pktin_recv_tmo(global->if0in, pkt_tbl, MAX_PKT_BURST,
wait_time);
@@ -189,6 +189,7 @@ int main(int argc, char **argv)
}
memset(global, 0, sizeof(global_data_t));
+ odp_atomic_init_u32(&global->exit_thr, 0);
global->shm = shm;
if (argc > 7 ||
diff --git a/example/l3fwd/odp_l3fwd.c b/example/l3fwd/odp_l3fwd.c
index 0f8b8525c..eda63881f 100644
--- a/example/l3fwd/odp_l3fwd.c
+++ b/example/l3fwd/odp_l3fwd.c
@@ -66,7 +66,8 @@ struct thread_arg_s {
};
typedef struct {
- char *if_names[MAX_NB_PKTIO];
+ char *if_names_buf; /* memory buffer for all if_names */
+ char *if_names[MAX_NB_PKTIO]; /* pointers to name strings stored in if_names_buf */
int if_count;
char *route_str[MAX_NB_ROUTE];
unsigned int worker_count;
@@ -89,7 +90,7 @@ typedef struct {
/** Shm for storing global data */
odp_shm_t shm;
/** Break workers loop if set to 1 */
- int exit_threads;
+ odp_atomic_u32_t exit_threads;
/* forward func, hash or lpm */
int (*fwd_func)(odp_packet_t pkt, int sif);
@@ -322,7 +323,7 @@ static int run_worker(void *arg)
odp_barrier_wait(&global->barrier);
- while (!global->exit_threads) {
+ while (!odp_atomic_load_u32(&global->exit_threads)) {
if (num_pktio > 1) {
if_idx = input_ifs[pktio];
inq = input_queues[pktio];
@@ -570,30 +571,25 @@ static void parse_cmdline_args(int argc, char *argv[], app_args_t *args)
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
+ args->if_names_buf = local;
- /* count the number of tokens separated by ',' */
+ /* store the if names (reset names string) */
strcpy(local, optarg);
for (token = strtok(local, ","), i = 0;
- token != NULL;
- token = strtok(NULL, ","), i++)
- ;
-
+ token != NULL; token = strtok(NULL, ","), i++) {
+ if (i >= MAX_NB_PKTIO) {
+ printf("too many ports specified, "
+ "truncated to %d", MAX_NB_PKTIO);
+ break; /* for */
+ }
+ args->if_names[i] = token;
+ }
if (i == 0) {
print_usage(argv[0]);
free(local);
exit(EXIT_FAILURE);
- } else if (i > MAX_NB_PKTIO) {
- printf("too many ports specified, "
- "truncated to %d", MAX_NB_PKTIO);
}
args->if_count = i;
-
- /* store the if names (reset names string) */
- strcpy(local, optarg);
- for (token = strtok(local, ","), i = 0;
- token != NULL; token = strtok(NULL, ","), i++) {
- args->if_names[i] = token;
- }
break;
/*Configure Route in forwarding database*/
@@ -976,6 +972,7 @@ int main(int argc, char **argv)
}
memset(global, 0, sizeof(global_data_t));
+ odp_atomic_init_u32(&global->exit_threads, 0);
global->shm = shm;
/* Initialize the dest mac as 2:0:0:0:0:x */
@@ -1121,7 +1118,7 @@ int main(int argc, char **argv)
}
print_speed_stats(nb_worker, args->duration, PRINT_INTERVAL);
- global->exit_threads = 1;
+ odp_atomic_store_u32(&global->exit_threads, 1);
/* wait for other threads to join */
for (i = 0; i < nb_worker; i++)
@@ -1137,8 +1134,8 @@ int main(int argc, char **argv)
}
}
- /* if_names share a single buffer, so only one free */
- free(args->if_names[0]);
+ /* if_names share a single buffer */
+ free(args->if_names_buf);
for (i = 0; i < MAX_NB_ROUTE; i++)
free(args->route_str[i]);
diff --git a/example/packet/odp_packet_dump.c b/example/packet/odp_packet_dump.c
index e1ef7e14d..04d6576c5 100644
--- a/example/packet/odp_packet_dump.c
+++ b/example/packet/odp_packet_dump.c
@@ -36,7 +36,7 @@ typedef struct test_options_t {
typedef struct test_global_t {
test_options_t opt;
odp_pool_t pool;
- int stop;
+ odp_atomic_u32_t stop;
struct {
odp_pktio_t pktio;
@@ -52,8 +52,7 @@ static void sig_handler(int signo)
{
(void)signo;
- test_global.stop = 1;
- odp_mb_full();
+ odp_atomic_store_u32(&test_global.stop, 1);
}
static void print_usage(void)
@@ -636,7 +635,7 @@ static int receive_packets(test_global_t *global)
int printed;
uint64_t num_packet = 0;
- while (!global->stop) {
+ while (!odp_atomic_load_u32(&global->stop)) {
ev = odp_schedule(NULL, ODP_SCHED_NO_WAIT);
if (ev == ODP_EVENT_INVALID)
@@ -674,6 +673,7 @@ int main(int argc, char *argv[])
global = &test_global;
memset(global, 0, sizeof(test_global_t));
+ odp_atomic_init_u32(&global->stop, 0);
signal(SIGINT, sig_handler);
diff --git a/example/packet/odp_pktio.c b/example/packet/odp_pktio.c
index 24aa039d5..6065bcc88 100644
--- a/example/packet/odp_pktio.c
+++ b/example/packet/odp_pktio.c
@@ -88,7 +88,7 @@ typedef struct {
/** Thread specific arguments */
thread_args_t thread[MAX_WORKERS];
/** Flag to exit worker threads */
- int exit_threads;
+ odp_atomic_u32_t exit_threads;
} args_t;
/** Global pointer to args */
@@ -206,7 +206,7 @@ static int pktio_queue_thread(void *arg)
}
/* Loop packets */
- while (!args->exit_threads) {
+ while (!odp_atomic_load_u32(&args->exit_threads)) {
odp_pktio_t pktio_tmp;
if (inq != ODP_QUEUE_INVALID)
@@ -296,7 +296,7 @@ static int pktio_ifburst_thread(void *arg)
}
/* Loop packets */
- while (!args->exit_threads) {
+ while (!odp_atomic_load_u32(&args->exit_threads)) {
pkts = odp_pktin_recv(pktin, pkt_tbl, MAX_PKT_BURST);
if (pkts > 0) {
/* Drop packets with errors */
@@ -392,6 +392,7 @@ int main(int argc, char *argv[])
}
memset(args, 0, sizeof(args_t));
+ odp_atomic_init_u32(&args->exit_threads, 0);
args->shm = shm;
/* Parse and store the application arguments */
@@ -482,7 +483,7 @@ int main(int argc, char *argv[])
}
/* use delay to let workers clean up queues */
odp_time_wait_ns(ODP_TIME_SEC_IN_NS);
- args->exit_threads = 1;
+ odp_atomic_store_u32(&args->exit_threads, 1);
}
/* Master thread waits for other threads to exit */
diff --git a/example/ping/odp_ping.c b/example/ping/odp_ping.c
index 750f3a9e3..ec5746bcf 100644
--- a/example/ping/odp_ping.c
+++ b/example/ping/odp_ping.c
@@ -32,7 +32,7 @@ typedef struct test_global_t {
uint64_t rx_packets;
uint64_t tx_replies;
odp_pool_t pool;
- int stop;
+ odp_atomic_u32_t stop;
struct {
odph_ethaddr_t eth_addr;
@@ -50,8 +50,7 @@ static void sig_handler(int signo)
{
(void)signo;
- test_global.stop = 1;
- odp_mb_full();
+ odp_atomic_store_u32(&test_global.stop, 1);
}
static void print_usage(void)
@@ -408,11 +407,12 @@ static void print_packet(odp_packet_t pkt, uint64_t num_packet)
nsec = nsec - (sec * ODP_TIME_SEC_IN_NS);
pktio = odp_packet_input(pkt);
- odp_pktio_info(pktio, &pktio_info);
-
printf("PACKET [%" PRIu64 "]\n", num_packet);
printf(" time: %" PRIu64 ".%09" PRIu64 " sec\n", sec, nsec);
- printf(" interface name: %s\n", pktio_info.name);
+ if (odp_pktio_info(pktio, &pktio_info) == 0)
+ printf(" interface name: %s\n", pktio_info.name);
+ else
+ printf(" interface name: n/a\n");
printf(" packet length: %u bytes\n", odp_packet_len(pkt));
/* L2 */
@@ -575,7 +575,7 @@ static int receive_packets(test_global_t *global)
odp_time_t cur = odp_time_local();
odp_time_t prev = cur;
- while (!global->stop) {
+ while (!odp_atomic_load_u32(&global->stop)) {
ev = odp_schedule(NULL, wait);
cur = odp_time_local();
@@ -629,6 +629,7 @@ int main(int argc, char *argv[])
global = &test_global;
memset(global, 0, sizeof(test_global_t));
+ odp_atomic_init_u32(&global->stop, 0);
signal(SIGINT, sig_handler);
diff --git a/example/simple_pipeline/odp_simple_pipeline.c b/example/simple_pipeline/odp_simple_pipeline.c
index 9beb8a78d..b01efee84 100644
--- a/example/simple_pipeline/odp_simple_pipeline.c
+++ b/example/simple_pipeline/odp_simple_pipeline.c
@@ -74,7 +74,7 @@ typedef struct {
odp_pktout_queue_t if0out, if1out;
odph_ethaddr_t src_addr; /* Source MAC address */
odph_ethaddr_t dst_addr; /* Destination MAC address */
- int exit_threads;
+ odp_atomic_u32_t exit_threads;
/* Application (parsed) arguments */
appl_args_t appl;
} global_data_t;
@@ -83,7 +83,7 @@ static global_data_t *global;
static void sig_handler(int signo ODP_UNUSED)
{
- global->exit_threads = 1;
+ odp_atomic_store_u32(&global->exit_threads, 1);
}
static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,
@@ -191,7 +191,7 @@ static inline int rx_thread(void *arg)
odp_barrier_wait(&global->init_barrier);
- while (!global->exit_threads) {
+ while (!odp_atomic_load_u32(&global->exit_threads)) {
pkts = odp_pktin_recv(pktin_queue, pkt_tbl, MAX_PKT_BURST);
if (odp_unlikely(pkts <= 0))
continue;
@@ -234,7 +234,7 @@ static inline int tx_thread(void *arg)
odp_barrier_wait(&global->init_barrier);
- while (!global->exit_threads) {
+ while (!odp_atomic_load_u32(&global->exit_threads)) {
events = odp_queue_deq_multi(rx_queue, event_tbl,
MAX_PKT_BURST);
if (odp_unlikely(events <= 0))
@@ -301,7 +301,7 @@ static inline int worker_thread(void *arg ODP_UNUSED)
odp_barrier_wait(&global->init_barrier);
- while (!global->exit_threads) {
+ while (!odp_atomic_load_u32(&global->exit_threads)) {
events = odp_queue_deq_multi(rx_queue, event_tbl,
MAX_PKT_BURST);
@@ -472,7 +472,7 @@ static int print_speed_stats(int num_workers, stats_t **thr_stats,
pkts_prev = total_pkts;
}
elapsed += timeout;
- } while (!global->exit_threads && (loop_forever ||
+ } while (!odp_atomic_load_u32(&global->exit_threads) && (loop_forever ||
(elapsed < duration)));
if (stats_enabled)
@@ -736,6 +736,7 @@ int main(int argc, char **argv)
}
memset(global, 0, sizeof(global_data_t));
+ odp_atomic_init_u32(&global->exit_threads, 0);
signal(SIGINT, sig_handler);
@@ -905,7 +906,7 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
- global->exit_threads = 1;
+ odp_atomic_store_u32(&global->exit_threads, 1);
odp_barrier_wait(&global->term_barrier);
odph_thread_join(thr_tbl, num_threads);
diff --git a/example/switch/odp_switch.c b/example/switch/odp_switch.c
index bcc87680e..989016fc8 100644
--- a/example/switch/odp_switch.c
+++ b/example/switch/odp_switch.c
@@ -131,7 +131,7 @@ typedef struct {
/** Global barrier to synchronize main and workers */
odp_barrier_t barrier;
/** Break workers loop if set to 1 */
- int exit_threads;
+ odp_atomic_u32_t exit_threads;
/** Table of pktio handles */
struct {
odp_pktio_t pktio;
@@ -154,7 +154,7 @@ static void sig_handler(int signo ODP_UNUSED)
{
if (gbl_args == NULL)
return;
- gbl_args->exit_threads = 1;
+ odp_atomic_store_u32(&gbl_args->exit_threads, 1);
}
/**
@@ -424,7 +424,7 @@ static int print_speed_stats(int num_workers, stats_t (*thr_stats)[MAX_PKTIOS],
PRIu64 " rx drops, %" PRIu64 " tx drops\n", rx_pkts_tot,
tx_pkts_tot, rx_drops_tot, tx_drops_tot);
- } while (!gbl_args->exit_threads &&
+ } while (!odp_atomic_load_u32(&gbl_args->exit_threads) &&
(loop_forever || (elapsed < duration)));
return rx_pkts_tot >= 100 ? 0 : -1;
@@ -686,7 +686,7 @@ static int run_worker(void *arg)
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) {
+ while (!odp_atomic_load_u32(&gbl_args->exit_threads)) {
odp_time_t time_cur;
odp_time_t time_diff;
int sent;
@@ -962,6 +962,7 @@ static void gbl_args_init(args_t *args)
int pktio;
memset(args, 0, sizeof(args_t));
+ odp_atomic_init_u32(&args->exit_threads, 0);
for (pktio = 0; pktio < MAX_PKTIOS; pktio++)
args->pktios[pktio].pktio = ODP_PKTIO_INVALID;
@@ -1132,7 +1133,7 @@ int main(int argc, char **argv)
ret = print_speed_stats(num_workers, gbl_args->stats,
gbl_args->appl.time, gbl_args->appl.accuracy);
- gbl_args->exit_threads = 1;
+ odp_atomic_store_u32(&gbl_args->exit_threads, 1);
/* Master thread waits for other threads to exit */
for (i = 0; i < num_workers; ++i)
diff --git a/example/timer/odp_timer_accuracy.c b/example/timer/odp_timer_accuracy.c
index dccf70326..7208f216c 100644
--- a/example/timer/odp_timer_accuracy.c
+++ b/example/timer/odp_timer_accuracy.c
@@ -721,7 +721,7 @@ quit:
if (test_global.file)
fclose(test_global.file);
- if (destroy_timers(&test_global))
+ if (test_global.timer_ctx && destroy_timers(&test_global))
ret = -1;
if (test_global.timer_ctx)
diff --git a/example/timer/odp_timer_simple.c b/example/timer/odp_timer_simple.c
index 8084a4568..efbdf7673 100644
--- a/example/timer/odp_timer_simple.c
+++ b/example/timer/odp_timer_simple.c
@@ -69,6 +69,7 @@ int main(int argc ODP_UNUSED, char *argv[] ODP_UNUSED)
ret += 1;
goto err_tp;
}
+ memset(&tparams, 0, sizeof(tparams));
tparams.res_ns = MAX(10 * ODP_TIME_MSEC_IN_NS,
timer_capa.highest_res_ns);
tparams.min_tmo = 10 * ODP_TIME_MSEC_IN_NS;
diff --git a/helper/Makefile.am b/helper/Makefile.am
index 762f80602..8347ff96d 100644
--- a/helper/Makefile.am
+++ b/helper/Makefile.am
@@ -62,6 +62,6 @@ __LIB__libodphelper_la_SOURCES += \
linux/thread.c
endif
-__LIB__libodphelper_la_LIBADD = $(PTHREAD_LIBS) $(LIB)/libodp-linux.la
+__LIB__libodphelper_la_LIBADD = $(PTHREAD_LIBS)
lib_LTLIBRARIES = $(LIB)/libodphelper.la
diff --git a/helper/cuckootable.c b/helper/cuckootable.c
index 237c2f297..47dd90b6c 100644
--- a/helper/cuckootable.c
+++ b/helper/cuckootable.c
@@ -260,7 +260,11 @@ odph_cuckoo_table_create(
pool = odp_pool_lookup(pool_name);
if (pool != ODP_POOL_INVALID)
- odp_pool_destroy(pool);
+ if (odp_pool_destroy(pool)) {
+ odp_shm_free(shm_tbl);
+ ODPH_DBG("failed to destroy pre-existing pool\n");
+ return NULL;
+ }
odp_pool_param_init(&param);
param.type = ODP_POOL_BUFFER;
@@ -285,7 +289,7 @@ odph_cuckoo_table_create(
queue = odp_queue_create(queue_name, &qparam);
if (queue == ODP_QUEUE_INVALID) {
ODPH_DBG("failed to create free_slots queue\n");
- odp_pool_destroy(pool);
+ (void)odp_pool_destroy(pool);
odp_shm_free(shm_tbl);
return NULL;
}
diff --git a/helper/iplookuptable.c b/helper/iplookuptable.c
index c02ee5415..eacfcf5f8 100644
--- a/helper/iplookuptable.c
+++ b/helper/iplookuptable.c
@@ -150,7 +150,7 @@ cache_destroy(odph_iplookup_table_impl *impl)
sprintf(
pool_name, "%s_%d_%d",
impl->name, i, count);
- odp_pool_destroy(odp_pool_lookup(pool_name));
+ (void)odp_pool_destroy(odp_pool_lookup(pool_name));
}
}
}
diff --git a/include/Makefile.am b/include/Makefile.am
index b779e9ad4..32d8a6825 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -127,7 +127,9 @@ odpapiabidefaultinclude_HEADERS = \
odp/api/abi-default/cpumask.h \
odp/api/abi-default/crypto.h \
odp/api/abi-default/debug.h \
+ odp/api/abi-default/errno.h \
odp/api/abi-default/event.h \
+ odp/api/abi-default/hash.h \
odp/api/abi-default/init.h \
odp/api/abi-default/ipsec.h \
odp/api/abi-default/packet.h \
@@ -171,7 +173,9 @@ odpapiabiarchinclude_HEADERS = \
odp/arch/arm32-linux/odp/api/abi/cpumask.h \
odp/arch/arm32-linux/odp/api/abi/crypto.h \
odp/arch/arm32-linux/odp/api/abi/debug.h \
+ odp/arch/arm32-linux/odp/api/abi/errno.h \
odp/arch/arm32-linux/odp/api/abi/event.h \
+ odp/arch/arm32-linux/odp/api/abi/hash.h \
odp/arch/arm32-linux/odp/api/abi/init.h \
odp/arch/arm32-linux/odp/api/abi/ipsec.h \
odp/arch/arm32-linux/odp/api/abi/packet.h \
@@ -211,7 +215,9 @@ odpapiabiarchinclude_HEADERS = \
odp/arch/arm64-linux/odp/api/abi/cpumask.h \
odp/arch/arm64-linux/odp/api/abi/crypto.h \
odp/arch/arm64-linux/odp/api/abi/debug.h \
+ odp/arch/arm64-linux/odp/api/abi/errno.h \
odp/arch/arm64-linux/odp/api/abi/event.h \
+ odp/arch/arm64-linux/odp/api/abi/hash.h \
odp/arch/arm64-linux/odp/api/abi/init.h \
odp/arch/arm64-linux/odp/api/abi/ipsec.h \
odp/arch/arm64-linux/odp/api/abi/packet.h \
@@ -251,7 +257,9 @@ odpapiabiarchinclude_HEADERS = \
odp/arch/default-linux/odp/api/abi/cpumask.h \
odp/arch/default-linux/odp/api/abi/crypto.h \
odp/arch/default-linux/odp/api/abi/debug.h \
+ odp/arch/default-linux/odp/api/abi/errno.h \
odp/arch/default-linux/odp/api/abi/event.h \
+ odp/arch/default-linux/odp/api/abi/hash.h \
odp/arch/default-linux/odp/api/abi/init.h \
odp/arch/default-linux/odp/api/abi/ipsec.h \
odp/arch/default-linux/odp/api/abi/packet.h \
@@ -291,7 +299,9 @@ odpapiabiarchinclude_HEADERS = \
odp/arch/mips64-linux/odp/api/abi/cpumask.h \
odp/arch/mips64-linux/odp/api/abi/crypto.h \
odp/arch/mips64-linux/odp/api/abi/debug.h \
+ odp/arch/mips64-linux/odp/api/abi/errno.h \
odp/arch/mips64-linux/odp/api/abi/event.h \
+ odp/arch/mips64-linux/odp/api/abi/hash.h \
odp/arch/mips64-linux/odp/api/abi/init.h \
odp/arch/mips64-linux/odp/api/abi/ipsec.h \
odp/arch/mips64-linux/odp/api/abi/packet.h \
@@ -331,7 +341,9 @@ odpapiabiarchinclude_HEADERS = \
odp/arch/power64-linux/odp/api/abi/cpumask.h \
odp/arch/power64-linux/odp/api/abi/crypto.h \
odp/arch/power64-linux/odp/api/abi/debug.h \
+ odp/arch/power64-linux/odp/api/abi/errno.h \
odp/arch/power64-linux/odp/api/abi/event.h \
+ odp/arch/power64-linux/odp/api/abi/hash.h \
odp/arch/power64-linux/odp/api/abi/init.h \
odp/arch/power64-linux/odp/api/abi/ipsec.h \
odp/arch/power64-linux/odp/api/abi/packet.h \
@@ -371,7 +383,9 @@ odpapiabiarchinclude_HEADERS = \
odp/arch/x86_32-linux/odp/api/abi/cpumask.h \
odp/arch/x86_32-linux/odp/api/abi/crypto.h \
odp/arch/x86_32-linux/odp/api/abi/debug.h \
+ odp/arch/x86_32-linux/odp/api/abi/errno.h \
odp/arch/x86_32-linux/odp/api/abi/event.h \
+ odp/arch/x86_32-linux/odp/api/abi/hash.h \
odp/arch/x86_32-linux/odp/api/abi/init.h \
odp/arch/x86_32-linux/odp/api/abi/ipsec.h \
odp/arch/x86_32-linux/odp/api/abi/packet.h \
@@ -411,7 +425,9 @@ odpapiabiarchinclude_HEADERS = \
odp/arch/x86_64-linux/odp/api/abi/cpumask.h \
odp/arch/x86_64-linux/odp/api/abi/crypto.h \
odp/arch/x86_64-linux/odp/api/abi/debug.h \
+ odp/arch/x86_64-linux/odp/api/abi/errno.h \
odp/arch/x86_64-linux/odp/api/abi/event.h \
+ odp/arch/x86_64-linux/odp/api/abi/hash.h \
odp/arch/x86_64-linux/odp/api/abi/init.h \
odp/arch/x86_64-linux/odp/api/abi/ipsec.h \
odp/arch/x86_64-linux/odp/api/abi/packet.h \
diff --git a/include/odp/api/abi-default/errno.h b/include/odp/api/abi-default/errno.h
new file mode 100644
index 000000000..6437930a0
--- /dev/null
+++ b/include/odp/api/abi-default/errno.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP errno
+ */
+
+#ifndef ODP_ABI_ERRNO_H_
+#define ODP_ABI_ERRNO_H_
+
+/* Empty header to allow platforms to override inlining
+ * of errno functions.
+ */
+
+#endif
diff --git a/include/odp/api/abi-default/hash.h b/include/odp/api/abi-default/hash.h
new file mode 100644
index 000000000..06e9e06c4
--- /dev/null
+++ b/include/odp/api/abi-default/hash.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP hash
+ */
+
+#ifndef ODP_ABI_HASH_H_
+#define ODP_ABI_HASH_H_
+
+/* Empty header to allow platforms to override inlining
+ * of hash functions.
+ */
+
+#endif
diff --git a/include/odp/api/errno.h b/include/odp/api/errno.h
index a0da42ff4..212e51244 100644
--- a/include/odp/api/errno.h
+++ b/include/odp/api/errno.h
@@ -17,6 +17,8 @@
extern "C" {
#endif
+#include <odp/api/abi/errno.h>
+
#include <odp/api/spec/errno.h>
#ifdef __cplusplus
diff --git a/include/odp/api/hash.h b/include/odp/api/hash.h
index b1ddf897a..f059d51ce 100644
--- a/include/odp/api/hash.h
+++ b/include/odp/api/hash.h
@@ -17,6 +17,8 @@
extern "C" {
#endif
+#include <odp/api/abi/hash.h>
+
#include <odp/api/spec/hash.h>
#ifdef __cplusplus
diff --git a/include/odp/api/spec/packet_io.h b/include/odp/api/spec/packet_io.h
index d97e45960..b7eaccaa3 100644
--- a/include/odp/api/spec/packet_io.h
+++ b/include/odp/api/spec/packet_io.h
@@ -1,4 +1,5 @@
/* Copyright (c) 2013-2018, Linaro Limited
+ * Copyright (c) 2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -1208,16 +1209,22 @@ void odp_pktio_config_init(odp_pktio_config_t *config);
*/
void odp_pktio_print(odp_pktio_t pktio);
+/** Link status */
+typedef enum odp_pktio_link_status_t {
+ ODP_PKTIO_LINK_STATUS_UNKNOWN = -1,
+ ODP_PKTIO_LINK_STATUS_DOWN = 0,
+ ODP_PKTIO_LINK_STATUS_UP = 1
+} odp_pktio_link_status_t;
+
/**
* Determine pktio link is up or down for a packet IO interface.
*
* @param pktio Packet IO handle.
*
- * @retval 1 link is up
- * @retval 0 link is down
- * @retval <0 on failure
+ * @retval ODP_PKTIO_LINK_STATUS_UP or ODP_PKTIO_LINK_STATUS_DOWN on success
+ * @retval ODP_PKTIO_LINK_STATUS_UNKNOWN on failure
*/
-int odp_pktio_link_status(odp_pktio_t pktio);
+odp_pktio_link_status_t odp_pktio_link_status(odp_pktio_t pktio);
/**
* Packet IO information
@@ -1255,6 +1262,112 @@ typedef struct odp_pktio_info_t {
*/
int odp_pktio_info(odp_pktio_t pktio, odp_pktio_info_t *info);
+/** @name Link speed
+ * Packet IO link speeds in Mbps
+ * @anchor link_speed
+ * @{
+ */
+
+/** Link speed unknown */
+#define ODP_PKTIO_LINK_SPEED_UNKNOWN 0
+/** Link speed 10 Mbit/s */
+#define ODP_PKTIO_LINK_SPEED_10M 10
+/** Link speed 100 Mbit/s */
+#define ODP_PKTIO_LINK_SPEED_100M 100
+/** Link speed 1 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_1G 1000
+/** Link speed 2.5 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_2_5G 2500
+/** Link speed 5 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_5G 5000
+/** Link speed 10 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_10G 10000
+/** Link speed 20 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_20G 20000
+/** Link speed 25 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_25G 25000
+/** Link speed 40 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_40G 40000
+/** Link speed 50 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_50G 50000
+/** Link speed 56 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_56G 56000
+/** Link speed 100 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_100G 100000
+/** Link speed 200 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_200G 200000
+/** Link speed 400 Gbit/s */
+#define ODP_PKTIO_LINK_SPEED_400G 400000
+
+/** @} */
+
+/** Autonegotiation mode */
+typedef enum odp_pktio_link_autoneg_t {
+ /** Autonegotiation state unknown */
+ ODP_PKTIO_LINK_AUTONEG_UNKNOWN = -1,
+ /** Autonegotiation disabled */
+ ODP_PKTIO_LINK_AUTONEG_OFF = 0,
+ /** Autonegotiation enabled */
+ ODP_PKTIO_LINK_AUTONEG_ON = 1
+} odp_pktio_link_autoneg_t;
+
+/** Duplex mode */
+typedef enum odp_pktio_link_duplex_t {
+ ODP_PKTIO_LINK_DUPLEX_UNKNOWN = -1,
+ ODP_PKTIO_LINK_DUPLEX_HALF = 0,
+ ODP_PKTIO_LINK_DUPLEX_FULL = 1
+} odp_pktio_link_duplex_t;
+
+/** Ethernet pause frame (flow control) mode */
+typedef enum odp_pktio_link_pause_t {
+ ODP_PKTIO_LINK_PAUSE_UNKNOWN = -1,
+ ODP_PKTIO_LINK_PAUSE_OFF = 0,
+ ODP_PKTIO_LINK_PAUSE_ON = 1
+} odp_pktio_link_pause_t;
+
+/**
+ * Packet IO link information
+ */
+typedef struct odp_pktio_link_info_t {
+ /** Link autonegotiation */
+ odp_pktio_link_autoneg_t autoneg;
+ /** Duplex mode */
+ odp_pktio_link_duplex_t duplex;
+ /** Link media type
+ *
+ * The implementation owned string describes link media type. Values are
+ * implementation specific short names like copper, fiber, or virtual.
+ * The value of "unknown" is used when media type cannot be determined. */
+ const char *media;
+ /** Reception of pause frames */
+ odp_pktio_link_pause_t pause_rx;
+ /** Transmission of pause frames */
+ odp_pktio_link_pause_t pause_tx;
+ /** Link speed in Mbps
+ *
+ * The value of zero means that the link speed is unknown.
+ * ODP_PKTIO_LINK_SPEED_* (@ref link_speed) defines can be used to
+ * compare the value to standard link speeds. */
+ uint32_t speed;
+ /** Link status */
+ odp_pktio_link_status_t status;
+} odp_pktio_link_info_t;
+
+/**
+ * Retrieve information about packet IO link status
+ *
+ * Fills in link information structure with the current link status values.
+ * May be called any time with a valid pktio handle. The call is not intended
+ * for fast path use. The info structure is written only on success.
+ *
+ * @param pktio Packet IO handle
+ * @param[out] info Pointer to packet IO link info struct for output
+ *
+ * @retval 0 on success
+ * @retval <0 on failure
+ */
+int odp_pktio_link_info(odp_pktio_t pktio, odp_pktio_link_info_t *info);
+
/**
* Packet input timestamp resolution in hertz
*
diff --git a/include/odp/api/spec/random.h b/include/odp/api/spec/random.h
index 89d7d9d3f..80f71c473 100644
--- a/include/odp/api/spec/random.h
+++ b/include/odp/api/spec/random.h
@@ -72,7 +72,7 @@ odp_random_kind_t odp_random_max_kind(void);
* is expected to fail if the implementation is unable to
* provide the requested type.
*
- * @return Number of bytes written
+ * @return Number of bytes written (0...len).
* @retval <0 on failure
*/
int32_t odp_random_data(uint8_t *buf, uint32_t len, odp_random_kind_t kind);
@@ -96,7 +96,7 @@ int32_t odp_random_data(uint8_t *buf, uint32_t len, odp_random_kind_t kind);
* variable. Results are undefined if multiple threads
* call this routine with the same seed variable.
*
- * @return Number of bytes written
+ * @return Number of bytes written (always len)
* @retval <0 on failure
*/
int32_t odp_random_test_data(uint8_t *buf, uint32_t len, uint64_t *seed);
diff --git a/include/odp/api/spec/time.h b/include/odp/api/spec/time.h
index c0a12064d..c5756e492 100644
--- a/include/odp/api/spec/time.h
+++ b/include/odp/api/spec/time.h
@@ -1,4 +1,5 @@
/* Copyright (c) 2013-2018, Linaro Limited
+ * Copyright (c) 2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -77,6 +78,24 @@ odp_time_t odp_time_local(void);
odp_time_t odp_time_global(void);
/**
+ * Current local time in nanoseconds
+ *
+ * Like odp_time_local(), but the time stamp value is converted into nanoseconds.
+ *
+ * @return Local time stamp in nanoseconds
+ */
+uint64_t odp_time_local_ns(void);
+
+/**
+ * Current global time in nanoseconds
+ *
+ * Like odp_time_global(), but the time stamp value is converted into nanoseconds.
+ *
+ * @return Global time stamp in nanoseconds
+ */
+uint64_t odp_time_global_ns(void);
+
+/**
* Time difference
*
* @param t2 Second time stamp
diff --git a/include/odp/api/spec/timer.h b/include/odp/api/spec/timer.h
index a48e79bf5..1f49e7b40 100644
--- a/include/odp/api/spec/timer.h
+++ b/include/odp/api/spec/timer.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2013-2018, Linaro Limited
- * Copyright (c) 2019, Nokia
+ * Copyright (c) 2019-2020, Nokia
*
* All rights reserved.
*
@@ -106,14 +106,20 @@ typedef enum {
typedef struct {
/** Timeout resolution in nanoseconds. Timer pool must serve timeouts
* with this or higher resolution. The minimum valid value (highest
- * resolution) is defined by timer capability 'highest_res_ns'. */
+ * resolution) is defined by timer resolution capability. When this
+ * parameter is used, set 'res_hz' to zero. */
uint64_t res_ns;
+ /** Timeout resolution in hertz. This may be used to specify the highest
+ * required resolution in hertz instead of nanoseconds. When this
+ * parameter is used, set 'res_ns' to zero. */
+ uint64_t res_hz;
+
/** Minimum relative timeout in nanoseconds. All requested timeouts
* will be at least this many nanoseconds after the current
* time of the timer pool. Timer set functions return an error, if too
- * short timeout was requested. The value may be also less than
- * 'res_ns'. */
+ * short timeout was requested. The value may be also smaller than
+ * the requested resolution. */
uint64_t min_tmo;
/** Maximum relative timeout in nanoseconds. All requested timeouts
@@ -143,6 +149,9 @@ typedef struct {
/** Timeout resolution in nanoseconds */
uint64_t res_ns;
+ /** Timeout resolution in hertz */
+ uint64_t res_hz;
+
/** Minimum relative timeout in nanoseconds */
uint64_t min_tmo;
@@ -186,8 +195,9 @@ typedef struct {
*
* This defines the highest resolution supported by a timer, with
* limits to min/max timeout values. The highest resolution for a timer
- * pool is defined by 'max_res.res_ns', therefore it's the minimum value
- * for 'res_ns' timer pool parameter. When this resolution is used:
+ * pool is defined by 'max_res.res_ns' in nanoseconds and
+ * 'max_res.res_hz' in hertz.
+ * When this resolution is used:
* - 'min_tmo' parameter value must be in minimum 'max_res.min_tmo'
* - 'max_tmo' parameter value must be in maximum 'max_res.max_tmo'
*/
@@ -201,7 +211,8 @@ typedef struct {
* value for 'max_tmo' timer pool parameter is defined by
* 'max_tmo.max_tmo'. When this max timeout value is used:
* - 'min_tmo' parameter value must be in minimum 'max_tmo.min_tmo'
- * - 'res_ns' parameter value must be in minimum 'max_tmo.res_ns'
+ * - 'res_ns' parameter value must be in minimum 'max_tmo.res_ns' or
+ * - 'res_hz' parameter value must be in maximum 'max_tmo.res_hz'
*/
odp_timer_res_capability_t max_tmo;
@@ -226,16 +237,16 @@ int odp_timer_capability(odp_timer_clk_src_t clk_src,
*
* This function fills in capability limits for timer pool resolution and
* min/max timeout values, based on either resolution or maximum timeout.
- * Set the required value to 'res_ns' or 'max_tmo', and set other fields to
- * zero. A successful call fills in the other two fields. The call returns
- * a failure, if the user defined value ('res_ns' or 'max_tmo)' exceeds
- * capability limits. Outputted values are minimums for 'res_ns' and 'min_tmo',
- * and a maximum for 'max_tmo'.
+ * Set the required value to a resolution field (res_ns or res_hz) or to the
+ * maximum timeout field (max_tmo), and set other fields to zero. A successful
+ * call fills in the other fields. The call returns a failure, if the user
+ * defined value exceeds capability limits. Outputted values are minimums for
+ * 'res_ns' and 'min_tmo', and maximums for 'res_hz' and 'max_tmo'.
*
* @param clk_src Clock source for timers
* @param[in,out] res_capa Resolution capability pointer for input/output.
- * Set either 'res_ns' or 'max_tmo', a successful call
- * fills in other fields.
+ * Set either a resolution or max timeout field,
+ * a successful call fills in other fields.
*
* @retval 0 on success
* @retval <0 on failure
diff --git a/include/odp/api/spec/traffic_mngr.h b/include/odp/api/spec/traffic_mngr.h
index 03294c820..04848a0ea 100644
--- a/include/odp/api/spec/traffic_mngr.h
+++ b/include/odp/api/spec/traffic_mngr.h
@@ -1651,7 +1651,8 @@ typedef struct {
/** Get tm_node Info
*
* The odp_tm_node_info() function is used to extract various bits of
- * configuration associated with a given tm_node.
+ * configuration associated with a given tm_node. The info structure is written
+ * only on success.
*
* @param tm_node Specifies the tm_node to be queried.
* @param[out] info A pointer to an odp_tm_node_info_t record that is to
@@ -1711,7 +1712,7 @@ typedef struct {
* from their fanin list, a reasonable list walk can occur - even while past or
* future entries are being removed or while future entries are being added.
* Note that all new additions to a fanin list always take place at the end of
- * the list.
+ * the list. The info structure is written only on success.
*
* @param tm_node Specifies the tm_node to be queried.
* @param[in,out] info A pointer to an odp_tm_node_fanin_info_t record that
@@ -1756,7 +1757,8 @@ typedef struct {
/** Get tm_queue Info
*
* The odp_tm_queue_info() function is used to extract various bits of
- * configuration associated with a given tm_queue.
+ * configuration associated with a given tm_queue. The info structure is
+ * written only on success.
*
* @param tm_queue Specifies the tm_queue to be queried.
* @param[out] info A pointer to an odp_tm_queue_info_t record that is to
@@ -1840,11 +1842,12 @@ typedef struct {
* byte counts or both are being requested. It is an error to request
* neither. The implementation may still return both sets of counts
* regardless of query_flags if the cost of returning all the counts is
- * comparable to the cost of checking the query_flags.
+ * comparable to the cost of checking the query_flags. The info structure is
+ * written only on success.
*
* @param tm_queue Specifies the tm_queue (and indirectly the
* TM system).
- * @param[out] query_flags A set of flag bits indicating which counters are
+ * @param query_flags A set of flag bits indicating which counters are
* being requested to be returned in the info record.
* @param[out] info Pointer to an odp_tm_query_info_t record where the
* requested queue info is returned.
@@ -1860,12 +1863,12 @@ int odp_tm_queue_query(odp_tm_queue_t tm_queue,
* requested. It is an error to request neither. The implementation may
* still return both sets of counts regardless of query_flags if the cost of
* returning all the counts is comparable to the cost of checking the
- * query_flags.
+ * query_flags. The info structure is written only on success.
*
* @param odp_tm Specifies the TM system.
* @param priority Supplies the strict priority level used to specify
* which tm_queues are included in the info values.
- * @param[out] query_flags A set of flag bits indicating which counters are
+ * @param query_flags A set of flag bits indicating which counters are
* being requested to be returned in the info record.
* @param[out] info Pointer to an odp_tm_query_info_t record where the
* requested queue info is returned.
@@ -1882,10 +1885,10 @@ int odp_tm_priority_query(odp_tm_t odp_tm,
* requested. It is an error to request neither. The implementation may
* still return both sets of counts regardless of query_flags if the cost of
* returning all the counts is comparable to the cost of checking the
- * query_flags.
+ * query_flags. The info structure is written only on success.
*
* @param odp_tm Specifies the TM system.
- * @param[out] query_flags A set of flag bits indicating which counters are
+ * @param query_flags A set of flag bits indicating which counters are
* being requested to be returned in the info record.
* @param[out] info Pointer to an odp_tm_query_info_t record where the
* requested queue info is returned.
@@ -1952,6 +1955,97 @@ odp_bool_t odp_tm_is_idle(odp_tm_t odp_tm);
void odp_tm_stats_print(odp_tm_t odp_tm);
/**
+ * Get printable value for an odp_tm_t
+ *
+ * @param hdl odp_tm_t handle to be printed
+ * @return uint64_t value that can be used to print/display this
+ * handle
+ *
+ * @note This routine is intended to be used for diagnostic purposes
+ * to enable applications to generate a printable value that represents
+ * an odp_tm_t handle.
+ */
+uint64_t odp_tm_to_u64(odp_tm_t hdl);
+
+/**
+ * Get printable value for an odp_tm_queue_t
+ *
+ * @param hdl odp_tm_queue_t handle to be printed
+ * @return uint64_t value that can be used to print/display this
+ * handle
+ *
+ * @note This routine is intended to be used for diagnostic purposes
+ * to enable applications to generate a printable value that represents
+ * an odp_tm_queue_t handle.
+ */
+uint64_t odp_tm_queue_to_u64(odp_tm_queue_t hdl);
+
+/**
+ * Get printable value for an odp_tm_node_t
+ *
+ * @param hdl odp_tm_node_t handle to be printed
+ * @return uint64_t value that can be used to print/display this
+ * handle
+ *
+ * @note This routine is intended to be used for diagnostic purposes
+ * to enable applications to generate a printable value that represents
+ * an odp_tm_node_t handle.
+ */
+uint64_t odp_tm_node_to_u64(odp_tm_node_t hdl);
+
+/**
+ * Get printable value for an odp_tm_shaper_t
+ *
+ * @param hdl odp_tm_shaper_t handle to be printed
+ * @return uint64_t value that can be used to print/display this
+ * handle
+ *
+ * @note This routine is intended to be used for diagnostic purposes
+ * to enable applications to generate a printable value that represents
+ * an odp_tm_shaper_t handle.
+ */
+uint64_t odp_tm_shaper_to_u64(odp_tm_shaper_t hdl);
+
+/**
+ * Get printable value for an odp_tm_sched_t
+ *
+ * @param hdl odp_tm_sched_t handle to be printed
+ * @return uint64_t value that can be used to print/display this
+ * handle
+ *
+ * @note This routine is intended to be used for diagnostic purposes
+ * to enable applications to generate a printable value that represents
+ * an odp_tm_sched_t handle.
+ */
+uint64_t odp_tm_sched_to_u64(odp_tm_sched_t hdl);
+
+/**
+ * Get printable value for an odp_tm_threshold_t
+ *
+ * @param hdl odp_tm_threshold_t handle to be printed
+ * @return uint64_t value that can be used to print/display this
+ * handle
+ *
+ * @note This routine is intended to be used for diagnostic purposes
+ * to enable applications to generate a printable value that represents
+ * an odp_tm_threshold_t handle.
+ */
+uint64_t odp_tm_threshold_to_u64(odp_tm_threshold_t hdl);
+
+/**
+ * Get printable value for an odp_tm_wred_t
+ *
+ * @param hdl odp_tm_wred_t handle to be printed
+ * @return uint64_t value that can be used to print/display this
+ * handle
+ *
+ * @note This routine is intended to be used for diagnostic purposes
+ * to enable applications to generate a printable value that represents
+ * an odp_tm_wred_t handle.
+ */
+uint64_t odp_tm_wred_to_u64(odp_tm_wred_t hdl);
+
+/**
* @}
*/
diff --git a/include/odp/arch/arm32-linux/odp/api/abi/errno.h b/include/odp/arch/arm32-linux/odp/api/abi/errno.h
new file mode 100644
index 000000000..69de49a0b
--- /dev/null
+++ b/include/odp/arch/arm32-linux/odp/api/abi/errno.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/errno.h>
diff --git a/include/odp/arch/arm32-linux/odp/api/abi/hash.h b/include/odp/arch/arm32-linux/odp/api/abi/hash.h
new file mode 100644
index 000000000..c9fb1976c
--- /dev/null
+++ b/include/odp/arch/arm32-linux/odp/api/abi/hash.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/hash.h>
diff --git a/include/odp/arch/arm64-linux/odp/api/abi/errno.h b/include/odp/arch/arm64-linux/odp/api/abi/errno.h
new file mode 100644
index 000000000..69de49a0b
--- /dev/null
+++ b/include/odp/arch/arm64-linux/odp/api/abi/errno.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/errno.h>
diff --git a/include/odp/arch/arm64-linux/odp/api/abi/hash.h b/include/odp/arch/arm64-linux/odp/api/abi/hash.h
new file mode 100644
index 000000000..c9fb1976c
--- /dev/null
+++ b/include/odp/arch/arm64-linux/odp/api/abi/hash.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/hash.h>
diff --git a/include/odp/arch/default-linux/odp/api/abi/errno.h b/include/odp/arch/default-linux/odp/api/abi/errno.h
new file mode 100644
index 000000000..69de49a0b
--- /dev/null
+++ b/include/odp/arch/default-linux/odp/api/abi/errno.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/errno.h>
diff --git a/include/odp/arch/default-linux/odp/api/abi/hash.h b/include/odp/arch/default-linux/odp/api/abi/hash.h
new file mode 100644
index 000000000..c9fb1976c
--- /dev/null
+++ b/include/odp/arch/default-linux/odp/api/abi/hash.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/hash.h>
diff --git a/include/odp/arch/mips64-linux/odp/api/abi/errno.h b/include/odp/arch/mips64-linux/odp/api/abi/errno.h
new file mode 100644
index 000000000..69de49a0b
--- /dev/null
+++ b/include/odp/arch/mips64-linux/odp/api/abi/errno.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/errno.h>
diff --git a/include/odp/arch/mips64-linux/odp/api/abi/hash.h b/include/odp/arch/mips64-linux/odp/api/abi/hash.h
new file mode 100644
index 000000000..c9fb1976c
--- /dev/null
+++ b/include/odp/arch/mips64-linux/odp/api/abi/hash.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/hash.h>
diff --git a/include/odp/arch/power64-linux/odp/api/abi/errno.h b/include/odp/arch/power64-linux/odp/api/abi/errno.h
new file mode 100644
index 000000000..69de49a0b
--- /dev/null
+++ b/include/odp/arch/power64-linux/odp/api/abi/errno.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/errno.h>
diff --git a/include/odp/arch/power64-linux/odp/api/abi/hash.h b/include/odp/arch/power64-linux/odp/api/abi/hash.h
new file mode 100644
index 000000000..c9fb1976c
--- /dev/null
+++ b/include/odp/arch/power64-linux/odp/api/abi/hash.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/hash.h>
diff --git a/include/odp/arch/x86_32-linux/odp/api/abi/errno.h b/include/odp/arch/x86_32-linux/odp/api/abi/errno.h
new file mode 100644
index 000000000..69de49a0b
--- /dev/null
+++ b/include/odp/arch/x86_32-linux/odp/api/abi/errno.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/errno.h>
diff --git a/include/odp/arch/x86_32-linux/odp/api/abi/hash.h b/include/odp/arch/x86_32-linux/odp/api/abi/hash.h
new file mode 100644
index 000000000..c9fb1976c
--- /dev/null
+++ b/include/odp/arch/x86_32-linux/odp/api/abi/hash.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/hash.h>
diff --git a/include/odp/arch/x86_64-linux/odp/api/abi/errno.h b/include/odp/arch/x86_64-linux/odp/api/abi/errno.h
new file mode 100644
index 000000000..69de49a0b
--- /dev/null
+++ b/include/odp/arch/x86_64-linux/odp/api/abi/errno.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/errno.h>
diff --git a/include/odp/arch/x86_64-linux/odp/api/abi/hash.h b/include/odp/arch/x86_64-linux/odp/api/abi/hash.h
new file mode 100644
index 000000000..c9fb1976c
--- /dev/null
+++ b/include/odp/arch/x86_64-linux/odp/api/abi/hash.h
@@ -0,0 +1,7 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <odp/api/abi-default/hash.h>
diff --git a/m4/odp_atomic.m4 b/m4/odp_atomic.m4
index c0068b5e4..cde313261 100644
--- a/m4/odp_atomic.m4
+++ b/m4/odp_atomic.m4
@@ -126,12 +126,13 @@ AC_CACHE_CHECK([whether -latomic is needed for 64-bit atomic compare exchange],
[odp_cv_atomic_needed_64bit_cmp_exc], [dnl
AC_LINK_IFELSE(
[AC_LANG_SOURCE([[
+ #include <stdbool.h>
#include <stdint.h>
static uint64_t loc;
int main(void)
{
uint64_t exp = 0;
- uint64_t = __atomic_compare_exchange_n(&loc, &exp, 1, 1,
+ bool res = __atomic_compare_exchange_8(&loc, &exp, 1, 1,
__ATOMIC_ACQUIRE,
__ATOMIC_RELAXED);
return 0;
@@ -157,14 +158,14 @@ AC_CACHE_CHECK([whether -latomic is needed for 128-bit atomic compare exchange],
[odp_cv_atomic_needed_128bit_cmp_exc], [dnl
AC_LINK_IFELSE(
[AC_LANG_SOURCE([[
- #include <stdint.h>
+ #include <stdbool.h>
static __int128 loc;
int main(void)
{
__int128 exp = 0;
- __int128 = __atomic_compare_exchange_n(&loc, &exp, 1, 1,
- __ATOMIC_ACQUIRE,
- __ATOMIC_RELAXED);
+ bool res = __atomic_compare_exchange_16(&loc, &exp, 1, 1,
+ __ATOMIC_ACQUIRE,
+ __ATOMIC_RELAXED);
return 0;
}
]])],
diff --git a/platform/Makefile.inc b/platform/Makefile.inc
index f99d39ffc..475d38c37 100644
--- a/platform/Makefile.inc
+++ b/platform/Makefile.inc
@@ -1,18 +1,18 @@
include $(top_srcdir)/Makefile.inc
pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libodp-linux.pc
+pkgconfig_DATA = lib$(ODP_LIB_NAME).pc
EXTRA_DIST = doc/platform_specific.dox
configdir = $(sysconfdir)/odp
if ODP_USE_CONFIG
-config_DATA = $(top_srcdir)/config/odp-$(with_platform).conf
-EXTRA_DIST += $(top_srcdir)/config/odp-$(with_platform).conf
+config_DATA = $(top_builddir)/$(rel_default_config_path)
+EXTRA_DIST += $(top_builddir)/$(rel_default_config_path)
endif
VPATH = $(srcdir) $(builddir)
-lib_LTLIBRARIES = $(LIB)/libodp-linux.la
+lib_LTLIBRARIES =
AM_LDFLAGS = -version-number '$(ODP_LIBSO_VERSION)'
diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am
index 30e9f1dbd..045051b79 100644
--- a/platform/linux-dpdk/Makefile.am
+++ b/platform/linux-dpdk/Makefile.am
@@ -1,5 +1,6 @@
include $(top_srcdir)/platform/Makefile.inc
include $(top_srcdir)/platform/@with_platform@/Makefile.inc
+lib_LTLIBRARIES += $(LIB)/libodp-linux.la
AM_CPPFLAGS = $(ODP_INCLUDES)
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/include
@@ -15,7 +16,7 @@ AM_CFLAGS += $(DPDK_CFLAGS)
AM_CFLAGS += $(LIBCONFIG_CFLAGS)
DISTCLEANFILES = include/odp_libconfig_config.h
-include/odp_libconfig_config.h: $(top_srcdir)/config/odp-$(with_platform).conf $(top_builddir)/config.status
+include/odp_libconfig_config.h: $(top_builddir)/$(rel_default_config_path) $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
odpapiabiarchincludedir = $(archincludedir)/odp/api/abi
@@ -55,7 +56,9 @@ odpapiabiarchinclude_HEADERS += \
include-abi/odp/api/abi/cpumask.h \
include-abi/odp/api/abi/crypto.h \
include-abi/odp/api/abi/debug.h \
+ include-abi/odp/api/abi/errno.h \
include-abi/odp/api/abi/event.h \
+ include-abi/odp/api/abi/hash.h \
include-abi/odp/api/abi/init.h \
include-abi/odp/api/abi/ipsec.h \
include-abi/odp/api/abi/packet.h \
@@ -138,7 +141,7 @@ noinst_HEADERS = \
include/protocols/udp.h \
Makefile.inc
-nodist_noinst_HEADERS = \
+BUILT_SOURCES = \
include/odp_libconfig_config.h
__LIB__libodp_linux_la_SOURCES = \
diff --git a/platform/linux-dpdk/include-abi/odp/api/abi/errno.h b/platform/linux-dpdk/include-abi/odp/api/abi/errno.h
new file mode 120000
index 000000000..0bc8b623d
--- /dev/null
+++ b/platform/linux-dpdk/include-abi/odp/api/abi/errno.h
@@ -0,0 +1 @@
+../../../../../linux-generic/include-abi/odp/api/abi/errno.h \ No newline at end of file
diff --git a/platform/linux-dpdk/include-abi/odp/api/abi/hash.h b/platform/linux-dpdk/include-abi/odp/api/abi/hash.h
new file mode 120000
index 000000000..cdcd8260a
--- /dev/null
+++ b/platform/linux-dpdk/include-abi/odp/api/abi/hash.h
@@ -0,0 +1 @@
+../../../../../linux-generic/include-abi/odp/api/abi/hash.h \ No newline at end of file
diff --git a/platform/linux-dpdk/include/odp/api/plat/time_inlines.h b/platform/linux-dpdk/include/odp/api/plat/time_inlines.h
index 0b49c09d6..a1b91682a 100644
--- a/platform/linux-dpdk/include/odp/api/plat/time_inlines.h
+++ b/platform/linux-dpdk/include/odp/api/plat/time_inlines.h
@@ -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,7 @@
/** @cond _ODP_HIDE_FROM_DOXYGEN_ */
#define _ODP_TIMESPEC_SIZE 16
+#define _ODP_TIME_GIGA_HZ 1000000000ULL
typedef odp_time_t (*time_cur_fn)(void);
typedef uint64_t (*time_res_fn)(void);
@@ -61,14 +63,43 @@ static inline odp_time_t _odp_time_cur(void)
return _odp_time_glob.handler.time_cur();
}
+static inline uint64_t _odp_time_hw_to_ns(odp_time_t time)
+{
+ uint64_t nsec;
+ uint64_t freq_hz = _odp_time_glob.hw_freq_hz;
+ uint64_t count = time.count;
+ uint64_t sec = 0;
+
+ if (count >= freq_hz) {
+ sec = count / freq_hz;
+ count = count - sec * freq_hz;
+ }
+
+ nsec = (_ODP_TIME_GIGA_HZ * count) / freq_hz;
+
+ return (sec * _ODP_TIME_GIGA_HZ) + nsec;
+}
+
+static inline uint64_t _odp_time_convert_to_ns(odp_time_t time)
+{
+ if (_odp_time_glob.use_hw)
+ return _odp_time_hw_to_ns(time);
+
+ return time.nsec;
+}
+
#ifndef _ODP_NO_INLINE
/* Inline functions by default */
#define _ODP_INLINE static inline
- #define odp_time_local __odp_time_local
- #define odp_time_global __odp_time_global
- #define odp_time_cmp __odp_time_cmp
- #define odp_time_diff __odp_time_diff
- #define odp_time_sum __odp_time_sum
+ #define odp_time_local __odp_time_local
+ #define odp_time_global __odp_time_global
+ #define odp_time_to_ns __odp_time_to_ns
+ #define odp_time_local_ns __odp_time_local_ns
+ #define odp_time_global_ns __odp_time_global_ns
+ #define odp_time_cmp __odp_time_cmp
+ #define odp_time_diff __odp_time_diff
+ #define odp_time_sum __odp_time_sum
+
#else
#define _ODP_INLINE
#endif
@@ -83,6 +114,21 @@ _ODP_INLINE odp_time_t odp_time_global(void)
return _odp_time_cur();
}
+_ODP_INLINE uint64_t odp_time_to_ns(odp_time_t time)
+{
+ return _odp_time_convert_to_ns(time);
+}
+
+_ODP_INLINE uint64_t odp_time_local_ns(void)
+{
+ return _odp_time_convert_to_ns(_odp_time_cur());
+}
+
+_ODP_INLINE uint64_t odp_time_global_ns(void)
+{
+ return _odp_time_convert_to_ns(_odp_time_cur());
+}
+
_ODP_INLINE int odp_time_cmp(odp_time_t t2, odp_time_t t1)
{
if (odp_likely(t2.u64 > t1.u64))
diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h b/platform/linux-dpdk/include/odp_packet_io_internal.h
index 5bc3a3590..44c8774f6 100644
--- a/platform/linux-dpdk/include/odp_packet_io_internal.h
+++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
@@ -159,6 +159,7 @@ typedef struct pktio_if_ops {
int (*mac_get)(pktio_entry_t *pktio_entry, void *mac_addr);
int (*mac_set)(pktio_entry_t *pktio_entry, const void *mac_addr);
int (*link_status)(pktio_entry_t *pktio_entry);
+ int (*link_info)(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info);
int (*capability)(pktio_entry_t *pktio_entry,
odp_pktio_capability_t *capa);
int (*config)(pktio_entry_t *pktio_entry,
diff --git a/platform/linux-dpdk/libodp-linux.pc.in b/platform/linux-dpdk/libodp-linux.pc.in
index 5b9421226..39729ea58 100644
--- a/platform/linux-dpdk/libodp-linux.pc.in
+++ b/platform/linux-dpdk/libodp-linux.pc.in
@@ -3,10 +3,10 @@ exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
-Name: libodp-linux
+Name: lib@ODP_LIB_NAME@
Description: The ODP packet processing engine
Version: @PKGCONFIG_VERSION@
Requires.private: libconfig@DPDK_PKG@
-Libs: -L${libdir} -lodp-linux @DPDK_LIBS_NON_ABI_COMPAT@
+Libs: -L${libdir} -l@ODP_LIB_NAME@ @DPDK_LIBS_NON_ABI_COMPAT@
Libs.private: @DPDK_LIBS_ABI_COMPAT@ @OPENSSL_STATIC_LIBS@ @PTHREAD_LIBS@ @TIMER_LIBS@ -lpthread @ATOMIC_LIBS@
Cflags: -I${includedir} @DPDK_CFLAGS@
diff --git a/platform/linux-dpdk/m4/configure.m4 b/platform/linux-dpdk/m4/configure.m4
index 5172d9edd..9c5f02a35 100644
--- a/platform/linux-dpdk/m4/configure.m4
+++ b/platform/linux-dpdk/m4/configure.m4
@@ -1,4 +1,5 @@
ODP_IMPLEMENTATION_NAME="odp-dpdk"
+ODP_LIB_NAME="odp-linux"
ODP_VISIBILITY
ODP_ATOMIC
diff --git a/platform/linux-dpdk/m4/odp_libconfig.m4 b/platform/linux-dpdk/m4/odp_libconfig.m4
index 2ab6aa047..40d882d30 100644
--- a/platform/linux-dpdk/m4/odp_libconfig.m4
+++ b/platform/linux-dpdk/m4/odp_libconfig.m4
@@ -20,9 +20,16 @@ AC_SUBST(_ODP_CONFIG_VERSION_MINOR)
##########################################################################
default_config_path="${srcdir}/config/odp-linux-dpdk.conf"
+AC_CHECK_PROGS([REALPATH], [realpath])
+AS_IF([test -z "$REALPATH"], [AC_MSG_ERROR([Could not find 'realpath'])])
+
AC_ARG_WITH([config-file],
AS_HELP_STRING([--with-config-file=FILE path to the default configuration file],
[(this file must include all configuration options).]),
[default_config_path=$withval], [])
-ODP_LIBCONFIG([linux-dpdk], [$default_config_path])
+rel_default_config_path=`realpath --relative-to=$(pwd) ${default_config_path}`
+AC_SUBST(default_config_path)
+AC_SUBST(rel_default_config_path)
+
+ODP_LIBCONFIG([linux-dpdk], [$rel_default_config_path])
diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c
index ba3f47b8f..af7fce4af 100644
--- a/platform/linux-dpdk/odp_packet_dpdk.c
+++ b/platform/linux-dpdk/odp_packet_dpdk.c
@@ -1453,7 +1453,64 @@ static int link_status_pkt_dpdk(pktio_entry_t *pktio_entry)
struct rte_eth_link link;
rte_eth_link_get(pkt_priv(pktio_entry)->port_id, &link);
- return link.link_status;
+
+ if (link.link_status)
+ return ODP_PKTIO_LINK_STATUS_UP;
+ return ODP_PKTIO_LINK_STATUS_DOWN;
+}
+
+static int dpdk_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info)
+{
+ struct rte_eth_link link;
+ struct rte_eth_fc_conf fc_conf;
+ uint16_t port_id = pkt_priv(pktio_entry)->port_id;
+ int ret;
+
+ memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf));
+ memset(&link, 0, sizeof(struct rte_eth_link));
+
+ ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);
+ if (ret && ret != -ENOTSUP) {
+ ODP_ERR("rte_eth_dev_flow_ctrl_get() failed\n");
+ return -1;
+ }
+
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF;
+ if (fc_conf.mode == RTE_FC_RX_PAUSE) {
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_ON;
+ } else if (fc_conf.mode == RTE_FC_TX_PAUSE) {
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_ON;
+ } else if (fc_conf.mode == RTE_FC_FULL) {
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_ON;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_ON;
+ }
+
+ rte_eth_link_get_nowait(port_id, &link);
+ if (link.link_autoneg == ETH_LINK_AUTONEG)
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_ON;
+ else
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+
+ if (link.link_duplex == ETH_LINK_FULL_DUPLEX)
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ else
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_HALF;
+
+ if (link.link_speed == ETH_SPEED_NUM_NONE)
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+ else
+ info->speed = link.link_speed;
+
+ if (link.link_status == ETH_LINK_UP)
+ info->status = ODP_PKTIO_LINK_STATUS_UP;
+ else
+ info->status = ODP_PKTIO_LINK_STATUS_DOWN;
+
+ info->media = "unknown";
+
+ return 0;
}
static void stats_convert(struct rte_eth_stats *rte_stats,
@@ -1514,6 +1571,7 @@ const pktio_if_ops_t dpdk_pktio_ops = {
.mac_get = mac_get_pkt_dpdk,
.mac_set = mac_set_pkt_dpdk,
.link_status = link_status_pkt_dpdk,
+ .link_info = dpdk_link_info,
.capability = capability_pkt_dpdk,
.config = NULL,
.input_queues_config = dpdk_input_queues_config,
diff --git a/platform/linux-dpdk/odp_time.c b/platform/linux-dpdk/odp_time.c
index 4cabc9b3b..f1489cf3c 100644
--- a/platform/linux-dpdk/odp_time.c
+++ b/platform/linux-dpdk/odp_time.c
@@ -81,11 +81,6 @@ static inline uint64_t time_spec_res(void)
return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec;
}
-static inline uint64_t time_spec_to_ns(odp_time_t time)
-{
- return time.nsec;
-}
-
static inline odp_time_t time_spec_from_ns(uint64_t ns)
{
odp_time_t time;
@@ -104,23 +99,6 @@ static inline uint64_t time_hw_res(void)
return _odp_time_glob.hw_freq_hz;
}
-static inline uint64_t time_hw_to_ns(odp_time_t time)
-{
- uint64_t nsec;
- uint64_t freq_hz = _odp_time_glob.hw_freq_hz;
- uint64_t count = time.count;
- uint64_t sec = 0;
-
- if (count >= freq_hz) {
- sec = count / freq_hz;
- count = count - sec * freq_hz;
- }
-
- nsec = (ODP_TIME_SEC_IN_NS * count) / freq_hz;
-
- return (sec * ODP_TIME_SEC_IN_NS) + nsec;
-}
-
static inline odp_time_t time_hw_from_ns(uint64_t ns)
{
odp_time_t time;
@@ -153,14 +131,6 @@ static inline uint64_t time_res(void)
return time_spec_res();
}
-static inline uint64_t time_to_ns(odp_time_t time)
-{
- if (_odp_time_glob.use_hw)
- return time_hw_to_ns(time);
-
- return time_spec_to_ns(time);
-}
-
static inline odp_time_t time_from_ns(uint64_t ns)
{
if (_odp_time_glob.use_hw)
@@ -198,12 +168,7 @@ uint64_t odp_time_diff_ns(odp_time_t t2, odp_time_t t1)
time.u64 = t2.u64 - t1.u64;
- return time_to_ns(time);
-}
-
-uint64_t odp_time_to_ns(odp_time_t time)
-{
- return time_to_ns(time);
+ return odp_time_to_ns(time);
}
odp_time_t odp_time_local_from_ns(uint64_t ns)
diff --git a/platform/linux-dpdk/odp_timer.c b/platform/linux-dpdk/odp_timer.c
index 460830239..3205c7d98 100644
--- a/platform/linux-dpdk/odp_timer.c
+++ b/platform/linux-dpdk/odp_timer.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2018, Linaro Limited
- * Copyright (c) 2019, Nokia
+ * Copyright (c) 2019-2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -25,6 +25,9 @@
#include <inttypes.h>
#include <string.h>
+/* One divided by one nanosecond in Hz */
+#define GIGA_HZ 1000000000
+
/* Timer states */
#define NOT_TICKING 0
#define EXPIRED 1
@@ -52,6 +55,7 @@ ODP_STATIC_ASSERT(MAX_TIMERS < MAX_TIMER_RING_SIZE,
/* Actual resolution depends on application polling frequency. Promise
* 10 usec resolution. */
#define MAX_RES_NS 10000
+#define MAX_RES_HZ (GIGA_HZ / MAX_RES_NS)
/* Limit minimum supported timeout in timer (CPU) cycles. Timer setup, polling,
* timer management, timeout enqueue, etc takes about this many CPU cycles.
@@ -267,9 +271,11 @@ int odp_timer_capability(odp_timer_clk_src_t clk_src,
capa->max_timers = MAX_TIMERS;
capa->highest_res_ns = MAX_RES_NS;
capa->max_res.res_ns = MAX_RES_NS;
+ capa->max_res.res_hz = MAX_RES_HZ;
capa->max_res.min_tmo = min_tmo;
capa->max_res.max_tmo = MAX_TMO_NS;
capa->max_tmo.res_ns = MAX_RES_NS;
+ capa->max_tmo.res_hz = MAX_RES_HZ;
capa->max_tmo.min_tmo = min_tmo;
capa->max_tmo.max_tmo = MAX_TMO_NS;
@@ -291,12 +297,13 @@ int odp_timer_res_capability(odp_timer_clk_src_t clk_src,
return -1;
}
- if (res_capa->res_ns) {
+ if (res_capa->res_ns || res_capa->res_hz) {
res_capa->min_tmo = min_tmo;
res_capa->max_tmo = MAX_TMO_NS;
} else { /* max_tmo */
res_capa->min_tmo = min_tmo;
res_capa->res_ns = MAX_RES_NS;
+ res_capa->res_hz = MAX_RES_HZ;
}
return 0;
@@ -315,7 +322,18 @@ odp_timer_pool_t odp_timer_pool_create(const char *name,
return ODP_TIMER_POOL_INVALID;
}
- if (param->res_ns < MAX_RES_NS) {
+ if ((param->res_ns && param->res_hz) ||
+ (param->res_ns == 0 && param->res_hz == 0)) {
+ ODP_ERR("Invalid timeout resolution\n");
+ return ODP_TIMER_POOL_INVALID;
+ }
+
+ if (param->res_hz == 0 && param->res_ns < MAX_RES_NS) {
+ ODP_ERR("Too high resolution\n");
+ return ODP_TIMER_POOL_INVALID;
+ }
+
+ if (param->res_ns == 0 && param->res_hz > MAX_RES_HZ) {
ODP_ERR("Too high resolution\n");
return ODP_TIMER_POOL_INVALID;
}
@@ -326,7 +344,12 @@ odp_timer_pool_t odp_timer_pool_create(const char *name,
}
num_timers = param->num_timers;
- res_ns = param->res_ns;
+
+ if (param->res_ns)
+ res_ns = param->res_ns;
+ else
+ res_ns = GIGA_HZ / param->res_hz;
+
/* Scan timer pool twice during resolution interval */
if (res_ns > ODP_TIME_USEC_IN_NS)
@@ -376,6 +399,7 @@ odp_timer_pool_t odp_timer_pool_create(const char *name,
}
timer_pool->param = *param;
+ timer_pool->param.res_ns = res_ns;
ring_u32_init(&timer_pool->free_timer.ring_hdr);
timer_pool->free_timer.ring_mask = num_timers - 1;
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 2986e08e8..267d02a7d 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -2,6 +2,7 @@
#export CUSTOM_STR=https://github.com/OpenDataPlane/odp.git
include $(top_srcdir)/platform/Makefile.inc
+lib_LTLIBRARIES += $(LIB)/libodp-linux.la
AM_CPPFLAGS = $(ODP_INCLUDES)
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/include
@@ -17,7 +18,7 @@ AM_CFLAGS += $(DPDK_CFLAGS)
AM_CFLAGS += $(LIBCONFIG_CFLAGS)
DISTCLEANFILES = include/odp_libconfig_config.h
-include/odp_libconfig_config.h: $(top_srcdir)/config/odp-$(with_platform).conf $(top_builddir)/config.status
+include/odp_libconfig_config.h: $(top_builddir)/$(rel_default_config_path) $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
odpapiabiarchincludedir = $(archincludedir)/odp/api/abi
@@ -57,7 +58,9 @@ odpapiabiarchinclude_HEADERS += \
include-abi/odp/api/abi/cpumask.h \
include-abi/odp/api/abi/crypto.h \
include-abi/odp/api/abi/debug.h \
+ include-abi/odp/api/abi/errno.h \
include-abi/odp/api/abi/event.h \
+ include-abi/odp/api/abi/hash.h \
include-abi/odp/api/abi/init.h \
include-abi/odp/api/abi/ipsec.h \
include-abi/odp/api/abi/packet.h \
@@ -148,7 +151,7 @@ noinst_HEADERS = \
include/protocols/tcp.h \
include/protocols/thash.h \
include/protocols/udp.h
-nodist_noinst_HEADERS = \
+BUILT_SOURCES = \
include/odp_libconfig_config.h
__LIB__libodp_linux_la_SOURCES = \
diff --git a/platform/linux-generic/include-abi/odp/api/abi/errno.h b/platform/linux-generic/include-abi/odp/api/abi/errno.h
new file mode 100644
index 000000000..6215a0676
--- /dev/null
+++ b/platform/linux-generic/include-abi/odp/api/abi/errno.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP errno
+ */
+
+#ifndef ODP_API_ABI_ERRNO_H_
+#define ODP_API_ABI_ERRNO_H_
+
+#include <odp/api/abi-default/errno.h>
+
+#endif
diff --git a/platform/linux-generic/include-abi/odp/api/abi/hash.h b/platform/linux-generic/include-abi/odp/api/abi/hash.h
new file mode 100644
index 000000000..fc81dcc91
--- /dev/null
+++ b/platform/linux-generic/include-abi/odp/api/abi/hash.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2020, Marvell
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP hash
+ */
+
+#ifndef ODP_API_ABI_HASH_H_
+#define ODP_API_ABI_HASH_H_
+
+#include <odp/api/abi-default/hash.h>
+
+#endif
diff --git a/platform/linux-generic/include/odp/api/plat/time_inlines.h b/platform/linux-generic/include/odp/api/plat/time_inlines.h
index 527490e3d..0b05aa4f7 100644
--- a/platform/linux-generic/include/odp/api/plat/time_inlines.h
+++ b/platform/linux-generic/include/odp/api/plat/time_inlines.h
@@ -1,4 +1,5 @@
/* Copyright (c) 2018, Linaro Limited
+ * Copyright (c) 2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -16,6 +17,7 @@
/** @cond _ODP_HIDE_FROM_DOXYGEN_ */
#define _ODP_TIMESPEC_SIZE 16
+#define _ODP_TIME_GIGA_HZ 1000000000ULL
typedef struct _odp_time_global_t {
/* Storage space for struct timespec. Posix headers are not included
@@ -44,14 +46,42 @@ static inline odp_time_t _odp_time_cur(void)
return _odp_timespec_cur();
}
+static inline uint64_t _odp_time_hw_to_ns(odp_time_t time)
+{
+ uint64_t nsec;
+ uint64_t freq_hz = _odp_time_glob.hw_freq_hz;
+ uint64_t count = time.count;
+ uint64_t sec = 0;
+
+ if (count >= freq_hz) {
+ sec = count / freq_hz;
+ count = count - sec * freq_hz;
+ }
+
+ nsec = (_ODP_TIME_GIGA_HZ * count) / freq_hz;
+
+ return (sec * _ODP_TIME_GIGA_HZ) + nsec;
+}
+
+static inline uint64_t _odp_time_convert_to_ns(odp_time_t time)
+{
+ if (_odp_time_glob.use_hw)
+ return _odp_time_hw_to_ns(time);
+
+ return time.nsec;
+}
+
#ifndef _ODP_NO_INLINE
/* Inline functions by default */
#define _ODP_INLINE static inline
- #define odp_time_local __odp_time_local
- #define odp_time_global __odp_time_global
- #define odp_time_cmp __odp_time_cmp
- #define odp_time_diff __odp_time_diff
- #define odp_time_sum __odp_time_sum
+ #define odp_time_local __odp_time_local
+ #define odp_time_global __odp_time_global
+ #define odp_time_to_ns __odp_time_to_ns
+ #define odp_time_local_ns __odp_time_local_ns
+ #define odp_time_global_ns __odp_time_global_ns
+ #define odp_time_cmp __odp_time_cmp
+ #define odp_time_diff __odp_time_diff
+ #define odp_time_sum __odp_time_sum
#else
#define _ODP_INLINE
@@ -67,6 +97,21 @@ _ODP_INLINE odp_time_t odp_time_global(void)
return _odp_time_cur();
}
+_ODP_INLINE uint64_t odp_time_to_ns(odp_time_t time)
+{
+ return _odp_time_convert_to_ns(time);
+}
+
+_ODP_INLINE uint64_t odp_time_local_ns(void)
+{
+ return _odp_time_convert_to_ns(_odp_time_cur());
+}
+
+_ODP_INLINE uint64_t odp_time_global_ns(void)
+{
+ return _odp_time_convert_to_ns(_odp_time_cur());
+}
+
_ODP_INLINE int odp_time_cmp(odp_time_t t2, odp_time_t t1)
{
if (odp_likely(t2.u64 > t1.u64))
diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h
index 0e6a8a335..4219ff114 100644
--- a/platform/linux-generic/include/odp_packet_io_internal.h
+++ b/platform/linux-generic/include/odp_packet_io_internal.h
@@ -180,6 +180,7 @@ typedef struct pktio_if_ops {
int (*mac_get)(pktio_entry_t *pktio_entry, void *mac_addr);
int (*mac_set)(pktio_entry_t *pktio_entry, const void *mac_addr);
int (*link_status)(pktio_entry_t *pktio_entry);
+ int (*link_info)(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info);
int (*capability)(pktio_entry_t *pktio_entry,
odp_pktio_capability_t *capa);
int (*config)(pktio_entry_t *pktio_entry,
diff --git a/platform/linux-generic/include/odp_socket_common.h b/platform/linux-generic/include/odp_socket_common.h
index afce0f55d..0a9704076 100644
--- a/platform/linux-generic/include/odp_socket_common.h
+++ b/platform/linux-generic/include/odp_socket_common.h
@@ -12,6 +12,8 @@
extern "C" {
#endif
+#include <odp/api/packet_io.h>
+
#include <string.h>
#include <linux/if_ether.h>
@@ -57,6 +59,11 @@ int promisc_mode_get_fd(int fd, const char *name);
*/
int link_status_fd(int fd, const char *name);
+/**
+ * Read link information from a packet socket
+ */
+int link_info_fd(int fd, const char *name, odp_pktio_link_info_t *info);
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/libodp-linux.pc.in b/platform/linux-generic/libodp-linux.pc.in
index 5fe806435..df92e9345 100644
--- a/platform/linux-generic/libodp-linux.pc.in
+++ b/platform/linux-generic/libodp-linux.pc.in
@@ -3,10 +3,10 @@ exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
-Name: libodp-linux
+Name: lib@ODP_LIB_NAME@
Description: The ODP packet processing engine
Version: @PKGCONFIG_VERSION@
Requires.private: libconfig@DPDK_PKG@
-Libs: -L${libdir} -lodp-linux
+Libs: -L${libdir} -l@ODP_LIB_NAME@
Libs.private: @OPENSSL_STATIC_LIBS@ @DPDK_LIBS@ @PCAP_LIBS@ @PTHREAD_LIBS@ @TIMER_LIBS@ -lpthread @ATOMIC_LIBS@
Cflags: -I${includedir}
diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4
index bcd55b7c5..06bff0669 100644
--- a/platform/linux-generic/m4/configure.m4
+++ b/platform/linux-generic/m4/configure.m4
@@ -1,4 +1,5 @@
ODP_IMPLEMENTATION_NAME="odp-linux"
+ODP_LIB_NAME="odp-linux"
ODP_VISIBILITY
ODP_ATOMIC
diff --git a/platform/linux-generic/m4/odp_libconfig.m4 b/platform/linux-generic/m4/odp_libconfig.m4
index f042d65d7..d13fcf274 100644
--- a/platform/linux-generic/m4/odp_libconfig.m4
+++ b/platform/linux-generic/m4/odp_libconfig.m4
@@ -20,9 +20,16 @@ AC_SUBST(_ODP_CONFIG_VERSION_MINOR)
##########################################################################
default_config_path="${srcdir}/config/odp-$with_platform.conf"
+AC_CHECK_PROGS([REALPATH], [realpath])
+AS_IF([test -z "$REALPATH"], [AC_MSG_ERROR([Could not find 'realpath'])])
+
AC_ARG_WITH([config-file],
AS_HELP_STRING([--with-config-file=FILE path to the default configuration file],
[(this file must include all configuration options).]),
[default_config_path=$withval], [])
-ODP_LIBCONFIG([$with_platform], [$default_config_path])
+rel_default_config_path=`realpath --relative-to=$(pwd) ${default_config_path}`
+AC_SUBST(default_config_path)
+AC_SUBST(rel_default_config_path)
+
+ODP_LIBCONFIG([$with_platform], [$rel_default_config_path])
diff --git a/platform/linux-generic/odp_crypto_openssl.c b/platform/linux-generic/odp_crypto_openssl.c
index 98a13ce4a..2a8d4fb9b 100644
--- a/platform/linux-generic/odp_crypto_openssl.c
+++ b/platform/linux-generic/odp_crypto_openssl.c
@@ -285,6 +285,9 @@ odp_crypto_generic_session_t *alloc_session(void)
}
odp_spinlock_unlock(&global->lock);
+ if (!session)
+ return NULL;
+
session->idx = session - global->sessions;
for (i = 0; i < ODP_THREAD_COUNT_MAX; i++)
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c
index 1cd5745aa..d57c21a9e 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2013-2018, Linaro Limited
- * Copyright (c) 2019, Nokia
+ * Copyright (c) 2019-2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -1168,15 +1168,15 @@ int odp_pktio_mac_addr_set(odp_pktio_t hdl, const void *mac_addr, int addr_size)
return ret;
}
-int odp_pktio_link_status(odp_pktio_t hdl)
+odp_pktio_link_status_t odp_pktio_link_status(odp_pktio_t hdl)
{
pktio_entry_t *entry;
- int ret = -1;
+ int ret = ODP_PKTIO_LINK_STATUS_UNKNOWN;
entry = get_pktio_entry(hdl);
if (entry == NULL) {
ODP_DBG("pktio entry %d does not exist\n", hdl);
- return -1;
+ return ODP_PKTIO_LINK_STATUS_UNKNOWN;
}
lock_entry(entry);
@@ -1184,7 +1184,7 @@ int odp_pktio_link_status(odp_pktio_t hdl)
if (odp_unlikely(is_free(entry))) {
unlock_entry(entry);
ODP_DBG("already freed pktio\n");
- return -1;
+ return ODP_PKTIO_LINK_STATUS_UNKNOWN;
}
if (entry->s.ops->link_status)
@@ -1244,6 +1244,23 @@ int odp_pktio_info(odp_pktio_t hdl, odp_pktio_info_t *info)
return 0;
}
+int odp_pktio_link_info(odp_pktio_t hdl, odp_pktio_link_info_t *info)
+{
+ pktio_entry_t *entry;
+
+ entry = get_pktio_entry(hdl);
+
+ if (entry == NULL) {
+ ODP_DBG("pktio entry %d does not exist\n", hdl);
+ return -1;
+ }
+
+ if (entry->s.ops->link_info)
+ return entry->s.ops->link_info(entry, info);
+
+ return -1;
+}
+
uint64_t odp_pktin_ts_res(odp_pktio_t hdl)
{
pktio_entry_t *entry;
diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
index d31f210e7..913e71f5a 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -666,9 +666,9 @@ static odp_pool_t pool_create(const char *name, const odp_pool_param_t *params,
/* Allocate extra memory for skipping packet buffers which cross huge
* page boundaries. */
if (params->type == ODP_POOL_PACKET) {
- num_extra = (((uint64_t)(num * block_size) +
+ num_extra = ((((uint64_t)num * block_size) +
FIRST_HP_SIZE - 1) / FIRST_HP_SIZE);
- num_extra += (((uint64_t)(num_extra * block_size) +
+ num_extra += ((((uint64_t)num_extra * block_size) +
FIRST_HP_SIZE - 1) / FIRST_HP_SIZE);
}
diff --git a/platform/linux-generic/odp_time.c b/platform/linux-generic/odp_time.c
index b033a733c..aea823eb6 100644
--- a/platform/linux-generic/odp_time.c
+++ b/platform/linux-generic/odp_time.c
@@ -78,11 +78,6 @@ static inline uint64_t time_spec_res(void)
return ODP_TIME_SEC_IN_NS / (uint64_t)tres.tv_nsec;
}
-static inline uint64_t time_spec_to_ns(odp_time_t time)
-{
- return time.nsec;
-}
-
static inline odp_time_t time_spec_from_ns(uint64_t ns)
{
odp_time_t time;
@@ -101,23 +96,6 @@ static inline uint64_t time_hw_res(void)
return _odp_time_glob.hw_freq_hz;
}
-static inline uint64_t time_hw_to_ns(odp_time_t time)
-{
- uint64_t nsec;
- uint64_t freq_hz = _odp_time_glob.hw_freq_hz;
- uint64_t count = time.count;
- uint64_t sec = 0;
-
- if (count >= freq_hz) {
- sec = count / freq_hz;
- count = count - sec * freq_hz;
- }
-
- nsec = (ODP_TIME_SEC_IN_NS * count) / freq_hz;
-
- return (sec * ODP_TIME_SEC_IN_NS) + nsec;
-}
-
static inline odp_time_t time_hw_from_ns(uint64_t ns)
{
odp_time_t time;
@@ -150,14 +128,6 @@ static inline uint64_t time_res(void)
return time_spec_res();
}
-static inline uint64_t time_to_ns(odp_time_t time)
-{
- if (_odp_time_glob.use_hw)
- return time_hw_to_ns(time);
-
- return time_spec_to_ns(time);
-}
-
static inline odp_time_t time_from_ns(uint64_t ns)
{
if (_odp_time_glob.use_hw)
@@ -181,12 +151,7 @@ uint64_t odp_time_diff_ns(odp_time_t t2, odp_time_t t1)
time.u64 = t2.u64 - t1.u64;
- return time_to_ns(time);
-}
-
-uint64_t odp_time_to_ns(odp_time_t time)
-{
- return time_to_ns(time);
+ return odp_time_to_ns(time);
}
odp_time_t odp_time_local_from_ns(uint64_t ns)
diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c
index 5fa020118..e7c0d4e51 100644
--- a/platform/linux-generic/odp_timer.c
+++ b/platform/linux-generic/odp_timer.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2013-2018, Linaro Limited
- * Copyright (c) 2019, Nokia
+ * Copyright (c) 2019-2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -54,6 +54,9 @@
/* Inlined API functions */
#include <odp/api/plat/event_inlines.h>
+/* One divided by one nanosecond in Hz */
+#define GIGA_HZ 1000000000
+
#define TMO_UNUSED ((uint64_t)0xFFFFFFFFFFFFFFFF)
/* TMO_INACTIVE is or-ed with the expiration tick to indicate an expired timer.
* The original expiration tick (63 bits) is still available so it can be used
@@ -148,6 +151,7 @@ typedef struct timer_global_t {
odp_shm_t shm;
/* Max timer resolution in nanoseconds */
uint64_t highest_res_ns;
+ uint64_t highest_res_hz;
uint64_t poll_interval_nsec;
int num_timer_pools;
uint8_t timer_pool_used[MAX_TIMER_POOLS];
@@ -324,7 +328,10 @@ static odp_timer_pool_t timer_pool_new(const char *name,
memset(tp, 0, tp_size);
- res_ns = param->res_ns;
+ if (param->res_ns)
+ res_ns = param->res_ns;
+ else
+ res_ns = GIGA_HZ / param->res_hz;
/* Scan timer pool twice during resolution interval */
if (res_ns > ODP_TIME_USEC_IN_NS)
@@ -344,6 +351,7 @@ static odp_timer_pool_t timer_pool_new(const char *name,
}
tp->shm = shm;
tp->param = *param;
+ tp->param.res_ns = res_ns;
tp->min_rel_tck = odp_timer_ns_to_tick(timer_pool_to_hdl(tp),
param->min_tmo);
tp->max_rel_tck = odp_timer_ns_to_tick(timer_pool_to_hdl(tp),
@@ -1239,9 +1247,11 @@ int odp_timer_capability(odp_timer_clk_src_t clk_src,
capa->max_timers = 0;
capa->highest_res_ns = timer_global->highest_res_ns;
capa->max_res.res_ns = timer_global->highest_res_ns;
+ capa->max_res.res_hz = timer_global->highest_res_hz;
capa->max_res.min_tmo = 0;
capa->max_res.max_tmo = MAX_TMO_NSEC;
capa->max_tmo.res_ns = timer_global->highest_res_ns;
+ capa->max_tmo.res_hz = timer_global->highest_res_hz;
capa->max_tmo.min_tmo = 0;
capa->max_tmo.max_tmo = MAX_TMO_NSEC;
@@ -1261,12 +1271,13 @@ int odp_timer_res_capability(odp_timer_clk_src_t clk_src,
return -1;
}
- if (res_capa->res_ns) {
+ if (res_capa->res_ns || res_capa->res_hz) {
res_capa->min_tmo = 0;
res_capa->max_tmo = MAX_TMO_NSEC;
} else { /* max_tmo */
res_capa->min_tmo = 0;
res_capa->res_ns = timer_global->highest_res_ns;
+ res_capa->res_hz = timer_global->highest_res_hz;
}
return 0;
@@ -1280,7 +1291,20 @@ odp_timer_pool_t odp_timer_pool_create(const char *name,
return ODP_TIMER_POOL_INVALID;
}
- if (param->res_ns < timer_global->highest_res_ns) {
+ if ((param->res_ns && param->res_hz) ||
+ (param->res_ns == 0 && param->res_hz == 0)) {
+ __odp_errno = EINVAL;
+ return ODP_TIMER_POOL_INVALID;
+ }
+
+ if (param->res_hz == 0 &&
+ param->res_ns < timer_global->highest_res_ns) {
+ __odp_errno = EINVAL;
+ return ODP_TIMER_POOL_INVALID;
+ }
+
+ if (param->res_ns == 0 &&
+ param->res_hz > timer_global->highest_res_hz) {
__odp_errno = EINVAL;
return ODP_TIMER_POOL_INVALID;
}
@@ -1561,6 +1585,9 @@ int _odp_timer_init_global(const odp_init_t *params)
block_sigalarm();
}
+ /* timer_res_init() may update highest_res_ns */
+ timer_global->highest_res_hz = GIGA_HZ / timer_global->highest_res_ns;
+
return 0;
error:
diff --git a/platform/linux-generic/odp_traffic_mngr.c b/platform/linux-generic/odp_traffic_mngr.c
index de9cbfb73..1b6ca2ec2 100644
--- a/platform/linux-generic/odp_traffic_mngr.c
+++ b/platform/linux-generic/odp_traffic_mngr.c
@@ -4575,7 +4575,8 @@ static int tm_query_info_copy(tm_queue_info_t *queue_info,
uint32_t query_flags,
odp_tm_query_info_t *info)
{
- tm_queue_thresholds_t *threshold_params;
+ if ((query_flags & ODP_TM_QUERY_THRESHOLDS) && !queue_info->threshold_params)
+ return -1;
memset(info, 0, sizeof(odp_tm_query_info_t));
info->total_pkt_cnt =
@@ -4587,9 +4588,7 @@ static int tm_query_info_copy(tm_queue_info_t *queue_info,
info->approx_byte_cnt = 0;
if (query_flags & ODP_TM_QUERY_THRESHOLDS) {
- threshold_params = queue_info->threshold_params;
- if (!threshold_params)
- return -1;
+ tm_queue_thresholds_t *threshold_params = queue_info->threshold_params;
info->max_pkt_cnt = threshold_params->max_pkts;
info->max_byte_cnt = threshold_params->max_bytes;
@@ -4722,6 +4721,41 @@ void odp_tm_stats_print(odp_tm_t odp_tm)
}
}
+uint64_t odp_tm_to_u64(odp_tm_t hdl)
+{
+ return _odp_pri(hdl);
+}
+
+uint64_t odp_tm_queue_to_u64(odp_tm_queue_t hdl)
+{
+ return _odp_pri(hdl);
+}
+
+uint64_t odp_tm_node_to_u64(odp_tm_node_t hdl)
+{
+ return _odp_pri(hdl);
+}
+
+uint64_t odp_tm_shaper_to_u64(odp_tm_shaper_t hdl)
+{
+ return _odp_pri(hdl);
+}
+
+uint64_t odp_tm_sched_to_u64(odp_tm_sched_t hdl)
+{
+ return _odp_pri(hdl);
+}
+
+uint64_t odp_tm_threshold_to_u64(odp_tm_threshold_t hdl)
+{
+ return _odp_pri(hdl);
+}
+
+uint64_t odp_tm_wred_to_u64(odp_tm_wred_t hdl)
+{
+ return _odp_pri(hdl);
+}
+
int _odp_tm_init_global(void)
{
odp_shm_t shm;
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c
index 18f583a65..7aee73dc1 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2016-2018, Linaro Limited
- * Copyright (c) 2019, Nokia
+ * Copyright (c) 2019-2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -2056,8 +2056,63 @@ static int dpdk_link_status(pktio_entry_t *pktio_entry)
memset(&link, 0, sizeof(struct rte_eth_link));
rte_eth_link_get_nowait(pkt_priv(pktio_entry)->port_id, &link);
+ if (link.link_status)
+ return ODP_PKTIO_LINK_STATUS_UP;
+ return ODP_PKTIO_LINK_STATUS_DOWN;
+}
+
+static int dpdk_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info)
+{
+ struct rte_eth_link link;
+ struct rte_eth_fc_conf fc_conf;
+ uint16_t port_id = pkt_priv(pktio_entry)->port_id;
+ int ret;
- return link.link_status;
+ memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf));
+ memset(&link, 0, sizeof(struct rte_eth_link));
+
+ ret = rte_eth_dev_flow_ctrl_get(port_id, &fc_conf);
+ if (ret && ret != -ENOTSUP) {
+ ODP_ERR("rte_eth_dev_flow_ctrl_get() failed\n");
+ return -1;
+ }
+
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF;
+ if (fc_conf.mode == RTE_FC_RX_PAUSE) {
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_ON;
+ } else if (fc_conf.mode == RTE_FC_TX_PAUSE) {
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_ON;
+ } else if (fc_conf.mode == RTE_FC_FULL) {
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_ON;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_ON;
+ }
+
+ rte_eth_link_get_nowait(port_id, &link);
+ if (link.link_autoneg == ETH_LINK_AUTONEG)
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_ON;
+ else
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+
+ if (link.link_duplex == ETH_LINK_FULL_DUPLEX)
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ else
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_HALF;
+
+ if (link.link_speed == ETH_SPEED_NUM_NONE)
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+ else
+ info->speed = link.link_speed;
+
+ if (link.link_status == ETH_LINK_UP)
+ info->status = ODP_PKTIO_LINK_STATUS_UP;
+ else
+ info->status = ODP_PKTIO_LINK_STATUS_DOWN;
+
+ info->media = "unknown";
+
+ return 0;
}
static void stats_convert(const struct rte_eth_stats *rte_stats,
@@ -2106,6 +2161,7 @@ const pktio_if_ops_t dpdk_pktio_ops = {
.recv = dpdk_recv,
.send = dpdk_send,
.link_status = dpdk_link_status,
+ .link_info = dpdk_link_info,
.mtu_get = dpdk_frame_maxlen,
.promisc_mode_set = dpdk_promisc_mode_set,
.promisc_mode_get = dpdk_promisc_mode_get,
diff --git a/platform/linux-generic/pktio/ipc.c b/platform/linux-generic/pktio/ipc.c
index d63a77b74..34b32ae2c 100644
--- a/platform/linux-generic/pktio/ipc.c
+++ b/platform/linux-generic/pktio/ipc.c
@@ -900,6 +900,35 @@ static int ipc_stop(pktio_entry_t *pktio_entry)
return 0;
}
+static int ipc_link_status(pktio_entry_t *pktio_entry)
+{
+ pkt_ipc_t *pktio_ipc = pkt_priv(pktio_entry);
+
+ if (odp_atomic_load_u32(&pktio_ipc->ready))
+ return ODP_PKTIO_LINK_STATUS_UP;
+ return ODP_PKTIO_LINK_STATUS_DOWN;
+}
+
+static int ipc_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info)
+{
+ pkt_ipc_t *pktio_ipc = pkt_priv(pktio_entry);
+
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ info->media = "virtual";
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+ if (odp_atomic_load_u32(&pktio_ipc->ready))
+ info->status = ODP_PKTIO_LINK_STATUS_UP;
+ else
+ info->status = ODP_PKTIO_LINK_STATUS_DOWN;
+
+ return 0;
+}
+
static int ipc_close(pktio_entry_t *pktio_entry)
{
pkt_ipc_t *pktio_ipc = pkt_priv(pktio_entry);
@@ -947,6 +976,8 @@ const pktio_if_ops_t ipc_pktio_ops = {
.send = ipc_pktio_send,
.start = ipc_start,
.stop = ipc_stop,
+ .link_status = ipc_link_status,
+ .link_info = ipc_link_info,
.mtu_get = ipc_mtu_get,
.promisc_mode_set = NULL,
.promisc_mode_get = NULL,
diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c
index e6d004d43..3de096139 100644
--- a/platform/linux-generic/pktio/loop.c
+++ b/platform/linux-generic/pktio/loop.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2013-2018, Linaro Limited
- * Copyright (c) 2013, Nokia Solutions and Networks
+ * Copyright (c) 2013-2020, Nokia Solutions and Networks
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -367,7 +367,22 @@ static int loopback_mac_addr_get(pktio_entry_t *pktio_entry ODP_UNUSED,
static int loopback_link_status(pktio_entry_t *pktio_entry ODP_UNUSED)
{
/* loopback interfaces are always up */
- return 1;
+ return ODP_PKTIO_LINK_STATUS_UP;
+}
+
+static int loopback_link_info(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_link_info_t *info)
+{
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ info->media = "virtual";
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+ info->status = ODP_PKTIO_LINK_STATUS_UP;
+
+ return 0;
}
static int loopback_init_capability(pktio_entry_t *pktio_entry)
@@ -467,6 +482,7 @@ const pktio_if_ops_t loopback_pktio_ops = {
.mac_get = loopback_mac_addr_get,
.mac_set = NULL,
.link_status = loopback_link_status,
+ .link_info = loopback_link_info,
.capability = loopback_capability,
.pktin_ts_res = NULL,
.pktin_ts_from_ns = NULL,
diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c
index e1a5da773..0f608c6f6 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2015-2018, Linaro Limited
- * Copyright (c) 2019, Nokia
+ * Copyright (c) 2019-2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -355,12 +355,33 @@ static int netmap_close(pktio_entry_t *pktio_entry)
static int netmap_link_status(pktio_entry_t *pktio_entry)
{
if (pkt_priv(pktio_entry)->is_virtual)
- return 1;
+ return ODP_PKTIO_LINK_STATUS_UP;
return link_status_fd(pkt_priv(pktio_entry)->sockfd,
pkt_priv(pktio_entry)->if_name);
}
+static int netmap_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info)
+{
+ pkt_netmap_t *pkt_nm = pkt_priv(pktio_entry);
+
+ if (pkt_nm->is_virtual) {
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ info->media = "virtual";
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+ info->status = ODP_PKTIO_LINK_STATUS_UP;
+
+ return 0;
+ }
+
+ return link_info_fd(pkt_nm->sockfd, pkt_nm->if_name, info);
+}
+
/**
* Wait for netmap link to come up
*
@@ -1225,6 +1246,7 @@ const pktio_if_ops_t netmap_pktio_ops = {
.start = netmap_start,
.stop = netmap_stop,
.link_status = netmap_link_status,
+ .link_info = netmap_link_info,
.stats = netmap_stats,
.stats_reset = netmap_stats_reset,
.mtu_get = netmap_mtu_get,
diff --git a/platform/linux-generic/pktio/null.c b/platform/linux-generic/pktio/null.c
index bb7f85c9b..d739ccafe 100644
--- a/platform/linux-generic/pktio/null.c
+++ b/platform/linux-generic/pktio/null.c
@@ -154,6 +154,26 @@ static int null_init_global(void)
return 0;
}
+static int null_link_status(pktio_entry_t *pktio_entry ODP_UNUSED)
+{
+ return ODP_PKTIO_LINK_STATUS_UP;
+}
+
+static int null_link_info(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_link_info_t *info)
+{
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ info->media = "virtual";
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+ info->status = ODP_PKTIO_LINK_STATUS_UP;
+
+ return 0;
+}
+
const pktio_if_ops_t null_pktio_ops = {
.name = "null",
.print = NULL,
@@ -179,4 +199,6 @@ const pktio_if_ops_t null_pktio_ops = {
.config = NULL,
.input_queues_config = null_inqueues_config,
.output_queues_config = null_outqueues_config,
+ .link_status = null_link_status,
+ .link_info = null_link_info
};
diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c
index 6ef998717..262528abc 100644
--- a/platform/linux-generic/pktio/pcap.c
+++ b/platform/linux-generic/pktio/pcap.c
@@ -444,6 +444,26 @@ static int pcapif_init_global(void)
return 0;
}
+static int pcapif_link_status(pktio_entry_t *pktio_entry ODP_UNUSED)
+{
+ return ODP_PKTIO_LINK_STATUS_UP;
+}
+
+static int pcapif_link_info(pktio_entry_t *pktio_entry ODP_UNUSED, odp_pktio_link_info_t *info)
+{
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ info->media = "virtual";
+ info->pause_rx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = ODP_PKTIO_LINK_PAUSE_OFF;
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+ info->status = ODP_PKTIO_LINK_STATUS_UP;
+
+ return 0;
+}
+
const pktio_if_ops_t pcap_pktio_ops = {
.name = "pcap",
.print = NULL,
@@ -466,4 +486,6 @@ const pktio_if_ops_t pcap_pktio_ops = {
.config = NULL,
.input_queues_config = NULL,
.output_queues_config = NULL,
+ .link_status = pcapif_link_status,
+ .link_info = pcapif_link_info
};
diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c
index d148edf03..4776b83f9 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -493,6 +493,11 @@ static int sock_link_status(pktio_entry_t *pktio_entry)
pktio_entry->s.name);
}
+static int sock_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info)
+{
+ return link_info_fd(pkt_priv(pktio_entry)->sockfd, pktio_entry->s.name, info);
+}
+
static int sock_capability(pktio_entry_t *pktio_entry ODP_UNUSED,
odp_pktio_capability_t *capa)
{
@@ -566,6 +571,7 @@ const pktio_if_ops_t sock_mmsg_pktio_ops = {
.mac_get = sock_mac_addr_get,
.mac_set = NULL,
.link_status = sock_link_status,
+ .link_info = sock_link_info,
.capability = sock_capability,
.pktin_ts_res = NULL,
.pktin_ts_from_ns = NULL,
diff --git a/platform/linux-generic/pktio/socket_common.c b/platform/linux-generic/pktio/socket_common.c
index 4fbf2f041..2eb3b4001 100644
--- a/platform/linux-generic/pktio/socket_common.c
+++ b/platform/linux-generic/pktio/socket_common.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2018, Linaro Limited
- * Copyright (c) 2019, Nokia
+ * Copyright (c) 2019-2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -14,7 +14,9 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
+#include <linux/ethtool.h>
#include <linux/if_packet.h>
+#include <linux/sockios.h>
#include <errno.h>
#include <odp_debug_internal.h>
#include <odp_errno_define.h>
@@ -155,8 +157,141 @@ int link_status_fd(int fd, const char *name)
__odp_errno = errno;
ODP_DBG("ioctl(SIOCGIFFLAGS): %s: \"%s\".\n", strerror(errno),
ifr.ifr_name);
+ return ODP_PKTIO_LINK_STATUS_UNKNOWN;
+ }
+
+ if (ifr.ifr_flags & IFF_RUNNING)
+ return ODP_PKTIO_LINK_STATUS_UP;
+ return ODP_PKTIO_LINK_STATUS_DOWN;
+}
+
+int link_info_fd(int fd, const char *name, odp_pktio_link_info_t *info)
+{
+ struct ethtool_link_settings hcmd = {.cmd = ETHTOOL_GLINKSETTINGS};
+ struct ethtool_link_settings *ecmd;
+ struct ethtool_pauseparam pcmd = {.cmd = ETHTOOL_GPAUSEPARAM};
+ struct ifreq ifr;
+ int status;
+
+ status = link_status_fd(fd, name);
+ if (status < 0)
+ return -1;
+
+ snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", name);
+
+ /* Link pause status */
+ ifr.ifr_data = (void *)&pcmd;
+ if (ioctl(fd, SIOCETHTOOL, &ifr) && errno != EOPNOTSUPP) {
+ __odp_errno = errno;
+ ODP_ERR("ioctl(SIOCETHTOOL): %s: \"%s\".\n", strerror(errno),
+ ifr.ifr_name);
+ return -1;
+ }
+
+ /* Try to perform handshake and fall back to old API if failed */
+ ifr.ifr_data = (void *)&hcmd;
+ if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
+ struct ethtool_cmd ecmd_old = {.cmd = ETHTOOL_GSET};
+
+ ifr.ifr_data = (void *)&ecmd_old;
+ if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
+ __odp_errno = errno;
+ ODP_ERR("ioctl(SIOCETHTOOL): %s: \"%s\".\n", strerror(errno), ifr.ifr_name);
+ return -1;
+ }
+
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+ info->speed = ethtool_cmd_speed(&ecmd_old);
+ if (info->speed == (uint32_t)SPEED_UNKNOWN)
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+
+ if (ecmd_old.autoneg == AUTONEG_ENABLE)
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_ON;
+ else if (ecmd_old.autoneg == AUTONEG_DISABLE)
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+ else
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_UNKNOWN;
+
+ if (ecmd_old.duplex == DUPLEX_HALF)
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_HALF;
+ else if (ecmd_old.duplex == DUPLEX_FULL)
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ else
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_UNKNOWN;
+
+ info->pause_rx = pcmd.rx_pause ? ODP_PKTIO_LINK_PAUSE_ON : ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = pcmd.tx_pause ? ODP_PKTIO_LINK_PAUSE_ON : ODP_PKTIO_LINK_PAUSE_OFF;
+
+ if (ecmd_old.port == PORT_TP)
+ info->media = "copper";
+ else if (ecmd_old.port == PORT_FIBRE)
+ info->media = "fiber";
+ else if (ecmd_old.port == PORT_OTHER)
+ info->media = "other";
+ else
+ info->media = "unknown";
+
+ info->status = status;
+
+ return 0;
+ }
+
+ if (hcmd.link_mode_masks_nwords >= 0 || hcmd.cmd != ETHTOOL_GLINKSETTINGS) {
+ ODP_ERR("ETHTOOL_GLINKSETTINGS handshake failed\n");
+ return -1;
+ }
+ /* Absolute value indicates kernel recommended 'link_mode_masks_nwords' value. */
+ hcmd.link_mode_masks_nwords = -hcmd.link_mode_masks_nwords;
+
+ /* Reserve space for the three bitmasks (map_supported, map_advertising, map_lp_advertising)
+ * at the end of struct ethtool_link_settings. 'link_mode_masks_nwords' defines the bitmask
+ * length in 32-bit words. */
+ uint8_t ODP_ALIGNED_CACHE data[offsetof(struct ethtool_link_settings, link_mode_masks) +
+ (3 * sizeof(uint32_t) * hcmd.link_mode_masks_nwords)];
+
+ ecmd = (void *)data;
+ *ecmd = hcmd;
+ ifr.ifr_data = (void *)ecmd;
+ if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
+ __odp_errno = errno;
+ ODP_ERR("ioctl(SIOCETHTOOL): %s: \"%s\".\n", strerror(errno),
+ ifr.ifr_name);
return -1;
}
- return !!(ifr.ifr_flags & IFF_RUNNING);
+ memset(info, 0, sizeof(odp_pktio_link_info_t));
+ if (ecmd->speed == (uint32_t)SPEED_UNKNOWN)
+ info->speed = ODP_PKTIO_LINK_SPEED_UNKNOWN;
+ else
+ info->speed = ecmd->speed;
+
+ if (ecmd->autoneg == AUTONEG_ENABLE)
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_ON;
+ else if (ecmd->autoneg == AUTONEG_DISABLE)
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_OFF;
+ else
+ info->autoneg = ODP_PKTIO_LINK_AUTONEG_UNKNOWN;
+
+ if (ecmd->duplex == DUPLEX_HALF)
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_HALF;
+ else if (ecmd->duplex == DUPLEX_FULL)
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_FULL;
+ else
+ info->duplex = ODP_PKTIO_LINK_DUPLEX_UNKNOWN;
+
+ info->pause_rx = pcmd.rx_pause ? ODP_PKTIO_LINK_PAUSE_ON : ODP_PKTIO_LINK_PAUSE_OFF;
+ info->pause_tx = pcmd.tx_pause ? ODP_PKTIO_LINK_PAUSE_ON : ODP_PKTIO_LINK_PAUSE_OFF;
+
+ if (ecmd->port == PORT_TP)
+ info->media = "copper";
+ else if (ecmd->port == PORT_FIBRE)
+ info->media = "fiber";
+ else if (ecmd->port == PORT_OTHER)
+ info->media = "other";
+ else
+ info->media = "unknown";
+
+ info->status = status;
+
+ return 0;
}
diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c
index bf1cbad81..d0d37636d 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -784,6 +784,11 @@ static int sock_mmap_link_status(pktio_entry_t *pktio_entry)
pktio_entry->s.name);
}
+static int sock_mmap_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info)
+{
+ return link_info_fd(pkt_priv(pktio_entry)->sockfd, pktio_entry->s.name, info);
+}
+
static int sock_mmap_capability(pktio_entry_t *pktio_entry ODP_UNUSED,
odp_pktio_capability_t *capa)
{
@@ -860,6 +865,7 @@ const pktio_if_ops_t sock_mmap_pktio_ops = {
.mac_get = sock_mmap_mac_addr_get,
.mac_set = NULL,
.link_status = sock_mmap_link_status,
+ .link_info = sock_mmap_link_info,
.capability = sock_mmap_capability,
.pktin_ts_res = NULL,
.pktin_ts_from_ns = NULL,
diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c
index db5c701b2..13a9feaf8 100644
--- a/platform/linux-generic/pktio/tap.c
+++ b/platform/linux-generic/pktio/tap.c
@@ -467,6 +467,11 @@ static int tap_link_status(pktio_entry_t *pktio_entry)
pktio_entry->s.name + 4);
}
+static int tap_link_info(pktio_entry_t *pktio_entry, odp_pktio_link_info_t *info)
+{
+ return link_info_fd(pkt_priv(pktio_entry)->skfd, pktio_entry->s.name + 4, info);
+}
+
static int tap_capability(pktio_entry_t *pktio_entry ODP_UNUSED,
odp_pktio_capability_t *capa)
{
@@ -501,6 +506,7 @@ const pktio_if_ops_t tap_pktio_ops = {
.mac_get = tap_mac_addr_get,
.mac_set = tap_mac_addr_set,
.link_status = tap_link_status,
+ .link_info = tap_link_info,
.capability = tap_capability,
.pktin_ts_res = NULL,
.pktin_ts_from_ns = NULL,
diff --git a/platform/linux-generic/test/pktio_ipc/ipc_common.c b/platform/linux-generic/test/pktio_ipc/ipc_common.c
index b064177bc..655cd80d5 100644
--- a/platform/linux-generic/test/pktio_ipc/ipc_common.c
+++ b/platform/linux-generic/test/pktio_ipc/ipc_common.c
@@ -22,6 +22,7 @@ int ipc_odp_packet_send_or_free(odp_pktio_t pktio,
odp_pktout_queue_t pktout;
int i;
+ memset(&pktout, 0, sizeof(pktout));
start_time = odp_time_local();
wait = odp_time_local_from_ns(ODP_TIME_SEC_IN_NS);
end_time = odp_time_sum(start_time, wait);
diff --git a/platform/linux-generic/test/pktio_ipc/pktio_ipc2.c b/platform/linux-generic/test/pktio_ipc/pktio_ipc2.c
index 0d64e94ba..9d4f91341 100644
--- a/platform/linux-generic/test/pktio_ipc/pktio_ipc2.c
+++ b/platform/linux-generic/test/pktio_ipc/pktio_ipc2.c
@@ -73,6 +73,7 @@ static int ipc_second_process(int master_pid)
return -1;
}
+ memset(&pktin, 0, sizeof(pktin)); /* not needed but makes GCC happy */
if (odp_pktin_queue(ipc_pktio, &pktin, 1) != 1) {
odp_pool_destroy(pool);
ODPH_ERR("no input queue\n");
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index a0d189722..a8976b1e5 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1,9 +1,11 @@
#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0
+#
# (c) 2001, Dave Jones. (the file handling bit)
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
-# Licensed under the terms of the GNU GPL License version 2
+# (c) 2010-2018 Joe Perches <joe@perches.com>
use strict;
use warnings;
@@ -11,6 +13,7 @@ use POSIX;
use File::Basename;
use Cwd 'abs_path';
use Term::ANSIColor qw(:constants);
+use Encode qw(decode encode);
my $P = $0;
my $D = dirname(abs_path($P));
@@ -48,7 +51,7 @@ my %ignore_type = ();
my @ignore = ();
my $help = 0;
my $configuration_file = ".checkpatch.conf";
-my $max_line_length = 80;
+my $max_line_length = 100;
my $ignore_perl_version = 0;
my $minimum_perl_version = 5.10.0;
my $min_conf_desc_length = 4;
@@ -58,7 +61,10 @@ my $codespellfile = "/usr/share/codespell/dictionary.txt";
my $conststructsfile = "$D/const_structs.checkpatch";
my $typedefsfile = "";
my $color = "auto";
-my $allow_c99_comments = 1;
+my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
+# git output parsing needs US English output, so first set backtick child process LANGUAGE
+my $git_command ='export LANGUAGE=en_US.UTF-8; git';
+my $tabsize = 8;
sub help {
my ($exitcode) = @_;
@@ -91,8 +97,11 @@ Options:
--types TYPE(,TYPE2...) show only these comma separated message types
--ignore TYPE(,TYPE2...) ignore various comma separated message types
--show-types show the specific message type in the output
- --max-line-length=n set the maximum line length, if exceeded, warn
+ --max-line-length=n set the maximum line length, (default $max_line_length)
+ if exceeded, warn on patches
+ requires --strict for use with --file
--min-conf-desc-length=n set the min description length, if shorter, warn
+ --tab-size=n set the number of spaces for tab (default $tabsize)
--root=PATH PATH to the kernel tree root
--no-summary suppress the per-file summary
--mailback only produce a report in case of warnings/errors
@@ -210,6 +219,7 @@ GetOptions(
'list-types!' => \$list_types,
'max-line-length=i' => \$max_line_length,
'min-conf-desc-length=i' => \$min_conf_desc_length,
+ 'tab-size=i' => \$tabsize,
'root=s' => \$root,
'summary!' => \$summary,
'mailback!' => \$mailback,
@@ -236,13 +246,15 @@ list_types(0) if ($list_types);
$fix = 1 if ($fix_inplace);
$check_orig = $check;
+die "$P: --git cannot be used with --file or --fix\n" if ($git && ($file || $fix));
+
my $exit = 0;
+my $perl_version_ok = 1;
if ($^V && $^V lt $minimum_perl_version) {
+ $perl_version_ok = 0;
printf "$P: requires at least perl version %vd\n", $minimum_perl_version;
- if (!$ignore_perl_version) {
- exit(1);
- }
+ exit(1) if (!$ignore_perl_version);
}
#if no filenames are given, push '-' to read patch from stdin
@@ -259,9 +271,12 @@ if ($color =~ /^[01]$/) {
} elsif ($color =~ /^auto$/i) {
$color = (-t STDOUT);
} else {
- die "Invalid color mode: $color\n";
+ die "$P: Invalid color mode: $color\n";
}
+# skip TAB size 1 to avoid additional checks on $tabsize - 1
+die "$P: Invalid TAB size: $tabsize\n" if ($tabsize < 2);
+
sub hash_save_array_words {
my ($hashRef, $arrayRef) = @_;
@@ -344,9 +359,10 @@ our $Sparse = qr{
__force|
__iomem|
__must_check|
- __init_refok|
__kprobes|
__ref|
+ __refconst|
+ __refdata|
__rcu|
__private
}x;
@@ -376,6 +392,7 @@ our $Attribute = qr{
__noclone|
__deprecated|
__read_mostly|
+ __ro_after_init|
__kprobes|
$InitAttribute|
____cacheline_aligned|
@@ -458,15 +475,22 @@ our $logFunctions = qr{(?x:
WARN(?:_RATELIMIT|_ONCE|)|
panic|
MODULE_[A-Z_]+|
- seq_vprintf|seq_printf|seq_puts|
- ODP_ASSERT|ODP_DBG|ODP_ERR|ODP_ABORT|ODP_LOG|ODP_PRINT|
- EXAMPLE_DBG|EXAMPLE_ERR|EXAMPLE_ABORT|
- LOG_DBG|LOG_ERR|LOG_ABORT|
- printf
+ seq_vprintf|seq_printf|seq_puts
+)};
+
+our $allocFunctions = qr{(?x:
+ (?:(?:devm_)?
+ (?:kv|k|v)[czm]alloc(?:_node|_array)? |
+ kstrdup(?:_const)? |
+ kmemdup(?:_nul)?) |
+ (?:\w+)?alloc_skb(?:_ip_align)? |
+ # dev_alloc_skb/netdev_alloc_skb, et al
+ dma_alloc_coherent
)};
our $signature_tags = qr{(?xi:
Signed-off-by:|
+ Co-developed-by:|
Acked-by:|
Tested-by:|
Reviewed-by:|
@@ -572,6 +596,27 @@ foreach my $entry (@mode_permission_funcs) {
}
$mode_perms_search = "(?:${mode_perms_search})";
+our %deprecated_apis = (
+ "synchronize_rcu_bh" => "synchronize_rcu",
+ "synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited",
+ "call_rcu_bh" => "call_rcu",
+ "rcu_barrier_bh" => "rcu_barrier",
+ "synchronize_sched" => "synchronize_rcu",
+ "synchronize_sched_expedited" => "synchronize_rcu_expedited",
+ "call_rcu_sched" => "call_rcu",
+ "rcu_barrier_sched" => "rcu_barrier",
+ "get_state_synchronize_sched" => "get_state_synchronize_rcu",
+ "cond_synchronize_sched" => "cond_synchronize_rcu",
+);
+
+#Create a search pattern for all these strings to speed up a loop below
+our $deprecated_apis_search = "";
+foreach my $entry (keys %deprecated_apis) {
+ $deprecated_apis_search .= '|' if ($deprecated_apis_search ne "");
+ $deprecated_apis_search .= $entry;
+}
+$deprecated_apis_search = "(?:${deprecated_apis_search})";
+
our $mode_perms_world_writable = qr{
S_IWUGO |
S_IWOTH |
@@ -769,12 +814,12 @@ sub build_types {
}x;
$Type = qr{
$NonptrType
- (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
+ (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
(?:\s+$Inline|\s+$Modifier)*
}x;
$TypeMisordered = qr{
$NonptrTypeMisordered
- (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
+ (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
(?:\s+$Inline|\s+$Modifier)*
}x;
$Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
@@ -795,7 +840,8 @@ our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant|$String)};
our $declaration_macros = qr{(?x:
(?:$Storage\s+)?(?:[A-Z_][A-Z0-9]*_){0,2}(?:DEFINE|DECLARE)(?:_[A-Z0-9]+){1,6}\s*\(|
(?:$Storage\s+)?[HLP]?LIST_HEAD\s*\(|
- (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\(
+ (?:$Storage\s+)?${Type}\s+uninitialized_var\s*\(|
+ (?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
)};
sub deparenthesize {
@@ -838,14 +884,29 @@ sub seed_camelcase_file {
}
}
+our %maintained_status = ();
+
sub is_maintained_obsolete {
my ($filename) = @_;
return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl"));
- my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
+ if (!exists($maintained_status{$filename})) {
+ $maintained_status{$filename} = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
+ }
- return $status =~ /obsolete/i;
+ return $maintained_status{$filename} =~ /obsolete/i;
+}
+
+sub is_SPDX_License_valid {
+ my ($license) = @_;
+
+ return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$root/.git"));
+
+ my $root_path = abs_path($root);
+ my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`;
+ return 0 if ($status ne "");
+ return 1;
}
my $camelcase_seeded = 0;
@@ -859,7 +920,7 @@ sub seed_camelcase_includes {
$camelcase_seeded = 1;
if (-e ".git") {
- my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`;
+ my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`;
chomp $git_last_include_commit;
$camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
} else {
@@ -887,7 +948,7 @@ sub seed_camelcase_includes {
}
if (-e ".git") {
- $files = `git ls-files "include/*.h"`;
+ $files = `${git_command} ls-files "include/*.h"`;
@include_files = split('\n', $files);
}
@@ -911,13 +972,13 @@ sub git_commit_info {
return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
- my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`;
+ my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`;
$output =~ s/^\s*//gm;
my @lines = split("\n", $output);
return ($id, $desc) if ($#lines < 0);
- if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) {
+ if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) {
# Maybe one day convert this block of bash into something that returns
# all matching commit ids, but it's very slow...
#
@@ -961,7 +1022,7 @@ if ($git) {
} else {
$git_range = "-1 $commit_expr";
}
- my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
+ my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
foreach my $line (split(/\n/, $lines)) {
$line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
next if (!defined($1) || !defined($2));
@@ -976,6 +1037,7 @@ if ($git) {
}
my $vname;
+$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"};
for my $filename (@ARGV) {
my $FILE;
if ($git) {
@@ -1000,6 +1062,7 @@ for my $filename (@ARGV) {
while (<$FILE>) {
chomp;
push(@rawlines, $_);
+ $vname = qq("$1") if ($filename eq '-' && $_ =~ m/^Subject:\s+(.+)/i);
}
close($FILE);
@@ -1027,11 +1090,11 @@ if (!$quiet) {
hash_show_words(\%use_type, "Used");
hash_show_words(\%ignore_type, "Ignored");
- if ($^V lt 5.10.0) {
+ if (!$perl_version_ok) {
print << "EOM"
NOTE: perl $^V is not modern enough to detect all possible issues.
- An upgrade to at least perl v5.10.0 is suggested.
+ An upgrade to at least perl $minimum_perl_version is suggested.
EOM
}
if ($exit) {
@@ -1066,6 +1129,7 @@ sub parse_email {
my ($formatted_email) = @_;
my $name = "";
+ my $name_comment = "";
my $address = "";
my $comment = "";
@@ -1079,7 +1143,7 @@ sub parse_email {
} elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) {
$address = $1;
$comment = $2 if defined $2;
- $formatted_email =~ s/$address.*$//;
+ $formatted_email =~ s/\Q$address\E.*$//;
$name = $formatted_email;
$name = trim($name);
$name =~ s/^\"|\"$//g;
@@ -1098,6 +1162,10 @@ sub parse_email {
$name = trim($name);
$name =~ s/^\"|\"$//g;
+ $name =~ s/(\s*\([^\)]+\))\s*//;
+ if (defined($1)) {
+ $name_comment = trim($1);
+ }
$address = trim($address);
$address =~ s/^\<|\>$//g;
@@ -1106,7 +1174,7 @@ sub parse_email {
$name = "\"$name\"";
}
- return ($name, $address, $comment);
+ return ($name, $name_comment, $address, $comment);
}
sub format_email {
@@ -1132,6 +1200,23 @@ sub format_email {
return $formatted_email;
}
+sub reformat_email {
+ my ($email) = @_;
+
+ my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
+ return format_email($email_name, $email_address);
+}
+
+sub same_email_addresses {
+ my ($email1, $email2) = @_;
+
+ my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1);
+ my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2);
+
+ return $email1_name eq $email2_name &&
+ $email1_address eq $email2_address;
+}
+
sub which {
my ($bin) = @_;
@@ -1165,7 +1250,7 @@ sub expand_tabs {
if ($c eq "\t") {
$res .= ' ';
$n++;
- for (; ($n % 8) != 0; $n++) {
+ for (; ($n % $tabsize) != 0; $n++) {
$res .= ' ';
}
next;
@@ -1221,7 +1306,7 @@ sub sanitise_line {
for ($off = 1; $off < length($line); $off++) {
$c = substr($line, $off, 1);
- # Comments we are wacking completly including the begin
+ # Comments we are whacking completely including the begin
# and end, all to $;.
if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
$sanitise_quote = '*/';
@@ -1301,6 +1386,7 @@ sub sanitise_line {
sub get_quoted_string {
my ($line, $rawline) = @_;
+ return "" if (!defined($line) || !defined($rawline));
return "" if ($line !~ m/($String)/g);
return substr($rawline, $-[0], $+[0] - $-[0]);
}
@@ -1593,8 +1679,16 @@ sub ctx_statement_level {
sub ctx_locate_comment {
my ($first_line, $end_line) = @_;
+ # If c99 comment on the current line, or the line before or after
+ my ($current_comment) = ($rawlines[$end_line - 1] =~ m@^\+.*(//.*$)@);
+ return $current_comment if (defined $current_comment);
+ ($current_comment) = ($rawlines[$end_line - 2] =~ m@^[\+ ].*(//.*$)@);
+ return $current_comment if (defined $current_comment);
+ ($current_comment) = ($rawlines[$end_line] =~ m@^[\+ ].*(//.*$)@);
+ return $current_comment if (defined $current_comment);
+
# Catch a comment on the end of the line itself.
- my ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
+ ($current_comment) = ($rawlines[$end_line - 1] =~ m@.*(/\*.*\*/)\s*(?:\\\s*)?$@);
return $current_comment if (defined $current_comment);
# Look through the context and try and figure out if there is a
@@ -1648,6 +1742,28 @@ sub raw_line {
return $line;
}
+sub get_stat_real {
+ my ($linenr, $lc) = @_;
+
+ my $stat_real = raw_line($linenr, 0);
+ for (my $count = $linenr + 1; $count <= $lc; $count++) {
+ $stat_real = $stat_real . "\n" . raw_line($count, 0);
+ }
+
+ return $stat_real;
+}
+
+sub get_stat_here {
+ my ($linenr, $cnt, $here) = @_;
+
+ my $herectx = $here . "\n";
+ for (my $n = 0; $n < $cnt; $n++) {
+ $herectx .= raw_line($linenr, $n) . "\n";
+ }
+
+ return $herectx;
+}
+
sub cat_vet {
my ($vet) = @_;
my ($res, $coded);
@@ -2155,7 +2271,7 @@ sub string_find_replace {
sub tabify {
my ($leading) = @_;
- my $source_indent = 8;
+ my $source_indent = $tabsize;
my $max_spaces_before_tab = $source_indent - 1;
my $spaces_to_tab = " " x $source_indent;
@@ -2197,6 +2313,19 @@ sub pos_last_openparen {
return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
}
+sub get_raw_comment {
+ my ($line, $rawline) = @_;
+ my $comment = '';
+
+ for my $i (0 .. (length($line) - 1)) {
+ if (substr($line, $i, 1) eq "$;") {
+ $comment .= substr($rawline, $i, 1);
+ }
+ }
+
+ return $comment;
+}
+
sub process {
my $filename = shift;
@@ -2213,14 +2342,19 @@ sub process {
our $clean = 1;
my $signoff = 0;
+ my $author = '';
+ my $authorsignoff = 0;
my $is_patch = 0;
+ my $is_binding_patch = -1;
my $in_header_lines = $file ? 0 : 1;
my $in_commit_log = 0; #Scanning lines before patch
+ my $has_patch_separator = 0; #Found a --- line
my $has_commit_log = 0; #Encountered lines before patch
+ my $commit_log_lines = 0; #Number of commit log lines
my $commit_log_possible_stack_dump = 0;
my $commit_log_long_line = 0;
my $commit_log_has_diff = 0;
- my $reported_maintainer_file = 1; # No MAINTAINTERS so silence warning
+ my $reported_maintainer_file = 1; # ODP has no MAINTAINERS file
my $non_utf8_charset = 0;
my $last_blank_line = 0;
@@ -2261,6 +2395,8 @@ sub process {
my $camelcase_file_seeded = 0;
+ my $checklicenseline = 1;
+
sanitise_line_reset();
my $line;
foreach my $rawline (@rawlines) {
@@ -2352,6 +2488,15 @@ sub process {
$sline =~ s/$;/ /g; #with comments as spaces
my $rawline = $rawlines[$linenr - 1];
+ my $raw_comment = get_raw_comment($line, $rawline);
+
+# check if it's a mode change, rename or start of a patch
+ if (!$in_commit_log &&
+ ($line =~ /^ mode change [0-7]+ => [0-7]+ \S+\s*$/ ||
+ ($line =~ /^rename (?:from|to) \S+\s*$/ ||
+ $line =~ /^diff --git a\/[\w\/\.\_\-]+ b\/\S+\s*$/))) {
+ $is_patch = 1;
+ }
#extract the line range in the file after the patch is applied
if (!$in_commit_log &&
@@ -2452,6 +2597,20 @@ sub process {
} else {
$check = $check_orig;
}
+ $checklicenseline = 1;
+
+ if ($realfile !~ /^MAINTAINERS/) {
+ my $last_binding_patch = $is_binding_patch;
+
+ $is_binding_patch = () = $realfile =~ m@^(?:Documentation/devicetree/|include/dt-bindings/)@;
+
+ if (($last_binding_patch != -1) &&
+ ($last_binding_patch ^ $is_binding_patch)) {
+ WARN("DT_SPLIT_BINDING_PATCH",
+ "DT binding docs and includes should be a separate patch. See: Documentation/devicetree/bindings/submitting-patches.rst\n");
+ }
+ }
+
next;
}
@@ -2463,6 +2622,18 @@ sub process {
$cnt_lines++ if ($realcnt != 0);
+# Verify the existence of a commit log if appropriate
+# 2 is used because a $signature is counted in $commit_log_lines
+ if ($in_commit_log) {
+ if ($line !~ /^\s*$/) {
+ $commit_log_lines++; #could be a $signature
+ }
+ } elsif ($has_commit_log && $commit_log_lines < 2) {
+ WARN("COMMIT_MESSAGE",
+ "Missing commit description - Add an appropriate one\n");
+ $commit_log_lines = 2; #warn only once
+ }
+
# Check if the commit log has what seems like a diff which can confuse patch
if ($in_commit_log && !$commit_log_has_diff &&
(($line =~ m@^\s+diff\b.*a/[\w/]+@ &&
@@ -2484,10 +2655,29 @@ sub process {
}
}
+# Check the patch for a From:
+ if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) {
+ $author = $1;
+ $author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i);
+ $author =~ s/"//g;
+ $author = reformat_email($author);
+ }
+
# Check the patch for a signoff:
- if ($line =~ /^\s*signed-off-by:/i) {
+ if ($line =~ /^\s*signed-off-by:\s*(.*)/i) {
$signoff++;
- #$in_commit_log = 0;
+ $in_commit_log = 0;
+ if ($author ne '') {
+ if (same_email_addresses($1, $author)) {
+ $authorsignoff = 1;
+ }
+ }
+ }
+
+# Check for patch separator
+ if ($line =~ /^---$/) {
+ $has_patch_separator = 1;
+ $in_commit_log = 0;
}
# Check if MAINTAINERS is being updated. If so, there's probably no need to
@@ -2497,7 +2687,7 @@ sub process {
}
# Check signature styles
- if (!$in_header_lines && $in_commit_log &&
+ if (!$in_header_lines &&
$line =~ /^(\s*)([a-z0-9_-]+by:|$signature_tags)(\s*)(.*)/i) {
my $space_before = $1;
my $sign_off = $2;
@@ -2535,7 +2725,7 @@ sub process {
}
}
- my ($email_name, $email_address, $comment) = parse_email($email);
+ my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
my $suggested_email = format_email(($email_name, $email_address));
if ($suggested_email eq "") {
ERROR("BAD_SIGN_OFF",
@@ -2546,9 +2736,7 @@ sub process {
$dequoted =~ s/" </ </;
# Don't force email to have quotes
# Allow just an angle bracketed address
- if ("$dequoted$comment" ne $email &&
- "<$email_address>$comment" ne $email &&
- "$suggested_email$comment" ne $email) {
+ if (!same_email_addresses($email, $suggested_email)) {
WARN("BAD_SIGN_OFF",
"email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
}
@@ -2564,6 +2752,24 @@ sub process {
} else {
$signatures{$sig_nospace} = 1;
}
+
+# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email
+ if ($sign_off =~ /^co-developed-by:$/i) {
+ if ($email eq $author) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
+ }
+ if (!defined $lines[$linenr]) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
+ } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
+ } elsif ($1 ne $email) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
+ }
+ }
}
# Check email subject for common tools that don't need to be mentioned
@@ -2573,16 +2779,10 @@ sub process {
"A patch subject line should describe the change not the tool that found it\n" . $herecurr);
}
-# Check for old stable address
- if ($line =~ /^\s*cc:\s*.*<?\bstable\@kernel\.org\b>?.*$/i) {
- ERROR("STABLE_ADDRESS",
- "The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr);
- }
-
-# Check for unwanted Gerrit info
- if ($in_commit_log && $line =~ /^\s*change-id:/i) {
+# Check for Gerrit Change-Ids not in any patch context
+ if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
ERROR("GERRIT_CHANGE_ID",
- "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
+ "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr);
}
# Check if the commit log is in a possible stack dump
@@ -2590,8 +2790,10 @@ sub process {
($line =~ /^\s*(?:WARNING:|BUG:)/ ||
$line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
# timestamp
- $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) {
- # stack dump address
+ $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) ||
+ $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ ||
+ $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) {
+ # stack dump address styles
$commit_log_possible_stack_dump = 1;
}
@@ -2618,7 +2820,7 @@ sub process {
# Check for git id commit length and improperly formed commit descriptions
if ($in_commit_log && !$commit_log_possible_stack_dump &&
- $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink):/i &&
+ $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
$line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
@@ -2687,6 +2889,14 @@ sub process {
"added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
}
+# Check for adding new DT bindings not in schema format
+ if (!$in_commit_log &&
+ ($line =~ /^new file mode\s*\d+\s*$/) &&
+ ($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) {
+ WARN("DT_SCHEMA_BINDING_PATCH",
+ "DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n");
+ }
+
# Check for wrappage within a valid hunk of the file
if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
ERROR("CORRUPTED_PATCH",
@@ -2763,6 +2973,17 @@ sub process {
}
}
+# check for invalid commit id
+ if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) {
+ my $id;
+ my $description;
+ ($id, $description) = git_commit_info($2, undef, undef);
+ if (!defined($id)) {
+ WARN("UNKNOWN_COMMIT_ID",
+ "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr);
+ }
+ }
+
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
@@ -2801,7 +3022,10 @@ sub process {
# Only applies when adding the entry originally, after that we do not have
# sufficient context to determine whether it is indeed long enough.
if ($realfile =~ /Kconfig/ &&
- $line =~ /^\+\s*config\s+/) {
+ # 'choice' is usually the last thing on the line (though
+ # Kconfig supports named choices), so use a word boundary
+ # (\b) rather than a whitespace character (\s)
+ $line =~ /^\+\s*(?:config|menuconfig|choice)\b/) {
my $length = 0;
my $cnt = $realcnt;
my $ln = $linenr + 1;
@@ -2816,9 +3040,13 @@ sub process {
next if ($f =~ /^-/);
last if (!$file && $f =~ /^\@\@/);
- if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate)\s*\"/) {
+ if ($lines[$ln - 1] =~ /^\+\s*(?:bool|tristate|prompt)\s*["']/) {
$is_start = 1;
- } elsif ($lines[$ln - 1] =~ /^\+\s*(?:---)?help(?:---)?$/) {
+ } elsif ($lines[$ln - 1] =~ /^\+\s*(?:help|---help---)\s*$/) {
+ if ($lines[$ln - 1] =~ "---help---") {
+ WARN("CONFIG_DESCRIPTION",
+ "prefer 'help' over '---help---' for new help texts\n" . $herecurr);
+ }
$length = -1;
}
@@ -2826,7 +3054,13 @@ sub process {
$f =~ s/#.*//;
$f =~ s/^\s+//;
next if ($f =~ /^$/);
- if ($f =~ /^\s*config\s/) {
+
+ # This only checks context lines in the patch
+ # and so hopefully shouldn't trigger false
+ # positives, even though some of these are
+ # common words in help texts
+ if ($f =~ /^\s*(?:config|menuconfig|choice|endchoice|
+ if|endif|menu|endmenu|source)\b/x) {
$is_end = 1;
last;
}
@@ -2839,14 +3073,43 @@ sub process {
#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
}
-# check for MAINTAINERS entries that don't have the right form
- if ($realfile =~ /^MAINTAINERS$/ &&
- $rawline =~ /^\+[A-Z]:/ &&
- $rawline !~ /^\+[A-Z]:\t\S/) {
- if (WARN("MAINTAINERS_STYLE",
- "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) &&
- $fix) {
- $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/;
+# check MAINTAINERS entries
+ if ($realfile =~ /^MAINTAINERS$/) {
+# check MAINTAINERS entries for the right form
+ if ($rawline =~ /^\+[A-Z]:/ &&
+ $rawline !~ /^\+[A-Z]:\t\S/) {
+ if (WARN("MAINTAINERS_STYLE",
+ "MAINTAINERS entries use one tab after TYPE:\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/^(\+[A-Z]):\s*/$1:\t/;
+ }
+ }
+# check MAINTAINERS entries for the right ordering too
+ my $preferred_order = 'MRLSWQBCPTFXNK';
+ if ($rawline =~ /^\+[A-Z]:/ &&
+ $prevrawline =~ /^[\+ ][A-Z]:/) {
+ $rawline =~ /^\+([A-Z]):\s*(.*)/;
+ my $cur = $1;
+ my $curval = $2;
+ $prevrawline =~ /^[\+ ]([A-Z]):\s*(.*)/;
+ my $prev = $1;
+ my $prevval = $2;
+ my $curindex = index($preferred_order, $cur);
+ my $previndex = index($preferred_order, $prev);
+ if ($curindex < 0) {
+ WARN("MAINTAINERS_STYLE",
+ "Unknown MAINTAINERS entry type: '$cur'\n" . $herecurr);
+ } else {
+ if ($previndex >= 0 && $curindex < $previndex) {
+ WARN("MAINTAINERS_STYLE",
+ "Misordered MAINTAINERS entry - list '$cur:' before '$prev:'\n" . $hereprev);
+ } elsif ((($prev eq 'F' && $cur eq 'F') ||
+ ($prev eq 'X' && $cur eq 'X')) &&
+ ($prevval cmp $curval) > 0) {
+ WARN("MAINTAINERS_STYLE",
+ "Misordered MAINTAINERS entry - list file patterns in alphabetic order\n" . $hereprev);
+ }
+ }
}
}
@@ -2879,7 +3142,7 @@ sub process {
my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
my $dt_path = $root . "/Documentation/devicetree/bindings/";
- my $vp_file = $dt_path . "vendor-prefixes.txt";
+ my $vp_file = $dt_path . "vendor-prefixes.yaml";
foreach my $compat (@compats) {
my $compat2 = $compat;
@@ -2894,7 +3157,7 @@ sub process {
next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
my $vendor = $1;
- `grep -Eq "^$vendor\\b" $vp_file`;
+ `grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`;
if ( $? >> 8 ) {
WARN("UNDOCUMENTED_DT_STRING",
"DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
@@ -2902,9 +3165,66 @@ sub process {
}
}
+# check for using SPDX license tag at beginning of files
+ if ($realline == $checklicenseline) {
+ if ($rawline =~ /^[ \+]\s*\#\!\s*\//) {
+ $checklicenseline = 2;
+ } elsif ($rawline =~ /^\+/) {
+ my $comment = "";
+ if ($realfile =~ /\.(h|s|S)$/) {
+ $comment = '/*';
+ } elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
+ $comment = '//';
+ } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
+ $comment = '#';
+ } elsif ($realfile =~ /\.rst$/) {
+ $comment = '..';
+ }
+
+# check SPDX comment style for .[chsS] files
+ if ($realfile =~ /\.[chsS]$/ &&
+ $rawline =~ /SPDX-License-Identifier:/ &&
+ $rawline !~ m@^\+\s*\Q$comment\E\s*@) {
+ WARN("SPDX_LICENSE_TAG",
+ "Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr);
+ }
+
+ if ($comment !~ /^$/ &&
+ $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) {
+ WARN("SPDX_LICENSE_TAG",
+ "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
+ } elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
+ my $spdx_license = $1;
+ if (!is_SPDX_License_valid($spdx_license)) {
+ WARN("SPDX_LICENSE_TAG",
+ "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
+ }
+ if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
+ not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ if (&{$msg_level}("SPDX_LICENSE_TAG",
+
+ "DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
+ }
+ }
+ }
+ }
+ }
+
# check we are in a valid source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
+# check for using SPDX-License-Identifier on the wrong line number
+ if ($realline != $checklicenseline &&
+ $rawline =~ /\bSPDX-License-Identifier:/ &&
+ substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) {
+ WARN("SPDX_LICENSE_TAG",
+ "Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr);
+ }
+
# line length limit (with some exclusions)
#
# There are a few types of lines that may extend beyond $max_line_length:
@@ -2962,8 +3282,10 @@ sub process {
if ($msg_type ne "" &&
(show_type("LONG_LINE") || show_type($msg_type))) {
- WARN($msg_type,
- "line over $max_line_length characters\n" . $herecurr);
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ &{$msg_level}($msg_type,
+ "line length of $length exceeds $max_line_length columns\n" . $herecurr);
}
}
@@ -2973,25 +3295,11 @@ sub process {
"adding a line without newline at end of file\n" . $herecurr);
}
-# Blackfin: use hi/lo macros
- if ($realfile =~ m@arch/blackfin/.*\.S$@) {
- if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) {
- my $herevet = "$here\n" . cat_vet($line) . "\n";
- ERROR("LO_MACRO",
- "use the LO() macro, not (... & 0xFFFF)\n" . $herevet);
- }
- if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) {
- my $herevet = "$here\n" . cat_vet($line) . "\n";
- ERROR("HI_MACRO",
- "use the HI() macro, not (... >> 16)\n" . $herevet);
- }
- }
-
# check we are in a valid source file C or perl if not then ignore this hunk
next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
# at the beginning of a line any tabs must come first and anything
-# more than 8 must use tabs.
+# more than $tabsize must use tabs.
if ($rawline =~ /^\+\s* \t\s*\S/ ||
$rawline =~ /^\+\s* \s*/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
@@ -3010,12 +3318,18 @@ sub process {
"please, no space before tabs\n" . $herevet) &&
$fix) {
while ($fixed[$fixlinenr] =~
- s/(^\+.*) {8,8}\t/$1\t\t/) {}
+ s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {}
while ($fixed[$fixlinenr] =~
s/(^\+.*) +\t/$1\t/) {}
}
}
+# check for assignments on the start of a line
+ if ($sline =~ /^\+\s+($Assignment)[^=]/) {
+ CHK("ASSIGNMENT_CONTINUATIONS",
+ "Assignment operator '$1' should be on the previous line\n" . $hereprev);
+ }
+
# check for && or || at the start of a line
if ($rawline =~ /^\+\s*(&&|\|\|)/) {
CHK("LOGICAL_CONTINUATIONS",
@@ -3023,20 +3337,20 @@ sub process {
}
# check indentation starts on a tab stop
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
my $indent = length($1);
- if ($indent % 8) {
+ if ($indent % $tabsize) {
if (WARN("TABSTOP",
"Statements should start on a tabstop\n" . $herecurr) &&
$fix) {
- $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e;
+ $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e;
}
}
}
# check multi-line statement indentation matches previous line
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|(?:\*\s*)*$Lval\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
$prevline =~ /^\+(\t*)(.*)$/;
my $oldindent = $1;
@@ -3048,8 +3362,8 @@ sub process {
my $newindent = $2;
my $goodtabindent = $oldindent .
- "\t" x ($pos / 8) .
- " " x ($pos % 8);
+ "\t" x ($pos / $tabsize) .
+ " " x ($pos % $tabsize);
my $goodspaceindent = $oldindent . " " x $pos;
if ($newindent ne $goodtabindent &&
@@ -3193,7 +3507,7 @@ sub process {
# known declaration macros
$sline =~ /^\+\s+$declaration_macros/ ||
# start of struct or union or enum
- $sline =~ /^\+\s+(?:union|struct|enum|typedef)\b/ ||
+ $sline =~ /^\+\s+(?:static\s+)?(?:const\s+)?(?:union|struct|enum|typedef)\b/ ||
# start or end of block or continuation of declaration
$sline =~ /^\+\s+(?:$|[\{\}\.\#\"\?\:\(\[])/ ||
# bitfield continuation
@@ -3273,18 +3587,6 @@ sub process {
"CVS style keyword markers, these will _not_ be updated\n". $herecurr);
}
-# Blackfin: don't use __builtin_bfin_[cs]sync
- if ($line =~ /__builtin_bfin_csync/) {
- my $herevet = "$here\n" . cat_vet($line) . "\n";
- ERROR("CSYNC",
- "use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
- }
- if ($line =~ /__builtin_bfin_ssync/) {
- my $herevet = "$here\n" . cat_vet($line) . "\n";
- ERROR("SSYNC",
- "use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
- }
-
# check for old HOTPLUG __dev<foo> section markings
if ($line =~ /\b(__dev(init|exit)(data|const|))\b/) {
WARN("HOTPLUG_SECTION",
@@ -3532,11 +3834,11 @@ sub process {
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
if ($check && $s ne '' &&
- (($sindent % 8) != 0 ||
+ (($sindent % $tabsize) != 0 ||
($sindent < $indent) ||
($sindent == $indent &&
($s !~ /^\s*(?:\}|\{|else\b)/)) ||
- ($sindent > $indent + 8))) {
+ ($sindent > $indent + $tabsize))) {
WARN("SUSPECT_CODE_INDENT",
"suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
}
@@ -3737,19 +4039,48 @@ sub process {
"type '$tmp' should be specified in [[un]signed] [short|int|long|long long] order\n" . $herecurr);
}
+# check for unnecessary <signed> int declarations of short/long/long long
+ while ($sline =~ m{\b($TypeMisordered(\s*\*)*|$C90_int_types)\b}g) {
+ my $type = trim($1);
+ next if ($type !~ /\bint\b/);
+ next if ($type !~ /\b(?:short|long\s+long|long)\b/);
+ my $new_type = $type;
+ $new_type =~ s/\b\s*int\s*\b/ /;
+ $new_type =~ s/\b\s*(?:un)?signed\b\s*/ /;
+ $new_type =~ s/^const\s+//;
+ $new_type = "unsigned $new_type" if ($type =~ /\bunsigned\b/);
+ $new_type = "const $new_type" if ($type =~ /^const\b/);
+ $new_type =~ s/\s+/ /g;
+ $new_type = trim($new_type);
+ if (WARN("UNNECESSARY_INT",
+ "Prefer '$new_type' over '$type' as the int is unnecessary\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\b\Q$type\E\b/$new_type/;
+ }
+ }
+
# check for static const char * arrays.
if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
WARN("STATIC_CONST_CHAR_ARRAY",
"static const char * array should probably be static const char * const\n" .
$herecurr);
- }
+ }
+
+# check for initialized const char arrays that should be static const
+ if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) {
+ if (WARN("STATIC_CONST_CHAR_ARRAY",
+ "const array should probably be static const\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/;
+ }
+ }
# check for static char foo[] = "bar" declarations.
if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
WARN("STATIC_CONST_CHAR_ARRAY",
"static char array declaration should probably be static const char\n" .
$herecurr);
- }
+ }
# check for const <foo> const where <foo> is not a pointer or array type
if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
@@ -3784,7 +4115,7 @@ sub process {
}
# check for function declarations without arguments like "int foo()"
- if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
+ if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) {
if (ERROR("FUNCTION_WITHOUT_ARGS",
"Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
$fix) {
@@ -3895,15 +4226,6 @@ sub process {
"Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr);
}
- if ($line =~ /\bpr_warning\s*\(/) {
- if (WARN("PREFER_PR_LEVEL",
- "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) &&
- $fix) {
- $fixed[$fixlinenr] =~
- s/\bpr_warning\b/pr_warn/;
- }
- }
-
if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
my $orig = $1;
my $level = lc($orig);
@@ -3921,9 +4243,20 @@ sub process {
"ENOSYS means 'invalid syscall nr' and nothing else\n" . $herecurr);
}
+# ENOTSUPP is not a standard error code and should be avoided in new patches.
+# Folks usually mean EOPNOTSUPP (also called ENOTSUP), when they type ENOTSUPP.
+# Similarly to ENOSYS warning a small number of false positives is expected.
+ if (!$file && $line =~ /\bENOTSUPP\b/) {
+ if (WARN("ENOTSUPP",
+ "ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\bENOTSUPP\b/EOPNOTSUPP/;
+ }
+ }
+
# function brace can't be on same line, except for #defines of do while,
# or if closed on same line
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ &&
$sline !~ /\#\s*define\b.*do\s*\{/ &&
$sline !~ /}/) {
@@ -4049,7 +4382,7 @@ sub process {
my ($where, $prefix) = ($-[1], $1);
if ($prefix !~ /$Type\s+$/ &&
($where != 0 || $prefix !~ /^.\s+$/) &&
- $prefix !~ /[{,]\s+$/) {
+ $prefix !~ /[{,:]\s+$/) {
if (ERROR("BRACKET_SPACE",
"space prohibited before open square bracket '['\n" . $herecurr) &&
$fix) {
@@ -4361,7 +4694,7 @@ sub process {
($op eq '>' &&
$ca =~ /<\S+\@\S+$/))
{
- $ok = 1;
+ $ok = 1;
}
# for asm volatile statements
@@ -4439,11 +4772,11 @@ sub process {
#need space before brace following if, while, etc
if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
- $line =~ /do\{/) {
+ $line =~ /\b(?:else|do)\{/) {
if (ERROR("SPACING",
"space required before the open brace '{'\n" . $herecurr) &&
$fix) {
- $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\)))\{/$1 {/;
+ $fixed[$fixlinenr] =~ s/^(\+.*(?:do|else|\)))\{/$1 {/;
}
}
@@ -4457,7 +4790,7 @@ sub process {
# closing brace should have a space following it when it has anything
# on the line
- if ($line =~ /}(?!(?:,|;|\)))\S/) {
+ if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
if (ERROR("SPACING",
"space required after that close brace '}'\n" . $herecurr) &&
$fix) {
@@ -4534,7 +4867,7 @@ sub process {
# check for unnecessary parentheses around comparisons in if uses
# when !drivers/staging or command-line uses --strict
if (($realfile !~ m@^(?:drivers/staging/)@ || $check_orig) &&
- $^V && $^V ge 5.10.0 && defined($stat) &&
+ $perl_version_ok && defined($stat) &&
$stat =~ /(^.\s*if\s*($balanced_parens))/) {
my $if_stat = $1;
my $test = substr($2, 1, -1);
@@ -4571,7 +4904,7 @@ sub process {
# return is not a function
if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
my $spacing = $1;
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$stat =~ /^.\s*return\s*($balanced_parens)\s*;\s*$/) {
my $value = $1;
$value = deparenthesize($value);
@@ -4598,7 +4931,7 @@ sub process {
}
# if statements using unnecessary parentheses - ie: if ((foo == bar))
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$line =~ /\bif\s*((?:\(\s*){2,})/) {
my $openparens = $1;
my $count = $openparens =~ tr@\(@\(@;
@@ -4615,7 +4948,7 @@ sub process {
# avoid cases like "foo + BAR < baz"
# only fix matches surrounded by parentheses to avoid incorrect
# conversions like "FOO < baz() + 5" being "misfixed" to "baz() > FOO + 5"
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
my $lead = $1;
my $const = $2;
@@ -4696,7 +5029,7 @@ sub process {
# conditional.
substr($s, 0, length($c), '');
$s =~ s/\n.*//g;
- $s =~ s/$;//g; # Remove any comments
+ $s =~ s/$;//g; # Remove any comments
if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
$c !~ /}\s*while\s*/)
{
@@ -4735,7 +5068,7 @@ sub process {
# if and else should not have general statements after it
if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
my $s = $1;
- $s =~ s/$;//g; # Remove any comments
+ $s =~ s/$;//g; # Remove any comments
if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
ERROR("TRAILING_STATEMENTS",
"trailing statements should be on next line\n" . $herecurr);
@@ -4807,24 +5140,11 @@ sub process {
while ($line =~ m{($Constant|$Lval)}g) {
my $var = $1;
-#gcc binary extension
- if ($var =~ /^$Binary$/) {
- if (WARN("GCC_BINARY_CONSTANT",
- "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) &&
- $fix) {
- my $hexval = sprintf("0x%x", oct($var));
- $fixed[$fixlinenr] =~
- s/\b$var\b/$hexval/;
- }
- }
-
#CamelCase
if ($var !~ /^$Constant$/ &&
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
#Ignore Page<foo> variants
$var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
-#Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show)
- $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/ &&
#ODP ignores
$var !~ /\bCU_/ &&
$var !~ /\bPRI[diux]8/ &&
@@ -4835,6 +5155,9 @@ sub process {
$var !~ /\bSCN[diux]16/ &&
$var !~ /\bSCN[diux]32/ &&
$var !~ /\bSCN[diux]64/ &&
+#Ignore SI style variants like nS, mV and dB
+#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
+ $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
#Ignore some three character SI units explicitly, like MiB and KHz
$var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
while ($var =~ m{($Ident)}g) {
@@ -4915,6 +5238,7 @@ sub process {
if (defined $define_args && $define_args ne "") {
$define_args = substr($define_args, 1, length($define_args) - 2);
$define_args =~ s/\s*//g;
+ $define_args =~ s/\\\+?//g;
@def_args = split(",", $define_args);
}
@@ -4930,7 +5254,7 @@ sub process {
{
}
- # Flatten any obvious string concatentation.
+ # Flatten any obvious string concatenation.
while ($dstat =~ s/($String)\s*$Ident/$1/ ||
$dstat =~ s/$Ident\s*($String)/$1/)
{
@@ -4955,12 +5279,8 @@ sub process {
#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
$ctx =~ s/\n*$//;
- my $herectx = $here . "\n";
my $stmt_cnt = statement_rawlines($ctx);
-
- for (my $n = 0; $n < $stmt_cnt; $n++) {
- $herectx .= raw_line($linenr, $n) . "\n";
- }
+ my $herectx = get_stat_here($linenr, $stmt_cnt, $here);
if ($dstat ne '' &&
$dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
@@ -5012,10 +5332,10 @@ sub process {
next if ($arg =~ /\.\.\./);
next if ($arg =~ /^type$/i);
my $tmp_stmt = $define_stmt;
- $tmp_stmt =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
+ $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
$tmp_stmt =~ s/\#+\s*$arg\b//g;
$tmp_stmt =~ s/\b$arg\s*\#\#//g;
- my $use_cnt = $tmp_stmt =~ s/\b$arg\b//g;
+ my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
if ($use_cnt > 1) {
CHK("MACRO_ARG_REUSE",
"Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
@@ -5032,12 +5352,9 @@ sub process {
# check for macros with flow control, but without ## concatenation
# ## concatenation is commonly a macro that defines a function so ignore those
if ($has_flow_statement && !$has_arg_concat) {
- my $herectx = $here . "\n";
my $cnt = statement_rawlines($ctx);
+ my $herectx = get_stat_here($linenr, $cnt, $here);
- for (my $n = 0; $n < $cnt; $n++) {
- $herectx .= raw_line($linenr, $n) . "\n";
- }
WARN("MACRO_WITH_FLOW_CONTROL",
"Macros with flow control statements should be avoided\n" . "$herectx");
}
@@ -5057,7 +5374,7 @@ sub process {
# do {} while (0) macro tests:
# single-statement macros do not need to be enclosed in do while (0) loop,
# macro should not end with a semicolon
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$realfile !~ m@/vmlinux.lds.h$@ &&
$line =~ /^.\s*\#\s*define\s+$Ident(\()?/) {
my $ln = $linenr;
@@ -5077,11 +5394,7 @@ sub process {
$ctx =~ s/\n*$//;
my $cnt = statement_rawlines($ctx);
- my $herectx = $here . "\n";
-
- for (my $n = 0; $n < $cnt; $n++) {
- $herectx .= raw_line($linenr, $n) . "\n";
- }
+ my $herectx = get_stat_here($linenr, $cnt, $here);
if (($stmts =~ tr/;/;/) == 1 &&
$stmts !~ /^\s*(if|while|for|switch)\b/) {
@@ -5095,27 +5408,13 @@ sub process {
} elsif ($dstat =~ /^\+\s*#\s*define\s+$Ident.*;\s*$/) {
$ctx =~ s/\n*$//;
my $cnt = statement_rawlines($ctx);
- my $herectx = $here . "\n";
-
- for (my $n = 0; $n < $cnt; $n++) {
- $herectx .= raw_line($linenr, $n) . "\n";
- }
+ my $herectx = get_stat_here($linenr, $cnt, $here);
WARN("TRAILING_SEMICOLON",
"macros should not use a trailing semicolon\n" . "$herectx");
}
}
-# make sure symbols are always wrapped with VMLINUX_SYMBOL() ...
-# all assignments may have only one of the following with an assignment:
-# .
-# ALIGN(...)
-# VMLINUX_SYMBOL(...)
- if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) {
- WARN("MISSING_VMLINUX_SYMBOL",
- "vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr);
- }
-
# check for redundant bracing round if etc
if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
my ($level, $endln, @chunks) =
@@ -5222,12 +5521,8 @@ sub process {
}
}
if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
- my $herectx = $here . "\n";
my $cnt = statement_rawlines($block);
-
- for (my $n = 0; $n < $cnt; $n++) {
- $herectx .= raw_line($linenr, $n) . "\n";
- }
+ my $herectx = get_stat_here($linenr, $cnt, $here);
WARN("BRACES",
"braces {} are not necessary for single statement blocks\n" . $herectx);
@@ -5325,15 +5620,28 @@ sub process {
}
# concatenated string without spaces between elements
- if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) {
- CHK("CONCATENATED_STRING",
- "Concatenated strings should use spaces between elements\n" . $herecurr);
+ if ($line =~ /$String[A-Za-z0-9_]/ || $line =~ /[A-Za-z0-9_]$String/) {
+ if (CHK("CONCATENATED_STRING",
+ "Concatenated strings should use spaces between elements\n" . $herecurr) &&
+ $fix) {
+ while ($line =~ /($String)/g) {
+ my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
+ $fixed[$fixlinenr] =~ s/\Q$extracted_string\E([A-Za-z0-9_])/$extracted_string $1/;
+ $fixed[$fixlinenr] =~ s/([A-Za-z0-9_])\Q$extracted_string\E/$1 $extracted_string/;
+ }
+ }
}
# uncoalesced string fragments
if ($line =~ /$String\s*"/) {
- WARN("STRING_FRAGMENTS",
- "Consecutive strings are generally better as a single string\n" . $herecurr);
+ if (WARN("STRING_FRAGMENTS",
+ "Consecutive strings are generally better as a single string\n" . $herecurr) &&
+ $fix) {
+ while ($line =~ /($String)(?=\s*")/g) {
+ my $extracted_string = substr($rawline, $-[0], $+[0] - $-[0]);
+ $fixed[$fixlinenr] =~ s/\Q$extracted_string\E\s*"/substr($extracted_string, 0, -1)/e;
+ }
+ }
}
# check for non-standard and hex prefixed decimal printf formats
@@ -5369,9 +5677,14 @@ sub process {
# warn about #if 0
if ($line =~ /^.\s*\#\s*if\s+0\b/) {
- CHK("REDUNDANT_CODE",
- "if this code is redundant consider removing it\n" .
- $herecurr);
+ WARN("IF_0",
+ "Consider removing the code enclosed by this #if 0 and its #endif\n" . $herecurr);
+ }
+
+# warn about #if 1
+ if ($line =~ /^.\s*\#\s*if\s+1\b/) {
+ WARN("IF_1",
+ "Consider removing the #if 1 and its #endif\n" . $herecurr);
}
# check for needless "if (<foo>) fn(<foo>)" uses
@@ -5418,7 +5731,8 @@ sub process {
my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
- if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|kmemdup|(?:dev_)?alloc_skb)/) {
+ if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ &&
+ $s !~ /\b__GFP_NOWARN\b/ ) {
WARN("OOM_MESSAGE",
"Possible unnecessary 'out of memory' message\n" . $hereprev);
}
@@ -5442,7 +5756,7 @@ sub process {
}
# check for mask then right shift without a parentheses
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
$4 !~ /^\&/) { # $LvalOrFunc may be &foo, ignore if so
WARN("MASK_THEN_SHIFT",
@@ -5450,7 +5764,7 @@ sub process {
}
# check for pointer comparisons to NULL
- if ($^V && $^V ge 5.10.0) {
+ if ($perl_version_ok) {
while ($line =~ /\b$LvalOrFunc\s*(==|\!=)\s*NULL\b/g) {
my $val = $1;
my $equal = "!";
@@ -5539,7 +5853,7 @@ sub process {
# ignore udelay's < 10, however
if (! ($delay < 10) ) {
CHK("USLEEP_RANGE",
- "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr);
+ "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
}
if ($delay > 2000) {
WARN("LONG_UDELAY",
@@ -5551,7 +5865,7 @@ sub process {
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
if ($1 < 20) {
WARN("MSLEEP",
- "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr);
+ "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
}
}
@@ -5700,6 +6014,18 @@ sub process {
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
}
+# Check for __attribute__ section, prefer __section
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
+ my $old = substr($rawline, $-[1], $+[1] - $-[1]);
+ my $new = substr($old, 1, -1);
+ if (WARN("PREFER_SECTION",
+ "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
+ }
+ }
+
# Check for __attribute__ format(printf, prefer __printf
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
@@ -5722,7 +6048,7 @@ sub process {
}
# Check for __attribute__ weak, or __weak declarations (may have link issues)
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$line =~ /(?:$Declare|$DeclareMisordered)\s*$Ident\s*$balanced_parens\s*(?:$Attribute)?\s*;/ &&
($line =~ /\b__attribute__\s*\(\s*\(.*\bweak\b/ ||
$line =~ /\b__weak\b/)) {
@@ -5803,41 +6129,58 @@ sub process {
}
}
- # check for vsprintf extension %p<foo> misuses
- if ($^V && $^V ge 5.10.0 &&
+# check for vsprintf extension %p<foo> misuses
+ if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
$1 !~ /^_*volatile_*$/) {
- my $bad_extension = "";
+ my $stat_real;
+
my $lc = $stat =~ tr@\n@@;
$lc = $lc + $linenr;
for (my $count = $linenr; $count <= $lc; $count++) {
+ my $specifier;
+ my $extension;
+ my $qualifier;
+ my $bad_specifier = "";
my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
$fmt =~ s/%%//g;
- if ($fmt =~ /(\%[\*\d\.]*p(?![\WSsBKRraEhMmIiUDdgVCbGNOx]).)/) {
- $bad_extension = $1;
- last;
- }
- }
- if ($bad_extension ne "") {
- my $stat_real = raw_line($linenr, 0);
- my $ext_type = "Invalid";
- my $use = "";
- for (my $count = $linenr + 1; $count <= $lc; $count++) {
- $stat_real = $stat_real . "\n" . raw_line($count, 0);
+
+ while ($fmt =~ /(\%[\*\d\.]*p(\w)(\w*))/g) {
+ $specifier = $1;
+ $extension = $2;
+ $qualifier = $3;
+ if ($extension !~ /[SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||
+ ($extension eq "f" &&
+ defined $qualifier && $qualifier !~ /^w/)) {
+ $bad_specifier = $specifier;
+ last;
+ }
+ if ($extension eq "x" && !defined($stat_real)) {
+ if (!defined($stat_real)) {
+ $stat_real = get_stat_real($linenr, $lc);
+ }
+ WARN("VSPRINTF_SPECIFIER_PX",
+ "Using vsprintf specifier '\%px' potentially exposes the kernel memory layout, if you don't really need the address please consider using '\%p'.\n" . "$here\n$stat_real\n");
+ }
}
- if ($bad_extension =~ /p[Ff]/) {
- $ext_type = "Deprecated";
- $use = " - use %pS instead";
- $use =~ s/pS/ps/ if ($bad_extension =~ /pf/);
+ if ($bad_specifier ne "") {
+ my $stat_real = get_stat_real($linenr, $lc);
+ my $ext_type = "Invalid";
+ my $use = "";
+ if ($bad_specifier =~ /p[Ff]/) {
+ $use = " - use %pS instead";
+ $use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
+ }
+
+ WARN("VSPRINTF_POINTER_EXTENSION",
+ "$ext_type vsprintf pointer extension '$bad_specifier'$use\n" . "$here\n$stat_real\n");
}
- WARN("VSPRINTF_POINTER_EXTENSION",
- "$ext_type vsprintf pointer extension '$bad_extension'$use\n" . "$here\n$stat_real\n");
}
}
# Check for misused memsets
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) {
@@ -5855,7 +6198,7 @@ sub process {
}
# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
-# if ($^V && $^V ge 5.10.0 &&
+# if ($perl_version_ok &&
# defined $stat &&
# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
# if (WARN("PREFER_ETHER_ADDR_COPY",
@@ -5866,7 +6209,7 @@ sub process {
# }
# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
-# if ($^V && $^V ge 5.10.0 &&
+# if ($perl_version_ok &&
# defined $stat &&
# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
# WARN("PREFER_ETHER_ADDR_EQUAL",
@@ -5875,7 +6218,7 @@ sub process {
# check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr
# check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr
-# if ($^V && $^V ge 5.10.0 &&
+# if ($perl_version_ok &&
# defined $stat &&
# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
#
@@ -5897,7 +6240,7 @@ sub process {
# }
# typecasts on min/max could be min_t/max_t
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+(?:.*?)\b(min|max)\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\)/) {
if (defined $2 || defined $7) {
@@ -5921,23 +6264,23 @@ sub process {
}
# check usleep_range arguments
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+(?:.*?)\busleep_range\s*\(\s*($FuncArg)\s*,\s*($FuncArg)\s*\)/) {
my $min = $1;
my $max = $7;
if ($min eq $max) {
WARN("USLEEP_RANGE",
- "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
+ "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
$min > $max) {
WARN("USLEEP_RANGE",
- "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
+ "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
}
}
# check for naked sscanf
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$line =~ /\bsscanf\b/ &&
($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
@@ -5945,24 +6288,18 @@ sub process {
$stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
my $lc = $stat =~ tr@\n@@;
$lc = $lc + $linenr;
- my $stat_real = raw_line($linenr, 0);
- for (my $count = $linenr + 1; $count <= $lc; $count++) {
- $stat_real = $stat_real . "\n" . raw_line($count, 0);
- }
+ my $stat_real = get_stat_real($linenr, $lc);
WARN("NAKED_SSCANF",
"unchecked sscanf return value\n" . "$here\n$stat_real\n");
}
# check for simple sscanf that should be kstrto<foo>
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$line =~ /\bsscanf\b/) {
my $lc = $stat =~ tr@\n@@;
$lc = $lc + $linenr;
- my $stat_real = raw_line($linenr, 0);
- for (my $count = $linenr + 1; $count <= $lc; $count++) {
- $stat_real = $stat_real . "\n" . raw_line($count, 0);
- }
+ my $stat_real = get_stat_real($linenr, $lc);
if ($stat_real =~ /\bsscanf\b\s*\(\s*$FuncArg\s*,\s*("[^"]+")/) {
my $format = $6;
my $count = $format =~ tr@%@%@;
@@ -6015,13 +6352,17 @@ sub process {
}
# check for function declarations that have arguments without identifier names
+# while avoiding uninitialized_var(x)
if (defined $stat &&
- $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
- $1 ne "void") {
- my $args = trim($1);
+ $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:($Ident)|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
+ (!defined($1) ||
+ (defined($1) && $1 ne "uninitialized_var")) &&
+ $2 ne "void") {
+ my $args = trim($2);
while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
my $arg = trim($1);
- if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
+ if ($arg =~ /^$Type$/ &&
+ $arg !~ /enum\s+$Ident$/) {
WARN("FUNCTION_ARGUMENTS",
"function definition argument '$arg' should also have an identifier name\n" . $herecurr);
}
@@ -6029,7 +6370,7 @@ sub process {
}
# check for function definitions
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
$context_function = $1;
@@ -6061,22 +6402,22 @@ sub process {
}
}
-# check for pointless casting of kmalloc return
- if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) {
+# check for pointless casting of alloc functions
+ if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
WARN("UNNECESSARY_CASTS",
"unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
}
# alloc style
# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
- if ($^V && $^V ge 5.10.0 &&
- $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
+ if ($perl_version_ok &&
+ $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
CHK("ALLOC_SIZEOF_STRUCT",
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
}
# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
my $oldfunc = $3;
@@ -6092,12 +6433,9 @@ sub process {
}
if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
!($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
- my $ctx = '';
- my $herectx = $here . "\n";
my $cnt = statement_rawlines($stat);
- for (my $n = 0; $n < $cnt; $n++) {
- $herectx .= raw_line($linenr, $n) . "\n";
- }
+ my $herectx = get_stat_here($linenr, $cnt, $here);
+
if (WARN("ALLOC_WITH_MULTIPLY",
"Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
$cnt == 1 &&
@@ -6108,8 +6446,9 @@ sub process {
}
# check for krealloc arg reuse
- if ($^V && $^V ge 5.10.0 &&
- $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*\1\s*,/) {
+ if ($perl_version_ok &&
+ $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*krealloc\s*\(\s*($Lval)\s*,/ &&
+ $1 eq $3) {
WARN("KREALLOC_ARG_REUSE",
"Reusing the krealloc arg is almost always a bug\n" . $herecurr);
}
@@ -6176,16 +6515,35 @@ sub process {
}
}
+# check for /* fallthrough */ like comment, prefer fallthrough;
+ my @fallthroughs = (
+ 'fallthrough',
+ '@fallthrough@',
+ 'lint -fallthrough[ \t]*',
+ 'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)',
+ '(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?',
+ 'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
+ 'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
+ );
+ if ($raw_comment ne '') {
+ foreach my $ft (@fallthroughs) {
+ if ($raw_comment =~ /$ft/) {
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ &{$msg_level}("PREFER_FALLTHROUGH",
+ "Prefer 'fallthrough;' over fallthrough comment\n" . $herecurr);
+ last;
+ }
+ }
+ }
+
# check for switch/default statements without a break;
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$stat =~ /^\+[$;\s]*(?:case[$;\s]+\w+[$;\s]*:[$;\s]*|)*[$;\s]*\bdefault[$;\s]*:[$;\s]*;/g) {
- my $ctx = '';
- my $herectx = $here . "\n";
my $cnt = statement_rawlines($stat);
- for (my $n = 0; $n < $cnt; $n++) {
- $herectx .= raw_line($linenr, $n) . "\n";
- }
+ my $herectx = get_stat_here($linenr, $cnt, $here);
+
WARN("DEFAULT_NO_BREAK",
"switch default: should use break\n" . $herectx);
}
@@ -6256,6 +6614,20 @@ sub process {
"please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
}
+# check for spin_is_locked(), suggest lockdep instead
+ if ($line =~ /\bspin_is_locked\(/) {
+ WARN("USE_LOCKDEP",
+ "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
+ }
+
+# check for deprecated apis
+ if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
+ my $deprecated_api = $1;
+ my $new_api = $deprecated_apis{$deprecated_api};
+ WARN("DEPRECATED_API",
+ "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr);
+ }
+
# check for various structs that are normally const (ops, kgdb, device_tree)
# and avoid what seem like struct definitions 'struct foo {'
if ($line !~ /\bconst\b/ &&
@@ -6284,12 +6656,18 @@ sub process {
}
# likely/unlikely comparisons similar to "(likely(foo) > 0)"
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
$line =~ /\b((?:un)?likely)\s*\(\s*$FuncArg\s*\)\s*$Compare/) {
WARN("LIKELY_MISUSE",
"Using $1 should generally have parentheses around the comparison\n" . $herecurr);
}
+# nested likely/unlikely calls
+ if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
+ WARN("LIKELY_MISUSE",
+ "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
+ }
+
# whine mightly about in_atomic
if ($line =~ /\bin_atomic\s*\(/) {
if ($realfile =~ m@^drivers/@) {
@@ -6327,7 +6705,7 @@ sub process {
# check for DEVICE_ATTR uses that could be DEVICE_ATTR_<FOO>
# and whether or not function naming is typical and if
# DEVICE_ATTR permissions uses are unusual too
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$stat =~ /\bDEVICE_ATTR\s*\(\s*(\w+)\s*,\s*\(?\s*(\s*(?:${multi_mode_perms_string_search}|0[0-7]{3,3})\s*)\s*\)?\s*,\s*(\w+)\s*,\s*(\w+)\s*\)/) {
my $var = $1;
@@ -6387,7 +6765,7 @@ sub process {
# specific definition of not visible in sysfs.
# o Ignore proc_create*(...) uses with a decimal 0 permission as that means
# use the default permissions
- if ($^V && $^V ge 5.10.0 &&
+ if ($perl_version_ok &&
defined $stat &&
$line =~ /$mode_perms_search/) {
foreach my $entry (@mode_permission_funcs) {
@@ -6396,10 +6774,7 @@ sub process {
my $lc = $stat =~ tr@\n@@;
$lc = $lc + $linenr;
- my $stat_real = raw_line($linenr, 0);
- for (my $count = $linenr + 1; $count <= $lc; $count++) {
- $stat_real = $stat_real . "\n" . raw_line($count, 0);
- }
+ my $stat_real = get_stat_real($linenr, $lc);
my $skip_args = "";
if ($arg_pos > 1) {
@@ -6425,7 +6800,7 @@ sub process {
}
# check for uses of S_<PERMS> that could be octal for readability
- if ($line =~ /\b($multi_mode_perms_string_search)\b/) {
+ while ($line =~ m{\b($multi_mode_perms_string_search)\b}g) {
my $oval = $1;
my $octal = perms_to_octal($oval);
if (WARN("SYMBOLIC_PERMS",
@@ -6452,6 +6827,12 @@ sub process {
"unknown module license " . $extracted_string . "\n" . $herecurr);
}
}
+
+# check for sysctl duplicate constants
+ if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
+ WARN("DUPLICATED_SYSCTL_CONST",
+ "duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
+ }
}
# If we have no input at all, then there is nothing to report on
@@ -6476,9 +6857,14 @@ sub process {
ERROR("NOT_UNIFIED_DIFF",
"Does not appear to be a unified-diff format patch\n");
}
- if ($is_patch && $has_commit_log && $chk_signoff && $signoff == 0) {
- ERROR("MISSING_SIGN_OFF",
- "Missing Signed-off-by: line(s)\n");
+ if ($is_patch && $has_commit_log && $chk_signoff) {
+ if ($signoff == 0) {
+ ERROR("MISSING_SIGN_OFF",
+ "Missing Signed-off-by: line(s)\n");
+ } elsif (!$authorsignoff) {
+ WARN("NO_AUTHOR_SIGN_OFF",
+ "Missing Signed-off-by: line by nominal patch author '$author'\n");
+ }
}
print report_dump();
@@ -6558,4 +6944,4 @@ EOM
}
}
return $clean;
-}
+} \ No newline at end of file
diff --git a/test/Makefile.inc b/test/Makefile.inc
index aa3881519..d3af8dcff 100644
--- a/test/Makefile.inc
+++ b/test/Makefile.inc
@@ -4,7 +4,7 @@ include $(top_srcdir)/Makefile.inc
COMMON_DIR = $(top_builddir)/test/common
-LIBODP = $(LIB)/libodphelper.la $(LIB)/libodp-linux.la
+LIBODP = $(LIB)/libodphelper.la $(LIB)/lib$(ODP_LIB_NAME).la
LIBCUNIT_COMMON = $(COMMON_DIR)/libcunit_common.la
LIBCPUMASK_COMMON = $(COMMON_DIR)/libcpumask_common.la
diff --git a/test/common/odp_cunit_common.h b/test/common/odp_cunit_common.h
index e8f14daa6..55e52ce1c 100644
--- a/test/common/odp_cunit_common.h
+++ b/test/common/odp_cunit_common.h
@@ -15,6 +15,7 @@
#include <stdint.h>
#include <inttypes.h>
+#include <stdlib.h>
#include <CUnit/Basic.h>
#include <odp_api.h>
@@ -105,4 +106,26 @@ void odp_cunit_register_global_term(int (*func_term_ptr)(odp_instance_t inst));
int odp_cunit_ret(int val);
int odp_cunit_print_inactive(void);
+/*
+ * Wrapper for CU_ASSERT_FATAL implementation to show the compiler that
+ * the function does not return if the assertion fails. This reduces bogus
+ * warnings generated from the code after the fatal assert.
+ */
+static inline void odp_cu_assert_fatal(CU_BOOL value, unsigned int line,
+ const char *condition, const char *file)
+{
+ CU_assertImplementation(value, line, condition, file, "", CU_TRUE);
+
+ if (!value) {
+ /* not reached */
+ abort(); /* this has noreturn function attribute */
+ for (;;) /* this also shows that return is not possible */
+ ;
+ }
+}
+
+#undef CU_ASSERT_FATAL
+#define CU_ASSERT_FATAL(value) \
+ { odp_cu_assert_fatal((value), __LINE__, #value, __FILE__); }
+
#endif /* ODP_CUNICT_COMMON_H */
diff --git a/test/performance/odp_bench_packet.c b/test/performance/odp_bench_packet.c
index d139006b3..c6798556e 100644
--- a/test/performance/odp_bench_packet.c
+++ b/test/performance/odp_bench_packet.c
@@ -126,7 +126,7 @@ typedef struct {
/** Number of benchmark functions */
int num_bench;
/** Break worker loop if set to 1 */
- int exit_thread;
+ odp_atomic_u32_t exit_thread;
struct {
/** Test packet length */
uint32_t len;
@@ -168,7 +168,7 @@ static void sig_handler(int signo ODP_UNUSED)
{
if (gbl_args == NULL)
return;
- gbl_args->exit_thread = 1;
+ odp_atomic_store_u32(&gbl_args->exit_thread, 1);
}
/**
@@ -183,7 +183,7 @@ static void run_indef(args_t *args, int idx)
printf("Running %s() indefinitely\n", desc);
- while (!gbl_args->exit_thread) {
+ while (!odp_atomic_load_u32(&gbl_args->exit_thread)) {
int ret;
if (args->bench[idx].init != NULL)
@@ -1789,6 +1789,7 @@ int main(int argc, char *argv[])
}
memset(gbl_args, 0, sizeof(args_t));
+ odp_atomic_init_u32(&gbl_args->exit_thread, 0);
gbl_args->bench = test_suite;
gbl_args->num_bench = sizeof(test_suite) / sizeof(test_suite[0]);
diff --git a/test/performance/odp_cpu_bench.c b/test/performance/odp_cpu_bench.c
index 38c18513a..a4999ae27 100644
--- a/test/performance/odp_cpu_bench.c
+++ b/test/performance/odp_cpu_bench.c
@@ -92,7 +92,7 @@ typedef struct {
/* Test lookup table */
lookup_entry_t *lookup_tbl;
/* Break workers loop if set to 1 */
- int exit_threads;
+ odp_atomic_u32_t exit_threads;
} args_t;
/* Global pointer to args */
@@ -175,7 +175,7 @@ static void sig_handler(int signo ODP_UNUSED)
{
if (gbl_args == NULL)
return;
- gbl_args->exit_threads = 1;
+ odp_atomic_store_u32(&gbl_args->exit_threads, 1);
}
static inline void init_packet(odp_packet_t pkt, uint32_t seq, uint16_t group)
@@ -278,7 +278,7 @@ static int run_thread(void *arg)
c1 = odp_cpu_cycles();
t1 = odp_time_local();
- while (!gbl_args->exit_threads) {
+ while (!odp_atomic_load_u32(&gbl_args->exit_threads)) {
odp_event_t event_tbl[MAX_EVENT_BURST];
odp_queue_t dst_queue;
int num_events;
@@ -469,10 +469,10 @@ static int print_stats(int num_workers, stats_t **thr_stats, int duration,
pkts_prev = pkts;
elapsed += accuracy;
- } while (!gbl_args->exit_threads &&
+ } while (!odp_atomic_load_u32(&gbl_args->exit_threads) &&
(loop_forever || (elapsed < duration)));
- gbl_args->exit_threads = 1;
+ odp_atomic_store_u32(&gbl_args->exit_threads, 1);
odp_barrier_wait(&gbl_args->term_barrier);
pkts = 0;
@@ -511,6 +511,7 @@ static int print_stats(int num_workers, stats_t **thr_stats, int duration,
static void gbl_args_init(args_t *args)
{
memset(args, 0, sizeof(args_t));
+ odp_atomic_init_u32(&args->exit_threads, 0);
}
/**
diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
index d899aa743..267e74950 100644
--- a/test/performance/odp_l2fwd.c
+++ b/test/performance/odp_l2fwd.c
@@ -174,7 +174,7 @@ typedef struct {
* mode. */
uint8_t dst_port_from_idx[MAX_PKTIO_INDEXES];
/* Break workers loop if set to 1 */
- int exit_threads;
+ odp_atomic_u32_t exit_threads;
} args_t;
@@ -185,7 +185,7 @@ static void sig_handler(int signo ODP_UNUSED)
{
if (gbl_args == NULL)
return;
- gbl_args->exit_threads = 1;
+ odp_atomic_store_u32(&gbl_args->exit_threads, 1);
}
/*
@@ -367,7 +367,7 @@ static int run_worker_sched_mode(void *arg)
odp_barrier_wait(&gbl_args->init_barrier);
/* Loop packets */
- while (!gbl_args->exit_threads) {
+ while (!odp_atomic_load_u32(&gbl_args->exit_threads)) {
odp_event_t ev_tbl[MAX_PKT_BURST];
odp_packet_t pkt_tbl[MAX_PKT_BURST];
int sent;
@@ -492,7 +492,7 @@ static int run_worker_plain_queue_mode(void *arg)
odp_barrier_wait(&gbl_args->init_barrier);
/* Loop packets */
- while (!gbl_args->exit_threads) {
+ while (!odp_atomic_load_u32(&gbl_args->exit_threads)) {
int sent;
unsigned tx_drops;
odp_event_t event[MAX_PKT_BURST];
@@ -627,7 +627,7 @@ static int run_worker_direct_mode(void *arg)
odp_barrier_wait(&gbl_args->init_barrier);
/* Loop packets */
- while (!gbl_args->exit_threads) {
+ while (!odp_atomic_load_u32(&gbl_args->exit_threads)) {
int sent;
unsigned tx_drops;
@@ -927,7 +927,7 @@ static int print_speed_stats(int num_workers, stats_t **thr_stats,
pkts_prev = pkts;
}
elapsed += timeout;
- } while (!gbl_args->exit_threads && (loop_forever ||
+ } while (!odp_atomic_load_u32(&gbl_args->exit_threads) && (loop_forever ||
(elapsed < duration)));
if (stats_enabled)
@@ -1503,6 +1503,7 @@ static void gbl_args_init(args_t *args)
int pktio, queue;
memset(args, 0, sizeof(args_t));
+ odp_atomic_init_u32(&args->exit_threads, 0);
for (pktio = 0; pktio < MAX_PKTIOS; pktio++) {
args->pktios[pktio].pktio = ODP_PKTIO_INVALID;
@@ -1852,7 +1853,7 @@ int main(int argc, char *argv[])
}
}
- gbl_args->exit_threads = 1;
+ odp_atomic_store_u32(&gbl_args->exit_threads, 1);
if (gbl_args->appl.in_mode != DIRECT_RECV)
odp_barrier_wait(&gbl_args->term_barrier);
diff --git a/test/performance/odp_packet_gen.c b/test/performance/odp_packet_gen.c
index eaca511e6..3287e7a9a 100644
--- a/test/performance/odp_packet_gen.c
+++ b/test/performance/odp_packet_gen.c
@@ -4,6 +4,11 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+/* enable usleep */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
#include <stdio.h>
#include <string.h>
#include <stdint.h>
@@ -11,6 +16,7 @@
#include <signal.h>
#include <stdlib.h>
#include <getopt.h>
+#include <unistd.h>
#include <odp_api.h>
#include <odp/helper/odph_api.h>
@@ -27,6 +33,7 @@
typedef struct test_options_t {
uint64_t gap_nsec;
uint64_t quit;
+ uint64_t update_msec;
uint32_t num_rx;
uint32_t num_tx;
uint32_t num_cpu;
@@ -79,6 +86,12 @@ typedef struct ODP_ALIGNED_CACHE thread_stat_t {
int thread_type;
+ struct {
+ uint64_t rx_packets;
+ uint64_t tx_packets;
+
+ } pktio[MAX_PKTIOS];
+
} thread_stat_t;
typedef struct test_global_t {
@@ -118,36 +131,38 @@ static void print_usage(void)
" At least one interface is required.\n"
"\n"
" Optional:\n"
- " -e, --eth_dst <mac> Destination MAC address. Comma-separated list of\n"
- " addresses (no spaces), one address per packet IO\n"
- " interface e.g. AA:BB:CC:DD:EE:FF,11:22:33:44:55:66\n"
- " Default per interface: 02:00:00:A0:B0:CX, where X = 0,1,...\n"
- " -v, --vlan <tpid:tci> VLAN configuration. Comma-separated list of VLAN TPID:TCI\n"
- " values in hexadecimal, starting from the outer most VLAN.\n"
- " For example:\n"
- " VLAN 200 (decimal): 8100:c8\n"
- " Double tagged VLANs 1 and 2: 88a8:1,8100:2\n"
- " -r, --num_rx Number of receive threads. Default: 1\n"
- " -t, --num_tx Number of transmit threads. Default: 1\n"
- " -n, --num_pkt Number of packets in the pool. Default: 1000\n"
- " -l, --len Packet length. Default: 512\n"
- " -b, --burst_size Transmit burst size. Default: 8\n"
- " -x, --bursts Number of bursts per one transmit round. Default: 1\n"
- " -g, --gap Gap between transmit rounds in nsec. Default: 1000000\n"
- " Transmit packet rate per interface:\n"
- " num_tx * burst_size * bursts * (10^9 / gap)\n"
- " -s, --ipv4_src IPv4 source address. Default: 192.168.0.1\n"
- " -d, --ipv4_dst IPv4 destination address. Default: 192.168.0.2\n"
- " -o, --udp_src UDP source port. Default: 10000\n"
- " -p, --udp_dst UDP destination port. Default: 20000\n"
- " -c, --c_mode <counts> Counter mode for incrementing UDP port numbers.\n"
- " Specify the number of port numbers used starting from\n"
- " udp_src/udp_dst. Comma-serarated (no spaces) list of\n"
- " count values: <udp_src count>,<udp_dst count>\n"
- " Default value: 0,0\n"
- " -q, --quit Quit after this many transmit rounds.\n"
- " Default: 0 (don't quit)\n"
- " -h, --help This help\n"
+ " -e, --eth_dst <mac> Destination MAC address. Comma-separated list of\n"
+ " addresses (no spaces), one address per packet IO\n"
+ " interface e.g. AA:BB:CC:DD:EE:FF,11:22:33:44:55:66\n"
+ " Default per interface: 02:00:00:A0:B0:CX, where X = 0,1,...\n"
+ " -v, --vlan <tpid:tci> VLAN configuration. Comma-separated list of VLAN TPID:TCI\n"
+ " values in hexadecimal, starting from the outer most VLAN.\n"
+ " For example:\n"
+ " VLAN 200 (decimal): 8100:c8\n"
+ " Double tagged VLANs 1 and 2: 88a8:1,8100:2\n"
+ " -r, --num_rx Number of receive threads. Default: 1\n"
+ " -t, --num_tx Number of transmit threads. Default: 1\n"
+ " -n, --num_pkt Number of packets in the pool. Default: 1000\n"
+ " -l, --len Packet length. Default: 512\n"
+ " -b, --burst_size Transmit burst size. Default: 8\n"
+ " -x, --bursts Number of bursts per one transmit round. Default: 1\n"
+ " -g, --gap Gap between transmit rounds in nsec. Default: 1000000\n"
+ " Transmit packet rate per interface:\n"
+ " num_tx * burst_size * bursts * (10^9 / gap)\n"
+ " -s, --ipv4_src IPv4 source address. Default: 192.168.0.1\n"
+ " -d, --ipv4_dst IPv4 destination address. Default: 192.168.0.2\n"
+ " -o, --udp_src UDP source port. Default: 10000\n"
+ " -p, --udp_dst UDP destination port. Default: 20000\n"
+ " -c, --c_mode <counts> Counter mode for incrementing UDP port numbers.\n"
+ " Specify the number of port numbers used starting from\n"
+ " udp_src/udp_dst. Comma-serarated (no spaces) list of\n"
+ " count values: <udp_src count>,<udp_dst count>\n"
+ " Default value: 0,0\n"
+ " -q, --quit Quit after this many transmit rounds.\n"
+ " Default: 0 (don't quit)\n"
+ " -u, --update_stat <msec> Update and print statistics every <msec> milliseconds.\n"
+ " 0: Don't print statistics periodically (default)\n"
+ " -h, --help This help\n"
"\n");
}
@@ -202,27 +217,28 @@ static int parse_options(int argc, char *argv[], test_global_t *global)
uint8_t default_eth_dst[6] = {0x02, 0x00, 0x00, 0xa0, 0xb0, 0xc0};
static const struct option longopts[] = {
- {"interface", required_argument, NULL, 'i'},
- {"eth_dst", required_argument, NULL, 'e'},
- {"num_rx", required_argument, NULL, 'r'},
- {"num_tx", required_argument, NULL, 't'},
- {"num_pkt", required_argument, NULL, 'n'},
- {"len", required_argument, NULL, 'l'},
- {"burst_size", required_argument, NULL, 'b'},
- {"bursts", required_argument, NULL, 'x'},
- {"gap", required_argument, NULL, 'g'},
- {"vlan", required_argument, NULL, 'v'},
- {"ipv4_src", required_argument, NULL, 's'},
- {"ipv4_dst", required_argument, NULL, 'd'},
- {"udp_src", required_argument, NULL, 'o'},
- {"udp_dst", required_argument, NULL, 'p'},
- {"c_mode", required_argument, NULL, 'c'},
- {"quit", required_argument, NULL, 'q'},
- {"help", no_argument, NULL, 'h'},
+ {"interface", required_argument, NULL, 'i'},
+ {"eth_dst", required_argument, NULL, 'e'},
+ {"num_rx", required_argument, NULL, 'r'},
+ {"num_tx", required_argument, NULL, 't'},
+ {"num_pkt", required_argument, NULL, 'n'},
+ {"len", required_argument, NULL, 'l'},
+ {"burst_size", required_argument, NULL, 'b'},
+ {"bursts", required_argument, NULL, 'x'},
+ {"gap", required_argument, NULL, 'g'},
+ {"vlan", required_argument, NULL, 'v'},
+ {"ipv4_src", required_argument, NULL, 's'},
+ {"ipv4_dst", required_argument, NULL, 'd'},
+ {"udp_src", required_argument, NULL, 'o'},
+ {"udp_dst", required_argument, NULL, 'p'},
+ {"c_mode", required_argument, NULL, 'c'},
+ {"quit", required_argument, NULL, 'q'},
+ {"update_stat", required_argument, NULL, 'u'},
+ {"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
- static const char *shortopts = "+i:e:r:t:n:l:b:x:g:v:s:d:o:p:c:q:h";
+ static const char *shortopts = "+i:e:r:t:n:l:b:x:g:v:s:d:o:p:c:q:u:h";
test_options->num_pktio = 0;
test_options->num_rx = 1;
@@ -244,6 +260,7 @@ static int parse_options(int argc, char *argv[], test_global_t *global)
test_options->c_mode.udp_src = 0;
test_options->c_mode.udp_dst = 0;
test_options->quit = 0;
+ test_options->update_msec = 0;
for (i = 0; i < MAX_PKTIOS; i++) {
memcpy(global->pktio[i].eth_dst.addr, default_eth_dst, 6);
@@ -375,6 +392,9 @@ static int parse_options(int argc, char *argv[], test_global_t *global)
case 'q':
test_options->quit = atoll(optarg);
break;
+ case 'u':
+ test_options->update_msec = atoll(optarg);
+ break;
case 'h':
/* fall through */
default:
@@ -764,9 +784,12 @@ static int rx_thread(void *arg)
{
int i, thr, num;
uint32_t exit_test;
+ uint64_t bytes;
odp_time_t t1, t2;
+ odp_packet_t pkt;
thread_arg_t *thread_arg = arg;
test_global_t *global = thread_arg->global;
+ int periodic_stat = global->test_options.update_msec ? 1 : 0;
uint64_t rx_timeouts = 0;
uint64_t rx_packets = 0;
uint64_t rx_bytes = 0;
@@ -808,15 +831,24 @@ static int rx_thread(void *arg)
clock_started = 1;
}
+ bytes = 0;
for (i = 0; i < num; i++) {
- odp_packet_t pkt;
-
pkt = odp_packet_from_event(ev[i]);
- rx_bytes += odp_packet_len(pkt);
+ bytes += odp_packet_len(pkt);
}
- odp_event_free_multi(ev, num);
rx_packets += num;
+ rx_bytes += bytes;
+
+ if (odp_unlikely(periodic_stat)) {
+ /* All packets from the same queue are from the same pktio interface */
+ int index = odp_packet_input_index(odp_packet_from_event(ev[0]));
+
+ if (index >= 0)
+ global->stat[thr].pktio[index].rx_packets += num;
+ }
+
+ odp_event_free_multi(ev, num);
}
t2 = odp_time_local();
@@ -864,6 +896,9 @@ static int init_packets(test_global_t *global, int pktio,
uint32_t udp_src_cnt = 0;
uint32_t udp_dst_cnt = 0;
+ if (num_vlan > MAX_VLANS)
+ num_vlan = MAX_VLANS;
+
for (i = 0; i < num; i++) {
pkt = packet[i];
pkt_len = odp_packet_len(pkt);
@@ -1003,6 +1038,7 @@ static int tx_thread(void *arg)
thread_arg_t *thread_arg = arg;
test_global_t *global = thread_arg->global;
test_options_t *test_options = &global->test_options;
+ int periodic_stat = test_options->update_msec ? 1 : 0;
odp_pool_t pool = global->pool;
uint64_t gap_nsec = test_options->gap_nsec;
uint64_t quit = test_options->quit;
@@ -1087,6 +1123,10 @@ static int tx_thread(void *arg)
tx_packets += sent;
if (odp_unlikely(sent < burst_size))
tx_drops += burst_size - sent;
+
+ if (odp_unlikely(periodic_stat))
+ global->stat[thr].pktio[i].tx_packets += sent;
+
}
}
}
@@ -1161,7 +1201,65 @@ static int start_workers(test_global_t *global, odp_instance_t instance)
return 0;
}
-static int print_stat(test_global_t *global)
+static void print_periodic_stat(test_global_t *global, uint64_t nsec)
+{
+ int i, j;
+ int num_pktio = global->test_options.num_pktio;
+ double sec = nsec / 1000000000.0;
+ uint64_t num_tx[num_pktio];
+ uint64_t num_rx[num_pktio];
+
+ for (i = 0; i < num_pktio; i++) {
+ num_tx[i] = 0;
+ num_rx[i] = 0;
+
+ for (j = 0; j < ODP_THREAD_COUNT_MAX; j++) {
+ if (global->stat[j].thread_type == RX_THREAD)
+ num_rx[i] += global->stat[j].pktio[i].rx_packets;
+ else if (global->stat[j].thread_type == TX_THREAD)
+ num_tx[i] += global->stat[j].pktio[i].tx_packets;
+ }
+ }
+
+ printf(" TX: %12.6fs", sec);
+ for (i = 0; i < num_pktio; i++)
+ printf(" %10" PRIu64 "", num_tx[i]);
+
+ printf("\n RX: %12.6fs", sec);
+ for (i = 0; i < num_pktio; i++)
+ printf(" %10" PRIu64 "", num_rx[i]);
+
+ printf("\n");
+}
+
+static void periodic_print_loop(test_global_t *global)
+{
+ odp_time_t t1, t2;
+ uint64_t nsec;
+ int i;
+ int num_pktio = global->test_options.num_pktio;
+
+ printf("\n\nPackets per interface\n");
+ printf(" Dir Time");
+ for (i = 0; i < num_pktio; i++)
+ printf(" %10i", i);
+
+ printf("\n -----------------");
+ for (i = 0; i < num_pktio; i++)
+ printf("-----------");
+
+ printf("\n");
+
+ t1 = odp_time_local();
+ while (odp_atomic_load_u32(&global->exit_test) == 0) {
+ usleep(1000 * global->test_options.update_msec);
+ t2 = odp_time_local();
+ nsec = odp_time_diff_ns(t2, t1);
+ print_periodic_stat(global, nsec);
+ }
+}
+
+static int print_final_stat(test_global_t *global)
{
int i, num_thr;
double rx_pkt_ave, rx_mbit_per_sec, tx_mbit_per_sec;
@@ -1378,6 +1476,10 @@ int main(int argc, char **argv)
/* Wait until workers have started. */
odp_barrier_wait(&global->barrier);
+ /* Periodic statistics printing */
+ if (global->test_options.update_msec)
+ periodic_print_loop(global);
+
/* Wait workers to exit */
odph_thread_join(global->thread_tbl,
global->test_options.num_cpu);
@@ -1390,7 +1492,7 @@ int main(int argc, char **argv)
if (close_pktios(global))
ret = -1;
- if (print_stat(global))
+ if (print_final_stat(global))
ret = -2;
term:
diff --git a/test/performance/odp_pktio_ordered.c b/test/performance/odp_pktio_ordered.c
index 46e6c1861..d5ffcc8ab 100644
--- a/test/performance/odp_pktio_ordered.c
+++ b/test/performance/odp_pktio_ordered.c
@@ -245,7 +245,7 @@ typedef struct {
/** Global barrier to synchronize main and workers */
odp_barrier_t barrier;
/** Break workers loop if set to 1 */
- int exit_threads;
+ odp_atomic_u32_t exit_threads;
} args_t;
/** Global pointer to args */
@@ -533,7 +533,7 @@ static int run_worker(void *arg)
odp_barrier_wait(&gbl_args->barrier);
/* Loop packets */
- while (!gbl_args->exit_threads) {
+ while (!odp_atomic_load_u32(&gbl_args->exit_threads)) {
pkts = odp_schedule_multi(&queue, ODP_SCHED_NO_WAIT, ev_tbl,
MAX_PKT_BURST);
if (pkts <= 0)
@@ -1034,6 +1034,7 @@ static void gbl_args_init(args_t *args)
int pktio, queue;
memset(args, 0, sizeof(args_t));
+ odp_atomic_init_u32(&args->exit_threads, 0);
for (pktio = 0; pktio < MAX_PKTIOS; pktio++) {
args->pktios[pktio].pktio = ODP_PKTIO_INVALID;
@@ -1320,7 +1321,7 @@ int main(int argc, char *argv[])
for (i = 0; i < if_count; i++)
odp_pktio_stop(gbl_args->pktios[i].pktio);
- gbl_args->exit_threads = 1;
+ odp_atomic_store_u32(&gbl_args->exit_threads, 1);
/* Master thread waits for other threads to exit */
for (i = 0; i < num_workers; ++i)
diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
index f31f6146c..3418f62f4 100644
--- a/test/performance/odp_pktio_perf.c
+++ b/test/performance/odp_pktio_perf.c
@@ -822,7 +822,7 @@ static int test_init(void)
static int empty_inq(odp_pktio_t pktio)
{
- odp_queue_t queue;
+ odp_queue_t queue = ODP_QUEUE_INVALID;
odp_event_t ev;
odp_queue_type_t q_type;
diff --git a/test/performance/odp_sched_pktio.c b/test/performance/odp_sched_pktio.c
index 8eb094873..fc814c541 100644
--- a/test/performance/odp_sched_pktio.c
+++ b/test/performance/odp_sched_pktio.c
@@ -1426,7 +1426,7 @@ int main(int argc, char *argv[])
odp_instance_t instance;
odp_init_t init;
odp_shm_t shm;
- odp_time_t t1, t2;
+ odp_time_t t1 = ODP_TIME_NULL, t2 = ODP_TIME_NULL;
odph_helper_options_t helper_options;
odph_odpthread_t thread[MAX_WORKERS];
test_options_t test_options;
diff --git a/test/validation/api/crypto/odp_crypto_test_inp.c b/test/validation/api/crypto/odp_crypto_test_inp.c
index 1710c23e2..b14b3d484 100644
--- a/test/validation/api/crypto/odp_crypto_test_inp.c
+++ b/test/validation/api/crypto/odp_crypto_test_inp.c
@@ -514,10 +514,6 @@ static void check_alg(odp_crypto_op_t op,
int rc, i;
int cipher_num = odp_crypto_cipher_capability(cipher_alg, NULL, 0);
int auth_num = odp_crypto_auth_capability(auth_alg, NULL, 0);
- odp_crypto_cipher_capability_t cipher_capa[cipher_num];
- odp_crypto_auth_capability_t auth_capa[auth_num];
- odp_bool_t cipher_tested[cipher_num];
- odp_bool_t auth_tested[auth_num];
odp_bool_t cipher_ok = false;
odp_bool_t auth_ok = false;
size_t idx;
@@ -525,6 +521,11 @@ static void check_alg(odp_crypto_op_t op,
CU_ASSERT_FATAL(cipher_num > 0);
CU_ASSERT_FATAL(auth_num > 0);
+ odp_crypto_cipher_capability_t cipher_capa[cipher_num];
+ odp_crypto_auth_capability_t auth_capa[auth_num];
+ odp_bool_t cipher_tested[cipher_num];
+ odp_bool_t auth_tested[auth_num];
+
rc = odp_crypto_capability(&capa);
CU_ASSERT(!rc);
diff --git a/test/validation/api/packet/packet.c b/test/validation/api/packet/packet.c
index 6026ca32a..51d251630 100644
--- a/test/validation/api/packet/packet.c
+++ b/test/validation/api/packet/packet.c
@@ -862,7 +862,7 @@ static void _verify_headroom_shift(odp_packet_t *pkt,
uint32_t room = odp_packet_headroom(*pkt);
uint32_t seg_data_len = odp_packet_seg_len(*pkt);
uint32_t pkt_data_len = odp_packet_len(*pkt);
- void *data;
+ void *data = NULL;
char *data_orig = odp_packet_data(*pkt);
char *head_orig = odp_packet_head(*pkt);
uint32_t seg_len;
@@ -1571,7 +1571,7 @@ static void packet_test_concatsplit(void)
{
odp_packet_t pkt, pkt2;
uint32_t pkt_len;
- odp_packet_t splits[4];
+ odp_packet_t splits[4] = {ODP_PACKET_INVALID};
odp_pool_t pool;
pool = odp_packet_pool(test_packet);
diff --git a/test/validation/api/pktio/parser.c b/test/validation/api/pktio/parser.c
index 896855006..9c493b45e 100644
--- a/test/validation/api/pktio/parser.c
+++ b/test/validation/api/pktio/parser.c
@@ -56,7 +56,7 @@ static inline void wait_linkup(odp_pktio_t pktio)
for (i = 0; i < wait_num; i++) {
ret = odp_pktio_link_status(pktio);
- if (ret < 0 || ret == 1)
+ if (ret == ODP_PKTIO_LINK_STATUS_UNKNOWN || ret == ODP_PKTIO_LINK_STATUS_UP)
break;
/* link is down, call status again after delay */
odp_time_wait_ns(wait_ns);
diff --git a/test/validation/api/pktio/pktio.c b/test/validation/api/pktio/pktio.c
index 20c33b461..4fa8f6d13 100644
--- a/test/validation/api/pktio/pktio.c
+++ b/test/validation/api/pktio/pktio.c
@@ -1,4 +1,5 @@
/* Copyright (c) 2014-2018, Linaro Limited
+ * Copyright (c) 2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -111,7 +112,7 @@ static inline void _pktio_wait_linkup(odp_pktio_t pktio)
for (i = 0; i < wait_num; i++) {
ret = odp_pktio_link_status(pktio);
- if (ret < 0 || ret == 1)
+ if (ret == ODP_PKTIO_LINK_STATUS_UNKNOWN || ret == ODP_PKTIO_LINK_STATUS_UP)
break;
/* link is down, call status again after delay */
odp_time_wait_ns(wait_ns);
@@ -649,7 +650,7 @@ static int recv_packets_tmo(odp_pktio_t pktio, odp_packet_t pkt_tbl[],
int num_q;
int i;
int n;
- unsigned from_val;
+ unsigned int from_val = 0;
unsigned *from = NULL;
if (mode == RECV_MQ_TMO)
@@ -1480,6 +1481,44 @@ static void pktio_test_info(void)
}
}
+static void pktio_test_link_info(void)
+{
+ odp_pktio_t pktio;
+ odp_pktio_link_info_t link_info;
+ int i;
+
+ for (i = 0; i < num_ifaces; i++) {
+ memset(&link_info, 0, sizeof(link_info));
+
+ pktio = create_pktio(i, ODP_PKTIN_MODE_QUEUE,
+ ODP_PKTOUT_MODE_DIRECT);
+ CU_ASSERT_FATAL(pktio != ODP_PKTIO_INVALID);
+
+ CU_ASSERT_FATAL(odp_pktio_link_info(pktio, &link_info) == 0);
+
+ CU_ASSERT(link_info.autoneg == ODP_PKTIO_LINK_AUTONEG_UNKNOWN ||
+ link_info.autoneg == ODP_PKTIO_LINK_AUTONEG_ON ||
+ link_info.autoneg == ODP_PKTIO_LINK_AUTONEG_OFF);
+ CU_ASSERT(link_info.duplex == ODP_PKTIO_LINK_DUPLEX_UNKNOWN ||
+ link_info.duplex == ODP_PKTIO_LINK_DUPLEX_HALF ||
+ link_info.duplex == ODP_PKTIO_LINK_DUPLEX_FULL);
+ CU_ASSERT(link_info.pause_rx == ODP_PKTIO_LINK_PAUSE_UNKNOWN ||
+ link_info.pause_rx == ODP_PKTIO_LINK_PAUSE_ON ||
+ link_info.pause_rx == ODP_PKTIO_LINK_PAUSE_OFF);
+ CU_ASSERT(link_info.pause_tx == ODP_PKTIO_LINK_PAUSE_UNKNOWN ||
+ link_info.pause_tx == ODP_PKTIO_LINK_PAUSE_ON ||
+ link_info.pause_tx == ODP_PKTIO_LINK_PAUSE_OFF);
+ CU_ASSERT(link_info.status == ODP_PKTIO_LINK_STATUS_UNKNOWN ||
+ link_info.status == ODP_PKTIO_LINK_STATUS_UP ||
+ link_info.status == ODP_PKTIO_LINK_STATUS_DOWN);
+ CU_ASSERT(link_info.media != NULL);
+
+ CU_ASSERT(odp_pktio_link_info(ODP_PKTIO_INVALID, &link_info) < 0);
+
+ CU_ASSERT(odp_pktio_close(pktio) == 0);
+ }
+}
+
static void pktio_test_pktin_queue_config_direct(void)
{
odp_pktio_t pktio;
@@ -1745,7 +1784,7 @@ static void pktio_test_statistics_counters(void)
pktio_tx = pktio[0];
pktio_rx = (num_ifaces > 1) ? pktio[1] : pktio_tx;
- CU_ASSERT(odp_pktout_queue(pktio_tx, &pktout, 1) == 1);
+ CU_ASSERT_FATAL(odp_pktout_queue(pktio_tx, &pktout, 1) == 1);
ret = odp_pktio_start(pktio_tx);
CU_ASSERT(ret == 0);
@@ -1849,7 +1888,7 @@ static void pktio_test_start_stop(void)
CU_ASSERT_FATAL(pktio[i] != ODP_PKTIO_INVALID);
}
- CU_ASSERT(odp_pktout_queue(pktio[0], &pktout, 1) == 1);
+ CU_ASSERT_FATAL(odp_pktout_queue(pktio[0], &pktout, 1) == 1);
/* Interfaces are stopped by default,
* Check that stop when stopped generates an error */
@@ -2908,6 +2947,7 @@ odp_testinfo_t pktio_suite_unsegmented[] = {
ODP_TEST_INFO(pktio_test_print),
ODP_TEST_INFO(pktio_test_pktio_config),
ODP_TEST_INFO(pktio_test_info),
+ ODP_TEST_INFO(pktio_test_link_info),
ODP_TEST_INFO(pktio_test_pktin_queue_config_direct),
ODP_TEST_INFO(pktio_test_pktin_queue_config_sched),
ODP_TEST_INFO(pktio_test_pktin_queue_config_multi_sched),
diff --git a/test/validation/api/pool/pool.c b/test/validation/api/pool/pool.c
index 24b47d4fb..7ac92ff0e 100644
--- a/test/validation/api/pool/pool.c
+++ b/test/validation/api/pool/pool.c
@@ -83,6 +83,7 @@ static void pool_test_lookup_info_print(void)
odp_pool_info_t info;
odp_pool_param_t param;
+ memset(&info, 0, sizeof(info));
odp_pool_param_init(&param);
param.type = ODP_POOL_BUFFER;
@@ -321,6 +322,7 @@ static void pool_test_info_packet(void)
odp_pool_param_t param;
const char pool_name[] = "test_pool_name";
+ memset(&info, 0, sizeof(info));
odp_pool_param_init(&param);
param.type = ODP_POOL_PACKET;
@@ -351,6 +353,7 @@ static void pool_test_info_data_range(void)
uint32_t i, num;
uintptr_t pool_len;
+ memset(&info, 0, sizeof(info));
odp_pool_param_init(&param);
param.type = ODP_POOL_PACKET;
diff --git a/test/validation/api/queue/queue.c b/test/validation/api/queue/queue.c
index 9b4ebd44c..a5ec628e4 100644
--- a/test/validation/api/queue/queue.c
+++ b/test/validation/api/queue/queue.c
@@ -580,8 +580,8 @@ static void queue_test_pair_lf_spsc(void)
static void queue_test_param(void)
{
odp_queue_t queue, null_queue;
- odp_event_t enev[BURST_SIZE];
- odp_event_t deev[BURST_SIZE];
+ odp_event_t enev[BURST_SIZE] = {ODP_EVENT_INVALID};
+ odp_event_t deev[BURST_SIZE] = {ODP_EVENT_INVALID};
odp_buffer_t buf;
odp_event_t ev;
odp_pool_t msg_pool;
diff --git a/test/validation/api/random/random.c b/test/validation/api/random/random.c
index cf7163e2d..481ceb303 100644
--- a/test/validation/api/random/random.c
+++ b/test/validation/api/random/random.c
@@ -9,11 +9,31 @@
static void random_test_get_size(void)
{
- int32_t ret;
+ /* odp_random_data may fail to return data on every call (i.e. lack of
+ * entropy). Therefore loop with some sane loop timeout value. Note that
+ * it is not required for implementation to return data in the "timeout"
+ * amount of steps. Rather it is a way for preventing the test to loop
+ * forever.
+ * Also note that the timeout value here is chosen completely
+ * arbitrarily (although considered sane) and neither platforms or
+ * applications are not required to use it.
+ */
+ int32_t ret, timeout_ns = 1 * ODP_TIME_MSEC_IN_NS, sleep_ns = 100;
+ uint32_t bytes = 0;
uint8_t buf[32];
- ret = odp_random_data(buf, sizeof(buf), ODP_RANDOM_BASIC);
- CU_ASSERT(ret == sizeof(buf));
+ do {
+ ret = odp_random_data(buf + bytes, sizeof(buf) - bytes,
+ ODP_RANDOM_BASIC);
+ bytes += ret;
+ if (ret < 0 || bytes >= sizeof(buf))
+ break;
+ odp_time_wait_ns(sleep_ns);
+ timeout_ns -= sleep_ns;
+ } while (timeout_ns > 0);
+
+ CU_ASSERT(ret > 0);
+ CU_ASSERT(bytes == (int32_t)sizeof(buf));
}
static void random_test_kind(void)
diff --git a/test/validation/api/time/time.c b/test/validation/api/time/time.c
index 3add81976..2b1efa8af 100644
--- a/test/validation/api/time/time.c
+++ b/test/validation/api/time/time.c
@@ -26,6 +26,7 @@ static uint64_t global_res;
typedef odp_time_t time_cb(void);
typedef uint64_t time_res_cb(void);
typedef odp_time_t time_from_ns_cb(uint64_t ns);
+typedef uint64_t time_nsec_cb(void);
static void time_test_constants(void)
{
@@ -120,10 +121,14 @@ static void time_test_monotony(void)
volatile uint64_t count = 0;
odp_time_t l_t1, l_t2, l_t3;
odp_time_t g_t1, g_t2, g_t3;
+ uint64_t lns_t1, lns_t2, lns_t3;
+ uint64_t gns_t1, gns_t2, gns_t3;
uint64_t ns1, ns2, ns3;
l_t1 = odp_time_local();
g_t1 = odp_time_global();
+ lns_t1 = odp_time_local_ns();
+ gns_t1 = odp_time_global_ns();
while (count < BUSY_LOOP_CNT) {
count++;
@@ -131,6 +136,8 @@ static void time_test_monotony(void)
l_t2 = odp_time_local();
g_t2 = odp_time_global();
+ lns_t2 = odp_time_local_ns();
+ gns_t2 = odp_time_global_ns();
while (count < BUSY_LOOP_CNT_LONG) {
count++;
@@ -138,6 +145,8 @@ static void time_test_monotony(void)
l_t3 = odp_time_local();
g_t3 = odp_time_global();
+ lns_t3 = odp_time_local_ns();
+ gns_t3 = odp_time_global_ns();
ns1 = odp_time_to_ns(l_t1);
ns2 = odp_time_to_ns(l_t2);
@@ -154,6 +163,14 @@ static void time_test_monotony(void)
/* Global time assertions */
CU_ASSERT(ns2 > ns1);
CU_ASSERT(ns3 > ns2);
+
+ /* Local time in nsec */
+ CU_ASSERT(lns_t2 > lns_t1);
+ CU_ASSERT(lns_t3 > lns_t2);
+
+ /* Global time in nsec */
+ CU_ASSERT(gns_t2 > gns_t1);
+ CU_ASSERT(gns_t3 > gns_t2);
}
static void time_test_cmp(time_cb time_cur, time_from_ns_cb time_from_ns)
@@ -481,6 +498,51 @@ static void time_test_global_accuracy(void)
time_test_accuracy(odp_time_global, odp_time_global_from_ns);
}
+static void time_test_accuracy_nsec(time_nsec_cb time_nsec)
+{
+ uint64_t t1, t2, diff;
+ struct timespec ts1, ts2, tsdiff;
+ double sec_t, sec_c;
+ int i, ret;
+
+ ret = clock_gettime(CLOCK_MONOTONIC, &ts1);
+ CU_ASSERT(ret == 0);
+ t1 = time_nsec();
+
+ for (i = 0; i < 5; i++)
+ odp_time_wait_ns(ODP_TIME_SEC_IN_NS);
+
+ ret = clock_gettime(CLOCK_MONOTONIC, &ts2);
+ CU_ASSERT(ret == 0);
+ t2 = time_nsec();
+
+ if (ts2.tv_nsec < ts1.tv_nsec) {
+ tsdiff.tv_nsec = 1000000000L + ts2.tv_nsec - ts1.tv_nsec;
+ tsdiff.tv_sec = ts2.tv_sec - 1 - ts1.tv_sec;
+ } else {
+ tsdiff.tv_nsec = ts2.tv_nsec - ts1.tv_nsec;
+ tsdiff.tv_sec = ts2.tv_sec - ts1.tv_sec;
+ }
+
+ diff = t2 - t1;
+ sec_t = ((double)diff) / ODP_TIME_SEC_IN_NS;
+ sec_c = ((double)(tsdiff.tv_nsec) / 1000000000L) + tsdiff.tv_sec;
+
+ /* Check that ODP time is within +-5% of system time */
+ CU_ASSERT(sec_t < sec_c * 1.05);
+ CU_ASSERT(sec_t > sec_c * 0.95);
+}
+
+static void time_test_local_accuracy_nsec(void)
+{
+ time_test_accuracy_nsec(odp_time_local_ns);
+}
+
+static void time_test_global_accuracy_nsec(void)
+{
+ time_test_accuracy_nsec(odp_time_global_ns);
+}
+
odp_testinfo_t time_suite_time[] = {
ODP_TEST_INFO(time_test_constants),
ODP_TEST_INFO(time_test_local_res),
@@ -499,6 +561,8 @@ odp_testinfo_t time_suite_time[] = {
ODP_TEST_INFO(time_test_global_sum),
ODP_TEST_INFO(time_test_global_wait_until),
ODP_TEST_INFO(time_test_global_accuracy),
+ ODP_TEST_INFO(time_test_local_accuracy_nsec),
+ ODP_TEST_INFO(time_test_global_accuracy_nsec),
ODP_TEST_INFO_NULL
};
diff --git a/test/validation/api/timer/timer.c b/test/validation/api/timer/timer.c
index b2c4b8964..09f8fc467 100644
--- a/test/validation/api/timer/timer.c
+++ b/test/validation/api/timer/timer.c
@@ -1,4 +1,5 @@
/* Copyright (c) 2015-2018, Linaro Limited
+ * Copyright (c) 2019-2020, Nokia
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -189,12 +190,20 @@ static void timer_test_capa(void)
CU_ASSERT_FATAL(ret == 0);
CU_ASSERT(capa.highest_res_ns == capa.max_res.res_ns);
+ /* Assuming max resoultion to be 100 msec or better */
+ CU_ASSERT(capa.max_res.res_ns <= 100000000);
+ CU_ASSERT(capa.max_res.res_hz >= 10);
CU_ASSERT(capa.max_res.res_ns < capa.max_res.max_tmo);
CU_ASSERT(capa.max_res.min_tmo < capa.max_res.max_tmo);
+
+ /* With max timeout, resolution may be low (worse than 1 sec) */
CU_ASSERT(capa.max_tmo.res_ns < capa.max_tmo.max_tmo);
CU_ASSERT(capa.max_tmo.min_tmo < capa.max_tmo.max_tmo);
+ CU_ASSERT(capa.max_tmo.res_ns != 0 || capa.max_tmo.res_hz != 0);
+ if (capa.max_tmo.res_hz == 0)
+ CU_ASSERT(capa.max_tmo.res_ns > 1000000000);
- /* Set max resolution */
+ /* Set max resolution in nsec */
memset(&res_capa, 0, sizeof(res_capa));
res_capa.res_ns = capa.max_res.res_ns;
@@ -204,6 +213,16 @@ static void timer_test_capa(void)
CU_ASSERT(res_capa.min_tmo == capa.max_res.min_tmo);
CU_ASSERT(res_capa.max_tmo == capa.max_res.max_tmo);
+ /* Set max resolution in hz */
+ memset(&res_capa, 0, sizeof(res_capa));
+ res_capa.res_hz = capa.max_res.res_hz;
+
+ ret = odp_timer_res_capability(ODP_CLOCK_CPU, &res_capa);
+ CU_ASSERT_FATAL(ret == 0);
+ CU_ASSERT(res_capa.res_hz == capa.max_res.res_hz);
+ CU_ASSERT(res_capa.min_tmo == capa.max_res.min_tmo);
+ CU_ASSERT(res_capa.max_tmo == capa.max_res.max_tmo);
+
/* Set max timeout */
memset(&res_capa, 0, sizeof(res_capa));
res_capa.max_tmo = capa.max_tmo.max_tmo;
@@ -213,6 +232,7 @@ static void timer_test_capa(void)
CU_ASSERT(res_capa.max_tmo == capa.max_tmo.max_tmo);
CU_ASSERT(res_capa.min_tmo == capa.max_tmo.min_tmo);
CU_ASSERT(res_capa.res_ns == capa.max_tmo.res_ns);
+ CU_ASSERT(res_capa.res_hz == capa.max_tmo.res_hz);
}
static void timer_test_timeout_pool_alloc(void)
@@ -367,6 +387,88 @@ static void timer_pool_create_destroy(void)
CU_ASSERT(odp_queue_destroy(queue) == 0);
}
+static void timer_pool_max_res(void)
+{
+ odp_timer_capability_t capa;
+ odp_timer_pool_param_t tp_param;
+ odp_timer_pool_t tp;
+ odp_timer_t timer;
+ odp_pool_param_t pool_param;
+ odp_pool_t pool;
+ odp_queue_t queue;
+ odp_timeout_t tmo;
+ odp_event_t ev;
+ uint64_t tick;
+ int ret, i;
+
+ memset(&capa, 0, sizeof(capa));
+ ret = odp_timer_capability(ODP_CLOCK_CPU, &capa);
+ CU_ASSERT_FATAL(ret == 0);
+
+ odp_pool_param_init(&pool_param);
+ pool_param.type = ODP_POOL_TIMEOUT;
+ pool_param.tmo.num = 10;
+ pool = odp_pool_create("timeout_pool", &pool_param);
+ CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+ queue = odp_queue_create("timer_queue", NULL);
+ CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+ /* Highest resolution: first in nsec, then in hz */
+ for (i = 0; i < 2; i++) {
+ memset(&tp_param, 0, sizeof(odp_timer_pool_param_t));
+
+ if (i == 0) {
+ printf("\n Highest resolution %" PRIu64 " nsec\n",
+ capa.max_res.res_ns);
+ tp_param.res_ns = capa.max_res.res_ns;
+ } else {
+ printf(" Highest resolution %" PRIu64 " Hz\n",
+ capa.max_res.res_hz);
+ tp_param.res_hz = capa.max_res.res_hz;
+ }
+
+ tp_param.min_tmo = capa.max_res.min_tmo;
+ tp_param.max_tmo = capa.max_res.max_tmo;
+ tp_param.num_timers = 100;
+ tp_param.priv = 0;
+ tp_param.clk_src = ODP_CLOCK_CPU;
+
+ tp = odp_timer_pool_create("high_res_tp", &tp_param);
+ CU_ASSERT_FATAL(tp != ODP_TIMER_POOL_INVALID);
+
+ odp_timer_pool_start();
+
+ /* Maximum timeout length with maximum resolution */
+ tick = odp_timer_ns_to_tick(tp, capa.max_res.max_tmo);
+
+ timer = odp_timer_alloc(tp, queue, USER_PTR);
+ CU_ASSERT_FATAL(timer != ODP_TIMER_INVALID);
+
+ tmo = odp_timeout_alloc(pool);
+ ev = odp_timeout_to_event(tmo);
+ CU_ASSERT_FATAL(ev != ODP_EVENT_INVALID);
+
+ ret = odp_timer_set_rel(timer, tick, &ev);
+ CU_ASSERT(ret == ODP_TIMER_SUCCESS);
+
+ ev = ODP_EVENT_INVALID;
+ ret = odp_timer_cancel(timer, &ev);
+ CU_ASSERT(ret == 0);
+
+ if (ret == 0) {
+ CU_ASSERT(ev != ODP_EVENT_INVALID);
+ odp_event_free(ev);
+ }
+
+ CU_ASSERT(odp_timer_free(timer) == ODP_EVENT_INVALID);
+ odp_timer_pool_destroy(tp);
+ }
+
+ CU_ASSERT(odp_queue_destroy(queue) == 0);
+ CU_ASSERT(odp_pool_destroy(pool) == 0);
+}
+
static void timer_test_event_type(odp_queue_type_t queue_type,
odp_event_type_t event_type)
{
@@ -566,6 +668,7 @@ static void timer_test_queue_type(odp_queue_type_t queue_type, int priv)
res_ns = global_mem->param.res_ns;
+ memset(&tparam, 0, sizeof(odp_timer_pool_param_t));
tparam.res_ns = global_mem->param.res_ns;
tparam.min_tmo = global_mem->param.min_tmo;
tparam.max_tmo = global_mem->param.max_tmo;
@@ -738,6 +841,7 @@ static void timer_test_cancel(void)
if (pool == ODP_POOL_INVALID)
CU_FAIL_FATAL("Timeout pool create failed");
+ memset(&tparam, 0, sizeof(odp_timer_pool_param_t));
tparam.res_ns = global_mem->param.res_ns;
tparam.min_tmo = global_mem->param.min_tmo;
tparam.max_tmo = global_mem->param.max_tmo;
@@ -1356,6 +1460,7 @@ static void timer_test_all(void)
max_tmo = global_mem->param.max_tmo;
min_tmo = global_mem->param.min_tmo;
+ memset(&tparam, 0, sizeof(odp_timer_pool_param_t));
tparam.res_ns = res_ns;
tparam.min_tmo = min_tmo;
tparam.max_tmo = max_tmo;
@@ -1455,6 +1560,7 @@ odp_testinfo_t timer_suite[] = {
ODP_TEST_INFO(timer_test_timeout_pool_alloc),
ODP_TEST_INFO(timer_test_timeout_pool_free),
ODP_TEST_INFO(timer_pool_create_destroy),
+ ODP_TEST_INFO(timer_pool_max_res),
ODP_TEST_INFO(timer_test_tmo_event_plain),
ODP_TEST_INFO(timer_test_tmo_event_sched),
ODP_TEST_INFO(timer_test_buf_event_plain),
diff --git a/test/validation/api/traffic_mngr/traffic_mngr.c b/test/validation/api/traffic_mngr/traffic_mngr.c
index 2b0b99325..b5132bc12 100644
--- a/test/validation/api/traffic_mngr/traffic_mngr.c
+++ b/test/validation/api/traffic_mngr/traffic_mngr.c
@@ -456,7 +456,7 @@ static int wait_linkup(odp_pktio_t pktio)
for (i = 0; i < wait_num; i++) {
ret = odp_pktio_link_status(pktio);
- if (ret < 0 || ret == 1)
+ if (ret == ODP_PKTIO_LINK_STATUS_UNKNOWN || ret == ODP_PKTIO_LINK_STATUS_UP)
break;
/* link is down, call status again after delay */
odp_time_wait_ns(wait_ns);
@@ -1324,7 +1324,8 @@ static int create_tm_queue(odp_tm_t odp_tm,
queue_desc->tm_queues[priority] = tm_queue;
rc = odp_tm_queue_connect(tm_queue, tm_node);
if (rc != 0) {
- ODPH_ERR("odp_tm_queue_connect() failed\n");
+ ODPH_ERR("odp_tm_queue_connect() failed for queue %" PRIx64
+ "\n", odp_tm_queue_to_u64(tm_queue));
odp_tm_queue_destroy(tm_queue);
return -1;
}
@@ -1652,7 +1653,8 @@ static int create_tm_system(void)
/* Test odp_tm_capability and odp_tm_find. */
rc = odp_tm_capability(odp_tm, &tm_capabilities);
if (rc != 0) {
- ODPH_ERR("odp_tm_capability() failed\n");
+ ODPH_ERR("odp_tm_capability() failed for tm: %" PRIx64 "\n",
+ odp_tm_to_u64(odp_tm));
return -1;
}
@@ -1677,7 +1679,7 @@ static void dump_tm_subtree(tm_node_desc_t *node_desc)
rc = odp_tm_node_info(node_desc->node, &node_info);
if (rc != 0) {
ODPH_ERR("odp_tm_node_info failed for tm_node=0x%" PRIX64 "\n",
- node_desc->node);
+ odp_tm_node_to_u64(node_desc->node));
}
num_queues = 0;
@@ -1688,8 +1690,9 @@ static void dump_tm_subtree(tm_node_desc_t *node_desc)
"level=%" PRIu32" parent=0x%" PRIX64 " children=%" PRIu32 " "
"queues=%" PRIu32 " queue_fanin=%" PRIu32 " "
"node_fanin=%" PRIu32 "\n",
- node_desc, node_desc->node_name, node_desc->node,
- node_desc->node_idx, node_desc->level, node_desc->parent_node,
+ node_desc, node_desc->node_name,
+ odp_tm_node_to_u64(node_desc->node), node_desc->node_idx,
+ node_desc->level, odp_tm_node_to_u64(node_desc->parent_node),
node_desc->num_children, num_queues, node_info.tm_queue_fanin,
node_info.tm_node_fanin);
@@ -1912,7 +1915,10 @@ static int destroy_all_shaper_profiles(void)
rc = odp_tm_shaper_destroy(shaper_profile);
if (rc != 0) {
ODPH_ERR("odp_tm_sched_destroy failed "
- "idx=%" PRIu32 " code=%d\n", idx, rc);
+ "node=%" PRIx64 " idx=%" PRIu32
+ " code=%d\n",
+ odp_tm_shaper_to_u64(shaper_profile),
+ idx, rc);
return rc;
}
shaper_profiles[idx] = ODP_TM_INVALID;
@@ -1934,7 +1940,10 @@ static int destroy_all_sched_profiles(void)
rc = odp_tm_sched_destroy(sched_profile);
if (rc != 0) {
ODPH_ERR("odp_tm_sched_destroy failed "
- "idx=%" PRIu32 " code=%d\n", idx, rc);
+ "node=%" PRIx64 " idx=%" PRIu32
+ " code=%d\n",
+ odp_tm_sched_to_u64(sched_profile),
+ idx, rc);
return rc;
}
sched_profiles[idx] = ODP_TM_INVALID;
@@ -1946,17 +1955,20 @@ static int destroy_all_sched_profiles(void)
static int destroy_all_threshold_profiles(void)
{
- odp_tm_threshold_t threshold_profile;
+ odp_tm_threshold_t thr_profile;
uint32_t idx;
int rc;
for (idx = 0; idx < NUM_THRESHOLD_PROFILES; idx++) {
- threshold_profile = threshold_profiles[idx];
- if (threshold_profile != ODP_TM_INVALID) {
- rc = odp_tm_threshold_destroy(threshold_profile);
+ thr_profile = threshold_profiles[idx];
+ if (thr_profile != ODP_TM_INVALID) {
+ rc = odp_tm_threshold_destroy(thr_profile);
if (rc != 0) {
ODPH_ERR("odp_tm_threshold_destroy failed "
- "idx=%" PRIu32 " code=%d\n", idx, rc);
+ "node=%" PRIx64 " idx=%" PRIu32
+ " code=%d\n",
+ odp_tm_threshold_to_u64(thr_profile),
+ idx, rc);
return rc;
}
threshold_profiles[idx] = ODP_TM_INVALID;
@@ -1968,19 +1980,20 @@ static int destroy_all_threshold_profiles(void)
static int destroy_all_wred_profiles(void)
{
- odp_tm_wred_t wred_profile;
+ odp_tm_wred_t wred_prof;
uint32_t idx, color;
int rc;
for (idx = 0; idx < NUM_WRED_PROFILES; idx++) {
for (color = 0; color < ODP_NUM_PKT_COLORS; color++) {
- wred_profile = wred_profiles[idx][color];
- if (wred_profile != ODP_TM_INVALID) {
- rc = odp_tm_wred_destroy(wred_profile);
+ wred_prof = wred_profiles[idx][color];
+ if (wred_prof != ODP_TM_INVALID) {
+ rc = odp_tm_wred_destroy(wred_prof);
if (rc != 0) {
ODPH_ERR("odp_tm_wred_destroy failed "
- "idx=%" PRIu32 " "
- "color=%" PRIu32 " code=%d\n",
+ "node=%" PRIx64 " idx=%" PRIu32
+ " color=%" PRIu32 " code=%d\n",
+ odp_tm_wred_to_u64(wred_prof),
idx, color, rc);
return rc;
}
@@ -2114,6 +2127,7 @@ static void check_shaper_profile(char *shaper_name, uint32_t shaper_idx)
{
odp_tm_shaper_params_t shaper_params;
odp_tm_shaper_t profile;
+ int rc;
profile = odp_tm_shaper_lookup(shaper_name);
CU_ASSERT(profile != ODP_TM_INVALID);
@@ -2121,7 +2135,9 @@ static void check_shaper_profile(char *shaper_name, uint32_t shaper_idx)
if (profile != shaper_profiles[shaper_idx - 1])
return;
- odp_tm_shaper_params_read(profile, &shaper_params);
+ memset(&shaper_params, 0, sizeof(shaper_params));
+ rc = odp_tm_shaper_params_read(profile, &shaper_params);
+ CU_ASSERT(rc == 0);
CU_ASSERT(approx_eq64(shaper_params.commit_bps,
shaper_idx * MIN_COMMIT_BW));
CU_ASSERT(approx_eq64(shaper_params.peak_bps,
@@ -2211,7 +2227,7 @@ static void traffic_mngr_test_sched_profile(void)
for (idx = 1; idx <= NUM_SCHED_TEST_PROFILES; idx++) {
snprintf(sched_name, sizeof(sched_name),
"sched_profile_%" PRIu32, idx);
- for (priority = 0; priority < 16; priority++) {
+ for (priority = 0; priority < ODP_TM_MAX_PRIORITIES; priority++) {
sched_params.sched_modes[priority] =
ODP_TM_BYTE_BASED_WEIGHTS;
sched_params.sched_weights[priority] = 8 + idx +
@@ -3276,6 +3292,7 @@ static int test_query_functions(const char *shaper_name,
expected_pkt_cnt = num_pkts - 2;
expected_byte_cnt = expected_pkt_cnt * PKT_BUF_SIZE;
+ memset(&query_info, 0, sizeof(query_info));
rc = odp_tm_queue_query(tm_queue,
ODP_TM_QUERY_PKT_CNT | ODP_TM_QUERY_BYTE_CNT,
&query_info);
@@ -3285,6 +3302,7 @@ static int test_query_functions(const char *shaper_name,
CU_ASSERT(query_info.total_byte_cnt_valid);
CU_ASSERT(expected_byte_cnt < query_info.total_byte_cnt);
+ memset(&query_info, 0, sizeof(query_info));
rc = odp_tm_priority_query(odp_tm_systems[0], priority,
ODP_TM_QUERY_PKT_CNT | ODP_TM_QUERY_BYTE_CNT,
&query_info);
@@ -3294,6 +3312,7 @@ static int test_query_functions(const char *shaper_name,
CU_ASSERT(query_info.total_byte_cnt_valid);
CU_ASSERT(expected_byte_cnt < query_info.total_byte_cnt);
+ memset(&query_info, 0, sizeof(query_info));
rc = odp_tm_total_query(odp_tm_systems[0],
ODP_TM_QUERY_PKT_CNT | ODP_TM_QUERY_BYTE_CNT,
&query_info);
@@ -3771,7 +3790,7 @@ static int walk_tree_backwards(odp_tm_node_t tm_node)
rc = odp_tm_node_info(tm_node, &node_info);
if (rc != 0) {
ODPH_ERR("odp_tm_node_info failed for tm_node=0x%" PRIX64 "\n",
- tm_node);
+ odp_tm_node_to_u64(tm_node));
return rc;
}