aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Uvarov <maxim.uvarov@linaro.org>2018-04-05 21:41:01 +0300
committerMaxim Uvarov <maxim.uvarov@linaro.org>2018-04-05 21:42:44 +0300
commit0d372bf1c890171f0caca7fbef6f78bb8462f7af (patch)
treefada2225655a46e022616a4693bf30bf0406bfe1
parentece4610e4f895860e935fc5920fa4f9f2654a58e (diff)
parente9a0f5f06f670907d4b88143c7a423d5e7e64f3b (diff)
downloadodp-dpdk-master.tar.gz
merge pr37HEADmaster
Merge pr37 with odp-dpdk up to TM API level. https://github.com/Linaro/odp-dpdk/pull/37 Merge branch 'dev/merge_18_0_1' of git://github.com/matiaselo/odp-dpdk Reviewed-by: Josep Puigdemont <josep.puigdemont@linaro.org> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>
-rw-r--r--.checkpatch.conf5
-rw-r--r--.shippable.yml16
-rw-r--r--.travis.yml28
-rw-r--r--CHANGELOG49
-rw-r--r--DEPENDENCIES6
-rw-r--r--Makefile.am8
-rw-r--r--config/README10
-rw-r--r--config/odp-linux-dpdk.conf32
-rw-r--r--config/odp-linux-generic.conf32
-rw-r--r--configure.ac43
-rw-r--r--m4/odp_dpdk.m44
-rw-r--r--m4/odp_libconfig.m428
-rw-r--r--platform/Makefile.inc5
-rw-r--r--platform/linux-dpdk/.gitignore1
-rw-r--r--platform/linux-dpdk/Makefile.am13
-rw-r--r--platform/linux-dpdk/README4
-rw-r--r--platform/linux-dpdk/include-abi/odp/api/abi/packet.h1
-rw-r--r--platform/linux-dpdk/include/odp/api/plat/packet_inlines.h6
-rw-r--r--platform/linux-dpdk/include/odp_buffer_inlines.h5
-rw-r--r--platform/linux-dpdk/include/odp_buffer_internal.h1
-rw-r--r--platform/linux-dpdk/include/odp_packet_dpdk.h3
-rw-r--r--platform/linux-dpdk/include/odp_packet_internal.h1
-rw-r--r--platform/linux-dpdk/include/odp_packet_io_internal.h9
-rw-r--r--platform/linux-dpdk/include/odp_pool_internal.h14
-rw-r--r--platform/linux-dpdk/libodp-linux.pc.in1
-rw-r--r--platform/linux-dpdk/m4/configure.m43
-rw-r--r--platform/linux-dpdk/odp_buffer.c16
-rw-r--r--platform/linux-dpdk/odp_init.c36
-rw-r--r--platform/linux-dpdk/odp_libconfig.c99
-rw-r--r--platform/linux-dpdk/odp_packet.c3
-rw-r--r--platform/linux-dpdk/odp_packet_dpdk.c113
-rw-r--r--platform/linux-dpdk/odp_pool.c70
-rw-r--r--platform/linux-dpdk/odp_queue_basic.c91
-rw-r--r--platform/linux-dpdk/odp_time.c6
-rw-r--r--platform/linux-generic/.gitignore1
-rw-r--r--platform/linux-generic/Makefile.am13
-rw-r--r--platform/linux-generic/include/odp_buffer_inlines.h5
-rw-r--r--platform/linux-generic/include/odp_internal.h5
-rw-r--r--platform/linux-generic/include/odp_libconfig_internal.h29
-rw-r--r--platform/linux-generic/include/odp_packet_dpdk.h10
-rw-r--r--platform/linux-generic/include/odp_queue_internal.h22
-rw-r--r--platform/linux-generic/include/odp_queue_lf.h1
-rw-r--r--platform/linux-generic/include/odp_schedule_if.h8
-rw-r--r--platform/linux-generic/libodp-linux.pc.in1
-rw-r--r--platform/linux-generic/m4/configure.m43
-rw-r--r--platform/linux-generic/odp_crypto.c20
-rw-r--r--platform/linux-generic/odp_impl.c30
-rw-r--r--platform/linux-generic/odp_init.c14
-rw-r--r--platform/linux-generic/odp_ipsec.c108
-rw-r--r--platform/linux-generic/odp_libconfig.c99
-rw-r--r--platform/linux-generic/odp_packet_io.c116
-rw-r--r--platform/linux-generic/odp_queue_basic.c97
-rw-r--r--platform/linux-generic/odp_queue_lf.c2
-rw-r--r--platform/linux-generic/odp_schedule_basic.c464
-rw-r--r--platform/linux-generic/odp_schedule_iquery.c23
-rw-r--r--platform/linux-generic/odp_schedule_sp.c7
-rw-r--r--platform/linux-generic/odp_system_info.c26
-rw-r--r--platform/linux-generic/pktio/dpdk.c73
-rwxr-xr-xplatform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.sh3
-rw-r--r--platform/linux-generic/test/ring/Makefile.am2
-rwxr-xr-xscripts/build-pktio-dpdk5
-rwxr-xr-xscripts/checkpatch.pl1552
-rw-r--r--test/performance/Makefile.am6
-rw-r--r--test/validation/api/classification/odp_classification_tests.c59
-rw-r--r--test/validation/api/classification/odp_classification_testsuites.h12
-rw-r--r--test/validation/api/ipsec/ipsec.c7
-rw-r--r--test/validation/api/ipsec/ipsec_test_out.c162
-rw-r--r--test/validation/api/ipsec/test_vectors.h18
-rw-r--r--test/validation/api/pktio/pktio.c204
-rw-r--r--test/validation/api/scheduler/scheduler.c4
70 files changed, 2853 insertions, 1120 deletions
diff --git a/.checkpatch.conf b/.checkpatch.conf
index 990a54d..7195642 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -10,5 +10,10 @@
--ignore=PREFER_SCANF
--ignore=VOLATILE
--ignore=AVOID_EXTERNS
+--ignore=CONST_STRUCT
+--ignore=PREFER_KERNEL_TYPES
+--ignore=CONSTANT_COMPARISON
+--ignore=BLOCK_COMMENT_STYLE
+--ignore=UNNECESSARY_PARENTHESES
--codespell
--codespellfile=/usr/share/codespell/dictionary.txt
diff --git a/.shippable.yml b/.shippable.yml
index 9828ed5..82960a3 100644
--- a/.shippable.yml
+++ b/.shippable.yml
@@ -6,7 +6,7 @@ compiler:
env:
- CONF="--disable-test-perf --disable-test-perf-proc"
- - CONF="--disable-abi-compat --disable-test-perf --disable-test-perf-proc"
+ # - CONF="--disable-abi-compat --disable-test-perf --disable-test-perf-proc"
# - CONF="--enable-schedule-sp"
# - CONF="--enable-schedule-iquery"
# - CONF="--enable-dpdk-zero-copy"
@@ -33,22 +33,20 @@ build:
options:
ci:
- - echo 1000 | sudo tee /proc/sys/vm/nr_hugepages
- - sudo mkdir -p /mnt/huge
- - sudo mount -t hugetlbfs nodev /mnt/huge
- - mkdir -p /dev/shm/odp
+ - mkdir -p $HOME/odp-shmdir
- ./bootstrap
- if [ "${CC#clang}" != "${CC}" ] ; then export CXX="${CC/clang/clang++}"; fi
- ./configure $CONF
- make -j $(nproc)
- - sudo env CI=true ODP_SHM_DIR=/dev/shm/odp ODP_TEST_OUT_XML=yes ODP_SCHEDULER=basic make check
+ - sudo env CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes ODP_SCHEDULER=basic make check
- ./scripts/shippable-post.sh basic
- - sudo env CI=true ODP_SHM_DIR=/dev/shm/odp ODP_TEST_OUT_XML=yes ODP_SCHEDULER=sp make check
+ - sudo env CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes ODP_SCHEDULER=sp make check
- ./scripts/shippable-post.sh sp
- - sudo env CI=true ODP_SHM_DIR=/dev/shm/odp ODP_TEST_OUT_XML=yes ODP_SCHEDULER=iquery make check
+ - sudo env CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes ODP_SCHEDULER=iquery make check
- ./scripts/shippable-post.sh iquery
- - sudo env CI=true ODP_SHM_DIR=/dev/shm/odp ODP_TEST_OUT_XML=yes ODP_SCHEDULER=scalable make check
+ - sudo env CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes ODP_SCHEDULER=scalable make check
- ./scripts/shippable-post.sh scalable
+ - rm -rf $HOME/odp-shmdir
on_failure:
- ./scripts/shippable-post.sh
diff --git a/.travis.yml b/.travis.yml
index 597a9c1..1be920d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,6 +23,7 @@ addons:
- gcc
- clang-3.8
- automake autoconf libtool libssl-dev graphviz mscgen
+ - libconfig-dev
- codespell
- libpcap-dev
- libnuma-dev
@@ -55,6 +56,9 @@ env:
- CONF="--disable-abi-compat"
- CONF="--enable-deprecated"
- CONF="--disable-static-applications"
+ - CONF="--disable-host-optimization"
+ - CONF="--disable-host-optimization --disable-abi-compat"
+ - DPDK_SHARED="y" CONF="--disable-static-applications"
compiler:
- gcc
@@ -216,10 +220,11 @@ install:
echo CONFIG_RTE_TOOLCHAIN_${DPDKCC^^}=y >> .config
popd
make build O=${TARGET} EXTRA_CFLAGS="-fPIC $DPDK_CFLAGS" CROSS="$DPDK_CROSS" CC="$CC" HOSTCC=gcc -j $(nproc)
+ make install O=${TARGET} DESTDIR=${TARGET}
rm -r ./doc ./${TARGET}/app ./${TARGET}/build
popd
fi
- EXTRA_CONF="$EXTRA_CONF --with-dpdk-path=`pwd`/dpdk/${TARGET}"
+ EXTRA_CONF="$EXTRA_CONF --with-dpdk-path=`pwd`/dpdk/${TARGET}/usr/local"
fi
script:
@@ -233,7 +238,7 @@ script:
# Run all tests only for default configuration
- if [ -z "$CROSS_ARCH" ] ; then
if [ -n "$CONF" ] ; then
- sudo LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" ODP_SHM_DIR=/dev/shm/odp make check ;
+ sudo ODP_CONFIG_FILE="`pwd`/config/odp-linux-dpdk.conf" LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" ODP_SHM_DIR=/dev/shm/odp make check ;
else
sudo ODP_SCHEDULER=basic LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" ODP_SHM_DIR=/dev/shm/odp make check ;
sudo ODP_SCHEDULER=sp LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" ODP_SHM_DIR=/dev/shm/odp make check ;
@@ -263,6 +268,8 @@ script:
sudo ODP_PLATFORM_PARAMS="-n 2" ./odp_hello_inst_static;
fi
fi
+ - popd
+ - ccache -s
jobs:
include:
@@ -270,17 +277,19 @@ jobs:
env: TEST=coverage
compiler: gcc
script:
- - sudo -H pip install coverage
+ - sudo pip install coverage
- ./bootstrap
- ./configure --prefix=$HOME/odp-install
--enable-user-guides
- --with-dpdk-path=`pwd`/dpdk/${TARGET}
+ --with-dpdk-path=`pwd`/dpdk/${TARGET}/usr/local
CFLAGS="-O0 -coverage"
CXXFLAGS="-O0 -coverage" LDFLAGS="--coverage"
--enable-debug=full
--enable-helper-linux
- CCACHE_DISABLE=1 make -j $(nproc)
- - sudo CCACHE_DISABLE=1 LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" PATH=${PATH//:\.\/node_modules\/\.bin/} make check
+ - sudo CCACHE_DISABLE=1 ODP_SCHEDULER=basic LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" make check
+ - sudo CCACHE_DISABLE=1 ODP_SCHEDULER=sp LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" make check
+ - sudo CCACHE_DISABLE=1 ODP_SCHEDULER=iquery LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" make check
- find . -type f -iname '*.[ch]' -not -path ".git/*" -execdir gcov {} \; ; bash <(curl -s https://codecov.io/bash) -X coveragepy
- stage: "build only"
env: TEST=doxygen
@@ -300,8 +309,7 @@ jobs:
- export PATH=$HOME/doxygen-install/bin:$PATH
script:
- ./bootstrap
- - ./configure
- --with-dpdk-path=`pwd`/dpdk/${TARGET}
+ - ./configure $EXTRA_CONF
# doxygen does not trap on warnings, check for them here.
- make doxygen-doc 2>&1 |tee doxygen.log
- |
@@ -316,16 +324,14 @@ jobs:
compiler: gcc
script:
- ./bootstrap
- - ./configure --enable-helper-linux
- --with-dpdk-path=`pwd`/dpdk/${TARGET}
+ - ./configure --enable-helper-linux $EXTRA_CONF
- make -j $(nproc)
- stage: "build only"
env: CONF=""
compiler: clang-3.8
script:
- ./bootstrap
- - ./configure --enable-helper-linux
- --with-dpdk-path=`pwd`/dpdk/${TARGET}
+ - ./configure --enable-helper-linux $EXTRA_CONF
- make -j $(nproc)
- stage: "build only"
env: CROSS_ARCH="i386"
diff --git a/CHANGELOG b/CHANGELOG
index cfebbbd..1dfdd0e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,52 @@
+== OpenDataPlane (1.18.0.1)
+=== Summary of Changes
+ODP v1.18.0.1 is a fix level for Tiger Moth Release Candidate 2 (RC 2).
+It incorporates fixes and performance / serviceability enhancements but no
+API changes.
+
+==== APIs
+No changes for this release.
+
+==== Corrected Crypto Functionality
+This release corrects a merge issue with crypto functionality that resulted in
+incorrect crypto operation for certain cipher suites.
+
+==== Runtime Configuration
+Introduces a runtime configuration file that can be used by applications to
+set selected ODP configuration parameters dynamically at runtime rather than
+at `configure` time. At present this is used to configure parameters needed
+by DPDK PMDs when using PktIO interfaces in the DPDK class. The intention is
+to expand the use of this file over time to allow more dynamic control
+of other aspect of ODP runtime configuration.
+
+For the ODP Reference Implementation, a template configuration file is
+provided in `config/odp-linux.conf`. Introduction of this support generates
+an additional dependency on the `libconfig` package, which must be present to
+build ODP.
+
+==== IPsec Traffic Flow Confidentiality (TFC) Corrections
+A few missing implementation features associated with TFC packet generation
+have been added in this fix level. This support is now functionally complete in
+the ODP Reference Implementation.
+
+==== Debug Print Improvements
+The information provided in debug builds of the Reference Implementation is
+improved to print the interface name on open, start, stop, and close calls.
+The driver name and number of queues are also printed to ease verification of
+correct configuration.
+
+==== Default Scheduler Performance Improvements
+The performance of the default scheduler in the Reference Implementation is
+significantly improved in providing scheduled access to PktIO queues. Scheduled
+I/O now operates within 10% of the performance achievable using Direct I/O,
+while providing incomparably better scalability in multicore environments.
+
+==== `.so` Numbering Changes
+In preparation for the Tiger Moth official release, ODP has adopted a
+simplified `.so` naming scheme, which is introduced here. ODP `.so` numbers
+are now tied to the ODP release number since ODP does not promise backward
+compatibility across release boundaries.
+
== OpenDataPlane (1.18.0.0)
=== New Features
ODP v1.18.0.0 is Tiger Moth Release Candidate 2 (RC 2). It completes the new
diff --git a/DEPENDENCIES b/DEPENDENCIES
index 6f374ca..2cd8ccb 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -17,9 +17,11 @@ Prerequisites for building the OpenDataPlane (ODP) API
On CentOS/RedHat/Fedora systems:
$ sudo yum install automake autoconf libtool pkgconfig
-3. Required libraries
+3. Required packages
- Libraries currently required to link: openssl, libatomic
+ Libraries currently required to link: openssl, libatomic, libconfig
+
+ Required tools: xxd
3.1 OpenSSL native compile
diff --git a/Makefile.am b/Makefile.am
index 6a69e85..469222d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,15 +16,15 @@ SUBDIRS = \
include \
$(PLATFORM_DIR) \
helper \
+ test \
+ $(PLATFORM_TEST_DIR) \
helper/test \
doc \
- example . \
- test \
- $(PLATFORM_TEST_DIR)
+ example
@DX_RULES@
-EXTRA_DIST = bootstrap CHANGELOG config/README
+EXTRA_DIST = bootstrap CHANGELOG config/README config/odp-$(with_platform).conf
distcheck-hook:
if test -n "$(DX_CLEANFILES)" ; \
diff --git a/config/README b/config/README
index 3f43361..9d6b87b 100644
--- a/config/README
+++ b/config/README
@@ -1,2 +1,12 @@
ODP configuration options
-------------------------
+
+Runtime configuration options can be passed to an ODP instance by
+setting ODP_CONFIG_FILE environment variable to point to a libconfig
+format configuration file. A template configuration file with default
+values is provided in config/odp-linux-generic.conf. The values set in
+config/odp-linux-generic.conf are hardcoded during configure/build
+phase. If ODP_CONFIG_FILE is not set at runtime, hardcoded default
+values are used instead of any configuration file. A configuration file
+passed using ODP_CONFIG_FILE doesn't have to include all available
+options. The missing options are replaced with hardcoded default values.
diff --git a/config/odp-linux-dpdk.conf b/config/odp-linux-dpdk.conf
new file mode 100644
index 0000000..341dba0
--- /dev/null
+++ b/config/odp-linux-dpdk.conf
@@ -0,0 +1,32 @@
+# ODP runtime configuration options
+#
+# This template configuration file (odp-linux-dpdk.conf) is hardcoded
+# during configure/build phase and the values defined here are used if
+# optional ODP_CONFIG_FILE is not set. This configuration file MUST
+# include all configuration options.
+#
+# ODP_CONFIG_FILE can be used to override default values and it doesn't
+# have to include all available options. The missing options are
+# replaced with hardcoded default values.
+#
+# The options defined here are implementation specific and valid option
+# values should be checked from the implementation code.
+#
+# See libconfig syntax: https://hyperrealm.github.io/libconfig/libconfig_manual.html#Configuration-Files
+
+# Mandatory fields
+odp_implementation = "linux-dpdk"
+config_file_version = "0.0.1"
+
+# DPDK pktio options
+pktio_dpdk: {
+ # Default options
+ num_rx_desc = 128
+ num_tx_desc = 512
+ rx_drop_en = 0
+
+ # Driver specific options (use PMD names from DPDK)
+ net_ixgbe: {
+ rx_drop_en = 1
+ }
+}
diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf
new file mode 100644
index 0000000..15e65d0
--- /dev/null
+++ b/config/odp-linux-generic.conf
@@ -0,0 +1,32 @@
+# ODP runtime configuration options
+#
+# This template configuration file (odp-linux-generic.conf) is hardcoded
+# during configure/build phase and the values defined here are used if
+# optional ODP_CONFIG_FILE is not set. This configuration file MUST
+# include all configuration options.
+#
+# ODP_CONFIG_FILE can be used to override default values and it doesn't
+# have to include all available options. The missing options are
+# replaced with hardcoded default values.
+#
+# The options defined here are implementation specific and valid option
+# values should be checked from the implementation code.
+#
+# See libconfig syntax: https://hyperrealm.github.io/libconfig/libconfig_manual.html#Configuration-Files
+
+# Mandatory fields
+odp_implementation = "linux-generic"
+config_file_version = "0.0.1"
+
+# DPDK pktio options
+pktio_dpdk: {
+ # Default options
+ num_rx_desc = 128
+ num_tx_desc = 512
+ rx_drop_en = 0
+
+ # Driver specific options (use PMD names from DPDK)
+ net_ixgbe: {
+ rx_drop_en = 1
+ }
+}
diff --git a/configure.ac b/configure.ac
index ee67527..152c079 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@ AC_PREREQ([2.5])
m4_define([odpapi_generation_version], [1])
m4_define([odpapi_major_version], [18])
m4_define([odpapi_minor_version], [0])
-m4_define([odpapi_point_version], [0])
+m4_define([odpapi_point_version], [1])
m4_define([odpapi_version],
[odpapi_generation_version.odpapi_major_version.odpapi_minor_version.odpapi_point_version])
AC_INIT([OpenDataPlane],[odpapi_version],[lng-odp@lists.linaro.org])
@@ -28,18 +28,17 @@ AM_SILENT_RULES([yes])
##########################################################################
# Set platform library version
#
-# Follow version rules described here:
-# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
-# Version is Current:Revision:Age
-# 1. if there are only source changes, use C:R+1:A
-# 2. if interfaces were added use C+1:0:A+1
-# 3. if interfaces were removed, then use C+1:0:0
+# ODP does not promise backwards compatibility between releases, so we
+# just enforce major:minor:release as version number.
##########################################################################
-ODP_LIBSO_VERSION=118:0:0
+m4_define([odpso_version],
+ [odpapi_generation_version[]odpapi_major_version:odpapi_minor_version:odpapi_point_version])
+
+ODP_LIBSO_VERSION=odpso_version
AC_SUBST(ODP_LIBSO_VERSION)
-ODPHELPER_LIBSO_VERSION=114:0:2
+ODPHELPER_LIBSO_VERSION=odpso_version
AC_SUBST(ODPHELPER_LIBSO_VERSION)
# Checks for programs.
@@ -232,6 +231,18 @@ AC_ARG_WITH([platform],
])
AC_SUBST([with_platform])
+##########################################################################
+# Run platform specific checks and settings
+##########################################################################
+AS_IF([test "${with_platform}" = "linux-generic"],
+ [m4_include([./platform/linux-generic/m4/configure.m4])],
+ [test "${with_platform}" = "linux-dpdk"],
+ [m4_include([./platform/linux-dpdk/m4/configure.m4])],
+ [AC_MSG_ERROR([UNSUPPORTED PLATFORM: ${with_platform}])])
+
+AC_DEFINE_UNQUOTED([ODP_IMPLEMENTATION_NAME], ["$ODP_IMPLEMENTATION_NAME"],
+ [Define to the name of the implementation])
+
##########################################################################
# Build examples/tests dynamically
@@ -258,18 +269,6 @@ m4_include([./helper/m4/configure.m4])
m4_include([./test/m4/configure.m4])
##########################################################################
-# Run platform specific checks and settings
-##########################################################################
-AS_IF([test "${with_platform}" = "linux-generic"],
- [m4_include([./platform/linux-generic/m4/configure.m4])],
- [test "${with_platform}" = "linux-dpdk"],
- [m4_include([./platform/linux-dpdk/m4/configure.m4])],
- [AC_MSG_ERROR([UNSUPPORTED PLATFORM: ${with_platform}])])
-
-AC_DEFINE_UNQUOTED([IMPLEMENTATION_NAME], ["$IMPLEMENTATION_NAME"],
- [Define to the name of the implementation])
-
-##########################################################################
# Set the install directory for test binaries/scripts
##########################################################################
AC_ARG_WITH([testdir],
@@ -387,7 +386,7 @@ AC_MSG_RESULT([
ODP Library version: ${ODP_LIBSO_VERSION}
Helper Library version: ${ODPHELPER_LIBSO_VERSION}
- implementation_name: ${IMPLEMENTATION_NAME}
+ implementation_name: ${ODP_IMPLEMENTATION_NAME}
host: ${host}
ARCH_DIR ${ARCH_DIR}
ARCH_ABI ${ARCH_ABI}
diff --git a/m4/odp_dpdk.m4 b/m4/odp_dpdk.m4
index c613fc2..ca07a09 100644
--- a/m4/odp_dpdk.m4
+++ b/m4/odp_dpdk.m4
@@ -123,13 +123,15 @@ AS_IF([test "x$1" = "xsystem"], [dnl
fi
DPDK_LIB_PATH=`AS_DIRNAME(["$DPDK_LIB_PATH"])`
], [dnl
- DPDK_CPPFLAGS="-isystem $1/include"
+ DPDK_CPPFLAGS="-isystem $1/include/dpdk"
DPDK_LIB_PATH="$1/lib"
DPDK_LDFLAGS="-L$DPDK_LIB_PATH"
if test -r "$DPDK_LIB_PATH"/libdpdk.so ; then
DPDK_RPATH="-Wl,-rpath,$DPDK_LIB_PATH"
DPDK_RPATH_LT="-R$DPDK_LIB_PATH"
DPDK_SHARED=yes
+ elif test ! -r "$DPDK_LIB_PATH"/libdpdk.a ; then
+ AC_MSG_FAILURE([Could not find DPDK])
fi
])
DPDK_PMD_PATH="$DPDK_LIB_PATH"
diff --git a/m4/odp_libconfig.m4 b/m4/odp_libconfig.m4
new file mode 100644
index 0000000..926ceca
--- /dev/null
+++ b/m4/odp_libconfig.m4
@@ -0,0 +1,28 @@
+# ODP_LIBCONFIG(PLATFORM)
+# -----------------------
+AC_DEFUN([ODP_LIBCONFIG],
+[dnl
+##########################################################################
+# Check for libconfig availability
+##########################################################################
+PKG_CHECK_MODULES([LIBCONFIG], [libconfig])
+
+##########################################################################
+# Check for xxd availability
+##########################################################################
+AC_CHECK_PROGS([XXD], [xxd])
+if test -z "$XXD";
+ then AC_MSG_ERROR([Could not find 'xxd'])
+fi
+
+##########################################################################
+# Create a header file odp_libconfig_config.h which containins null
+# terminated hex dump of odp-linux.conf
+##########################################################################
+AC_CONFIG_COMMANDS([platform/$1/include/odp_libconfig_config.h],
+[mkdir -p platform/$1/include
+ (cd ${srcdir}/config ; xxd -i odp-$1.conf) | \
+ sed 's/\([[0-9a-f]]\)$/\0, 0x00/' > \
+ platform/$1/include/odp_libconfig_config.h],
+ [with_platform=$with_platform])
+]) # ODP_LIBCONFIG
diff --git a/platform/Makefile.inc b/platform/Makefile.inc
index bb23a4c..ae4d52f 100644
--- a/platform/Makefile.inc
+++ b/platform/Makefile.inc
@@ -3,6 +3,9 @@ include $(top_srcdir)/Makefile.inc
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libodp-linux.pc
+configdir = $(sysconfdir)/odp
+config_DATA = $(top_srcdir)/config/odp-$(with_platform).conf
+
VPATH = $(srcdir) $(builddir)
lib_LTLIBRARIES = $(LIB)/libodp-linux.la
@@ -14,7 +17,7 @@ else
AM_LDFLAGS += -export-symbols-regex '^(_deprecated_)?_?odp_'
endif
-AM_CFLAGS = "-DGIT_HASH=$(VERSION)"
+AM_CFLAGS = "-DODP_VERSION_BUILD=$(VERSION)"
AM_CFLAGS += $(VISIBILITY_CFLAGS)
AM_CFLAGS += @PTHREAD_CFLAGS@
diff --git a/platform/linux-dpdk/.gitignore b/platform/linux-dpdk/.gitignore
index fd5ade7..16e788a 100644
--- a/platform/linux-dpdk/.gitignore
+++ b/platform/linux-dpdk/.gitignore
@@ -1 +1,2 @@
libodp-linux.pc
+odp_libconfig_config.h
diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am
index 83af08e..53b1dbd 100644
--- a/platform/linux-dpdk/Makefile.am
+++ b/platform/linux-dpdk/Makefile.am
@@ -3,6 +3,7 @@ include $(top_srcdir)/platform/@with_platform@/Makefile.inc
AM_CPPFLAGS = $(ODP_INCLUDES)
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/include
+AM_CPPFLAGS += -I$(top_builddir)/platform/$(with_platform)/include
AM_CPPFLAGS += -I$(top_srcdir)/platform/linux-generic/include
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/arch
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/arch/@ARCH_DIR@
@@ -11,6 +12,12 @@ AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/arch/default
AM_CPPFLAGS += $(OPENSSL_CPPFLAGS)
AM_CPPFLAGS += $(DPDK_CPPFLAGS)
+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
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
if !ODP_ABI_COMPAT
odpapiplatincludedir= $(includedir)/odp/api/plat
odpapiplatinclude_HEADERS = \
@@ -88,6 +95,7 @@ noinst_HEADERS = \
${top_srcdir}/platform/linux-generic/include/odp_forward_typedefs_internal.h \
${top_srcdir}/platform/linux-generic/include/odp_internal.h \
${top_srcdir}/platform/linux-generic/include/odp_ipsec_internal.h \
+ ${top_srcdir}/platform/linux-generic/include/odp_libconfig_internal.h \
${top_srcdir}/platform/linux-generic/include/odp_llqueue.h \
${top_srcdir}/platform/linux-generic/include/odp_macros_internal.h \
include/odp_packet_dpdk.h \
@@ -121,6 +129,9 @@ noinst_HEADERS = \
include/protocols/udp.h \
Makefile.inc
+nodist_noinst_HEADERS = \
+ include/odp_libconfig_config.h
+
__LIB__libodp_linux_la_SOURCES = \
../linux-generic/odp_atomic.c \
../linux-generic/odp_barrier.c \
@@ -141,6 +152,7 @@ __LIB__libodp_linux_la_SOURCES = \
../linux-generic/odp_ipsec_events.c \
../linux-generic/odp_ipsec_sad.c \
../linux-generic/odp_name_table.c \
+ odp_libconfig.c \
odp_packet.c \
odp_packet_dpdk.c \
odp_packet_flags.c \
@@ -256,6 +268,7 @@ endif
__LIB__libodp_linux_la_LIBADD = $(ATOMIC_LIBS)
__LIB__libodp_linux_la_LIBADD += $(OPENSSL_LIBS)
+__LIB__libodp_linux_la_LIBADD += $(LIBCONFIG_LIBS)
__LIB__libodp_linux_la_LIBADD += $(DPDK_LIBS_LIBODP)
__LIB__libodp_linux_la_LIBADD += $(PTHREAD_LIBS)
__LIB__libodp_linux_la_LIBADD += $(TIMER_LIBS)
diff --git a/platform/linux-dpdk/README b/platform/linux-dpdk/README
index c75d94a..71cced1 100644
--- a/platform/linux-dpdk/README
+++ b/platform/linux-dpdk/README
@@ -89,10 +89,10 @@ path with the --with-dpdk-path option.
The following step depends on whether ODP shared libraries are to be built.
SHARED libraries (requires building DPDK with -fPIC, see above):
- ./configure --with-dpdk-path=<dpdk-dir>/x86_64-native-linuxapp-gcc
+ ./configure --with-dpdk-path=<dpdk-dir>/install
STATIC libraries (better performance):
- ./configure --with-dpdk-path=<dpdk-dir>/x86_64-native-linuxapp-gcc --disable-shared
+ ./configure --with-dpdk-path=<dpdk-dir>/install --disable-shared
make
diff --git a/platform/linux-dpdk/include-abi/odp/api/abi/packet.h b/platform/linux-dpdk/include-abi/odp/api/abi/packet.h
index 6e46b87..3b27326 100644
--- a/platform/linux-dpdk/include-abi/odp/api/abi/packet.h
+++ b/platform/linux-dpdk/include-abi/odp/api/abi/packet.h
@@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-
/**
* @file
*
diff --git a/platform/linux-dpdk/include/odp/api/plat/packet_inlines.h b/platform/linux-dpdk/include/odp/api/plat/packet_inlines.h
index 44fe53d..32d9733 100644
--- a/platform/linux-dpdk/include/odp/api/plat/packet_inlines.h
+++ b/platform/linux-dpdk/include/odp/api/plat/packet_inlines.h
@@ -193,7 +193,8 @@ static inline uint32_t _odp_packet_flow_hash(odp_packet_t pkt)
return _odp_pkt_get(pkt, uint32_t, rss);
}
-static inline void _odp_packet_flow_hash_set(odp_packet_t pkt, uint32_t flow_hash)
+static inline void _odp_packet_flow_hash_set(odp_packet_t pkt,
+ uint32_t flow_hash)
{
uint32_t *rss = &_odp_pkt_get(pkt, uint32_t, rss);
uint64_t *ol_flags = &_odp_pkt_get(pkt, uint64_t, ol_flags);
@@ -243,7 +244,8 @@ static inline odp_packet_seg_t _odp_packet_next_seg(odp_packet_t pkt,
return (odp_packet_seg_t)(uintptr_t)mb->next;
}
-static inline void _odp_packet_prefetch(odp_packet_t pkt, uint32_t offset, uint32_t len)
+static inline void _odp_packet_prefetch(odp_packet_t pkt, uint32_t offset,
+ uint32_t len)
{
const char *addr = (char *)_odp_packet_data(pkt) + offset;
size_t ofs;
diff --git a/platform/linux-dpdk/include/odp_buffer_inlines.h b/platform/linux-dpdk/include/odp_buffer_inlines.h
index 84e9c9f..421096a 100644
--- a/platform/linux-dpdk/include/odp_buffer_inlines.h
+++ b/platform/linux-dpdk/include/odp_buffer_inlines.h
@@ -39,6 +39,11 @@ static inline void _odp_buffer_event_type_set(odp_buffer_t buf, int ev)
buf_hdl_to_hdr(buf)->event_type = ev;
}
+static inline odp_event_t event_from_buf_hdr(odp_buffer_hdr_t *hdr)
+{
+ return (odp_event_t)hdr;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-dpdk/include/odp_buffer_internal.h b/platform/linux-dpdk/include/odp_buffer_internal.h
index 4269791..f96a80e 100644
--- a/platform/linux-dpdk/include/odp_buffer_internal.h
+++ b/platform/linux-dpdk/include/odp_buffer_internal.h
@@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-
/**
* @file
*
diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h b/platform/linux-dpdk/include/odp_packet_dpdk.h
index f8c5b3f..a2c9132 100644
--- a/platform/linux-dpdk/include/odp_packet_dpdk.h
+++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
@@ -47,7 +47,4 @@
#include <rte_jhash.h>
#include <rte_hash_crc.h>
-#define RTE_TEST_RX_DESC_DEFAULT 128
-#define RTE_TEST_TX_DESC_DEFAULT 512
-
#endif
diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h
index 8607f0b..ccba63a 100644
--- a/platform/linux-dpdk/include/odp_packet_internal.h
+++ b/platform/linux-dpdk/include/odp_packet_internal.h
@@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-
/**
* @file
*
diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h b/platform/linux-dpdk/include/odp_packet_io_internal.h
index 9613c95..963ea7f 100644
--- a/platform/linux-dpdk/include/odp_packet_io_internal.h
+++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
@@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-
/**
* @file
*
@@ -50,6 +49,13 @@ typedef struct {
uint8_t idx; /**< index of "loop" device */
} pkt_loop_t;
+/** DPDK runtime configuration options */
+typedef struct {
+ int num_rx_desc;
+ int num_tx_desc;
+ int rx_drop_en;
+} dpdk_opt_t;
+
/** Packet socket using dpdk mmaped rings for both Rx and Tx */
typedef struct {
uint16_t port_id; /**< DPDK port identifier */
@@ -63,6 +69,7 @@ typedef struct {
odp_ticketlock_t tx_lock[PKTIO_MAX_QUEUES]; /**< TX queue locks */
uint8_t vdev_sysc_promisc; /**< promiscuous mode defined with
system call */
+ dpdk_opt_t opt;
} pkt_dpdk_t;
struct pktio_entry {
diff --git a/platform/linux-dpdk/include/odp_pool_internal.h b/platform/linux-dpdk/include/odp_pool_internal.h
index e95e590..a94afd7 100644
--- a/platform/linux-dpdk/include/odp_pool_internal.h
+++ b/platform/linux-dpdk/include/odp_pool_internal.h
@@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-
/**
* @file
*
@@ -31,6 +30,8 @@ extern "C" {
#include <string.h>
/* for DPDK */
+#include <rte_config.h>
+#include <rte_mbuf.h>
#include <rte_mempool.h>
/* Use ticketlock instead of spinlock */
@@ -39,7 +40,6 @@ extern "C" {
/* Extra error checks */
/* #define POOL_ERROR_CHECK */
-
#ifdef POOL_USE_TICKETLOCK
#include <odp/api/ticketlock.h>
#else
@@ -50,7 +50,7 @@ typedef struct ODP_ALIGNED_CACHE {
#ifdef POOL_USE_TICKETLOCK
odp_ticketlock_t ODP_ALIGNED_CACHE lock;
#else
- odp_spinlock_t ODP_ALIGNED_CACHE lock ;
+ odp_spinlock_t ODP_ALIGNED_CACHE lock;
#endif
char name[ODP_POOL_NAME_LEN];
odp_pool_param_t params;
@@ -76,6 +76,14 @@ static inline pool_t *pool_entry_from_hdl(odp_pool_t pool_hdl)
return &pool_tbl->pool[_odp_typeval(pool_hdl)];
}
+static inline void buffer_free_multi(odp_buffer_hdr_t *buf_hdr[], int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++)
+ rte_ctrlmbuf_free((struct rte_mbuf *)(uintptr_t)buf_hdr[i]);
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-dpdk/libodp-linux.pc.in b/platform/linux-dpdk/libodp-linux.pc.in
index 4076ede..b3e5f05 100644
--- a/platform/linux-dpdk/libodp-linux.pc.in
+++ b/platform/linux-dpdk/libodp-linux.pc.in
@@ -6,6 +6,7 @@ includedir=@includedir@
Name: libodp-linux
Description: The ODP packet processing engine
Version: @PKGCONFIG_VERSION@
+Requires.private: libconfig
Libs: -L${libdir} -lodp-linux
Libs.private: @DPDK_LIBS@ @OPENSSL_STATIC_LIBS@ @PTHREAD_LIBS@ @TIMER_LIBS@ -lpthread @ATOMIC_LIBS@
Cflags: -I${includedir} @DPDK_CPPFLAGS@
diff --git a/platform/linux-dpdk/m4/configure.m4 b/platform/linux-dpdk/m4/configure.m4
index 1ec34ac..5a84199 100644
--- a/platform/linux-dpdk/m4/configure.m4
+++ b/platform/linux-dpdk/m4/configure.m4
@@ -1,4 +1,4 @@
-IMPLEMENTATION_NAME="odp-dpdk"
+ODP_IMPLEMENTATION_NAME="odp-dpdk"
ODP_VISIBILITY
ODP_ATOMIC
@@ -10,6 +10,7 @@ AM_CONDITIONAL([PKTIO_DPDK], [false])
ODP_PTHREAD
ODP_TIMER
ODP_OPENSSL
+ODP_LIBCONFIG([linux-dpdk])
ODP_SCHEDULER
##########################################################################
diff --git a/platform/linux-dpdk/odp_buffer.c b/platform/linux-dpdk/odp_buffer.c
index 6e19c74..59ea26f 100644
--- a/platform/linux-dpdk/odp_buffer.c
+++ b/platform/linux-dpdk/odp_buffer.c
@@ -73,21 +73,21 @@ int odp_buffer_snprint(char *str, uint32_t n, odp_buffer_t buf)
hdr = buf_hdl_to_hdr(buf);
pool = hdr->pool_ptr;
- len += snprintf(&str[len], n-len,
+ len += snprintf(&str[len], n - len,
"Buffer\n");
- len += snprintf(&str[len], n-len,
+ len += snprintf(&str[len], n - len,
" pool %" PRIu64 "\n",
odp_pool_to_u64(pool->pool_hdl));
- len += snprintf(&str[len], n-len,
+ len += snprintf(&str[len], n - len,
" phy_addr %"PRIu64"\n", hdr->mb.buf_physaddr);
- len += snprintf(&str[len], n-len,
+ len += snprintf(&str[len], n - len,
" addr %p\n", hdr->mb.buf_addr);
- len += snprintf(&str[len], n-len,
+ len += snprintf(&str[len], n - len,
" size %u\n", hdr->mb.buf_len);
- len += snprintf(&str[len], n-len,
+ len += snprintf(&str[len], n - len,
" ref_count %i\n",
rte_mbuf_refcnt_read(&hdr->mb));
- len += snprintf(&str[len], n-len,
+ len += snprintf(&str[len], n - len,
" odp type %i\n", hdr->type);
return len;
@@ -99,7 +99,7 @@ void odp_buffer_print(odp_buffer_t buf)
char str[max_len];
int len;
- len = odp_buffer_snprint(str, max_len-1, buf);
+ len = odp_buffer_snprint(str, max_len - 1, buf);
str[len] = 0;
ODP_PRINT("\n%s\n", str);
diff --git a/platform/linux-dpdk/odp_init.c b/platform/linux-dpdk/odp_init.c
index 57a60bd..7a51ff2 100644
--- a/platform/linux-dpdk/odp_init.c
+++ b/platform/linux-dpdk/odp_init.c
@@ -14,6 +14,7 @@
#include <unistd.h>
#include <odp_internal.h>
#include <odp_schedule_if.h>
+#include <odp_libconfig_internal.h>
#include <odp_shm_internal.h>
#include <string.h>
#include <stdio.h>
@@ -25,12 +26,12 @@
#include <sys/types.h>
#include <pwd.h>
-#define MEMPOOL_OPS(hdl) extern void mp_hdlr_init_##hdl(void);
-MEMPOOL_OPS(ops_mp_mc)
-MEMPOOL_OPS(ops_sp_sc)
-MEMPOOL_OPS(ops_mp_sc)
-MEMPOOL_OPS(ops_sp_mc)
-MEMPOOL_OPS(ops_stack)
+#define MEMPOOL_OPS(hdl) extern void mp_hdlr_init_##hdl(void)
+MEMPOOL_OPS(ops_mp_mc);
+MEMPOOL_OPS(ops_sp_sc);
+MEMPOOL_OPS(ops_mp_sc);
+MEMPOOL_OPS(ops_sp_mc);
+MEMPOOL_OPS(ops_stack);
#ifndef RTE_BUILD_SHARED_LIB
/*
@@ -39,7 +40,8 @@ MEMPOOL_OPS(ops_stack)
* constructors of mempool handlers are linked as well. Otherwise the linker
* would omit them. It's not an issue with dynamic linking. */
void refer_constructors(void);
-void refer_constructors(void) {
+void refer_constructors(void)
+{
mp_hdlr_init_ops_mp_mc();
mp_hdlr_init_ops_sp_sc();
mp_hdlr_init_ops_mp_sc();
@@ -65,7 +67,6 @@ static void print_dpdk_env_help(void)
rte_eal_init(dpdk_argc, dpdk_argv);
}
-
static int odp_init_dpdk(const char *cmdline)
{
char **dpdk_argv;
@@ -115,9 +116,8 @@ static int odp_init_dpdk(const char *cmdline)
cmdlen = sprintf(full_cmdline, "odpdpdk -c %s %s", mask_str, cmdline);
for (i = 0, dpdk_argc = 1; i < cmdlen; ++i) {
- if (isspace(full_cmdline[i])) {
+ if (isspace(full_cmdline[i]))
++dpdk_argc;
- }
}
dpdk_argv = malloc(dpdk_argc * sizeof(char *));
@@ -158,10 +158,11 @@ int odp_init_global(odp_instance_t *instance,
const odp_init_t *params,
const odp_platform_init_t *platform_params)
{
+ enum init_stage stage = NO_INIT;
+
memset(&odp_global_data, 0, sizeof(struct odp_global_data_s));
odp_global_data.main_pid = getpid();
- enum init_stage stage = NO_INIT;
odp_global_data.log_fn = odp_override_log;
odp_global_data.abort_fn = odp_override_abort;
@@ -172,6 +173,12 @@ int odp_init_global(odp_instance_t *instance,
odp_global_data.abort_fn = params->abort_fn;
}
+ if (_odp_libconfig_init_global()) {
+ ODP_ERR("ODP runtime config init failed.\n");
+ goto init_failed;
+ }
+ stage = LIBCONFIG_INIT;
+
if (odp_cpumask_init_global(params)) {
ODP_ERR("ODP cpumask init failed.\n");
goto init_failed;
@@ -425,6 +432,13 @@ int _odp_term_global(enum init_stage stage)
}
/* Fall through */
+ case LIBCONFIG_INIT:
+ if (_odp_libconfig_term_global()) {
+ ODP_ERR("ODP runtime config term failed.\n");
+ rc = -1;
+ }
+ /* Fall through */
+
case NO_INIT:
;
}
diff --git a/platform/linux-dpdk/odp_libconfig.c b/platform/linux-dpdk/odp_libconfig.c
new file mode 100644
index 0000000..6d5ee52
--- /dev/null
+++ b/platform/linux-dpdk/odp_libconfig.c
@@ -0,0 +1,99 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <libconfig.h>
+
+#include <odp/api/version.h>
+#include <odp_internal.h>
+#include <odp_debug_internal.h>
+#include <odp_libconfig_internal.h>
+#include <odp_libconfig_config.h>
+
+#define CONF_STR_NAME ((const char *)odp_linux_dpdk_conf)
+
+extern struct odp_global_data_s odp_global_data;
+
+int _odp_libconfig_init_global(void)
+{
+ const char *filename;
+ const char *vers;
+ const char *vers_rt;
+ const char *ipml;
+ const char *ipml_rt;
+ config_t *config = &odp_global_data.libconfig_default;
+ config_t *config_rt = &odp_global_data.libconfig_runtime;
+
+ config_init(config);
+ config_init(config_rt);
+
+ if (!config_read_string(config, CONF_STR_NAME)) {
+ ODP_ERR("Failed to read default config: %s(%d): %s\n",
+ config_error_file(config), config_error_line(config),
+ config_error_text(config));
+ goto fail;
+ }
+
+ filename = getenv("ODP_CONFIG_FILE");
+ if (filename == NULL)
+ return 0;
+
+ if (!config_read_file(config_rt, filename)) {
+ ODP_ERR("Failed to read config file: %s(%d): %s\n",
+ config_error_file(config_rt),
+ config_error_line(config_rt),
+ config_error_text(config_rt));
+ goto fail;
+ }
+
+ /* Check runtime configuration's implementation name and version */
+ if (!config_lookup_string(config, "odp_implementation", &ipml) ||
+ !config_lookup_string(config_rt, "odp_implementation", &ipml_rt)) {
+ ODP_ERR("Configuration missing 'odp_implementation' field\n");
+ goto fail;
+ }
+ if (!config_lookup_string(config, "config_file_version", &vers) ||
+ !config_lookup_string(config_rt, "config_file_version", &vers_rt)) {
+ ODP_ERR("Configuration missing 'config_file_version' field\n");
+ goto fail;
+ }
+ if (strcmp(vers, vers_rt) || strcmp(ipml, ipml_rt)) {
+ ODP_ERR("Runtime configuration mismatch\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ config_destroy(config);
+ config_destroy(config_rt);
+ return -1;
+}
+
+int _odp_libconfig_term_global(void)
+{
+ config_destroy(&odp_global_data.libconfig_default);
+ config_destroy(&odp_global_data.libconfig_runtime);
+
+ return 0;
+}
+
+int _odp_libconfig_lookup_int(const char *path, int *value)
+{
+ int ret_def = CONFIG_FALSE;
+ int ret_rt = CONFIG_FALSE;
+
+ ret_def = config_lookup_int(&odp_global_data.libconfig_default, path,
+ value);
+
+ /* Runtime option overrides default value */
+ ret_rt = config_lookup_int(&odp_global_data.libconfig_runtime, path,
+ value);
+
+ return (ret_def == CONFIG_TRUE || ret_rt == CONFIG_TRUE) ? 1 : 0;
+}
diff --git a/platform/linux-dpdk/odp_packet.c b/platform/linux-dpdk/odp_packet.c
index 86c0314..e0d565d 100644
--- a/platform/linux-dpdk/odp_packet.c
+++ b/platform/linux-dpdk/odp_packet.c
@@ -257,6 +257,7 @@ uint32_t odp_packet_buf_len(odp_packet_t pkt)
void *odp_packet_tail(odp_packet_t pkt)
{
struct rte_mbuf *mb = &(packet_hdr(pkt)->buf_hdr.mb);
+
mb = rte_pktmbuf_lastseg(mb);
return (void *)(rte_pktmbuf_mtod(mb, char *) + mb->data_len);
}
@@ -264,6 +265,7 @@ void *odp_packet_tail(odp_packet_t pkt)
void *odp_packet_push_head(odp_packet_t pkt, uint32_t len)
{
struct rte_mbuf *mb = &(packet_hdr(pkt)->buf_hdr.mb);
+
return (void *)rte_pktmbuf_prepend(mb, len);
}
@@ -348,6 +350,7 @@ int odp_packet_extend_head(odp_packet_t *pkt, uint32_t len, void **data_ptr,
void *odp_packet_pull_head(odp_packet_t pkt, uint32_t len)
{
struct rte_mbuf *mb = &(packet_hdr(pkt)->buf_hdr.mb);
+
return (void *)rte_pktmbuf_adj(mb, len);
}
diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c
index 410211a..1c85577 100644
--- a/platform/linux-dpdk/odp_packet_dpdk.c
+++ b/platform/linux-dpdk/odp_packet_dpdk.c
@@ -31,9 +31,9 @@
#include <odp_debug_internal.h>
#include <odp_classification_internal.h>
#include <odp_packet_io_internal.h>
+#include <odp_libconfig_internal.h>
#include <odp_packet_dpdk.h>
#include <net/if.h>
-#include <math.h>
/* DPDK poll mode drivers requiring minimum RX burst size DPDK_MIN_RX_BURST */
#define IXGBE_DRV_NAME "net_ixgbe"
@@ -57,6 +57,64 @@ extern void *pktio_entry_ptr[ODP_CONFIG_PKTIO_ENTRIES];
static uint32_t mtu_get_pkt_dpdk(pktio_entry_t *pktio_entry);
+static int lookup_opt(const char *path, const char *drv_name, int *val)
+{
+ const char *base = "pktio_dpdk";
+ char opt_path[256];
+ int ret = 0;
+
+ /* Default option */
+ snprintf(opt_path, sizeof(opt_path), "%s.%s", base, path);
+ ret += _odp_libconfig_lookup_int(opt_path, val);
+
+ /* Driver specific option overrides default option */
+ snprintf(opt_path, sizeof(opt_path), "%s.%s.%s", base, drv_name, path);
+ ret += _odp_libconfig_lookup_int(opt_path, val);
+
+ if (ret == 0)
+ ODP_ERR("Unable to find DPDK configuration option: %s\n", path);
+ return ret;
+}
+
+static int init_options(pktio_entry_t *pktio_entry,
+ const struct rte_eth_dev_info *dev_info)
+{
+ dpdk_opt_t *opt = &pktio_entry->s.pkt_dpdk.opt;
+
+ if (!lookup_opt("num_rx_desc", dev_info->driver_name,
+ &opt->num_rx_desc))
+ return -1;
+ if (opt->num_rx_desc < dev_info->rx_desc_lim.nb_min ||
+ opt->num_rx_desc > dev_info->rx_desc_lim.nb_max ||
+ opt->num_rx_desc % dev_info->rx_desc_lim.nb_align) {
+ ODP_ERR("Invalid number of RX descriptors\n");
+ return -1;
+ }
+
+ if (!lookup_opt("num_tx_desc", dev_info->driver_name,
+ &opt->num_tx_desc))
+ return -1;
+ if (opt->num_tx_desc < dev_info->tx_desc_lim.nb_min ||
+ opt->num_tx_desc > dev_info->tx_desc_lim.nb_max ||
+ opt->num_tx_desc % dev_info->tx_desc_lim.nb_align) {
+ ODP_ERR("Invalid number of TX descriptors\n");
+ return -1;
+ }
+
+ if (!lookup_opt("rx_drop_en", dev_info->driver_name,
+ &opt->rx_drop_en))
+ return -1;
+ opt->rx_drop_en = !!opt->rx_drop_en;
+
+ ODP_PRINT("DPDK interface (%s): %" PRIu16 "\n", dev_info->driver_name,
+ pktio_entry->s.pkt_dpdk.port_id);
+ ODP_PRINT(" num_rx_desc: %d\n", opt->num_rx_desc);
+ ODP_PRINT(" num_tx_desc: %d\n", opt->num_tx_desc);
+ ODP_PRINT(" rx_drop_en: %d\n", opt->rx_drop_en);
+
+ return 0;
+}
+
/* Test if s has only digits or not. Dpdk pktio uses only digits.*/
static int _dpdk_netdev_is_valid(const char *s)
{
@@ -295,6 +353,12 @@ static int setup_pkt_dpdk(odp_pktio_t pktio ODP_UNUSED,
return -1;
}
+ /* Initialize runtime options */
+ if (init_options(pktio_entry, &dev_info)) {
+ ODP_ERR("Initializing runtime options failed\n");
+ return -1;
+ }
+
/* Drivers requiring minimum burst size. Supports also *_vf versions
* of the drivers. */
if (!strncmp(dev_info.driver_name, IXGBE_DRV_NAME,
@@ -370,8 +434,6 @@ static int start_pkt_dpdk(pktio_entry_t *pktio_entry)
int socket_id = sid < 0 ? 0 : sid;
uint16_t nbrxq, nbtxq;
pool_t *pool = pool_entry_from_hdl(pktio_entry->s.pool);
- uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
- uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
struct rte_eth_rss_conf rss_conf;
uint16_t hw_ip_checksum = 0;
struct rte_eth_dev_info dev_info;
@@ -397,7 +459,8 @@ static int start_pkt_dpdk(pktio_entry_t *pktio_entry)
.mq_mode = ETH_MQ_RX_RSS,
.split_hdr_size = 0,
.header_split = 0, /**< Header Split */
- .hw_ip_checksum = hw_ip_checksum, /**< IP checksum offload */
+ /* IP checksum offload */
+ .hw_ip_checksum = hw_ip_checksum,
.hw_vlan_filter = 0, /**< VLAN filtering */
.jumbo_frame = 1, /**< Jumbo Frame Support */
.hw_strip_crc = 0, /**< CRC stripp by hardware */
@@ -427,22 +490,15 @@ static int start_pkt_dpdk(pktio_entry_t *pktio_entry)
return -1;
}
- if (nb_rxd + nb_txd > pool->params.pkt.num / 4) {
- double downrate = (double)(pool->params.pkt.num / 4) /
- (double)(nb_rxd + nb_txd);
- nb_rxd >>= (int)ceil(downrate);
- nb_txd >>= (int)ceil(downrate);
- ODP_DBG("downrate %f\n", downrate);
- ODP_DBG("Descriptors scaled down. RX: %u TX: %u pool: %u\n",
- nb_rxd, nb_txd, pool->params.pkt.num);
- }
/* init RX queues */
rte_eth_dev_info_get(port_id, &dev_info);
rxconf = &dev_info.default_rxconf;
- rxconf->rx_drop_en = 1;
+ rxconf->rx_drop_en = pkt_dpdk->opt.rx_drop_en;
for (i = 0; i < nbrxq; i++) {
- ret = rte_eth_rx_queue_setup(port_id, i, nb_rxd, socket_id,
- rxconf, pool->rte_mempool);
+ ret = rte_eth_rx_queue_setup(port_id, i,
+ pkt_dpdk->opt.num_rx_desc,
+ socket_id, rxconf,
+ pool->rte_mempool);
if (ret < 0) {
ODP_ERR("rxq:err=%d, port=%" PRIu16 "\n", ret, port_id);
return -1;
@@ -461,8 +517,9 @@ static int start_pkt_dpdk(pktio_entry_t *pktio_entry)
/* else - use the default tx queue settings*/
for (i = 0; i < nbtxq; i++) {
- ret = rte_eth_tx_queue_setup(port_id, i, nb_txd, socket_id,
- txconf);
+ ret = rte_eth_tx_queue_setup(port_id, i,
+ pkt_dpdk->opt.num_rx_desc,
+ socket_id, txconf);
if (ret < 0) {
ODP_ERR("txq:err=%d, port=%" PRIu16 "\n", ret, port_id);
return -1;
@@ -844,23 +901,17 @@ static int send_pkt_dpdk(pktio_entry_t *pktio_entry, int index,
odp_pktout_config_opt_t *pktout_capa =
&pktio_entry->s.capa.config.pktout;
int pkts;
- int i;
- uint32_t mtu = pkt_dpdk->mtu;
- uint16_t num_tx = 0;
- for (i = 0; i < num; i++) {
- struct rte_mbuf *mbuf = pkt_to_mbuf(pkt_table[i]);
+ if (chksum_insert_ena) {
+ int i;
- if (odp_unlikely(mbuf->pkt_len > mtu))
- break;
+ for (i = 0; i < num; i++) {
+ struct rte_mbuf *mbuf = pkt_to_mbuf(pkt_table[i]);
- mbuf->ol_flags = 0;
- if (chksum_insert_ena)
pkt_set_ol_tx(pktout_cfg, pktout_capa,
packet_hdr(pkt_table[i]), mbuf,
rte_pktmbuf_mtod(mbuf, char *));
-
- num_tx++;
+ }
}
if (!pkt_dpdk->lockless_tx)
@@ -869,7 +920,7 @@ static int send_pkt_dpdk(pktio_entry_t *pktio_entry, int index,
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"
pkts = rte_eth_tx_burst(pkt_dpdk->port_id, index,
- (struct rte_mbuf **)pkt_table, num_tx);
+ (struct rte_mbuf **)pkt_table, num);
#pragma GCC diagnostic pop
if (!pkt_dpdk->lockless_tx)
@@ -881,7 +932,7 @@ static int send_pkt_dpdk(pktio_entry_t *pktio_entry, int index,
if (odp_unlikely(rte_errno != 0))
return -1;
- if (odp_unlikely(mbuf->pkt_len > mtu)) {
+ if (odp_unlikely(mbuf->pkt_len > pkt_dpdk->mtu)) {
__odp_errno = EMSGSIZE;
return -1;
}
diff --git a/platform/linux-dpdk/odp_pool.c b/platform/linux-dpdk/odp_pool.c
index f0effa0..463d7ae 100644
--- a/platform/linux-dpdk/odp_pool.c
+++ b/platform/linux-dpdk/odp_pool.c
@@ -171,8 +171,8 @@ odp_dpdk_mbuf_pool_ctor(struct rte_mempool *mp,
if (mp->private_data_size < sizeof(struct mbuf_pool_ctor_arg)) {
ODP_ERR("(%s) private_data_size %d < %d",
- mp->name, (int) mp->private_data_size,
- (int) sizeof(struct mbuf_pool_ctor_arg));
+ mp->name, (int)mp->private_data_size,
+ (int)sizeof(struct mbuf_pool_ctor_arg));
return;
}
mbp_priv = rte_mempool_get_priv(mp);
@@ -340,7 +340,7 @@ odp_pool_t odp_pool_create(const char *name, odp_pool_param_t *params)
pool_name[ODP_POOL_NAME_LEN - 1] = 0;
}
- /* Find an unused buffer pool slot and initalize it as requested */
+ /* Find an unused buffer pool slot and initialize it as requested */
for (i = 0; i < ODP_CONFIG_POOLS; i++) {
uint32_t num;
struct rte_mempool *mp;
@@ -439,7 +439,6 @@ odp_pool_t odp_pool_create(const char *name, odp_pool_param_t *params)
params->type);
UNLOCK(&pool->lock);
return ODP_POOL_INVALID;
- break;
}
mb_ctor_arg.seg_buf_offset =
@@ -463,7 +462,7 @@ odp_pool_t odp_pool_create(const char *name, odp_pool_param_t *params)
break;
}
if (odp_unlikely(cache_size > RTE_MEMPOOL_CACHE_MAX_SIZE ||
- (uint32_t) cache_size * 1.5 > num)) {
+ (uint32_t)cache_size * 1.5 > num)) {
ODP_ERR("cache_size calc failure: %d\n", cache_size);
cache_size = 0;
}
@@ -521,7 +520,6 @@ odp_pool_t odp_pool_create(const char *name, odp_pool_param_t *params)
return pool_hdl;
}
-
odp_pool_t odp_pool_lookup(const char *name)
{
struct rte_mempool *mp = NULL;
@@ -546,52 +544,54 @@ odp_pool_t odp_pool_lookup(const char *name)
return pool_hdl;
}
-
-static odp_buffer_t buffer_alloc(pool_t *pool)
+static inline int buffer_alloc_multi(pool_t *pool, odp_buffer_hdr_t *buf_hdr[],
+ int num)
{
- odp_buffer_hdr_t *buf_hdr;
- struct rte_mbuf *mbuf;
+ int i;
+ struct rte_mempool *mp = pool->rte_mempool;
- if (odp_unlikely(pool->params.type != ODP_POOL_BUFFER &&
- pool->params.type != ODP_POOL_TIMEOUT)) {
- rte_errno = EINVAL;
- return ODP_BUFFER_INVALID;
- }
+ ODP_ASSERT(pool->params.type == ODP_POOL_BUFFER ||
+ pool->params.type == ODP_POOL_TIMEOUT);
- mbuf = rte_ctrlmbuf_alloc(pool->rte_mempool);
- if (odp_unlikely(mbuf == NULL)) {
- rte_errno = ENOMEM;
- return ODP_BUFFER_INVALID;
- }
+ for (i = 0; i < num; i++) {
+ struct rte_mbuf *mbuf;
+
+ mbuf = rte_ctrlmbuf_alloc(mp);
+ if (odp_unlikely(mbuf == NULL))
+ return i;
- buf_hdr = mbuf_to_buf_hdr(mbuf);
+ buf_hdr[i] = mbuf_to_buf_hdr(mbuf);
+ }
- return buf_from_buf_hdr(buf_hdr);
+ return i;
}
odp_buffer_t odp_buffer_alloc(odp_pool_t pool_hdl)
{
+ odp_buffer_t buf;
+ pool_t *pool;
+ int ret;
+
ODP_ASSERT(ODP_POOL_INVALID != pool_hdl);
- pool_t *pool = pool_entry_from_hdl(pool_hdl);
+ pool = pool_entry_from_hdl(pool_hdl);
+ ret = buffer_alloc_multi(pool, (odp_buffer_hdr_t **)&buf, 1);
+
+ if (odp_likely(ret == 1))
+ return buf;
- return buffer_alloc(pool);
+ return ODP_BUFFER_INVALID;
}
int odp_buffer_alloc_multi(odp_pool_t pool_hdl, odp_buffer_t buf[], int num)
{
- int i;
+ pool_t *pool;
ODP_ASSERT(ODP_POOL_INVALID != pool_hdl);
- pool_t *pool = pool_entry_from_hdl(pool_hdl);
+ pool = pool_entry_from_hdl(pool_hdl);
- for (i = 0; i < num; i++) {
- buf[i] = buffer_alloc(pool);
- if (buf[i] == ODP_BUFFER_INVALID)
- return rte_errno == ENOMEM ? i : -EINVAL;
- }
- return i;
+ return buffer_alloc_multi(pool, (odp_buffer_hdr_t **)buf, num);
}
void odp_buffer_free(odp_buffer_t buf)
@@ -601,10 +601,7 @@ void odp_buffer_free(odp_buffer_t buf)
void odp_buffer_free_multi(const odp_buffer_t buf[], int num)
{
- int i;
-
- for (i = 0; i < num; i++)
- rte_ctrlmbuf_free(buf_to_mbuf(buf[i]));
+ buffer_free_multi((odp_buffer_hdr_t **)(uintptr_t)buf, num);
}
void odp_pool_print(odp_pool_t pool_hdl)
@@ -672,4 +669,3 @@ uint64_t odp_pool_to_u64(odp_pool_t hdl)
{
return _odp_pri(hdl);
}
-
diff --git a/platform/linux-dpdk/odp_queue_basic.c b/platform/linux-dpdk/odp_queue_basic.c
index b30d19c..5df48ec 100644
--- a/platform/linux-dpdk/odp_queue_basic.c
+++ b/platform/linux-dpdk/odp_queue_basic.c
@@ -8,7 +8,6 @@
#include <odp/api/queue.h>
#include <odp_queue_internal.h>
-#include <odp_queue_lf.h>
#include <odp_queue_if.h>
#include <odp/api/std_types.h>
#include <odp/api/align.h>
@@ -40,15 +39,7 @@
static int queue_init(queue_entry_t *queue, const char *name,
const odp_queue_param_t *param);
-typedef struct queue_global_t {
- queue_entry_t queue[ODP_CONFIG_QUEUES];
- uint32_t queue_lf_num;
- uint32_t queue_lf_size;
- queue_lf_func_t queue_lf_func;
-
-} queue_global_t;
-
-static queue_global_t *queue_glb;
+queue_global_t *queue_glb;
static inline queue_entry_t *get_qentry(uint32_t queue_id)
{
@@ -62,14 +53,37 @@ static inline queue_entry_t *handle_to_qentry(odp_queue_t handle)
return get_qentry(queue_id);
}
+static int queue_capa(odp_queue_capability_t *capa, int sched)
+{
+ memset(capa, 0, sizeof(odp_queue_capability_t));
+
+ /* Reserve some queues for internal use */
+ capa->max_queues = ODP_CONFIG_QUEUES - NUM_INTERNAL_QUEUES;
+ capa->plain.max_num = capa->max_queues;
+ capa->plain.max_size = CONFIG_QUEUE_SIZE - 1;
+ capa->plain.lockfree.max_num = queue_glb->queue_lf_num;
+ capa->plain.lockfree.max_size = queue_glb->queue_lf_size;
+ capa->sched.max_num = capa->max_queues;
+ capa->sched.max_size = CONFIG_QUEUE_SIZE - 1;
+
+ if (sched) {
+ capa->max_ordered_locks = sched_fn->max_ordered_locks();
+ capa->max_sched_groups = sched_fn->num_grps();
+ capa->sched_prios = odp_schedule_num_prio();
+ }
+
+ return 0;
+}
+
static int queue_init_global(void)
{
uint32_t i;
odp_shm_t shm;
uint32_t lf_size = 0;
queue_lf_func_t *lf_func;
+ odp_queue_capability_t capa;
- ODP_DBG("Queue init ... ");
+ ODP_DBG("Starts...\n");
shm = odp_shm_reserve("odp_queues",
sizeof(queue_global_t),
@@ -95,13 +109,14 @@ static int queue_init_global(void)
queue_glb->queue_lf_num = queue_lf_init_global(&lf_size, lf_func);
queue_glb->queue_lf_size = lf_size;
- ODP_DBG("done\n");
- ODP_DBG("Queue init global\n");
- ODP_DBG(" struct queue_entry_s size %zu\n",
- sizeof(struct queue_entry_s));
- ODP_DBG(" queue_entry_t size %zu\n",
- sizeof(queue_entry_t));
- ODP_DBG("\n");
+ queue_capa(&capa, 0);
+
+ ODP_DBG("... done.\n");
+ ODP_DBG(" queue_entry_t size %u\n", sizeof(queue_entry_t));
+ ODP_DBG(" max num queues %u\n", capa.max_queues);
+ ODP_DBG(" max queue size %u\n", capa.plain.max_size);
+ ODP_DBG(" max num lockfree %u\n", capa.plain.lockfree.max_num);
+ ODP_DBG(" max lockfree size %u\n\n", capa.plain.lockfree.max_size);
return 0;
}
@@ -146,21 +161,7 @@ static int queue_term_global(void)
static int queue_capability(odp_queue_capability_t *capa)
{
- memset(capa, 0, sizeof(odp_queue_capability_t));
-
- /* Reserve some queues for internal use */
- capa->max_queues = ODP_CONFIG_QUEUES - NUM_INTERNAL_QUEUES;
- capa->max_ordered_locks = sched_fn->max_ordered_locks();
- capa->max_sched_groups = sched_fn->num_grps();
- capa->sched_prios = odp_schedule_num_prio();
- capa->plain.max_num = capa->max_queues;
- capa->plain.max_size = CONFIG_QUEUE_SIZE - 1;
- capa->plain.lockfree.max_num = queue_glb->queue_lf_num;
- capa->plain.lockfree.max_size = queue_glb->queue_lf_size;
- capa->sched.max_num = capa->max_queues;
- capa->sched.max_size = CONFIG_QUEUE_SIZE - 1;
-
- return 0;
+ return queue_capa(capa, 1);
}
static odp_queue_type_t queue_type(odp_queue_t handle)
@@ -294,6 +295,17 @@ void sched_cb_queue_destroy_finalize(uint32_t queue_index)
UNLOCK(queue);
}
+void sched_cb_queue_set_status(uint32_t queue_index, int status)
+{
+ queue_entry_t *queue = get_qentry(queue_index);
+
+ LOCK(queue);
+
+ queue->s.status = status;
+
+ UNLOCK(queue);
+}
+
static int queue_destroy(odp_queue_t handle)
{
queue_entry_t *queue;
@@ -465,7 +477,7 @@ static int queue_enq(odp_queue_t handle, odp_event_t ev)
}
static inline int deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
- int num)
+ int num, int update_status)
{
int status_sync = sched_fn->status_sync;
int num_deq;
@@ -483,7 +495,7 @@ static inline int deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
if (num_deq == 0) {
/* Already empty queue */
- if (queue->s.status == QUEUE_STATUS_SCHED) {
+ if (update_status && queue->s.status == QUEUE_STATUS_SCHED) {
queue->s.status = QUEUE_STATUS_NOTSCHED;
if (status_sync)
@@ -508,7 +520,7 @@ static int queue_int_deq_multi(queue_t q_int, odp_buffer_hdr_t *buf_hdr[],
{
queue_entry_t *queue = qentry_from_int(q_int);
- return deq_multi(queue, buf_hdr, num);
+ return deq_multi(queue, buf_hdr, num, 0);
}
static odp_buffer_hdr_t *queue_int_deq(queue_t q_int)
@@ -517,7 +529,7 @@ static odp_buffer_hdr_t *queue_int_deq(queue_t q_int)
odp_buffer_hdr_t *buf_hdr = NULL;
int ret;
- ret = deq_multi(queue, &buf_hdr, 1);
+ ret = deq_multi(queue, &buf_hdr, 1, 0);
if (ret == 1)
return buf_hdr;
@@ -627,11 +639,12 @@ static int queue_info(odp_queue_t handle, odp_queue_info_t *info)
return 0;
}
-int sched_cb_queue_deq_multi(uint32_t queue_index, odp_event_t ev[], int num)
+int sched_cb_queue_deq_multi(uint32_t queue_index, odp_event_t ev[], int num,
+ int update_status)
{
queue_entry_t *qe = get_qentry(queue_index);
- return deq_multi(qe, (odp_buffer_hdr_t **)ev, num);
+ return deq_multi(qe, (odp_buffer_hdr_t **)ev, num, update_status);
}
int sched_cb_queue_empty(uint32_t queue_index)
diff --git a/platform/linux-dpdk/odp_time.c b/platform/linux-dpdk/odp_time.c
index 3107d24..3cbb771 100644
--- a/platform/linux-dpdk/odp_time.c
+++ b/platform/linux-dpdk/odp_time.c
@@ -373,9 +373,9 @@ int odp_time_init_global(void)
global.use_hw = 1;
global.hw_start = rte_get_timer_cycles();
if (global.hw_start == 0)
- return -1;
- else
- return 0;
+ return -1;
+ else
+ return 0;
}
global.handler.time_cur = time_cur;
diff --git a/platform/linux-generic/.gitignore b/platform/linux-generic/.gitignore
index fd5ade7..16e788a 100644
--- a/platform/linux-generic/.gitignore
+++ b/platform/linux-generic/.gitignore
@@ -1 +1,2 @@
libodp-linux.pc
+odp_libconfig_config.h
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index c35c0bf..7e57994 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -5,6 +5,7 @@ include $(top_srcdir)/platform/Makefile.inc
AM_CPPFLAGS = $(ODP_INCLUDES)
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/include
+AM_CPPFLAGS += -I$(top_builddir)/platform/$(with_platform)/include
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/arch
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/arch/@ARCH_DIR@
AM_CPPFLAGS += -I$(top_srcdir)/platform/$(with_platform)/arch/default
@@ -13,6 +14,12 @@ AM_CPPFLAGS += $(OPENSSL_CPPFLAGS)
AM_CPPFLAGS += $(DPDK_CPPFLAGS)
AM_CPPFLAGS += $(NETMAP_CPPFLAGS)
+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
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
if !ODP_ABI_COMPAT
odpapiplatincludedir= $(includedir)/odp/api/plat
odpapiplatinclude_HEADERS = \
@@ -94,6 +101,7 @@ noinst_HEADERS = \
include/odp_forward_typedefs_internal.h \
include/odp_internal.h \
include/odp_ipsec_internal.h \
+ include/odp_libconfig_internal.h \
include/odp_llqueue.h \
include/odp_macros_internal.h \
include/odp_name_table_internal.h \
@@ -131,6 +139,9 @@ noinst_HEADERS = \
include/protocols/thash.h \
include/protocols/udp.h
+nodist_noinst_HEADERS = \
+ include/odp_libconfig_config.h
+
__LIB__libodp_linux_la_SOURCES = \
_fdserver.c \
_ishm.c \
@@ -154,6 +165,7 @@ __LIB__libodp_linux_la_SOURCES = \
odp_ipsec.c \
odp_ipsec_events.c \
odp_ipsec_sad.c \
+ odp_libconfig.c \
odp_name_table.c \
odp_packet.c \
odp_packet_flags.c \
@@ -287,6 +299,7 @@ endif
__LIB__libodp_linux_la_LIBADD = $(ATOMIC_LIBS)
__LIB__libodp_linux_la_LIBADD += $(OPENSSL_LIBS)
+__LIB__libodp_linux_la_LIBADD += $(LIBCONFIG_LIBS)
__LIB__libodp_linux_la_LIBADD += $(DPDK_LIBS_LIBODP)
__LIB__libodp_linux_la_LIBADD += $(PTHREAD_LIBS)
__LIB__libodp_linux_la_LIBADD += $(TIMER_LIBS)
diff --git a/platform/linux-generic/include/odp_buffer_inlines.h b/platform/linux-generic/include/odp_buffer_inlines.h
index 9abe79f..9e3b6ef 100644
--- a/platform/linux-generic/include/odp_buffer_inlines.h
+++ b/platform/linux-generic/include/odp_buffer_inlines.h
@@ -28,6 +28,11 @@ static inline odp_buffer_t buf_from_buf_hdr(odp_buffer_hdr_t *hdr)
return (odp_buffer_t)hdr;
}
+static inline odp_event_t event_from_buf_hdr(odp_buffer_hdr_t *hdr)
+{
+ return (odp_event_t)hdr;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h
index ff8e417..153c787 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -23,6 +23,7 @@ extern "C" {
#include <odp_errno_define.h>
#include <stdio.h>
#include <sys/types.h>
+#include <libconfig.h>
#define MAX_CPU_NUMBER 128
#define UID_MAXLEN 30
@@ -55,10 +56,14 @@ struct odp_global_data_s {
odp_cpumask_t control_cpus;
odp_cpumask_t worker_cpus;
int num_cpus_installed;
+ config_t libconfig_default;
+ config_t libconfig_runtime;
+
};
enum init_stage {
NO_INIT = 0, /* No init stages completed */
+ LIBCONFIG_INIT,
CPUMASK_INIT,
TIME_INIT,
SYSINFO_INIT,
diff --git a/platform/linux-generic/include/odp_libconfig_internal.h b/platform/linux-generic/include/odp_libconfig_internal.h
new file mode 100644
index 0000000..0429177
--- /dev/null
+++ b/platform/linux-generic/include/odp_libconfig_internal.h
@@ -0,0 +1,29 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * Common libconfig functions
+ */
+
+#ifndef ODP_LIBCONFIG_INTERNAL_H_
+#define ODP_LIBCONFIG_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _odp_libconfig_init_global(void);
+int _odp_libconfig_term_global(void);
+
+int _odp_libconfig_lookup_int(const char *path, int *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp_packet_dpdk.h b/platform/linux-generic/include/odp_packet_dpdk.h
index 94fe376..7600b57 100644
--- a/platform/linux-generic/include/odp_packet_dpdk.h
+++ b/platform/linux-generic/include/odp_packet_dpdk.h
@@ -21,8 +21,6 @@
#define DPDK_NB_MBUF 16384
#define DPDK_MBUF_BUF_SIZE RTE_MBUF_DEFAULT_BUF_SIZE
#define DPDK_MEMPOOL_CACHE_SIZE 64
-#define DPDK_NM_RX_DESC 128
-#define DPDK_NM_TX_DESC 512
ODP_STATIC_ASSERT((DPDK_NB_MBUF % DPDK_MEMPOOL_CACHE_SIZE == 0) &&
(DPDK_MEMPOOL_CACHE_SIZE <= RTE_MEMPOOL_CACHE_MAX_SIZE) &&
@@ -33,6 +31,13 @@ ODP_STATIC_ASSERT((DPDK_NB_MBUF % DPDK_MEMPOOL_CACHE_SIZE == 0) &&
/* Minimum RX burst size */
#define DPDK_MIN_RX_BURST 4
+/** DPDK runtime configuration options */
+typedef struct {
+ int num_rx_desc;
+ int num_tx_desc;
+ int rx_drop_en;
+} dpdk_opt_t;
+
/** Cache for storing packets */
struct pkt_cache_t {
/** array for storing extra RX packets */
@@ -64,6 +69,7 @@ typedef struct ODP_ALIGNED_CACHE {
odp_ticketlock_t tx_lock[PKTIO_MAX_QUEUES]; /**< TX queue locks */
/** cache for storing extra RX packets */
pkt_cache_t rx_cache[PKTIO_MAX_QUEUES];
+ dpdk_opt_t opt;
} pkt_dpdk_t;
#endif
diff --git a/platform/linux-generic/include/odp_queue_internal.h b/platform/linux-generic/include/odp_queue_internal.h
index 0540bf7..3aec3fe 100644
--- a/platform/linux-generic/include/odp_queue_internal.h
+++ b/platform/linux-generic/include/odp_queue_internal.h
@@ -30,6 +30,7 @@ extern "C" {
#include <odp/api/ticketlock.h>
#include <odp_config_internal.h>
#include <odp_ring_st_internal.h>
+#include <odp_queue_lf.h>
#define QUEUE_STATUS_FREE 0
#define QUEUE_STATUS_DESTROYED 1
@@ -62,6 +63,27 @@ union queue_entry_u {
uint8_t pad[ROUNDUP_CACHE_LINE(sizeof(struct queue_entry_s))];
};
+typedef struct ODP_ALIGNED_CACHE {
+ /* Storage space for ring data */
+ uint32_t data[CONFIG_QUEUE_SIZE];
+} queue_ring_data_t;
+
+typedef struct queue_global_t {
+ queue_entry_t queue[ODP_CONFIG_QUEUES];
+ queue_ring_data_t ring_data[ODP_CONFIG_QUEUES];
+ uint32_t queue_lf_num;
+ uint32_t queue_lf_size;
+ queue_lf_func_t queue_lf_func;
+
+} queue_global_t;
+
+extern queue_global_t *queue_glb;
+
+static inline queue_t queue_index_to_qint(uint32_t queue_id)
+{
+ return (queue_t)&queue_glb->queue[queue_id];
+}
+
static inline uint32_t queue_to_index(odp_queue_t handle)
{
return _odp_typeval(handle) - 1;
diff --git a/platform/linux-generic/include/odp_queue_lf.h b/platform/linux-generic/include/odp_queue_lf.h
index ef178e0..8a973a8 100644
--- a/platform/linux-generic/include/odp_queue_lf.h
+++ b/platform/linux-generic/include/odp_queue_lf.h
@@ -12,7 +12,6 @@ extern "C" {
#endif
#include <odp_queue_if.h>
-#include <odp_queue_internal.h>
/* Lock-free queue functions */
typedef struct {
diff --git a/platform/linux-generic/include/odp_schedule_if.h b/platform/linux-generic/include/odp_schedule_if.h
index 66e0504..4bd127a 100644
--- a/platform/linux-generic/include/odp_schedule_if.h
+++ b/platform/linux-generic/include/odp_schedule_if.h
@@ -77,12 +77,16 @@ typedef struct schedule_fn_t {
extern const schedule_fn_t *sched_fn;
/* Interface for the scheduler */
-int sched_cb_pktin_poll(int pktio_index, int num_queue, int index[]);
+int sched_cb_pktin_poll(int pktio_index, int pktin_index,
+ odp_buffer_hdr_t *hdr_tbl[], int num);
+int sched_cb_pktin_poll_old(int pktio_index, int num_queue, int index[]);
int sched_cb_pktin_poll_one(int pktio_index, int rx_queue, odp_event_t evts[]);
void sched_cb_pktio_stop_finalize(int pktio_index);
odp_queue_t sched_cb_queue_handle(uint32_t queue_index);
void sched_cb_queue_destroy_finalize(uint32_t queue_index);
-int sched_cb_queue_deq_multi(uint32_t queue_index, odp_event_t ev[], int num);
+void sched_cb_queue_set_status(uint32_t queue_index, int status);
+int sched_cb_queue_deq_multi(uint32_t queue_index, odp_event_t ev[], int num,
+ int update_status);
int sched_cb_queue_empty(uint32_t queue_index);
/* API functions */
diff --git a/platform/linux-generic/libodp-linux.pc.in b/platform/linux-generic/libodp-linux.pc.in
index 5125f83..66ac78f 100644
--- a/platform/linux-generic/libodp-linux.pc.in
+++ b/platform/linux-generic/libodp-linux.pc.in
@@ -6,6 +6,7 @@ includedir=@includedir@
Name: libodp-linux
Description: The ODP packet processing engine
Version: @PKGCONFIG_VERSION@
+Requires.private: libconfig
Libs: -L${libdir} -lodp-linux
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 083a658..7cf0a9b 100644
--- a/platform/linux-generic/m4/configure.m4
+++ b/platform/linux-generic/m4/configure.m4
@@ -1,4 +1,4 @@
-IMPLEMENTATION_NAME="odp-linux"
+ODP_IMPLEMENTATION_NAME="odp-linux"
ODP_VISIBILITY
ODP_ATOMIC
@@ -6,6 +6,7 @@ ODP_ATOMIC
ODP_PTHREAD
ODP_TIMER
ODP_OPENSSL
+ODP_LIBCONFIG([linux-generic])
m4_include([platform/linux-generic/m4/odp_pcap.m4])
m4_include([platform/linux-generic/m4/odp_netmap.m4])
m4_include([platform/linux-generic/m4/odp_dpdk.m4])
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index f1d5fca..a7fddb5 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -816,7 +816,7 @@ aes_gmac_gen_init(odp_crypto_generic_session_t *session)
EVP_EncryptInit_ex(ctx, session->auth.evp_cipher, NULL,
session->auth.key, NULL);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
- session->p.cipher_iv.length, NULL);
+ session->p.auth_iv.length, NULL);
EVP_CIPHER_CTX_set_padding(ctx, 0);
}
@@ -858,7 +858,7 @@ aes_gmac_check_init(odp_crypto_generic_session_t *session)
EVP_DecryptInit_ex(ctx, session->auth.evp_cipher, NULL,
session->auth.key, NULL);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
- session->p.cipher_iv.length, NULL);
+ session->p.auth_iv.length, NULL);
EVP_CIPHER_CTX_set_padding(ctx, 0);
}
@@ -1646,6 +1646,10 @@ odp_crypto_init_global(void)
/* Allocate our globally shared memory */
shm = odp_shm_reserve("crypto_pool", mem_size,
ODP_CACHE_LINE_SIZE, 0);
+ if (ODP_SHM_INVALID == shm) {
+ ODP_ERR("unable to allocate crypto pool\n");
+ return -1;
+ }
global = odp_shm_addr(shm);
@@ -1868,9 +1872,9 @@ int odp_crypto_result(odp_crypto_packet_result_t *result,
}
static
-int odp_crypto_int(odp_packet_t pkt_in,
- odp_packet_t *pkt_out,
- const odp_crypto_packet_op_param_t *param)
+int crypto_int(odp_packet_t pkt_in,
+ odp_packet_t *pkt_out,
+ const odp_crypto_packet_op_param_t *param)
{
odp_crypto_alg_err_t rc_cipher = ODP_CRYPTO_ALG_ERR_NONE;
odp_crypto_alg_err_t rc_auth = ODP_CRYPTO_ALG_ERR_NONE;
@@ -1944,7 +1948,7 @@ int odp_crypto_int(odp_packet_t pkt_in,
err:
if (allocated) {
odp_packet_free(out_pkt);
- out_pkt = ODP_PACKET_INVALID;
+ *pkt_out = ODP_PACKET_INVALID;
}
return -1;
@@ -1962,7 +1966,7 @@ int odp_crypto_op(const odp_packet_t pkt_in[],
ODP_ASSERT(ODP_CRYPTO_SYNC == session->p.op_mode);
for (i = 0; i < num_pkt; i++) {
- rc = odp_crypto_int(pkt_in[i], &pkt_out[i], &param[i]);
+ rc = crypto_int(pkt_in[i], &pkt_out[i], &param[i]);
if (rc < 0)
break;
}
@@ -1986,7 +1990,7 @@ int odp_crypto_op_enq(const odp_packet_t pkt_in[],
for (i = 0; i < num_pkt; i++) {
pkt = pkt_out[i];
- rc = odp_crypto_int(pkt_in[i], &pkt, &param[i]);
+ rc = crypto_int(pkt_in[i], &pkt, &param[i]);
if (rc < 0)
break;
diff --git a/platform/linux-generic/odp_impl.c b/platform/linux-generic/odp_impl.c
index b699429..227d500 100644
--- a/platform/linux-generic/odp_impl.c
+++ b/platform/linux-generic/odp_impl.c
@@ -5,26 +5,11 @@
*/
#include "config.h"
-
-
-/**
- * @file
- *
- * ODP Implementation information
- */
-
-#ifndef ODP_IMPL_H_
-#define ODP_IMPL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include <odp/api/version.h>
#define ODP_VERSION_IMPL 0
#define ODP_VERSION_IMPL_STR \
- ODP_VERSION_TO_STR(IMPLEMENTATION_NAME) " " \
+ ODP_IMPLEMENTATION_NAME " " \
ODP_VERSION_TO_STR(ODP_VERSION_API_GENERATION) "." \
ODP_VERSION_TO_STR(ODP_VERSION_API_MAJOR) "." \
ODP_VERSION_TO_STR(ODP_VERSION_API_MINOR) "-" \
@@ -32,10 +17,7 @@ extern "C" {
ODP_VERSION_TO_STR(ODP_VERSION_API_GENERATION) "." \
ODP_VERSION_TO_STR(ODP_VERSION_API_MAJOR) "." \
ODP_VERSION_TO_STR(ODP_VERSION_API_MINOR) ") " \
- ODP_VERSION_TO_STR(GIT_HASH)
-
-#define ODP_VERSION_IMPL_NAME \
- ODP_VERSION_TO_STR(IMPLEMENTATION_NAME)
+ ODP_VERSION_TO_STR(ODP_VERSION_BUILD)
const char *odp_version_impl_str(void)
{
@@ -44,11 +26,5 @@ const char *odp_version_impl_str(void)
const char *odp_version_impl_name(void)
{
- return ODP_VERSION_IMPL_NAME;
+ return ODP_IMPLEMENTATION_NAME;
}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c
index 19003b6..0cd66ca 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -12,6 +12,7 @@
#include <unistd.h>
#include <odp_internal.h>
#include <odp_schedule_if.h>
+#include <odp_libconfig_internal.h>
#include <string.h>
#include <stdio.h>
#include <linux/limits.h>
@@ -48,6 +49,12 @@ int odp_init_global(odp_instance_t *instance,
odp_global_data.abort_fn = params->abort_fn;
}
+ if (_odp_libconfig_init_global()) {
+ ODP_ERR("ODP runtime config init failed.\n");
+ goto init_failed;
+ }
+ stage = LIBCONFIG_INIT;
+
if (odp_cpumask_init_global(params)) {
ODP_ERR("ODP cpumask init failed.\n");
goto init_failed;
@@ -306,6 +313,13 @@ int _odp_term_global(enum init_stage stage)
}
/* Fall through */
+ case LIBCONFIG_INIT:
+ if (_odp_libconfig_term_global()) {
+ ODP_ERR("ODP runtime config term failed.\n");
+ rc = -1;
+ }
+ /* Fall through */
+
case NO_INIT:
;
}
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c
index fb852e7..1e90cea 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -476,6 +476,12 @@ static int ipsec_in_esp(odp_packet_t *pkt,
state->in.hdr_len = _ODP_ESPHDR_LEN + ipsec_sa->esp_iv_len;
state->in.trl_len = _ODP_ESPTRL_LEN + ipsec_sa->icv_len;
+ if (odp_unlikely(state->ip_tot_len <
+ state->ip_hdr_len + state->in.hdr_len + ipsec_sa->icv_len)) {
+ status->error.proto = 1;
+ return -1;
+ }
+
param->cipher_range.offset = ipsec_offset + state->in.hdr_len;
param->cipher_range.length = state->ip_tot_len -
state->ip_hdr_len -
@@ -949,8 +955,10 @@ static int ipsec_out_tunnel_ipv4(odp_packet_t *pkt,
state->ip_hdr_len = _ODP_IPV4HDR_LEN;
if (state->is_ipv4)
state->ip_next_hdr = _ODP_IPPROTO_IPIP;
- else
+ else if (state->is_ipv6)
state->ip_next_hdr = _ODP_IPPROTO_IPV6;
+ else
+ state->ip_next_hdr = _ODP_IPPROTO_NO_NEXT;
state->ip_next_hdr_offset = state->ip_offset +
_ODP_IPV4HDR_PROTO_OFFSET;
@@ -1008,8 +1016,10 @@ static int ipsec_out_tunnel_ipv6(odp_packet_t *pkt,
state->ip_hdr_len = _ODP_IPV6HDR_LEN;
if (state->is_ipv4)
state->ip_next_hdr = _ODP_IPPROTO_IPIP;
- else
+ else if (state->is_ipv6)
state->ip_next_hdr = _ODP_IPPROTO_IPV6;
+ else
+ state->ip_next_hdr = _ODP_IPPROTO_NO_NEXT;
state->ip_next_hdr_offset = state->ip_offset + _ODP_IPV6HDR_NHDR_OFFSET;
state->is_ipv4 = 0;
@@ -1061,7 +1071,8 @@ static int ipsec_out_esp(odp_packet_t *pkt,
ipsec_sa_t *ipsec_sa,
odp_crypto_packet_op_param_t *param,
odp_ipsec_op_status_t *status,
- uint32_t mtu)
+ uint32_t mtu,
+ const odp_ipsec_out_opt_t *opt)
{
_odp_esphdr_t esp;
_odp_esptrl_t esptrl;
@@ -1069,17 +1080,25 @@ static int ipsec_out_esp(odp_packet_t *pkt,
uint32_t encrypt_len;
uint16_t ip_data_len = state->ip_tot_len -
state->ip_hdr_len;
+ uint16_t tfc_len = (opt->flag.tfc_pad || opt->flag.tfc_dummy) ?
+ opt->tfc_pad_len : 0;
uint32_t pad_block = ipsec_sa->esp_block_len;
uint16_t ipsec_offset = state->ip_offset + state->ip_hdr_len;
unsigned hdr_len;
unsigned trl_len;
+ unsigned pkt_len, new_len;
uint8_t proto = _ODP_IPPROTO_ESP;
+ if (odp_unlikely(opt->flag.tfc_dummy)) {
+ ip_data_len = 0;
+ state->ip_tot_len = state->ip_offset + state->ip_hdr_len;
+ }
+
/* ESP trailer should be 32-bit right aligned */
if (pad_block < 4)
pad_block = 4;
- encrypt_len = IPSEC_PAD_LEN(ip_data_len + _ODP_ESPTRL_LEN,
+ encrypt_len = IPSEC_PAD_LEN(ip_data_len + tfc_len + _ODP_ESPTRL_LEN,
pad_block);
hdr_len = _ODP_ESPHDR_LEN + ipsec_sa->esp_iv_len;
@@ -1120,7 +1139,7 @@ static int ipsec_out_esp(odp_packet_t *pkt,
param->aad_ptr = (uint8_t *)&state->esp.aad;
memset(&esptrl, 0, sizeof(esptrl));
- esptrl.pad_len = encrypt_len - ip_data_len - _ODP_ESPTRL_LEN;
+ esptrl.pad_len = encrypt_len - ip_data_len - tfc_len - _ODP_ESPTRL_LEN;
esptrl.next_header = state->ip_next_hdr;
odp_packet_copy_from_mem(*pkt, state->ip_next_hdr_offset, 1, &proto);
@@ -1129,19 +1148,34 @@ static int ipsec_out_esp(odp_packet_t *pkt,
_odp_ipv4hdr_t *ipv4hdr = state->ip;
ipv4hdr->tot_len = _odp_cpu_to_be_16(state->ip_tot_len);
- } else {
+ } else if (state->is_ipv6) {
_odp_ipv6hdr_t *ipv6hdr = state->ip;
ipv6hdr->payload_len = _odp_cpu_to_be_16(state->ip_tot_len -
_ODP_IPV6HDR_LEN);
}
- if (odp_packet_extend_tail(pkt, trl_len, NULL, NULL) < 0 ||
- odp_packet_extend_head(pkt, hdr_len, NULL, NULL) < 0) {
+ if (odp_packet_extend_head(pkt, hdr_len, NULL, NULL) < 0) {
status->error.alg = 1;
return -1;
}
+ pkt_len = odp_packet_len(*pkt);
+ new_len = state->ip_offset + state->ip_tot_len;
+ if (pkt_len >= new_len) {
+ if (odp_packet_trunc_tail(pkt, pkt_len - new_len,
+ NULL, NULL) < 0) {
+ status->error.alg = 1;
+ return -1;
+ }
+ } else {
+ if (odp_packet_extend_tail(pkt, new_len - pkt_len,
+ NULL, NULL) < 0) {
+ status->error.alg = 1;
+ return -1;
+ }
+ }
+
odp_packet_move_data(*pkt, 0, hdr_len, ipsec_offset);
uint32_t esptrl_offset = state->ip_offset +
@@ -1165,6 +1199,10 @@ static int ipsec_out_esp(odp_packet_t *pkt,
ipsec_offset + _ODP_ESPHDR_LEN,
ipsec_sa->esp_iv_len,
state->iv + ipsec_sa->salt_length);
+ /* 0xa5 is a good value to fill data instead of generating random data
+ * to create TFC padding */
+ _odp_packet_set_data(*pkt, esptrl_offset - esptrl.pad_len - tfc_len,
+ 0xa5, tfc_len);
odp_packet_copy_from_mem(*pkt,
esptrl_offset - esptrl.pad_len,
esptrl.pad_len, ipsec_padding);
@@ -1172,6 +1210,12 @@ static int ipsec_out_esp(odp_packet_t *pkt,
esptrl_offset, _ODP_ESPTRL_LEN,
&esptrl);
+ if (odp_unlikely(state->ip_tot_len <
+ state->ip_hdr_len + hdr_len + ipsec_sa->icv_len)) {
+ status->error.proto = 1;
+ return -1;
+ }
+
param->cipher_range.offset = ipsec_offset + hdr_len;
param->cipher_range.length = state->ip_tot_len -
state->ip_hdr_len -
@@ -1323,15 +1367,30 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
odp_ipsec_frag_mode_t frag_mode;
uint32_t mtu;
- state.ip_offset = odp_packet_l3_offset(pkt);
- ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != state.ip_offset);
-
- state.ip = odp_packet_l3_ptr(pkt, NULL);
- ODP_ASSERT(NULL != state.ip);
-
ipsec_sa = _odp_ipsec_sa_use(sa);
ODP_ASSERT(NULL != ipsec_sa);
+ if (opt->flag.tfc_dummy) {
+ odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt);
+
+ ODP_ASSERT(ODP_IPSEC_MODE_TUNNEL == ipsec_sa->mode);
+ pkt_hdr->p.l2_offset = ODP_PACKET_OFFSET_INVALID;
+ pkt_hdr->p.l3_offset = 0;
+ state.ip_offset = 0;
+ state.ip = NULL;
+ state.is_ipv4 = 0;
+ state.is_ipv6 = 0;
+ } else {
+ state.ip_offset = odp_packet_l3_offset(pkt);
+ ODP_ASSERT(ODP_PACKET_OFFSET_INVALID != state.ip_offset);
+
+ state.ip = odp_packet_l3_ptr(pkt, NULL);
+ ODP_ASSERT(NULL != state.ip);
+
+ state.is_ipv4 = (((uint8_t *)state.ip)[0] >> 4) == 0x4;
+ state.is_ipv6 = (((uint8_t *)state.ip)[0] >> 4) == 0x6;
+ }
+
frag_mode = opt->flag.frag_mode ? opt->frag_mode :
ipsec_sa->out.frag_mode;
if (frag_mode == ODP_IPSEC_FRAG_CHECK)
@@ -1342,9 +1401,6 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
/* Initialize parameters block */
memset(&param, 0, sizeof(param));
- state.is_ipv4 = (((uint8_t *)state.ip)[0] >> 4) == 0x4;
- state.is_ipv6 = (((uint8_t *)state.ip)[0] >> 4) == 0x6;
-
if (ODP_IPSEC_MODE_TRANSPORT == ipsec_sa->mode) {
if (state.is_ipv4)
rc = ipsec_parse_ipv4(&state, pkt);
@@ -1360,7 +1416,12 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
rc = ipsec_out_tunnel_parse_ipv4(&state, ipsec_sa);
else if (state.is_ipv6)
rc = ipsec_out_tunnel_parse_ipv6(&state, ipsec_sa);
- else
+ else if (opt->flag.tfc_dummy) {
+ state.out_tunnel.ip_tos = 0;
+ state.out_tunnel.ip_df = 0;
+ state.out_tunnel.ip_flabel = 0;
+ rc = 0;
+ } else
rc = -1;
if (rc < 0) {
status->error.alg = 1;
@@ -1384,7 +1445,8 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt,
}
if (ODP_IPSEC_ESP == ipsec_sa->proto) {
- rc = ipsec_out_esp(&pkt, &state, ipsec_sa, &param, status, mtu);
+ rc = ipsec_out_esp(&pkt, &state, ipsec_sa, &param, status, mtu,
+ opt);
} else if (ODP_IPSEC_AH == ipsec_sa->proto) {
rc = ipsec_out_ah(&pkt, &state, ipsec_sa, &param, status, mtu);
} else {
@@ -1740,9 +1802,14 @@ int odp_ipsec_out_inline(const odp_packet_t pkt_in[], int num_in,
else
opt = &param->opt[opt_idx];
+ ipsec_sa = ipsec_out_single(pkt, sa, &pkt, opt, &status);
+ ODP_ASSERT(NULL != ipsec_sa);
+
hdr_len = inline_param[in_pkt].outer_hdr.len;
ptr = inline_param[in_pkt].outer_hdr.ptr;
offset = odp_packet_l3_offset(pkt);
+ if (odp_unlikely(offset == ODP_PACKET_OFFSET_INVALID))
+ offset = 0;
if (offset >= hdr_len) {
if (odp_packet_trunc_head(&pkt, offset - hdr_len,
NULL, NULL) < 0)
@@ -1761,9 +1828,6 @@ int odp_ipsec_out_inline(const odp_packet_t pkt_in[], int num_in,
ptr) < 0)
status.error.alg = 1;
- ipsec_sa = ipsec_out_single(pkt, sa, &pkt, opt, &status);
- ODP_ASSERT(NULL != ipsec_sa);
-
packet_subtype_set(pkt, ODP_EVENT_PACKET_IPSEC);
result = ipsec_pkt_result(pkt);
memset(result, 0, sizeof(*result));
diff --git a/platform/linux-generic/odp_libconfig.c b/platform/linux-generic/odp_libconfig.c
new file mode 100644
index 0000000..3b3b317
--- /dev/null
+++ b/platform/linux-generic/odp_libconfig.c
@@ -0,0 +1,99 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <libconfig.h>
+
+#include <odp/api/version.h>
+#include <odp_internal.h>
+#include <odp_debug_internal.h>
+#include <odp_libconfig_internal.h>
+#include <odp_libconfig_config.h>
+
+#define CONF_STR_NAME ((const char *)odp_linux_generic_conf)
+
+extern struct odp_global_data_s odp_global_data;
+
+int _odp_libconfig_init_global(void)
+{
+ const char *filename;
+ const char *vers;
+ const char *vers_rt;
+ const char *ipml;
+ const char *ipml_rt;
+ config_t *config = &odp_global_data.libconfig_default;
+ config_t *config_rt = &odp_global_data.libconfig_runtime;
+
+ config_init(config);
+ config_init(config_rt);
+
+ if (!config_read_string(config, CONF_STR_NAME)) {
+ ODP_ERR("Failed to read default config: %s(%d): %s\n",
+ config_error_file(config), config_error_line(config),
+ config_error_text(config));
+ goto fail;
+ }
+
+ filename = getenv("ODP_CONFIG_FILE");
+ if (filename == NULL)
+ return 0;
+
+ if (!config_read_file(config_rt, filename)) {
+ ODP_ERR("Failed to read config file: %s(%d): %s\n",
+ config_error_file(config_rt),
+ config_error_line(config_rt),
+ config_error_text(config_rt));
+ goto fail;
+ }
+
+ /* Check runtime configuration's implementation name and version */
+ if (!config_lookup_string(config, "odp_implementation", &ipml) ||
+ !config_lookup_string(config_rt, "odp_implementation", &ipml_rt)) {
+ ODP_ERR("Configuration missing 'odp_implementation' field\n");
+ goto fail;
+ }
+ if (!config_lookup_string(config, "config_file_version", &vers) ||
+ !config_lookup_string(config_rt, "config_file_version", &vers_rt)) {
+ ODP_ERR("Configuration missing 'config_file_version' field\n");
+ goto fail;
+ }
+ if (strcmp(vers, vers_rt) || strcmp(ipml, ipml_rt)) {
+ ODP_ERR("Runtime configuration mismatch\n");
+ goto fail;
+ }
+
+ return 0;
+fail:
+ config_destroy(config);
+ config_destroy(config_rt);
+ return -1;
+}
+
+int _odp_libconfig_term_global(void)
+{
+ config_destroy(&odp_global_data.libconfig_default);
+ config_destroy(&odp_global_data.libconfig_runtime);
+
+ return 0;
+}
+
+int _odp_libconfig_lookup_int(const char *path, int *value)
+{
+ int ret_def = CONFIG_FALSE;
+ int ret_rt = CONFIG_FALSE;
+
+ ret_def = config_lookup_int(&odp_global_data.libconfig_default, path,
+ value);
+
+ /* Runtime option overrides default value */
+ ret_rt = config_lookup_int(&odp_global_data.libconfig_runtime, path,
+ value);
+
+ return (ret_def == CONFIG_TRUE || ret_rt == CONFIG_TRUE) ? 1 : 0;
+}
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c
index ae8e390..56e9f68 100644
--- a/platform/linux-generic/odp_packet_io.c
+++ b/platform/linux-generic/odp_packet_io.c
@@ -237,8 +237,6 @@ static odp_pktio_t setup_pktio_entry(const char *name, odp_pool_t pool,
pktio_entry->s.ops = pktio_if_ops[pktio_if];
unlock_entry(pktio_entry);
- ODP_DBG("%s uses %s\n", name, pktio_if_ops[pktio_if]->name);
-
return hdl;
}
@@ -255,6 +253,18 @@ static int pool_type_is_packet(odp_pool_t pool)
return pool_info.params.type == ODP_POOL_PACKET;
}
+static const char *driver_name(odp_pktio_t hdl)
+{
+ pktio_entry_t *entry;
+
+ if (hdl != ODP_PKTIO_INVALID) {
+ entry = get_pktio_entry(hdl);
+ return entry->s.ops->name;
+ }
+
+ return "bad handle";
+}
+
odp_pktio_t odp_pktio_open(const char *name, odp_pool_t pool,
const odp_pktio_param_t *param)
{
@@ -279,6 +289,8 @@ odp_pktio_t odp_pktio_open(const char *name, odp_pool_t pool,
hdl = setup_pktio_entry(name, pool, param);
odp_spinlock_unlock(&pktio_tbl->lock);
+ ODP_DBG("interface: %s, driver: %s\n", name, driver_name(hdl));
+
return hdl;
}
@@ -391,6 +403,8 @@ int odp_pktio_close(odp_pktio_t hdl)
unlock_entry(entry);
+ ODP_DBG("interface: %s\n", entry->s.name);
+
return 0;
}
@@ -488,6 +502,9 @@ int odp_pktio_start(odp_pktio_t hdl)
sched_fn->pktio_start(_odp_pktio_index(hdl), num, index, odpq);
}
+ ODP_DBG("interface: %s, input queues: %u, output queues: %u\n",
+ entry->s.name, entry->s.num_in_queue, entry->s.num_out_queue);
+
return res;
}
@@ -526,6 +543,8 @@ int odp_pktio_stop(odp_pktio_t hdl)
res = _pktio_stop(entry);
unlock_entry(entry);
+ ODP_DBG("interface: %s\n", entry->s.name);
+
return res;
}
@@ -559,7 +578,7 @@ odp_pktio_t odp_pktio_lookup(const char *name)
return hdl;
}
-static inline int pktin_recv_buf(odp_pktin_queue_t queue,
+static inline int pktin_recv_buf(pktio_entry_t *entry, int pktin_index,
odp_buffer_hdr_t *buffer_hdrs[], int num)
{
odp_packet_t pkt;
@@ -570,7 +589,7 @@ static inline int pktin_recv_buf(odp_pktin_queue_t queue,
int pkts;
int num_rx = 0;
- pkts = odp_pktin_recv(queue, packets, num);
+ pkts = entry->s.ops->recv(entry, pktin_index, packets, num);
for (i = 0; i < pkts; i++) {
pkt = packets[i];
@@ -624,19 +643,36 @@ static odp_buffer_hdr_t *pktin_dequeue(queue_t q_int)
odp_buffer_hdr_t *buf_hdr;
odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
int pkts;
+ odp_pktin_queue_t pktin_queue = queue_fn->get_pktin(q_int);
+ odp_pktio_t pktio = pktin_queue.pktio;
+ int pktin_index = pktin_queue.index;
+ pktio_entry_t *entry = get_pktio_entry(pktio);
buf_hdr = queue_fn->deq(q_int);
if (buf_hdr != NULL)
return buf_hdr;
- pkts = pktin_recv_buf(queue_fn->get_pktin(q_int),
- hdr_tbl, QUEUE_MULTI_MAX);
+ pkts = pktin_recv_buf(entry, pktin_index, hdr_tbl, QUEUE_MULTI_MAX);
if (pkts <= 0)
return NULL;
- if (pkts > 1)
- queue_fn->enq_multi(q_int, &hdr_tbl[1], pkts - 1);
+ if (pkts > 1) {
+ int num_enq;
+ int num = pkts - 1;
+
+ num_enq = queue_fn->enq_multi(q_int, &hdr_tbl[1], num);
+
+ if (odp_unlikely(num_enq < num)) {
+ if (odp_unlikely(num_enq < 0))
+ num_enq = 0;
+
+ ODP_DBG("Interface %s dropped %i packets\n",
+ entry->s.name, num - num_enq);
+ buffer_free_multi(&hdr_tbl[num_enq + 1], num - num_enq);
+ }
+ }
+
buf_hdr = hdr_tbl[0];
return buf_hdr;
}
@@ -646,6 +682,10 @@ static int pktin_deq_multi(queue_t q_int, odp_buffer_hdr_t *buf_hdr[], int num)
int nbr;
odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
int pkts, i, j;
+ odp_pktin_queue_t pktin_queue = queue_fn->get_pktin(q_int);
+ odp_pktio_t pktio = pktin_queue.pktio;
+ int pktin_index = pktin_queue.index;
+ pktio_entry_t *entry = get_pktio_entry(pktio);
nbr = queue_fn->deq_multi(q_int, buf_hdr, num);
if (odp_unlikely(nbr > num))
@@ -657,8 +697,8 @@ static int pktin_deq_multi(queue_t q_int, odp_buffer_hdr_t *buf_hdr[], int num)
if (nbr == num)
return nbr;
- pkts = pktin_recv_buf(queue_fn->get_pktin(q_int),
- hdr_tbl, QUEUE_MULTI_MAX);
+ pkts = pktin_recv_buf(entry, pktin_index, hdr_tbl, QUEUE_MULTI_MAX);
+
if (pkts <= 0)
return nbr;
@@ -669,8 +709,21 @@ static int pktin_deq_multi(queue_t q_int, odp_buffer_hdr_t *buf_hdr[], int num)
for (j = 0; i < pkts; i++, j++)
hdr_tbl[j] = hdr_tbl[i];
- if (j)
- queue_fn->enq_multi(q_int, hdr_tbl, j);
+ if (j) {
+ int num_enq;
+
+ num_enq = queue_fn->enq_multi(q_int, hdr_tbl, j);
+
+ if (odp_unlikely(num_enq < j)) {
+ if (odp_unlikely(num_enq < 0))
+ num_enq = 0;
+
+ ODP_DBG("Interface %s dropped %i packets\n",
+ entry->s.name, j - num_enq);
+ buffer_free_multi(&buf_hdr[num_enq], j - num_enq);
+ }
+ }
+
return nbr;
}
@@ -720,12 +773,29 @@ int sched_cb_pktin_poll_one(int pktio_index,
return num_rx;
}
-int sched_cb_pktin_poll(int pktio_index, int num_queue, int index[])
+int sched_cb_pktin_poll(int pktio_index, int pktin_index,
+ odp_buffer_hdr_t *hdr_tbl[], int num)
+{
+ pktio_entry_t *entry = pktio_entry_by_index(pktio_index);
+ int state = entry->s.state;
+
+ if (odp_unlikely(state != PKTIO_STATE_STARTED)) {
+ if (state < PKTIO_STATE_ACTIVE ||
+ state == PKTIO_STATE_STOP_PENDING)
+ return -1;
+
+ ODP_DBG("Interface %s not started\n", entry->s.name);
+ return 0;
+ }
+
+ return pktin_recv_buf(entry, pktin_index, hdr_tbl, num);
+}
+
+int sched_cb_pktin_poll_old(int pktio_index, int num_queue, int index[])
{
odp_buffer_hdr_t *hdr_tbl[QUEUE_MULTI_MAX];
int num, idx;
- pktio_entry_t *entry;
- entry = pktio_entry_by_index(pktio_index);
+ pktio_entry_t *entry = pktio_entry_by_index(pktio_index);
int state = entry->s.state;
if (odp_unlikely(state != PKTIO_STATE_STARTED)) {
@@ -739,9 +809,10 @@ int sched_cb_pktin_poll(int pktio_index, int num_queue, int index[])
for (idx = 0; idx < num_queue; idx++) {
queue_t q_int;
- odp_pktin_queue_t pktin = entry->s.in_queue[index[idx]].pktin;
+ int num_enq;
- num = pktin_recv_buf(pktin, hdr_tbl, QUEUE_MULTI_MAX);
+ num = pktin_recv_buf(entry, index[idx], hdr_tbl,
+ QUEUE_MULTI_MAX);
if (num == 0)
continue;
@@ -752,7 +823,16 @@ int sched_cb_pktin_poll(int pktio_index, int num_queue, int index[])
}
q_int = entry->s.in_queue[index[idx]].queue_int;
- queue_fn->enq_multi(q_int, hdr_tbl, num);
+ num_enq = queue_fn->enq_multi(q_int, hdr_tbl, num);
+
+ if (odp_unlikely(num_enq < num)) {
+ if (odp_unlikely(num_enq < 0))
+ num_enq = 0;
+
+ ODP_DBG("Interface %s dropped %i packets\n",
+ entry->s.name, num - num_enq);
+ buffer_free_multi(&hdr_tbl[num_enq], num - num_enq);
+ }
}
return 0;
diff --git a/platform/linux-generic/odp_queue_basic.c b/platform/linux-generic/odp_queue_basic.c
index e4f6fd8..1218987 100644
--- a/platform/linux-generic/odp_queue_basic.c
+++ b/platform/linux-generic/odp_queue_basic.c
@@ -8,7 +8,6 @@
#include <odp/api/queue.h>
#include <odp_queue_internal.h>
-#include <odp_queue_lf.h>
#include <odp_queue_if.h>
#include <odp/api/std_types.h>
#include <odp/api/align.h>
@@ -40,21 +39,7 @@
static int queue_init(queue_entry_t *queue, const char *name,
const odp_queue_param_t *param);
-typedef struct ODP_ALIGNED_CACHE {
- /* Storage space for ring data */
- uint32_t data[CONFIG_QUEUE_SIZE];
-} ring_data_t;
-
-typedef struct queue_global_t {
- queue_entry_t queue[ODP_CONFIG_QUEUES];
- ring_data_t ring_data[ODP_CONFIG_QUEUES];
- uint32_t queue_lf_num;
- uint32_t queue_lf_size;
- queue_lf_func_t queue_lf_func;
-
-} queue_global_t;
-
-static queue_global_t *queue_glb;
+queue_global_t *queue_glb;
static inline queue_entry_t *get_qentry(uint32_t queue_id)
{
@@ -68,14 +53,37 @@ static inline queue_entry_t *handle_to_qentry(odp_queue_t handle)
return get_qentry(queue_id);
}
+static int queue_capa(odp_queue_capability_t *capa, int sched)
+{
+ memset(capa, 0, sizeof(odp_queue_capability_t));
+
+ /* Reserve some queues for internal use */
+ capa->max_queues = ODP_CONFIG_QUEUES - NUM_INTERNAL_QUEUES;
+ capa->plain.max_num = capa->max_queues;
+ capa->plain.max_size = CONFIG_QUEUE_SIZE;
+ capa->plain.lockfree.max_num = queue_glb->queue_lf_num;
+ capa->plain.lockfree.max_size = queue_glb->queue_lf_size;
+ capa->sched.max_num = capa->max_queues;
+ capa->sched.max_size = CONFIG_QUEUE_SIZE;
+
+ if (sched) {
+ capa->max_ordered_locks = sched_fn->max_ordered_locks();
+ capa->max_sched_groups = sched_fn->num_grps();
+ capa->sched_prios = odp_schedule_num_prio();
+ }
+
+ return 0;
+}
+
static int queue_init_global(void)
{
uint32_t i;
odp_shm_t shm;
uint32_t lf_size = 0;
queue_lf_func_t *lf_func;
+ odp_queue_capability_t capa;
- ODP_DBG("Queue init ... ");
+ ODP_DBG("Starts...\n");
shm = odp_shm_reserve("odp_queues",
sizeof(queue_global_t),
@@ -100,13 +108,14 @@ static int queue_init_global(void)
queue_glb->queue_lf_num = queue_lf_init_global(&lf_size, lf_func);
queue_glb->queue_lf_size = lf_size;
- ODP_DBG("done\n");
- ODP_DBG("Queue init global\n");
- ODP_DBG(" struct queue_entry_s size %zu\n",
- sizeof(struct queue_entry_s));
- ODP_DBG(" queue_entry_t size %zu\n",
- sizeof(queue_entry_t));
- ODP_DBG("\n");
+ queue_capa(&capa, 0);
+
+ ODP_DBG("... done.\n");
+ ODP_DBG(" queue_entry_t size %u\n", sizeof(queue_entry_t));
+ ODP_DBG(" max num queues %u\n", capa.max_queues);
+ ODP_DBG(" max queue size %u\n", capa.plain.max_size);
+ ODP_DBG(" max num lockfree %u\n", capa.plain.lockfree.max_num);
+ ODP_DBG(" max lockfree size %u\n\n", capa.plain.lockfree.max_size);
return 0;
}
@@ -151,21 +160,7 @@ static int queue_term_global(void)
static int queue_capability(odp_queue_capability_t *capa)
{
- memset(capa, 0, sizeof(odp_queue_capability_t));
-
- /* Reserve some queues for internal use */
- capa->max_queues = ODP_CONFIG_QUEUES - NUM_INTERNAL_QUEUES;
- capa->max_ordered_locks = sched_fn->max_ordered_locks();
- capa->max_sched_groups = sched_fn->num_grps();
- capa->sched_prios = odp_schedule_num_prio();
- capa->plain.max_num = capa->max_queues;
- capa->plain.max_size = CONFIG_QUEUE_SIZE;
- capa->plain.lockfree.max_num = queue_glb->queue_lf_num;
- capa->plain.lockfree.max_size = queue_glb->queue_lf_size;
- capa->sched.max_num = capa->max_queues;
- capa->sched.max_size = CONFIG_QUEUE_SIZE;
-
- return 0;
+ return queue_capa(capa, 1);
}
static odp_queue_type_t queue_type(odp_queue_t handle)
@@ -299,6 +294,17 @@ void sched_cb_queue_destroy_finalize(uint32_t queue_index)
UNLOCK(queue);
}
+void sched_cb_queue_set_status(uint32_t queue_index, int status)
+{
+ queue_entry_t *queue = get_qentry(queue_index);
+
+ LOCK(queue);
+
+ queue->s.status = status;
+
+ UNLOCK(queue);
+}
+
static int queue_destroy(odp_queue_t handle)
{
queue_entry_t *queue;
@@ -493,7 +499,7 @@ static int queue_enq(odp_queue_t handle, odp_event_t ev)
}
static inline int deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
- int num)
+ int num, int update_status)
{
int status_sync = sched_fn->status_sync;
int num_deq;
@@ -515,7 +521,7 @@ static inline int deq_multi(queue_entry_t *queue, odp_buffer_hdr_t *buf_hdr[],
if (num_deq == 0) {
/* Already empty queue */
- if (queue->s.status == QUEUE_STATUS_SCHED) {
+ if (update_status && queue->s.status == QUEUE_STATUS_SCHED) {
queue->s.status = QUEUE_STATUS_NOTSCHED;
if (status_sync)
@@ -542,7 +548,7 @@ static int queue_int_deq_multi(queue_t q_int, odp_buffer_hdr_t *buf_hdr[],
{
queue_entry_t *queue = qentry_from_int(q_int);
- return deq_multi(queue, buf_hdr, num);
+ return deq_multi(queue, buf_hdr, num, 0);
}
static odp_buffer_hdr_t *queue_int_deq(queue_t q_int)
@@ -551,7 +557,7 @@ static odp_buffer_hdr_t *queue_int_deq(queue_t q_int)
odp_buffer_hdr_t *buf_hdr = NULL;
int ret;
- ret = deq_multi(queue, &buf_hdr, 1);
+ ret = deq_multi(queue, &buf_hdr, 1, 0);
if (ret == 1)
return buf_hdr;
@@ -661,11 +667,12 @@ static int queue_info(odp_queue_t handle, odp_queue_info_t *info)
return 0;
}
-int sched_cb_queue_deq_multi(uint32_t queue_index, odp_event_t ev[], int num)
+int sched_cb_queue_deq_multi(uint32_t queue_index, odp_event_t ev[], int num,
+ int update_status)
{
queue_entry_t *qe = get_qentry(queue_index);
- return deq_multi(qe, (odp_buffer_hdr_t **)ev, num);
+ return deq_multi(qe, (odp_buffer_hdr_t **)ev, num, update_status);
}
int sched_cb_queue_empty(uint32_t queue_index)
diff --git a/platform/linux-generic/odp_queue_lf.c b/platform/linux-generic/odp_queue_lf.c
index 74f5294..066e6a6 100644
--- a/platform/linux-generic/odp_queue_lf.c
+++ b/platform/linux-generic/odp_queue_lf.c
@@ -7,7 +7,7 @@
#include <odp/api/queue.h>
#include <odp/api/atomic.h>
#include <odp/api/shared_memory.h>
-#include <odp_queue_lf.h>
+#include <odp_queue_internal.h>
#include <string.h>
#include <stdio.h>
diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c
index e5e1fe6..cd20b39 100644
--- a/platform/linux-generic/odp_schedule_basic.c
+++ b/platform/linux-generic/odp_schedule_basic.c
@@ -26,6 +26,7 @@
#include <odp_ring_internal.h>
#include <odp_timer_internal.h>
#include <odp_queue_internal.h>
+#include <odp_buffer_inlines.h>
/* Number of priority levels */
#define NUM_PRIO 8
@@ -50,39 +51,15 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) &&
/* Size of poll weight table */
#define WEIGHT_TBL_SIZE ((QUEUES_PER_PRIO - 1) * PREFER_RATIO)
-/* Packet input poll cmd queues */
-#define PKTIO_CMD_QUEUES 4
-
-/* Mask for wrapping command queues */
-#define PKTIO_CMD_QUEUE_MASK (PKTIO_CMD_QUEUES - 1)
-
-/* Maximum number of packet input queues per command */
-#define MAX_PKTIN 16
-
/* Maximum number of packet IO interfaces */
#define NUM_PKTIO ODP_CONFIG_PKTIO_ENTRIES
-/* Maximum number of pktio poll commands */
-#define NUM_PKTIO_CMD (MAX_PKTIN * NUM_PKTIO)
+/* Maximum pktin index. Needs to fit into 8 bits. */
+#define MAX_PKTIN_INDEX 255
/* Not a valid index */
#define NULL_INDEX ((uint32_t)-1)
-/* Not a valid poll command */
-#define PKTIO_CMD_INVALID NULL_INDEX
-
-/* Pktio command is free */
-#define PKTIO_CMD_FREE PKTIO_CMD_INVALID
-
-/* Packet IO poll queue ring size. In worst case, all pktios have all pktins
- * enabled and one poll command is created per pktin queue. The ring size must
- * be larger than or equal to NUM_PKTIO_CMD / PKTIO_CMD_QUEUES, so that it can
- * hold all poll commands in the worst case. */
-#define PKTIO_RING_SIZE (NUM_PKTIO_CMD / PKTIO_CMD_QUEUES)
-
-/* Mask for wrapping around pktio poll command index */
-#define PKTIO_RING_MASK (PKTIO_RING_SIZE - 1)
-
/* Priority queue ring size. In worst case, all event queues are scheduled
* queues and have the same priority. The ring size must be larger than or
* equal to ODP_CONFIG_QUEUES / QUEUES_PER_PRIO, so that it can hold all
@@ -90,7 +67,7 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) &&
#define PRIO_QUEUE_RING_SIZE (ODP_CONFIG_QUEUES / QUEUES_PER_PRIO)
/* Mask for wrapping around priority queue index */
-#define PRIO_QUEUE_MASK (PRIO_QUEUE_RING_SIZE - 1)
+#define RING_MASK (PRIO_QUEUE_RING_SIZE - 1)
/* Priority queue empty, not a valid queue index. */
#define PRIO_QUEUE_EMPTY NULL_INDEX
@@ -103,15 +80,6 @@ ODP_STATIC_ASSERT(CHECK_IS_POWER2(ODP_CONFIG_QUEUES),
ODP_STATIC_ASSERT(CHECK_IS_POWER2(PRIO_QUEUE_RING_SIZE),
"Ring_size_is_not_power_of_two");
-/* Ring size must be power of two, so that PKTIO_RING_MASK can be used. */
-ODP_STATIC_ASSERT(CHECK_IS_POWER2(PKTIO_RING_SIZE),
- "pktio_ring_size_is_not_power_of_two");
-
-/* Number of commands queues must be power of two, so that PKTIO_CMD_QUEUE_MASK
- * can be used. */
-ODP_STATIC_ASSERT(CHECK_IS_POWER2(PKTIO_CMD_QUEUES),
- "pktio_cmd_queues_is_not_power_of_two");
-
/* Mask of queues per priority */
typedef uint8_t pri_mask_t;
@@ -146,14 +114,20 @@ ODP_STATIC_ASSERT(sizeof(lock_called_t) == sizeof(uint32_t),
/* Scheduler local data */
typedef struct {
int thr;
- int num;
- int index;
- int pause;
+ uint16_t stash_num;
+ uint16_t stash_index;
+ uint16_t pause;
uint16_t round;
- uint16_t pktin_polls;
- uint32_t queue_index;
- odp_queue_t queue;
- odp_event_t ev_stash[MAX_DEQ];
+ uint32_t stash_qi;
+ odp_queue_t stash_queue;
+ odp_event_t stash_ev[MAX_DEQ];
+
+ uint32_t grp_epoch;
+ int num_grp;
+ uint8_t grp[NUM_SCHED_GRPS];
+ uint8_t weight_tbl[WEIGHT_TBL_SIZE];
+ uint8_t grp_weight[WEIGHT_TBL_SIZE];
+
struct {
/* Source queue index */
uint32_t src_queue;
@@ -165,12 +139,6 @@ typedef struct {
ordered_stash_t stash[MAX_ORDERED_STASH];
} ordered;
- uint32_t grp_epoch;
- int num_grp;
- uint8_t grp[NUM_SCHED_GRPS];
- uint8_t weight_tbl[WEIGHT_TBL_SIZE];
- uint8_t grp_weight[WEIGHT_TBL_SIZE];
-
} sched_local_t;
/* Priority queue */
@@ -183,24 +151,6 @@ typedef struct ODP_ALIGNED_CACHE {
} prio_queue_t;
-/* Packet IO queue */
-typedef struct ODP_ALIGNED_CACHE {
- /* Ring header */
- ring_t ring;
-
- /* Ring data: pktio poll command indexes */
- uint32_t cmd_index[PKTIO_RING_SIZE];
-
-} pktio_queue_t;
-
-/* Packet IO poll command */
-typedef struct {
- int pktio_index;
- int num_pktin;
- int pktin[MAX_PKTIN];
- uint32_t cmd_index;
-} pktio_cmd_t;
-
/* Order context of a queue */
typedef struct ODP_ALIGNED_CACHE {
/* Current ordered context id */
@@ -220,16 +170,6 @@ typedef struct {
prio_queue_t prio_q[NUM_SCHED_GRPS][NUM_PRIO][QUEUES_PER_PRIO];
- odp_spinlock_t poll_cmd_lock;
- /* Number of commands in a command queue */
- uint16_t num_pktio_cmd[PKTIO_CMD_QUEUES];
-
- /* Packet IO command queues */
- pktio_queue_t pktio_q[PKTIO_CMD_QUEUES];
-
- /* Packet IO poll commands */
- pktio_cmd_t pktio_cmd[NUM_PKTIO_CMD];
-
odp_shm_t shm;
uint32_t pri_count[NUM_PRIO][QUEUES_PER_PRIO];
@@ -244,22 +184,34 @@ typedef struct {
} sched_grp[NUM_SCHED_GRPS];
struct {
- int grp;
- int prio;
- int queue_per_prio;
- int sync;
- uint32_t order_lock_count;
+ uint8_t grp;
+ uint8_t prio;
+ uint8_t queue_per_prio;
+ uint8_t sync;
+ uint8_t order_lock_count;
+ uint8_t poll_pktin;
+ uint8_t pktio_index;
+ uint8_t pktin_index;
} queue[ODP_CONFIG_QUEUES];
struct {
- /* Number of active commands for a pktio interface */
- int num_cmd;
+ int num_pktin;
} pktio[NUM_PKTIO];
+ odp_spinlock_t pktio_lock;
order_context_t order[ODP_CONFIG_QUEUES];
} sched_global_t;
+/* Check that queue[] variables are large enough */
+ODP_STATIC_ASSERT(NUM_SCHED_GRPS <= 256, "Group_does_not_fit_8_bits");
+ODP_STATIC_ASSERT(NUM_PRIO <= 256, "Prio_does_not_fit_8_bits");
+ODP_STATIC_ASSERT(QUEUES_PER_PRIO <= 256,
+ "Queues_per_prio_does_not_fit_8_bits");
+ODP_STATIC_ASSERT(CONFIG_QUEUE_MAX_ORD_LOCKS <= 256,
+ "Ordered_lock_count_does_not_fit_8_bits");
+ODP_STATIC_ASSERT(NUM_PKTIO <= 256, "Pktio_index_does_not_fit_8_bits");
+
/* Global scheduler context */
static sched_global_t *sched;
@@ -277,9 +229,9 @@ static void sched_local_init(void)
memset(&sched_local, 0, sizeof(sched_local_t));
- sched_local.thr = odp_thread_id();
- sched_local.queue = ODP_QUEUE_INVALID;
- sched_local.queue_index = PRIO_QUEUE_EMPTY;
+ sched_local.thr = odp_thread_id();
+ sched_local.stash_queue = ODP_QUEUE_INVALID;
+ sched_local.stash_qi = PRIO_QUEUE_EMPTY;
sched_local.ordered.src_queue = NULL_INDEX;
id = sched_local.thr & (QUEUES_PER_PRIO - 1);
@@ -337,16 +289,9 @@ static int schedule_init_global(void)
}
}
- odp_spinlock_init(&sched->poll_cmd_lock);
- for (i = 0; i < PKTIO_CMD_QUEUES; i++) {
- ring_init(&sched->pktio_q[i].ring);
-
- for (j = 0; j < PKTIO_RING_SIZE; j++)
- sched->pktio_q[i].cmd_index[j] = PKTIO_CMD_INVALID;
- }
-
- for (i = 0; i < NUM_PKTIO_CMD; i++)
- sched->pktio_cmd[i].cmd_index = PKTIO_CMD_FREE;
+ odp_spinlock_init(&sched->pktio_lock);
+ for (i = 0; i < NUM_PKTIO; i++)
+ sched->pktio[i].num_pktin = 0;
odp_spinlock_init(&sched->grp_lock);
odp_atomic_init_u32(&sched->grp_epoch, 0);
@@ -384,14 +329,14 @@ static int schedule_term_global(void)
ring_t *ring = &sched->prio_q[grp][i][j].ring;
uint32_t qi;
- while ((qi = ring_deq(ring, PRIO_QUEUE_MASK)) !=
+ while ((qi = ring_deq(ring, RING_MASK)) !=
RING_EMPTY) {
odp_event_t events[1];
int num;
num = sched_cb_queue_deq_multi(qi,
events,
- 1);
+ 1, 1);
if (num < 0)
queue_destroy_finalize(qi);
@@ -420,7 +365,7 @@ static int schedule_init_local(void)
static int schedule_term_local(void)
{
- if (sched_local.num) {
+ if (sched_local.stash_num) {
ODP_ERR("Locally pre-scheduled events exist.\n");
return -1;
}
@@ -519,6 +464,9 @@ static int schedule_init_queue(uint32_t queue_index,
sched->queue[queue_index].queue_per_prio = queue_per_prio(queue_index);
sched->queue[queue_index].sync = sched_param->sync;
sched->queue[queue_index].order_lock_count = sched_param->lock_count;
+ sched->queue[queue_index].poll_pktin = 0;
+ sched->queue[queue_index].pktio_index = 0;
+ sched->queue[queue_index].pktin_index = 0;
odp_atomic_init_u64(&sched->order[queue_index].ctx, 0);
odp_atomic_init_u64(&sched->order[queue_index].next_ctx, 0);
@@ -554,101 +502,52 @@ static void schedule_destroy_queue(uint32_t queue_index)
ODP_ERR("queue reorder incomplete\n");
}
-static int poll_cmd_queue_idx(int pktio_index, int pktin_idx)
-{
- return PKTIO_CMD_QUEUE_MASK & (pktio_index ^ pktin_idx);
-}
-
-static inline pktio_cmd_t *alloc_pktio_cmd(void)
-{
- int i;
- pktio_cmd_t *cmd = NULL;
-
- odp_spinlock_lock(&sched->poll_cmd_lock);
-
- /* Find next free command */
- for (i = 0; i < NUM_PKTIO_CMD; i++) {
- if (sched->pktio_cmd[i].cmd_index == PKTIO_CMD_FREE) {
- cmd = &sched->pktio_cmd[i];
- cmd->cmd_index = i;
- break;
- }
- }
-
- odp_spinlock_unlock(&sched->poll_cmd_lock);
-
- return cmd;
-}
-
-static inline void free_pktio_cmd(pktio_cmd_t *cmd)
+static int schedule_sched_queue(uint32_t queue_index)
{
- odp_spinlock_lock(&sched->poll_cmd_lock);
-
- cmd->cmd_index = PKTIO_CMD_FREE;
+ int grp = sched->queue[queue_index].grp;
+ int prio = sched->queue[queue_index].prio;
+ int queue_per_prio = sched->queue[queue_index].queue_per_prio;
+ ring_t *ring = &sched->prio_q[grp][prio][queue_per_prio].ring;
- odp_spinlock_unlock(&sched->poll_cmd_lock);
+ ring_enq(ring, RING_MASK, queue_index);
+ return 0;
}
static void schedule_pktio_start(int pktio_index, int num_pktin,
- int pktin_idx[], odp_queue_t odpq[] ODP_UNUSED)
+ int pktin_idx[], odp_queue_t queue[])
{
- int i, idx;
- pktio_cmd_t *cmd;
-
- if (num_pktin > MAX_PKTIN)
- ODP_ABORT("Too many input queues for scheduler\n");
+ int i;
+ uint32_t qi;
- sched->pktio[pktio_index].num_cmd = num_pktin;
+ sched->pktio[pktio_index].num_pktin = num_pktin;
- /* Create a pktio poll command per queue */
for (i = 0; i < num_pktin; i++) {
+ qi = queue_to_index(queue[i]);
+ sched->queue[qi].poll_pktin = 1;
+ sched->queue[qi].pktio_index = pktio_index;
+ sched->queue[qi].pktin_index = pktin_idx[i];
- cmd = alloc_pktio_cmd();
-
- if (cmd == NULL)
- ODP_ABORT("Scheduler out of pktio commands\n");
+ ODP_ASSERT(pktin_idx[i] <= MAX_PKTIN_INDEX);
- idx = poll_cmd_queue_idx(pktio_index, pktin_idx[i]);
-
- odp_spinlock_lock(&sched->poll_cmd_lock);
- sched->num_pktio_cmd[idx]++;
- odp_spinlock_unlock(&sched->poll_cmd_lock);
-
- cmd->pktio_index = pktio_index;
- cmd->num_pktin = 1;
- cmd->pktin[0] = pktin_idx[i];
- ring_enq(&sched->pktio_q[idx].ring, PKTIO_RING_MASK,
- cmd->cmd_index);
+ /* Start polling */
+ sched_cb_queue_set_status(qi, QUEUE_STATUS_SCHED);
+ schedule_sched_queue(qi);
}
}
-static int schedule_pktio_stop(int pktio_index, int first_pktin)
-{
- int num;
- int idx = poll_cmd_queue_idx(pktio_index, first_pktin);
-
- odp_spinlock_lock(&sched->poll_cmd_lock);
- sched->num_pktio_cmd[idx]--;
- sched->pktio[pktio_index].num_cmd--;
- num = sched->pktio[pktio_index].num_cmd;
- odp_spinlock_unlock(&sched->poll_cmd_lock);
-
- return num;
-}
-
static void schedule_release_atomic(void)
{
- uint32_t qi = sched_local.queue_index;
+ uint32_t qi = sched_local.stash_qi;
- if (qi != PRIO_QUEUE_EMPTY && sched_local.num == 0) {
+ if (qi != PRIO_QUEUE_EMPTY && sched_local.stash_num == 0) {
int grp = sched->queue[qi].grp;
int prio = sched->queue[qi].prio;
int queue_per_prio = sched->queue[qi].queue_per_prio;
ring_t *ring = &sched->prio_q[grp][prio][queue_per_prio].ring;
/* Release current atomic queue */
- ring_enq(ring, PRIO_QUEUE_MASK, qi);
- sched_local.queue_index = PRIO_QUEUE_EMPTY;
+ ring_enq(ring, RING_MASK, qi);
+ sched_local.stash_qi = PRIO_QUEUE_EMPTY;
}
}
@@ -683,13 +582,23 @@ static inline void ordered_stash_release(void)
for (i = 0; i < sched_local.ordered.stash_num; i++) {
queue_entry_t *queue_entry;
odp_buffer_hdr_t **buf_hdr;
- int num;
+ int num, num_enq;
queue_entry = sched_local.ordered.stash[i].queue_entry;
buf_hdr = sched_local.ordered.stash[i].buf_hdr;
num = sched_local.ordered.stash[i].num;
- queue_fn->enq_multi(qentry_to_int(queue_entry), buf_hdr, num);
+ num_enq = queue_fn->enq_multi(qentry_to_int(queue_entry),
+ buf_hdr, num);
+
+ /* Drop packets that were not enqueued */
+ if (odp_unlikely(num_enq < num)) {
+ if (odp_unlikely(num_enq < 0))
+ num_enq = 0;
+
+ ODP_DBG("Dropped %i packets\n", num - num_enq);
+ buffer_free_multi(&buf_hdr[num_enq], num - num_enq);
+ }
}
sched_local.ordered.stash_num = 0;
}
@@ -726,7 +635,7 @@ static void schedule_release_ordered(void)
queue_index = sched_local.ordered.src_queue;
- if (odp_unlikely((queue_index == NULL_INDEX) || sched_local.num))
+ if (odp_unlikely((queue_index == NULL_INDEX) || sched_local.stash_num))
return;
release_ordered();
@@ -740,14 +649,14 @@ static inline void schedule_release_context(void)
schedule_release_atomic();
}
-static inline int copy_events(odp_event_t out_ev[], unsigned int max)
+static inline int copy_from_stash(odp_event_t out_ev[], unsigned int max)
{
int i = 0;
- while (sched_local.num && max) {
- out_ev[i] = sched_local.ev_stash[sched_local.index];
- sched_local.index++;
- sched_local.num--;
+ while (sched_local.stash_num && max) {
+ out_ev[i] = sched_local.stash_ev[sched_local.stash_index];
+ sched_local.stash_index++;
+ sched_local.stash_num--;
max--;
i++;
}
@@ -797,6 +706,67 @@ static int schedule_ord_enq_multi(queue_t q_int, void *buf_hdr[],
return 1;
}
+static inline int queue_is_pktin(uint32_t queue_index)
+{
+ return sched->queue[queue_index].poll_pktin;
+}
+
+static inline int poll_pktin(uint32_t qi, int stash)
+{
+ odp_buffer_hdr_t *b_hdr[MAX_DEQ];
+ int pktio_index, pktin_index, num, num_pktin, i;
+ int ret;
+ queue_t qint;
+
+ pktio_index = sched->queue[qi].pktio_index;
+ pktin_index = sched->queue[qi].pktin_index;
+
+ num = sched_cb_pktin_poll(pktio_index, pktin_index, b_hdr, MAX_DEQ);
+
+ if (num == 0)
+ return 0;
+
+ /* Pktio stopped or closed. Call stop_finalize when we have stopped
+ * polling all pktin queues of the pktio. */
+ if (odp_unlikely(num < 0)) {
+ odp_spinlock_lock(&sched->pktio_lock);
+ sched->pktio[pktio_index].num_pktin--;
+ num_pktin = sched->pktio[pktio_index].num_pktin;
+ odp_spinlock_unlock(&sched->pktio_lock);
+
+ sched_cb_queue_set_status(qi, QUEUE_STATUS_NOTSCHED);
+
+ if (num_pktin == 0)
+ sched_cb_pktio_stop_finalize(pktio_index);
+
+ return num;
+ }
+
+ if (stash) {
+ for (i = 0; i < num; i++)
+ sched_local.stash_ev[i] = event_from_buf_hdr(b_hdr[i]);
+
+ return num;
+ }
+
+ qint = queue_index_to_qint(qi);
+
+ ret = queue_fn->enq_multi(qint, b_hdr, num);
+
+ /* Drop packets that were not enqueued */
+ if (odp_unlikely(ret < num)) {
+ int num_enq = ret;
+
+ if (odp_unlikely(ret < 0))
+ num_enq = 0;
+
+ ODP_DBG("Dropped %i packets\n", num - num_enq);
+ buffer_free_multi(&b_hdr[num_enq], num - num_enq);
+ }
+
+ return ret;
+}
+
static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[],
unsigned int max_num, int grp, int first)
{
@@ -820,6 +790,7 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[],
int ordered;
odp_queue_t handle;
ring_t *ring;
+ int pktin;
if (id >= QUEUES_PER_PRIO)
id = 0;
@@ -834,7 +805,7 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[],
/* Get queue index from the priority queue */
ring = &sched->prio_q[grp][prio][id].ring;
- qi = ring_deq(ring, PRIO_QUEUE_MASK);
+ qi = ring_deq(ring, RING_MASK);
/* Priority queue empty */
if (qi == RING_EMPTY) {
@@ -857,8 +828,10 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[],
if (ordered && max_num < MAX_DEQ)
max_deq = max_num;
- num = sched_cb_queue_deq_multi(qi, sched_local.ev_stash,
- max_deq);
+ pktin = queue_is_pktin(qi);
+
+ num = sched_cb_queue_deq_multi(qi, sched_local.stash_ev,
+ max_deq, !pktin);
if (num < 0) {
/* Destroyed queue. Continue scheduling the same
@@ -868,17 +841,34 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[],
}
if (num == 0) {
- /* Remove empty queue from scheduling. Continue
- * scheduling the same priority queue. */
- continue;
+ /* Poll packet input. Continue scheduling queue
+ * connected to a packet input. Move to the next
+ * priority to avoid starvation of other
+ * priorities. Stop scheduling queue when pktio
+ * has been stopped. */
+ if (pktin) {
+ int stash = !ordered;
+ int num_pkt = poll_pktin(qi, stash);
+
+ if (odp_unlikely(num_pkt < 0))
+ continue;
+
+ if (num_pkt == 0 || !stash) {
+ ring_enq(ring, RING_MASK, qi);
+ break;
+ }
+
+ /* Process packets from an atomic or
+ * parallel queue right away. */
+ num = num_pkt;
+ } else {
+ /* Remove empty queue from scheduling.
+ * Continue scheduling the same priority
+ * queue. */
+ continue;
+ }
}
- handle = queue_from_index(qi);
- sched_local.num = num;
- sched_local.index = 0;
- sched_local.queue = handle;
- ret = copy_events(out_ev, max_num);
-
if (ordered) {
uint64_t ctx;
odp_atomic_u64_t *next_ctx;
@@ -890,16 +880,22 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[],
sched_local.ordered.src_queue = qi;
/* Continue scheduling ordered queues */
- ring_enq(ring, PRIO_QUEUE_MASK, qi);
+ ring_enq(ring, RING_MASK, qi);
} else if (queue_is_atomic(qi)) {
/* Hold queue during atomic access */
- sched_local.queue_index = qi;
+ sched_local.stash_qi = qi;
} else {
/* Continue scheduling the queue */
- ring_enq(ring, PRIO_QUEUE_MASK, qi);
+ ring_enq(ring, RING_MASK, qi);
}
+ handle = queue_from_index(qi);
+ sched_local.stash_num = num;
+ sched_local.stash_index = 0;
+ sched_local.stash_queue = handle;
+ ret = copy_from_stash(out_ev, max_num);
+
/* Output the source queue handle */
if (out_queue)
*out_queue = handle;
@@ -919,15 +915,15 @@ static inline int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[],
{
int i, num_grp;
int ret;
- int id, first, grp_id;
+ int first, grp_id;
uint16_t round;
uint32_t epoch;
- if (sched_local.num) {
- ret = copy_events(out_ev, max_num);
+ if (sched_local.stash_num) {
+ ret = copy_from_stash(out_ev, max_num);
if (out_queue)
- *out_queue = sched_local.queue;
+ *out_queue = sched_local.stash_queue;
return ret;
}
@@ -972,66 +968,11 @@ static inline int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[],
grp_id = 0;
}
- /*
- * Poll packet input when there are no events
- * * Each thread starts the search for a poll command from its
- * preferred command queue. If the queue is empty, it moves to other
- * queues.
- * * Most of the times, the search stops on the first command found to
- * optimize multi-threaded performance. A small portion of polls
- * have to do full iteration to avoid packet input starvation when
- * there are less threads than command queues.
- */
- id = sched_local.thr & PKTIO_CMD_QUEUE_MASK;
-
- for (i = 0; i < PKTIO_CMD_QUEUES; i++, id = ((id + 1) &
- PKTIO_CMD_QUEUE_MASK)) {
- ring_t *ring;
- uint32_t cmd_index;
- pktio_cmd_t *cmd;
-
- if (odp_unlikely(sched->num_pktio_cmd[id] == 0))
- continue;
-
- ring = &sched->pktio_q[id].ring;
- cmd_index = ring_deq(ring, PKTIO_RING_MASK);
-
- if (odp_unlikely(cmd_index == RING_EMPTY))
- continue;
-
- cmd = &sched->pktio_cmd[cmd_index];
-
- /* Poll packet input */
- if (odp_unlikely(sched_cb_pktin_poll(cmd->pktio_index,
- cmd->num_pktin,
- cmd->pktin))){
- /* Pktio stopped or closed. Remove poll command and call
- * stop_finalize when all commands of the pktio has
- * been removed. */
- if (schedule_pktio_stop(cmd->pktio_index,
- cmd->pktin[0]) == 0)
- sched_cb_pktio_stop_finalize(cmd->pktio_index);
-
- free_pktio_cmd(cmd);
- } else {
- /* Continue scheduling the pktio */
- ring_enq(ring, PKTIO_RING_MASK, cmd_index);
-
- /* Do not iterate through all pktin poll command queues
- * every time. */
- if (odp_likely(sched_local.pktin_polls & 0xf))
- break;
- }
- }
-
- sched_local.pktin_polls++;
return 0;
}
-
-static int schedule_loop(odp_queue_t *out_queue, uint64_t wait,
- odp_event_t out_ev[],
- unsigned int max_num)
+static inline int schedule_loop(odp_queue_t *out_queue, uint64_t wait,
+ odp_event_t out_ev[], unsigned int max_num)
{
odp_time_t next, wtime;
int first = 1;
@@ -1387,17 +1328,6 @@ static void schedule_prefetch(int num ODP_UNUSED)
{
}
-static int schedule_sched_queue(uint32_t queue_index)
-{
- int grp = sched->queue[queue_index].grp;
- int prio = sched->queue[queue_index].prio;
- int queue_per_prio = sched->queue[queue_index].queue_per_prio;
- ring_t *ring = &sched->prio_q[grp][prio][queue_per_prio].ring;
-
- ring_enq(ring, PRIO_QUEUE_MASK, queue_index);
- return 0;
-}
-
static int schedule_num_grps(void)
{
return NUM_SCHED_GRPS;
diff --git a/platform/linux-generic/odp_schedule_iquery.c b/platform/linux-generic/odp_schedule_iquery.c
index ea62c36..40f2e9f 100644
--- a/platform/linux-generic/odp_schedule_iquery.c
+++ b/platform/linux-generic/odp_schedule_iquery.c
@@ -291,7 +291,7 @@ static int schedule_term_global(void)
odp_event_t events[1];
if (sched->availables[i])
- count = sched_cb_queue_deq_multi(i, events, 1);
+ count = sched_cb_queue_deq_multi(i, events, 1, 1);
if (count < 0)
sched_cb_queue_destroy_finalize(i);
@@ -674,9 +674,9 @@ static inline void pktio_poll_input(void)
cmd = &sched->pktio_poll.commands[index];
/* Poll packet input */
- if (odp_unlikely(sched_cb_pktin_poll(cmd->pktio,
- cmd->count,
- cmd->pktin))) {
+ if (odp_unlikely(sched_cb_pktin_poll_old(cmd->pktio,
+ cmd->count,
+ cmd->pktin))) {
/* Pktio stopped or closed. Remove poll
* command and call stop_finalize when all
* commands of the pktio has been removed.
@@ -1136,13 +1136,22 @@ static inline void ordered_stash_release(void)
for (i = 0; i < thread_local.ordered.stash_num; i++) {
queue_entry_t *queue_entry;
odp_buffer_hdr_t **buf_hdr;
- int num;
+ int num, num_enq;
queue_entry = thread_local.ordered.stash[i].queue_entry;
buf_hdr = thread_local.ordered.stash[i].buf_hdr;
num = thread_local.ordered.stash[i].num;
- queue_fn->enq_multi(qentry_to_int(queue_entry), buf_hdr, num);
+ num_enq = queue_fn->enq_multi(qentry_to_int(queue_entry),
+ buf_hdr, num);
+
+ if (odp_unlikely(num_enq < num)) {
+ if (odp_unlikely(num_enq < 0))
+ num_enq = 0;
+
+ ODP_DBG("Dropped %i packets\n", num - num_enq);
+ buffer_free_multi(&buf_hdr[num_enq], num - num_enq);
+ }
}
thread_local.ordered.stash_num = 0;
}
@@ -1527,7 +1536,7 @@ static inline int consume_queue(int prio, unsigned int queue_index)
max = 1;
count = sched_cb_queue_deq_multi(
- queue_index, cache->stash, max);
+ queue_index, cache->stash, max, 1);
if (count < 0) {
DO_SCHED_UNLOCK();
diff --git a/platform/linux-generic/odp_schedule_sp.c b/platform/linux-generic/odp_schedule_sp.c
index 007d673..84d16d3 100644
--- a/platform/linux-generic/odp_schedule_sp.c
+++ b/platform/linux-generic/odp_schedule_sp.c
@@ -524,8 +524,9 @@ static int schedule_multi(odp_queue_t *from, uint64_t wait,
cmd = sched_cmd();
if (cmd && cmd->s.type == CMD_PKTIO) {
- if (sched_cb_pktin_poll(cmd->s.index, cmd->s.num_pktin,
- cmd->s.pktin_idx)) {
+ if (sched_cb_pktin_poll_old(cmd->s.index,
+ cmd->s.num_pktin,
+ cmd->s.pktin_idx)) {
/* Pktio stopped or closed. */
sched_cb_pktio_stop_finalize(cmd->s.index);
} else {
@@ -559,7 +560,7 @@ static int schedule_multi(odp_queue_t *from, uint64_t wait,
}
qi = cmd->s.index;
- num = sched_cb_queue_deq_multi(qi, events, 1);
+ num = sched_cb_queue_deq_multi(qi, events, 1, 1);
if (num > 0) {
sched_local.cmd = cmd;
diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c
index d460a19..d1cda1e 100644
--- a/platform/linux-generic/odp_system_info.c
+++ b/platform/linux-generic/odp_system_info.c
@@ -489,26 +489,36 @@ int odp_cpu_count(void)
void odp_sys_info_print(void)
{
- int len;
+ int len, num_cpu;
int max_len = 512;
+ odp_cpumask_t cpumask;
+ char cpumask_str[ODP_CPUMASK_STR_SIZE];
char str[max_len];
+ memset(cpumask_str, 0, sizeof(cpumask_str));
+
+ num_cpu = odp_cpumask_all_available(&cpumask);
+ odp_cpumask_to_str(&cpumask, cpumask_str, ODP_CPUMASK_STR_SIZE);
+
len = snprintf(str, max_len, "\n"
"ODP system info\n"
"---------------\n"
- "ODP API version: %s\n"
- "ODP impl name: %s\n"
- "CPU model: %s\n"
- "CPU freq (hz): %" PRIu64 "\n"
- "Cache line size: %i\n"
- "CPU count: %i\n"
+ "ODP API version: %s\n"
+ "ODP impl name: %s\n"
+ "ODP impl details: %s\n"
+ "CPU model: %s\n"
+ "CPU freq (hz): %" PRIu64 "\n"
+ "Cache line size: %i\n"
+ "CPU count: %i\n"
+ "CPU mask: %s\n"
"\n",
odp_version_api_str(),
odp_version_impl_name(),
+ odp_version_impl_str(),
odp_cpu_model_str(),
odp_cpu_hz_max(),
odp_sys_cache_line_size(),
- odp_cpu_count());
+ num_cpu, cpumask_str);
str[len] = '\0';
ODP_PRINT("%s", str);
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c
index a31b0db..7b9fed7 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -24,6 +24,7 @@
#include <odp_classification_internal.h>
#include <odp_packet_dpdk.h>
#include <odp_debug_internal.h>
+#include <odp_libconfig_internal.h>
#include <protocols/eth.h>
@@ -93,6 +94,64 @@ void refer_constructors(void)
}
#endif
+static int lookup_opt(const char *path, const char *drv_name, int *val)
+{
+ const char *base = "pktio_dpdk";
+ char opt_path[256];
+ int ret = 0;
+
+ /* Default option */
+ snprintf(opt_path, sizeof(opt_path), "%s.%s", base, path);
+ ret += _odp_libconfig_lookup_int(opt_path, val);
+
+ /* Driver specific option overrides default option */
+ snprintf(opt_path, sizeof(opt_path), "%s.%s.%s", base, drv_name, path);
+ ret += _odp_libconfig_lookup_int(opt_path, val);
+
+ if (ret == 0)
+ ODP_ERR("Unable to find DPDK configuration option: %s\n", path);
+ return ret;
+}
+
+static int init_options(pktio_entry_t *pktio_entry,
+ const struct rte_eth_dev_info *dev_info)
+{
+ dpdk_opt_t *opt = &pktio_entry->s.pkt_dpdk.opt;
+
+ if (!lookup_opt("num_rx_desc", dev_info->driver_name,
+ &opt->num_rx_desc))
+ return -1;
+ if (opt->num_rx_desc < dev_info->rx_desc_lim.nb_min ||
+ opt->num_rx_desc > dev_info->rx_desc_lim.nb_max ||
+ opt->num_rx_desc % dev_info->rx_desc_lim.nb_align) {
+ ODP_ERR("Invalid number of RX descriptors\n");
+ return -1;
+ }
+
+ if (!lookup_opt("num_tx_desc", dev_info->driver_name,
+ &opt->num_tx_desc))
+ return -1;
+ if (opt->num_tx_desc < dev_info->tx_desc_lim.nb_min ||
+ opt->num_tx_desc > dev_info->tx_desc_lim.nb_max ||
+ opt->num_tx_desc % dev_info->tx_desc_lim.nb_align) {
+ ODP_ERR("Invalid number of TX descriptors\n");
+ return -1;
+ }
+
+ if (!lookup_opt("rx_drop_en", dev_info->driver_name,
+ &opt->rx_drop_en))
+ return -1;
+ opt->rx_drop_en = !!opt->rx_drop_en;
+
+ ODP_PRINT("DPDK interface (%s): %" PRIu16 "\n", dev_info->driver_name,
+ pktio_entry->s.pkt_dpdk.port_id);
+ ODP_PRINT(" num_rx_desc: %d\n", opt->num_rx_desc);
+ ODP_PRINT(" num_tx_desc: %d\n", opt->num_tx_desc);
+ ODP_PRINT(" rx_drop_en: %d\n", opt->rx_drop_en);
+
+ return 0;
+}
+
/**
* Calculate valid cache size for DPDK packet pool
*/
@@ -1337,6 +1396,12 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
dpdk_init_capability(pktio_entry, &dev_info);
+ /* Initialize runtime options */
+ if (init_options(pktio_entry, &dev_info)) {
+ ODP_ERR("Initializing runtime options failed\n");
+ return -1;
+ }
+
mtu = dpdk_mtu_get(pktio_entry);
if (mtu == 0) {
ODP_ERR("Failed to read interface MTU\n");
@@ -1464,7 +1529,8 @@ static int dpdk_start(pktio_entry_t *pktio_entry)
pktio_entry->s.chksum_insert_ena = 1;
}
- ret = rte_eth_tx_queue_setup(port_id, i, DPDK_NM_TX_DESC,
+ ret = rte_eth_tx_queue_setup(port_id, i,
+ pkt_dpdk->opt.num_tx_desc,
rte_eth_dev_socket_id(port_id),
txconf);
if (ret < 0) {
@@ -1476,9 +1542,10 @@ static int dpdk_start(pktio_entry_t *pktio_entry)
/* Init RX queues */
rte_eth_dev_info_get(port_id, &dev_info);
rxconf = &dev_info.default_rxconf;
- rxconf->rx_drop_en = 1;
+ rxconf->rx_drop_en = pkt_dpdk->opt.rx_drop_en;
for (i = 0; i < pktio_entry->s.num_in_queue; i++) {
- ret = rte_eth_rx_queue_setup(port_id, i, DPDK_NM_RX_DESC,
+ ret = rte_eth_rx_queue_setup(port_id, i,
+ pkt_dpdk->opt.num_rx_desc,
rte_eth_dev_socket_id(port_id),
rxconf, pkt_dpdk->pkt_pool);
if (ret < 0) {
diff --git a/platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.sh b/platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.sh
index 91f7831..ae263ee 100755
--- a/platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.sh
+++ b/platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.sh
@@ -69,6 +69,9 @@ plat_mmap_vlan_ins${EXEEXT} pktiop0p1 pcap:out=${PCAP_OUT} \
plat_mmap_vlan_ins${EXEEXT} pcap:in=${PCAP_IN} pktiop1p0 \
01:02:03:04:05:06 01:08:09:0a:0b:0c
+# Give both processes time to close before removing interfaces
+sleep 4
+
rm -f ${PCAP_OUT}
cleanup_pktio_env
diff --git a/platform/linux-generic/test/ring/Makefile.am b/platform/linux-generic/test/ring/Makefile.am
index 3f77434..999beed 100644
--- a/platform/linux-generic/test/ring/Makefile.am
+++ b/platform/linux-generic/test/ring/Makefile.am
@@ -16,6 +16,8 @@ PRELDADD += $(LIBCUNIT_COMMON)
AM_CPPFLAGS += -I$(top_srcdir)/platform/linux-generic/include
+AM_CFLAGS += $(LIBCONFIG_CFLAGS)
+
TESTNAME = linux-generic-ring
TESTENV = tests-$(TESTNAME).env
diff --git a/scripts/build-pktio-dpdk b/scripts/build-pktio-dpdk
index 97916c1..26afd97 100755
--- a/scripts/build-pktio-dpdk
+++ b/scripts/build-pktio-dpdk
@@ -28,12 +28,13 @@ sed -ri 's,(CONFIG_RTE_LIBRTE_PMD_PCAP=).*,\1y,' .config
popd
#Build DPDK
-make install T=${TARGET} EXTRA_CFLAGS="-fPIC"
+make build O=${TARGET} EXTRA_CFLAGS="-fPIC"
+make install O=${TARGET} DESTDIR=${TARGET}
popd
#Build ODP
./bootstrap;
./configure --enable-test-vald --enable-test-perf --enable-test-cpp \
--enable-debug --enable-debug-print \
- --with-dpdk-path=`pwd`/dpdk/${TARGET}
+ --with-dpdk-path=`pwd`/dpdk/${TARGET}/usr/local
make
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index d366f25..d5ffd1d 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/env perl
# (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)
@@ -6,9 +6,11 @@
# Licensed under the terms of the GNU GPL License version 2
use strict;
+use warnings;
use POSIX;
use File::Basename;
use Cwd 'abs_path';
+use Term::ANSIColor qw(:constants);
my $P = $0;
my $D = dirname(abs_path($P));
@@ -24,13 +26,17 @@ my $chk_patch = 1;
my $tst_only;
my $emacs = 0;
my $terse = 0;
+my $showfile = 0;
my $file = 0;
+my $git = 0;
+my %git_commits = ();
my $check = 0;
my $check_orig = 0;
my $summary = 1;
my $mailback = 0;
my $summary_file = 0;
my $show_types = 0;
+my $list_types = 0;
my $fix = 0;
my $fix_inplace = 0;
my $root;
@@ -48,7 +54,11 @@ my $minimum_perl_version = 5.10.0;
my $min_conf_desc_length = 4;
my $spelling_file = "$D/spelling.txt";
my $codespell = 0;
-my $codespellfile = "/usr/local/share/codespell/dictionary.txt";
+my $codespellfile = "/usr/share/codespell/dictionary.txt";
+my $conststructsfile = "$D/const_structs.checkpatch";
+my $typedefsfile = "";
+my $color = "auto";
+my $allow_c99_comments = 1;
sub help {
my ($exitcode) = @_;
@@ -64,13 +74,25 @@ Options:
--patch treat FILE as patchfile (default)
--emacs emacs compile window format
--terse one line per report
+ --showfile emit diffed file position, not input file position
+ -g, --git treat FILE as a single commit or git revision range
+ single git commit with:
+ <rev>
+ <rev>^
+ <rev>~n
+ multiple git commits with:
+ <rev1>..<rev2>
+ <rev1>...<rev2>
+ <rev>-<count>
+ git merges are ignored
-f, --file treat FILE as regular source file
--subjective, --strict enable more subjective tests
+ --list-types list the possible message types
--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
--min-conf-desc-length=n set the min description length, if shorter, warn
- --show-types show the message "types" in the output
--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
@@ -91,8 +113,11 @@ Options:
--ignore-perl-version override checking of perl version. expect
runtime errors.
--codespell Use the codespell dictionary for spelling/typos
- (default:/usr/local/share/codespell/dictionary.txt)
+ (default:/usr/share/codespell/dictionary.txt)
--codespellfile Use this codespell dictionary
+ --typedefsfile Read additional types from this file
+ --color[=WHEN] Use colors 'always', 'never', or only when output
+ is a terminal ('auto'). Default is 'auto'.
-h, --help, --version display this help and exit
When FILE is - read standard input.
@@ -101,6 +126,38 @@ EOM
exit($exitcode);
}
+sub uniq {
+ my %seen;
+ return grep { !$seen{$_}++ } @_;
+}
+
+sub list_types {
+ my ($exitcode) = @_;
+
+ my $count = 0;
+
+ local $/ = undef;
+
+ open(my $script, '<', abs_path($P)) or
+ die "$P: Can't read '$P' $!\n";
+
+ my $text = <$script>;
+ close($script);
+
+ my @types = ();
+ # Also catch when type or level is passed through a variable
+ for ($text =~ /(?:(?:\bCHK|\bWARN|\bERROR|&\{\$msg_level})\s*\(|\$msg_type\s*=)\s*"([^"]+)"/g) {
+ push (@types, $_);
+ }
+ @types = sort(uniq(@types));
+ print("#\tMessage type\n\n");
+ foreach my $type (@types) {
+ print(++$count . "\t" . $type . "\n");
+ }
+
+ exit($exitcode);
+}
+
my $conf = which_conf($configuration_file);
if (-f $conf) {
my @conf_args;
@@ -127,6 +184,14 @@ if (-f $conf) {
unshift(@ARGV, @conf_args) if @conf_args;
}
+# Perl's Getopt::Long allows options to take optional arguments after a space.
+# Prevent --color by itself from consuming other arguments
+foreach (@ARGV) {
+ if ($_ eq "--color" || $_ eq "-color") {
+ $_ = "--color=$color";
+ }
+}
+
GetOptions(
'q|quiet+' => \$quiet,
'tree!' => \$tree,
@@ -134,12 +199,15 @@ GetOptions(
'patch!' => \$chk_patch,
'emacs!' => \$emacs,
'terse!' => \$terse,
+ 'showfile!' => \$showfile,
'f|file!' => \$file,
+ 'g|git!' => \$git,
'subjective!' => \$check,
'strict!' => \$check,
'ignore=s' => \@ignore,
'types=s' => \@use,
'show-types!' => \$show_types,
+ 'list-types!' => \$list_types,
'max-line-length=i' => \$max_line_length,
'min-conf-desc-length=i' => \$min_conf_desc_length,
'root=s' => \$root,
@@ -153,12 +221,18 @@ GetOptions(
'test-only=s' => \$tst_only,
'codespell!' => \$codespell,
'codespellfile=s' => \$codespellfile,
+ 'typedefsfile=s' => \$typedefsfile,
+ 'color=s' => \$color,
+ 'no-color' => \$color, #keep old behaviors of -nocolor
+ 'nocolor' => \$color, #keep old behaviors of -nocolor
'h|help' => \$help,
'version' => \$help
) or help(1);
help(0) if ($help);
+list_types(0) if ($list_types);
+
$fix = 1 if ($fix_inplace);
$check_orig = $check;
@@ -171,9 +245,21 @@ if ($^V && $^V lt $minimum_perl_version) {
}
}
+#if no filenames are given, push '-' to read patch from stdin
if ($#ARGV < 0) {
- print "$P: no input files\n";
- exit(1);
+ push(@ARGV, '-');
+}
+
+if ($color =~ /^[01]$/) {
+ $color = !$color;
+} elsif ($color =~ /^always$/i) {
+ $color = 1;
+} elsif ($color =~ /^never$/i) {
+ $color = 0;
+} elsif ($color =~ /^auto$/i) {
+ $color = (-t STDOUT);
+} else {
+ die "Invalid color mode: $color\n";
}
sub hash_save_array_words {
@@ -196,12 +282,12 @@ sub hash_save_array_words {
sub hash_show_words {
my ($hashRef, $prefix) = @_;
- if ($quiet == 0 && keys %$hashRef) {
- print "NOTE: $prefix message types:";
+ if (keys %$hashRef) {
+ print "\nNOTE: $prefix message types:";
foreach my $word (sort keys %$hashRef) {
print " $word";
}
- print "\n\n";
+ print "\n";
}
}
@@ -261,7 +347,8 @@ our $Sparse = qr{
__init_refok|
__kprobes|
__ref|
- __rcu
+ __rcu|
+ __private
}x;
our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
@@ -276,7 +363,7 @@ our $Attribute = qr{
__percpu|
__nocast|
__safe|
- __bitwise__|
+ __bitwise|
__packed__|
__packed2__|
__naked|
@@ -347,19 +434,27 @@ our $UTF8 = qr{
| $NON_ASCII_UTF8
}x;
+our $typeC99Typedefs = qr{(?:__)?(?:[us]_?)?int_?(?:8|16|32|64)_t};
our $typeOtherOSTypedefs = qr{(?x:
u_(?:char|short|int|long) | # bsd
u(?:nchar|short|int|long) # sysv
)};
-
-our $typeTypedefs = qr{(?x:
+our $typeKernelTypedefs = qr{(?x:
(?:__)?(?:u|s|be|le)(?:8|16|32|64)|
atomic_t
)};
+our $typeTypedefs = qr{(?x:
+ $typeC99Typedefs\b|
+ $typeOtherOSTypedefs\b|
+ $typeKernelTypedefs\b
+)};
+
+our $zero_initializer = qr{(?:(?:0[xX])?0+$Int_type?|NULL|false)\b};
our $logFunctions = qr{(?x:
- printk(?:_ratelimited|_once|)|
+ printk(?:_ratelimited|_once|_deferred_once|_deferred|)|
(?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
+ TP_printk|
WARN(?:_RATELIMIT|_ONCE|)|
panic|
MODULE_[A-Z_]+|
@@ -422,6 +517,29 @@ our @typeList = (
qr{${Ident}_handler_fn},
@typeListMisordered,
);
+
+our $C90_int_types = qr{(?x:
+ long\s+long\s+int\s+(?:un)?signed|
+ long\s+long\s+(?:un)?signed\s+int|
+ long\s+long\s+(?:un)?signed|
+ (?:(?:un)?signed\s+)?long\s+long\s+int|
+ (?:(?:un)?signed\s+)?long\s+long|
+ int\s+long\s+long\s+(?:un)?signed|
+ int\s+(?:(?:un)?signed\s+)?long\s+long|
+
+ long\s+int\s+(?:un)?signed|
+ long\s+(?:un)?signed\s+int|
+ long\s+(?:un)?signed|
+ (?:(?:un)?signed\s+)?long\s+int|
+ (?:(?:un)?signed\s+)?long|
+ int\s+long\s+(?:un)?signed|
+ int\s+(?:(?:un)?signed\s+)?long|
+
+ int\s+(?:un)?signed|
+ (?:(?:un)?signed\s+)?int
+)};
+
+our @typeListFile = ();
our @typeListWithAttr = (
@typeList,
qr{struct\s+$InitAttribute\s+$Ident},
@@ -431,6 +549,7 @@ our @typeListWithAttr = (
our @modifierList = (
qr{fastcall},
);
+our @modifierListFile = ();
our @mode_permission_funcs = (
["module_param", 3],
@@ -438,7 +557,11 @@ our @mode_permission_funcs = (
["module_param_array_named", 5],
["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2],
["proc_create(?:_data|)", 2],
- ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2],
+ ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2],
+ ["IIO_DEV_ATTR_[A-Z_]+", 1],
+ ["SENSOR_(?:DEVICE_|)ATTR_2", 2],
+ ["SENSOR_TEMPLATE(?:_2|)", 3],
+ ["__ATTR", 2],
);
#Create a search pattern for all these functions to speed up a loop below
@@ -447,6 +570,7 @@ foreach my $entry (@mode_permission_funcs) {
$mode_perms_search .= '|' if ($mode_perms_search ne "");
$mode_perms_search .= $entry->[0];
}
+$mode_perms_search = "(?:${mode_perms_search})";
our $mode_perms_world_writable = qr{
S_IWUGO |
@@ -456,6 +580,63 @@ our $mode_perms_world_writable = qr{
0[0-7][0-7][2367]
}x;
+our %mode_permission_string_types = (
+ "S_IRWXU" => 0700,
+ "S_IRUSR" => 0400,
+ "S_IWUSR" => 0200,
+ "S_IXUSR" => 0100,
+ "S_IRWXG" => 0070,
+ "S_IRGRP" => 0040,
+ "S_IWGRP" => 0020,
+ "S_IXGRP" => 0010,
+ "S_IRWXO" => 0007,
+ "S_IROTH" => 0004,
+ "S_IWOTH" => 0002,
+ "S_IXOTH" => 0001,
+ "S_IRWXUGO" => 0777,
+ "S_IRUGO" => 0444,
+ "S_IWUGO" => 0222,
+ "S_IXUGO" => 0111,
+);
+
+#Create a search pattern for all these strings to speed up a loop below
+our $mode_perms_string_search = "";
+foreach my $entry (keys %mode_permission_string_types) {
+ $mode_perms_string_search .= '|' if ($mode_perms_string_search ne "");
+ $mode_perms_string_search .= $entry;
+}
+our $single_mode_perms_string_search = "(?:${mode_perms_string_search})";
+our $multi_mode_perms_string_search = qr{
+ ${single_mode_perms_string_search}
+ (?:\s*\|\s*${single_mode_perms_string_search})*
+}x;
+
+sub perms_to_octal {
+ my ($string) = @_;
+
+ return trim($string) if ($string =~ /^\s*0[0-7]{3,3}\s*$/);
+
+ my $val = "";
+ my $oval = "";
+ my $to = 0;
+ my $curpos = 0;
+ my $lastpos = 0;
+ while ($string =~ /\b(($single_mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) {
+ $curpos = pos($string);
+ my $match = $2;
+ my $omatch = $1;
+ last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos));
+ $lastpos = $curpos;
+ $to |= $mode_permission_string_types{$match};
+ $val .= '\s*\|\s*' if ($val ne "");
+ $val .= $match;
+ $oval .= $omatch;
+ }
+ $oval =~ s/^\s*\|\s*//;
+ $oval =~ s/\s*\|\s*$//;
+ return sprintf("%04o", $to);
+}
+
our $allowed_asm_includes = qr{(?x:
irq|
memory|
@@ -513,14 +694,51 @@ if ($codespell) {
$misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
+sub read_words {
+ my ($wordsRef, $file) = @_;
+
+ if (open(my $words, '<', $file)) {
+ while (<$words>) {
+ my $line = $_;
+
+ $line =~ s/\s*\n?$//g;
+ $line =~ s/^\s*//g;
+
+ next if ($line =~ m/^\s*#/);
+ next if ($line =~ m/^\s*$/);
+ if ($line =~ /\s/) {
+ print("$file: '$line' invalid - ignored\n");
+ next;
+ }
+
+ $$wordsRef .= '|' if ($$wordsRef ne "");
+ $$wordsRef .= $line;
+ }
+ close($file);
+ return 1;
+ }
+
+ return 0;
+}
+
+my $const_structs = "";
+read_words(\$const_structs, $conststructsfile)
+ or warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
+
+my $typeOtherTypedefs = "";
+if (length($typedefsfile)) {
+ read_words(\$typeOtherTypedefs, $typedefsfile)
+ or warn "No additional types will be considered - file '$typedefsfile': $!\n";
+}
+$typeTypedefs .= '|' . $typeOtherTypedefs if ($typeOtherTypedefs ne "");
+
sub build_types {
- my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
- my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
+ my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)";
+ my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)";
my $Misordered = "(?x: \n" . join("|\n ", @typeListMisordered) . "\n)";
my $allWithAttr = "(?x: \n" . join("|\n ", @typeListWithAttr) . "\n)";
$Modifier = qr{(?:$Attribute|$Sparse|$mods)};
$BasicType = qr{
- (?:$typeOtherOSTypedefs\b)|
(?:$typeTypedefs\b)|
(?:${all}\b)
}x;
@@ -528,7 +746,6 @@ sub build_types {
(?:$Modifier\s+|const\s+)*
(?:
(?:typeof|__typeof__)\s*\([^\)]*\)|
- (?:$typeOtherOSTypedefs\b)|
(?:$typeTypedefs\b)|
(?:${all}\b)
)
@@ -546,7 +763,6 @@ sub build_types {
(?:
(?:typeof|__typeof__)\s*\([^\)]*\)|
(?:$typeTypedefs\b)|
- (?:$typeOtherOSTypedefs\b)|
(?:${allWithAttr}\b)
)
(?:\s+$Modifier|\s+const)*
@@ -577,8 +793,8 @@ our $LvalOrFunc = qr{((?:[\&\*]\s*)?$Lval)\s*($balanced_parens{0,1})\s*};
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,2}\s*\(|
- (?:$Storage\s+)?LIST_HEAD\s*\(|
+ (?:$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*\(
)};
@@ -622,6 +838,16 @@ sub seed_camelcase_file {
}
}
+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`;
+
+ return $status =~ /obsolete/i;
+}
+
my $camelcase_seeded = 0;
sub seed_camelcase_includes {
return if ($camelcase_seeded);
@@ -702,6 +928,7 @@ sub git_commit_info {
# echo "commit $(cut -c 1-12,41-)"
# done
} elsif ($lines[0] =~ /^fatal: ambiguous argument '$commit': unknown revision or path not in the working tree\./) {
+ $id = undef;
} else {
$id = substr($lines[0], 0, 12);
$desc = substr($lines[0], 41);
@@ -719,10 +946,42 @@ my @fixed_inserted = ();
my @fixed_deleted = ();
my $fixlinenr = -1;
+# If input is git commits, extract all commits from the commit expressions.
+# For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'.
+die "$P: No git repository found\n" if ($git && !-e ".git");
+
+if ($git) {
+ my @commits = ();
+ foreach my $commit_expr (@ARGV) {
+ my $git_range;
+ if ($commit_expr =~ m/^(.*)-(\d+)$/) {
+ $git_range = "-$2 $1";
+ } elsif ($commit_expr =~ m/\.\./) {
+ $git_range = "$commit_expr";
+ } else {
+ $git_range = "-1 $commit_expr";
+ }
+ my $lines = `git 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));
+ my $sha1 = $1;
+ my $subject = $2;
+ unshift(@commits, $sha1);
+ $git_commits{$sha1} = $subject;
+ }
+ }
+ die "$P: no git commits after extraction!\n" if (@commits == 0);
+ @ARGV = @commits;
+}
+
my $vname;
for my $filename (@ARGV) {
my $FILE;
- if ($file) {
+ if ($git) {
+ open($FILE, '-|', "git format-patch -M --stdout -1 $filename") ||
+ die "$P: $filename: git format-patch failed - $!\n";
+ } elsif ($file) {
open($FILE, '-|', "diff -u /dev/null $filename") ||
die "$P: $filename: diff failed - $!\n";
} elsif ($filename eq '-') {
@@ -733,6 +992,8 @@ for my $filename (@ARGV) {
}
if ($filename eq '-') {
$vname = 'Your patch';
+ } elsif ($git) {
+ $vname = "Commit " . substr($filename, 0, 12) . ' ("' . $git_commits{$filename} . '")';
} else {
$vname = $filename;
}
@@ -741,6 +1002,13 @@ for my $filename (@ARGV) {
push(@rawlines, $_);
}
close($FILE);
+
+ if ($#ARGV > 0 && $quiet == 0) {
+ print '-' x length($vname) . "\n";
+ print "$vname\n";
+ print '-' x length($vname) . "\n";
+ }
+
if (!process($filename)) {
$exit = 1;
}
@@ -750,6 +1018,29 @@ for my $filename (@ARGV) {
@fixed_inserted = ();
@fixed_deleted = ();
$fixlinenr = -1;
+ @modifierListFile = ();
+ @typeListFile = ();
+ build_types();
+}
+
+if (!$quiet) {
+ hash_show_words(\%use_type, "Used");
+ hash_show_words(\%ignore_type, "Ignored");
+
+ if ($^V lt 5.10.0) {
+ 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.
+EOM
+ }
+ if ($exit) {
+ print << "EOM"
+
+NOTE: If any of the errors are false positives, please report
+ them to the maintainer, see CHECKPATCH in MAINTAINERS.
+EOM
+ }
}
exit($exit);
@@ -999,13 +1290,18 @@ sub sanitise_line {
$res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
}
+ if ($allow_c99_comments && $res =~ m@(//.*$)@) {
+ my $match = $1;
+ $res =~ s/\Q$match\E/"$;" x length($match)/e;
+ }
+
return $res;
}
sub get_quoted_string {
my ($line, $rawline) = @_;
- return "" if ($line !~ m/(\"[X\t]+\")/g);
+ return "" if ($line !~ m/($String)/g);
return substr($rawline, $-[0], $+[0] - $-[0]);
}
@@ -1614,13 +1910,13 @@ sub possible {
for my $modifier (split(' ', $possible)) {
if ($modifier !~ $notPermitted) {
warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
- push(@modifierList, $modifier);
+ push(@modifierListFile, $modifier);
}
}
} else {
warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
- push(@typeList, $possible);
+ push(@typeListFile, $possible);
}
build_types();
} else {
@@ -1633,6 +1929,8 @@ my $prefix = '';
sub show_type {
my ($type) = @_;
+ $type =~ tr/[a-z]/[A-Z]/;
+
return defined $use_type{$type} if (scalar keys %use_type > 0);
return !defined $ignore_type{$type};
@@ -1645,15 +1943,32 @@ sub report {
(defined $tst_only && $msg !~ /\Q$tst_only\E/)) {
return 0;
}
- my $line;
+ my $output = '';
+ if ($color) {
+ if ($level eq 'ERROR') {
+ $output .= RED;
+ } elsif ($level eq 'WARNING') {
+ $output .= YELLOW;
+ } else {
+ $output .= GREEN;
+ }
+ }
+ $output .= $prefix . $level . ':';
if ($show_types) {
- $line = "$prefix$level:$type: $msg\n";
- } else {
- $line = "$prefix$level: $msg\n";
+ $output .= BLUE if ($color);
+ $output .= "$type:";
}
- $line = (split('\n', $line))[0] . "\n" if ($terse);
+ $output .= RESET if ($color);
+ $output .= ' ' . $msg . "\n";
- push(our @report, $line);
+ if ($showfile) {
+ my @lines = split("\n", $output, -1);
+ splice(@lines, 1, 1);
+ $output = join("\n", @lines);
+ }
+ $output = (split('\n', $output))[0] . "\n" if ($terse);
+
+ push(our @report, $output);
return 1;
}
@@ -1899,11 +2214,13 @@ sub process {
our $clean = 1;
my $signoff = 0;
my $is_patch = 0;
-
my $in_header_lines = $file ? 0 : 1;
my $in_commit_log = 0; #Scanning lines before patch
+ my $has_commit_log = 0; #Encountered lines before patch
+ my $commit_log_possible_stack_dump = 0;
my $commit_log_long_line = 0;
- my $reported_maintainer_file = 1; # No MAINTAINTERS so silence warning
+ my $commit_log_has_diff = 0;
+ my $reported_maintainer_file = 1; # No MAINTAINTERS so silence warning
my $non_utf8_charset = 0;
my $last_blank_line = 0;
@@ -1920,6 +2237,7 @@ sub process {
my $realline = 0;
my $realcnt = 0;
my $here = '';
+ my $context_function; #undef'd unless there's a known function
my $in_comment = 0;
my $comment_edge = 0;
my $first_line = 0;
@@ -1953,12 +2271,12 @@ sub process {
if ($rawline=~/^\+\+\+\s+(\S+)/) {
$setup_docs = 0;
- if ($1 =~ m@Documentation/kernel-parameters.txt$@) {
+ if ($1 =~ m@Documentation/admin-guide/kernel-parameters.rst$@) {
$setup_docs = 1;
}
#next;
}
- if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
+ if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
$realline=$1-1;
if (defined $2) {
$realcnt=$3+1;
@@ -2036,7 +2354,9 @@ sub process {
my $rawline = $rawlines[$linenr - 1];
#extract the line range in the file after the patch is applied
- if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
+ if (!$in_commit_log &&
+ $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) {
+ my $context = $4;
$is_patch = 1;
$first_line = $linenr + 1;
$realline=$1-1;
@@ -2052,6 +2372,11 @@ sub process {
%suppress_whiletrailers = ();
%suppress_export = ();
$suppress_statement = 0;
+ if ($context =~ /\b(\w+)\s*\(/) {
+ $context_function = $1;
+ } else {
+ undef $context_function;
+ }
next;
# track the line number as we move through the hunk, note that
@@ -2077,10 +2402,6 @@ sub process {
my $hunk_line = ($realcnt != 0);
-#make up the handle for any error we report on this line
- $prefix = "$filename:$realline: " if ($emacs && $file);
- $prefix = "$filename:$linenr: " if ($emacs && !$file);
-
$here = "#$linenr: " if (!$file);
$here = "#$realline: " if ($file);
@@ -2110,8 +2431,23 @@ sub process {
$found_file = 1;
}
+#make up the handle for any error we report on this line
+ if ($showfile) {
+ $prefix = "$realfile:$realline: "
+ } elsif ($emacs) {
+ if ($file) {
+ $prefix = "$filename:$realline: ";
+ } else {
+ $prefix = "$filename:$linenr: ";
+ }
+ }
+
if ($found_file) {
- if ($realfile =~ m@^(drivers/net/|net/)@) {
+ if (is_maintained_obsolete($realfile)) {
+ WARN("OBSOLETE",
+ "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. No unnecessary modifications please.\n");
+ }
+ if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) {
$check = 1;
} else {
$check = $check_orig;
@@ -2127,6 +2463,17 @@ sub process {
$cnt_lines++ if ($realcnt != 0);
+# 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/]+@ &&
+ $line =~ m@^\s+diff\b.*a/([\w/]+)\s+b/$1\b@) ||
+ $line =~ m@^\s*(?:\-\-\-\s+a/|\+\+\+\s+b/)@ ||
+ $line =~ m/^\s*\@\@ \-\d+,\d+ \+\d+,\d+ \@\@/)) {
+ ERROR("DIFF_IN_COMMIT_MSG",
+ "Avoid using diff content in the commit message - patch(1) might not work\n" . $herecurr);
+ $commit_log_has_diff = 1;
+ }
+
# Check for incorrect file permissions
if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
my $permhere = $here . "FILE: $realfile\n";
@@ -2238,18 +2585,47 @@ sub process {
"Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
}
+# Check if the commit log is in a possible stack dump
+ if ($in_commit_log && !$commit_log_possible_stack_dump &&
+ ($line =~ /^\s*(?:WARNING:|BUG:)/ ||
+ $line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
+ # timestamp
+ $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) {
+ # stack dump address
+ $commit_log_possible_stack_dump = 1;
+ }
+
# Check for line lengths > 75 in commit log, warn once
if ($in_commit_log && !$commit_log_long_line &&
- length($line) > 75) {
+ length($line) > 75 &&
+ !($line =~ /^\s*[a-zA-Z0-9_\/\.]+\s+\|\s+\d+/ ||
+ # file delta changes
+ $line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
+ # filename then :
+ $line =~ /^\s*(?:Fixes:|Link:)/i ||
+ # A Fixes: or Link: line
+ $commit_log_possible_stack_dump)) {
WARN("COMMIT_LOG_LONG_LINE",
"Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
$commit_log_long_line = 1;
}
+# Reset possible stack dump if a blank line is found
+ if ($in_commit_log && $commit_log_possible_stack_dump &&
+ $line =~ /^\s*$/) {
+ $commit_log_possible_stack_dump = 0;
+ }
+
# Check for git id commit length and improperly formed commit descriptions
- if ($in_commit_log && $line =~ /\b(c)ommit\s+([0-9a-f]{5,})/i) {
- my $init_char = $1;
- my $orig_commit = lc($2);
+ if ($in_commit_log && !$commit_log_possible_stack_dump &&
+ $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink):/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 &&
+ $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
+ $line !~ /\bfixes:\s*[0-9a-f]{12,40}/i))) {
+ my $init_char = "c";
+ my $orig_commit = "";
my $short = 1;
my $long = 0;
my $case = 1;
@@ -2260,6 +2636,13 @@ sub process {
my $orig_desc = "commit description";
my $description = "";
+ if ($line =~ /\b(c)ommit\s+([0-9a-f]{5,})\b/i) {
+ $init_char = $1;
+ $orig_commit = lc($2);
+ } elsif ($line =~ /\b([0-9a-f]{12,40})\b/i) {
+ $orig_commit = lc($1);
+ }
+
$short = 0 if ($line =~ /\bcommit\s+[0-9a-f]{12,40}/i);
$long = 1 if ($line =~ /\bcommit\s+[0-9a-f]{41,}/i);
$space = 0 if ($line =~ /\bcommit [0-9a-f]/i);
@@ -2285,7 +2668,8 @@ sub process {
($id, $description) = git_commit_info($orig_commit,
$id, $orig_desc);
- if ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens) {
+ if (defined($id) &&
+ ($short || $long || $space || $case || ($orig_desc ne $description) || !$hasparens)) {
ERROR("GIT_COMMIT_ID",
"Please use git commit description style 'commit <12+ chars of sha1> (\"<title line>\")' - ie: '${init_char}ommit $id (\"$description\")'\n" . $herecurr);
}
@@ -2297,6 +2681,7 @@ sub process {
$line =~ /^rename (?:from|to) [\w\/\.\-]+\s*$/ ||
($line =~ /\{\s*([\w\/\.\-]*)\s*\=\>\s*([\w\/\.\-]*)\s*\}/ &&
(defined($1) || defined($2))))) {
+ $is_patch = 1;
$reported_maintainer_file = 1;
WARN("FILE_PATH_CHANGES",
"added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
@@ -2309,20 +2694,6 @@ sub process {
$herecurr) if (!$emitted_corrupt++);
}
-# Check for absolute kernel paths.
- if ($tree) {
- while ($line =~ m{(?:^|\s)(/\S*)}g) {
- my $file = $1;
-
- if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
- check_absolute_file($1, $herecurr)) {
- #
- } else {
- check_absolute_file($file, $herecurr);
- }
- }
- }
-
# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
if (($realfile =~ /^$/ || $line =~ /^\+/) &&
$rawline !~ m/^$UTF8*$/) {
@@ -2339,10 +2710,11 @@ sub process {
# Check if it's the start of a commit log
# (not a header line and we haven't seen the patch filename)
if ($in_header_lines && $realfile =~ /^$/ &&
- !($rawline =~ /^\s+\S/ ||
- $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) {
+ !($rawline =~ /^\s+(?:\S|$)/ ||
+ $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) {
$in_header_lines = 0;
$in_commit_log = 1;
+ $has_commit_log = 1;
}
# Check if there is UTF-8 in a commit log when a mail header has explicitly
@@ -2359,6 +2731,20 @@ sub process {
"8-bit UTF-8 used in possible commit log\n" . $herecurr);
}
+# Check for absolute kernel paths in commit message
+ if ($tree && $in_commit_log) {
+ while ($line =~ m{(?:^|\s)(/\S*)}g) {
+ my $file = $1;
+
+ if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
+ check_absolute_file($1, $herecurr)) {
+ #
+ } else {
+ check_absolute_file($file, $herecurr);
+ }
+ }
+ }
+
# Check for various typo / spelling mistakes
if (defined($misspellings) &&
($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
@@ -2367,10 +2753,10 @@ sub process {
my $typo_fix = $spelling_fix{lc($typo)};
$typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
$typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
- my $msg_type = \&WARN;
- $msg_type = \&CHK if ($file);
- if (&{$msg_type}("TYPO_SPELLING",
- "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ if (&{$msg_level}("TYPO_SPELLING",
+ "'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
$fix) {
$fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
}
@@ -2401,13 +2787,14 @@ sub process {
# Check for FSF mailing addresses.
if ($rawline =~ /\bwrite to the Free/i ||
+ $rawline =~ /\b675\s+Mass\s+Ave/i ||
$rawline =~ /\b59\s+Temple\s+Pl/i ||
$rawline =~ /\b51\s+Franklin\s+St/i) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
- my $msg_type = \&ERROR;
- $msg_type = \&CHK if ($file);
- &{$msg_type}("FSF_MAILING_ADDRESS",
- "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
+ my $msg_level = \&ERROR;
+ $msg_level = \&CHK if ($file);
+ &{$msg_level}("FSF_MAILING_ADDRESS",
+ "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
}
# check for Kconfig help text having a real description
@@ -2452,11 +2839,15 @@ sub process {
#print "is_start<$is_start> is_end<$is_end> length<$length>\n";
}
-# discourage the addition of CONFIG_EXPERIMENTAL in Kconfig.
- if ($realfile =~ /Kconfig/ &&
- $line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/) {
- WARN("CONFIG_EXPERIMENTAL",
- "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\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/;
+ }
}
# discourage the use of boolean for type definition attributes of Kconfig options
@@ -2512,18 +2903,68 @@ sub process {
}
# check we are in a valid source file if not then ignore this hunk
- next if ($realfile !~ /\.(h|c|s|S|pl|sh|dtsi|dts)$/);
-
-#line length limit
- if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
- $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
- !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?$String\s*(?:|,|\)\s*;)\s*$/ ||
- $line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ ||
- $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) &&
- $length > $max_line_length)
- {
- WARN("LONG_LINE",
- "line over $max_line_length characters\n" . $herecurr);
+ next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
+
+# line length limit (with some exclusions)
+#
+# There are a few types of lines that may extend beyond $max_line_length:
+# logging functions like pr_info that end in a string
+# lines with a single string
+# #defines that are a single string
+# lines with an RFC3986 like URL
+#
+# There are 3 different line length message types:
+# LONG_LINE_COMMENT a comment starts before but extends beyond $max_line_length
+# LONG_LINE_STRING a string starts before but extends beyond $max_line_length
+# LONG_LINE all other lines longer than $max_line_length
+#
+# if LONG_LINE is ignored, the other 2 types are also ignored
+#
+
+ if ($line =~ /^\+/ && $length > $max_line_length) {
+ my $msg_type = "LONG_LINE";
+
+ # Check the allowed long line types first
+
+ # logging functions that end in a string that starts
+ # before $max_line_length
+ if ($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(?:KERN_\S+\s*|[^"]*))?($String\s*(?:|,|\)\s*;)\s*)$/ &&
+ length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
+ $msg_type = "";
+
+ # lines with only strings (w/ possible termination)
+ # #defines with only strings
+ } elsif ($line =~ /^\+\s*$String\s*(?:\s*|,|\)\s*;)\s*$/ ||
+ $line =~ /^\+\s*#\s*define\s+\w+\s+$String$/) {
+ $msg_type = "";
+
+ # More special cases
+ } elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/ ||
+ $line =~ /^\+\s*(?:\w+)?\s*DEFINE_PER_CPU/) {
+ $msg_type = "";
+
+ # URL ($rawline is used in case the URL is in a comment)
+ } elsif ($rawline =~ /^\+.*\b[a-z][\w\.\+\-]*:\/\/\S+/i) {
+ $msg_type = "";
+
+ # Otherwise set the alternate message types
+
+ # a comment starts before $max_line_length
+ } elsif ($line =~ /($;[\s$;]*)$/ &&
+ length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
+ $msg_type = "LONG_LINE_COMMENT"
+
+ # a quoted string starts before $max_line_length
+ } elsif ($sline =~ /\s*($String(?:\s*(?:\\|,\s*|\)\s*;\s*))?)$/ &&
+ length(expand_tabs(substr($line, 1, length($line) - length($1) - 1))) <= $max_line_length) {
+ $msg_type = "LONG_LINE_STRING"
+ }
+
+ if ($msg_type ne "" &&
+ (show_type("LONG_LINE") || show_type($msg_type))) {
+ WARN($msg_type,
+ "line over $max_line_length characters\n" . $herecurr);
+ }
}
# check for adding lines without a newline.
@@ -2581,9 +3022,22 @@ sub process {
"Logical continuations should be on the previous line\n" . $hereprev);
}
+# check indentation starts on a tab stop
+ if ($^V && $^V ge 5.10.0 &&
+ $sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
+ my $indent = length($1);
+ if ($indent % 8) {
+ if (WARN("TABSTOP",
+ "Statements should start on a tabstop\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e;
+ }
+ }
+ }
+
# check multi-line statement indentation matches previous line
if ($^V && $^V ge 5.10.0 &&
- $prevline =~ /^\+([ \t]*)((?:$c90_Keywords(?:\s+if)\s*)|(?:$Declare\s*)?(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*|$Ident\s*=\s*$Ident\s*)\(.*(\&\&|\|\||,)\s*$/) {
+ $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;
my $rest = $2;
@@ -2628,6 +3082,8 @@ sub process {
}
}
+# Block comment styles
+# Networking with an initial /*
if ($realfile =~ m@^(drivers/net/|net/)@ &&
$prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
$rawline =~ /^\+[ \t]*\*/ &&
@@ -2636,22 +3092,47 @@ sub process {
"networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
}
- if ($realfile =~ m@^(drivers/net/|net/)@ &&
- $prevrawline =~ /^\+[ \t]*\/\*/ && #starting /*
+# Block comments use * on subsequent lines
+ if ($prevline =~ /$;[ \t]*$/ && #ends in comment
+ $prevrawline =~ /^\+.*?\/\*/ && #starting /*
$prevrawline !~ /\*\/[ \t]*$/ && #no trailing */
$rawline =~ /^\+/ && #line is new
$rawline !~ /^\+[ \t]*\*/) { #no leading *
- WARN("NETWORKING_BLOCK_COMMENT_STYLE",
- "networking block comments start with * on subsequent lines\n" . $hereprev);
+ WARN("BLOCK_COMMENT_STYLE",
+ "Block comments use * on subsequent lines\n" . $hereprev);
}
- if ($realfile =~ m@^(drivers/net/|net/)@ &&
- $rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */
+# Block comments use */ on trailing lines
+ if ($rawline !~ m@^\+[ \t]*\*/[ \t]*$@ && #trailing */
$rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ && #inline /*...*/
$rawline !~ m@^\+.*\*{2,}/[ \t]*$@ && #trailing **/
$rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) { #non blank */
- WARN("NETWORKING_BLOCK_COMMENT_STYLE",
- "networking block comments put the trailing */ on a separate line\n" . $herecurr);
+ WARN("BLOCK_COMMENT_STYLE",
+ "Block comments use a trailing */ on a separate line\n" . $herecurr);
+ }
+
+# Block comment * alignment
+ if ($prevline =~ /$;[ \t]*$/ && #ends in comment
+ $line =~ /^\+[ \t]*$;/ && #leading comment
+ $rawline =~ /^\+[ \t]*\*/ && #leading *
+ (($prevrawline =~ /^\+.*?\/\*/ && #leading /*
+ $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */
+ $prevrawline =~ /^\+[ \t]*\*/)) { #leading *
+ my $oldindent;
+ $prevrawline =~ m@^\+([ \t]*/?)\*@;
+ if (defined($1)) {
+ $oldindent = expand_tabs($1);
+ } else {
+ $prevrawline =~ m@^\+(.*/?)\*@;
+ $oldindent = expand_tabs($1);
+ }
+ $rawline =~ m@^\+([ \t]*)\*@;
+ my $newindent = $1;
+ $newindent = expand_tabs($newindent);
+ if (length($oldindent) ne length($newindent)) {
+ WARN("BLOCK_COMMENT_STYLE",
+ "Block comments should align the * on each line\n" . $hereprev);
+ }
}
# check for missing blank lines after struct/union declarations
@@ -2665,6 +3146,7 @@ sub process {
$line =~ /^\+[a-z_]*init/ ||
$line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ ||
$line =~ /^\+\s*DECLARE/ ||
+ $line =~ /^\+\s*builtin_[\w_]*driver/ ||
$line =~ /^\+\s*__setup/)) {
if (CHK("LINE_SPACING",
"Please use a blank line after function/struct/union/enum declarations\n" . $hereprev) &&
@@ -2744,6 +3226,23 @@ sub process {
# check we are in a valid C source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c)$/);
+# check for unusual line ending [ or (
+ if ($line =~ /^\+.*([\[\(])\s*$/) {
+ CHK("OPEN_ENDED_LINE",
+ "Lines should not end with a '$1'\n" . $herecurr);
+ }
+
+# check if this appears to be the start function declaration, save the name
+ if ($sline =~ /^\+\{\s*$/ &&
+ $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) {
+ $context_function = $1;
+ }
+
+# check if this appears to be the end of function declaration
+ if ($sline =~ /^\+\}\s*$/) {
+ undef $context_function;
+ }
+
# check indentation of any line with a bare else
# (but not if it is a multiple line "if (foo) return bar; else return baz;")
# if the previous line is a break or return and is indented 1 tab more...
@@ -2768,12 +3267,6 @@ sub process {
}
}
-# discourage the addition of CONFIG_EXPERIMENTAL in #if(def).
- if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) {
- WARN("CONFIG_EXPERIMENTAL",
- "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n");
- }
-
# check for RCS/CVS revision markers
if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
WARN("CVS_KEYWORD",
@@ -2802,7 +3295,7 @@ sub process {
my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
$realline_next);
#print "LINE<$line>\n";
- if ($linenr >= $suppress_statement &&
+ if ($linenr > $suppress_statement &&
$realcnt && $sline =~ /.\s*\S/) {
($stat, $cond, $line_nr_next, $remain_next, $off_next) =
ctx_statement_block($linenr, $realcnt, 0);
@@ -2949,7 +3442,7 @@ sub process {
}
# Check relative indent for conditionals and blocks.
- if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
+ if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|(?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
($stat, $cond, $line_nr_next, $remain_next, $off_next) =
ctx_statement_block($linenr, $realcnt, 0)
if (!defined $stat);
@@ -2957,15 +3450,22 @@ sub process {
substr($s, 0, length($c), '');
- # Make sure we remove the line prefixes as we have
- # none on the first line, and are going to readd them
- # where necessary.
- $s =~ s/\n./\n/gs;
+ # remove inline comments
+ $s =~ s/$;/ /g;
+ $c =~ s/$;/ /g;
# Find out how long the conditional actually is.
my @newlines = ($c =~ /\n/gs);
my $cond_lines = 1 + $#newlines;
+ # Make sure we remove the line prefixes as we have
+ # none on the first line, and are going to readd them
+ # where necessary.
+ $s =~ s/\n./\n/gs;
+ while ($s =~ /\n\s+\\\n/) {
+ $cond_lines += $s =~ s/\n\s+\\\n/\n/g;
+ }
+
# We want to check the first line inside the block
# starting at the end of the conditional, so remove:
# 1) any blank line termination
@@ -3031,8 +3531,12 @@ 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 && (($sindent % 8) != 0 ||
- ($sindent <= $indent && $s ne ''))) {
+ if ($check && $s ne '' &&
+ (($sindent % 8) != 0 ||
+ ($sindent < $indent) ||
+ ($sindent == $indent &&
+ ($s !~ /^\s*(?:\}|\{|else\b)/)) ||
+ ($sindent > $indent + 8))) {
WARN("SUSPECT_CODE_INDENT",
"suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
}
@@ -3054,6 +3558,42 @@ sub process {
#ignore lines not being added
next if ($line =~ /^[^\+]/);
+# check for dereferences that span multiple lines
+ if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ &&
+ $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) {
+ $prevline =~ /($Lval\s*(?:\.|->))\s*$/;
+ my $ref = $1;
+ $line =~ /^.\s*($Lval)/;
+ $ref .= $1;
+ $ref =~ s/\s//g;
+ WARN("MULTILINE_DEREFERENCE",
+ "Avoid multiple line dereference - prefer '$ref'\n" . $hereprev);
+ }
+
+# check for declarations of signed or unsigned without int
+ while ($line =~ m{\b($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) {
+ my $type = $1;
+ my $var = $2;
+ $var = "" if (!defined $var);
+ if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) {
+ my $sign = $1;
+ my $pointer = $2;
+
+ $pointer = "" if (!defined $pointer);
+
+ if (WARN("UNSPECIFIED_INT",
+ "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) &&
+ $fix) {
+ my $decl = trim($sign) . " int ";
+ my $comp_pointer = $pointer;
+ $comp_pointer =~ s/\s//g;
+ $decl .= $comp_pointer;
+ $decl = rtrim($decl) if ($var eq "");
+ $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@;
+ }
+ }
+ }
+
# TEST: allow direct testing of the type matcher.
if ($dbg_type) {
if ($line =~ /^.\s*$Declare\s*$/) {
@@ -3089,7 +3629,7 @@ sub process {
$fixedline =~ s/\s*=\s*$/ = {/;
fix_insert_line($fixlinenr, $fixedline);
$fixedline = $line;
- $fixedline =~ s/^(.\s*){\s*/$1/;
+ $fixedline =~ s/^(.\s*)\{\s*/$1/;
fix_insert_line($fixlinenr, $fixedline);
}
}
@@ -3173,21 +3713,20 @@ sub process {
}
# check for global initialisers.
- if ($line =~ /^\+(\s*$Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/) {
+ if ($line =~ /^\+$Type\s*$Ident(?:\s+$Modifier)*\s*=\s*($zero_initializer)\s*;/) {
if (ERROR("GLOBAL_INITIALISERS",
- "do not initialise globals to 0 or NULL\n" .
- $herecurr) &&
+ "do not initialise globals to $1\n" . $herecurr) &&
$fix) {
- $fixed[$fixlinenr] =~ s/($Type\s*$Ident\s*(?:\s+$Modifier))*\s*=\s*(0|NULL|false)\s*;/$1;/;
+ $fixed[$fixlinenr] =~ s/(^.$Type\s*$Ident(?:\s+$Modifier)*)\s*=\s*$zero_initializer\s*;/$1;/;
}
}
# check for static initialisers.
- if ($line =~ /^\+.*\bstatic\s.*=\s*(0|NULL|false)\s*;/) {
+ if ($line =~ /^\+.*\bstatic\s.*=\s*($zero_initializer)\s*;/) {
if (ERROR("INITIALISED_STATIC",
- "do not initialise statics to 0 or NULL\n" .
+ "do not initialise statics to $1\n" .
$herecurr) &&
$fix) {
- $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*(0|NULL|false)\s*;/$1;/;
+ $fixed[$fixlinenr] =~ s/(\bstatic\s.*?)\s*=\s*$zero_initializer\s*;/$1;/;
}
}
@@ -3253,23 +3792,13 @@ sub process {
}
}
-# check for uses of DEFINE_PCI_DEVICE_TABLE
- if ($line =~ /\bDEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=/) {
- if (WARN("DEFINE_PCI_DEVICE_TABLE",
- "Prefer struct pci_device_id over deprecated DEFINE_PCI_DEVICE_TABLE\n" . $herecurr) &&
- $fix) {
- $fixed[$fixlinenr] =~ s/\b(?:static\s+|)DEFINE_PCI_DEVICE_TABLE\s*\(\s*(\w+)\s*\)\s*=\s*/static const struct pci_device_id $1\[\] = /;
- }
- }
-
# check for new typedefs, only function parameters and sparse annotations
# make sense.
if ($line =~ /\btypedef\s/ &&
$line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
$line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
$line !~ /\b$typeTypedefs\b/ &&
- $line !~ /\b$typeOtherOSTypedefs\b/ &&
- $line !~ /\b__bitwise(?:__|)\b/) {
+ $line !~ /\b__bitwise\b/) {
WARN("NEW_TYPEDEFS",
"do not add new typedefs\n" . $herecurr);
}
@@ -3330,13 +3859,15 @@ sub process {
}
}
-# # no BUG() or BUG_ON()
-# if ($line =~ /\b(BUG|BUG_ON)\b/) {
-# print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
-# print "$herecurr";
-# $clean = 0;
-# }
+# avoid BUG() or BUG_ON()
+ if ($line =~ /\b(?:BUG|BUG_ON)\b/) {
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ &{$msg_level}("AVOID_BUG",
+ "Avoid crashing the kernel - try using WARN_ON & recovery code rather than BUG() or BUG_ON()\n" . $herecurr);
+ }
+# avoid LINUX_VERSION_CODE
if ($line =~ /\bLINUX_VERSION_CODE\b/) {
WARN("LINUX_VERSION_CODE",
"LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
@@ -3348,28 +3879,10 @@ sub process {
"Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
}
-# printk should use KERN_* levels. Note that follow on printk's on the
-# same line do not need a level, so we use the current block context
-# to try and find and validate the current printk. In summary the current
-# printk includes all preceding printk's which have no newline on the end.
-# we assume the first bad printk is the one to report.
- if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
- my $ok = 0;
- for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
- #print "CHECK<$lines[$ln - 1]\n";
- # we have a preceding printk if it ends
- # with "\n" ignore it, else it is to blame
- if ($lines[$ln - 1] =~ m{\bprintk\(}) {
- if ($rawlines[$ln - 1] !~ m{\\n"}) {
- $ok = 1;
- }
- last;
- }
- }
- if ($ok == 0) {
- WARN("PRINTK_WITHOUT_KERN_LEVEL",
- "printk() should include KERN_ facility level\n" . $herecurr);
- }
+# printk should use KERN_* levels
+ if ($line =~ /\bprintk\s*\(\s*(?!KERN_[A-Z]+\b)/) {
+ WARN("PRINTK_WITHOUT_KERN_LEVEL",
+ "printk() should include KERN_<LEVEL> facility level\n" . $herecurr);
}
if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) {
@@ -3410,11 +3923,12 @@ sub process {
# function brace can't be on same line, except for #defines of do while,
# or if closed on same line
- if (($line=~/$Type\s*$Ident\(.*\).*\s*{/) and
- !($line=~/ODP_/) and
- !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) {
+ if ($^V && $^V ge 5.10.0 &&
+ $sline =~ /$Type\s*$Ident\s*$balanced_parens\s*\{/ &&
+ $sline !~ /\#\s*define\b.*do\s*\{/ &&
+ $sline !~ /}/) {
if (ERROR("OPEN_BRACE",
- "open brace '{' following function declarations go on the next line\n" . $herecurr) &&
+ "open brace '{' following function definitions go on the next line\n" . $herecurr) &&
$fix) {
fix_delete_line($fixlinenr, $rawline);
my $fixed_line = $rawline;
@@ -3440,7 +3954,7 @@ sub process {
my $fixedline = rtrim($prevrawline) . " {";
fix_insert_line($fixlinenr, $fixedline);
$fixedline = $rawline;
- $fixedline =~ s/^(.\s*){\s*/$1\t/;
+ $fixedline =~ s/^(.\s*)\{\s*/$1\t/;
if ($fixedline !~ /^\+\s*$/) {
fix_insert_line($fixlinenr, $fixedline);
}
@@ -3860,11 +4374,11 @@ sub process {
# messages are ERROR, but ?: are CHK
if ($ok == 0) {
- my $msg_type = \&ERROR;
- $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
+ my $msg_level = \&ERROR;
+ $msg_level = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
- if (&{$msg_type}("SPACING",
- "spaces required around that '$op' $at\n" . $hereptr)) {
+ if (&{$msg_level}("SPACING",
+ "spaces required around that '$op' $at\n" . $hereptr)) {
$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
if (defined $fix_elements[$n + 2]) {
$fix_elements[$n + 2] =~ s/^\s+//;
@@ -3924,12 +4438,12 @@ sub process {
## }
#need space before brace following if, while, etc
- if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\){/) ||
+ if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) ||
$line =~ /do\{/) {
if (ERROR("SPACING",
"space required before the open brace '{'\n" . $herecurr) &&
$fix) {
- $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\))){/$1 {/;
+ $fixed[$fixlinenr] =~ s/^(\+.*(?:do|\)))\{/$1 {/;
}
}
@@ -4017,6 +4531,32 @@ 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) &&
+ $stat =~ /(^.\s*if\s*($balanced_parens))/) {
+ my $if_stat = $1;
+ my $test = substr($2, 1, -1);
+ my $herectx;
+ while ($test =~ /(?:^|[^\w\&\!\~])+\s*\(\s*([\&\!\~]?\s*$Lval\s*(?:$Compare\s*$FuncArg)?)\s*\)/g) {
+ my $match = $1;
+ # avoid parentheses around potential macro args
+ next if ($match =~ /^\s*\w+\s*$/);
+ if (!defined($herectx)) {
+ $herectx = $here . "\n";
+ my $cnt = statement_rawlines($if_stat);
+ for (my $n = 0; $n < $cnt; $n++) {
+ my $rl = raw_line($linenr, $n);
+ $herectx .= $rl . "\n";
+ last if $rl =~ /^[ \+].*\{/;
+ }
+ }
+ CHK("UNNECESSARY_PARENTHESES",
+ "Unnecessary parentheses around '$match'\n" . $herectx);
+ }
+ }
+
#goto labels aren't indented, allow a single space however
if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
!($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
@@ -4071,6 +4611,35 @@ sub process {
}
}
+# comparisons with a constant or upper case identifier on the left
+# 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 &&
+ $line =~ /^\+(.*)\b($Constant|[A-Z_][A-Z0-9_]*)\s*($Compare)\s*($LvalOrFunc)/) {
+ my $lead = $1;
+ my $const = $2;
+ my $comp = $3;
+ my $to = $4;
+ my $newcomp = $comp;
+ if ($lead !~ /(?:$Operators|\.)\s*$/ &&
+ $to !~ /^(?:Constant|[A-Z_][A-Z0-9_]*)$/ &&
+ WARN("CONSTANT_COMPARISON",
+ "Comparisons should place the constant on the right side of the test\n" . $herecurr) &&
+ $fix) {
+ if ($comp eq "<") {
+ $newcomp = ">";
+ } elsif ($comp eq "<=") {
+ $newcomp = ">=";
+ } elsif ($comp eq ">") {
+ $newcomp = "<";
+ } elsif ($comp eq ">=") {
+ $newcomp = "<=";
+ }
+ $fixed[$fixlinenr] =~ s/\(\s*\Q$const\E\s*$Compare\s*\Q$to\E\s*\)/($to $newcomp $const)/;
+ }
+ }
+
# Return of what appears to be an errno should normally be negative
if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) {
my $name = $1;
@@ -4256,13 +4825,17 @@ sub process {
$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_]+)?$/ &&
-#Ignore some three character SI units explicitly, like MiB and KHz
+#ODP ignores
$var !~ /\bCU_/ &&
+ $var !~ /\bPRI[diux]8/ &&
+ $var !~ /\bPRI[diux]16/ &&
$var !~ /\bPRI[diux]32/ &&
$var !~ /\bPRI[diux]64/ &&
$var !~ /\bSCN[diux]8/ &&
+ $var !~ /\bSCN[diux]16/ &&
$var !~ /\bSCN[diux]32/ &&
$var !~ /\bSCN[diux]64/ &&
+#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) {
my $word = $1;
@@ -4332,9 +4905,19 @@ sub process {
#print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
$has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/);
- $has_arg_concat = 1 if ($ctx =~ /\#\#/);
+ $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/);
+
+ $dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//;
+ my $define_args = $1;
+ my $define_stmt = $dstat;
+ my @def_args = ();
+
+ if (defined $define_args && $define_args ne "") {
+ $define_args = substr($define_args, 1, length($define_args) - 2);
+ $define_args =~ s/\s*//g;
+ @def_args = split(",", $define_args);
+ }
- $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//;
$dstat =~ s/$;//g;
$dstat =~ s/\\\n.//g;
$dstat =~ s/^\s*//s;
@@ -4343,16 +4926,19 @@ sub process {
# Flatten any parentheses and braces
while ($dstat =~ s/\([^\(\)]*\)/1/ ||
$dstat =~ s/\{[^\{\}]*\}/1/ ||
- $dstat =~ s/\[[^\[\]]*\]/1/)
+ $dstat =~ s/.\[[^\[\]]*\]/1/)
{
}
# Flatten any obvious string concatentation.
- while ($dstat =~ s/("X*")\s*$Ident/$1/ ||
- $dstat =~ s/$Ident\s*("X*")/$1/)
+ while ($dstat =~ s/($String)\s*$Ident/$1/ ||
+ $dstat =~ s/$Ident\s*($String)/$1/)
{
}
+ # Make asm volatile uses seem like a generic function
+ $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g;
+
my $exceptions = qr{
$Declare|
module_param_named|
@@ -4363,9 +4949,19 @@ sub process {
union|
struct|
\.$Ident\s*=\s*|
- ^\"|\"$
+ ^\"|\"$|
+ ^\[
}x;
#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";
+ }
+
if ($dstat ne '' &&
$dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(),
$dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo();
@@ -4381,21 +4977,56 @@ sub process {
$dstat !~ /^\(\{/ && # ({...
$ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
{
- $ctx =~ s/\n*$//;
- my $herectx = $here . "\n";
- my $cnt = statement_rawlines($ctx);
-
- for (my $n = 0; $n < $cnt; $n++) {
- $herectx .= raw_line($linenr, $n) . "\n";
- }
-
- if ($dstat =~ /;/) {
+ if ($dstat =~ /^\s*if\b/) {
+ ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
+ "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
+ } elsif ($dstat =~ /;/) {
ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
"Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
} else {
ERROR("COMPLEX_MACRO",
"Macros with complex values should be enclosed in parentheses\n" . "$herectx");
}
+
+ }
+
+ # Make $define_stmt single line, comment-free, etc
+ my @stmt_array = split('\n', $define_stmt);
+ my $first = 1;
+ $define_stmt = "";
+ foreach my $l (@stmt_array) {
+ $l =~ s/\\$//;
+ if ($first) {
+ $define_stmt = $l;
+ $first = 0;
+ } elsif ($l =~ /^[\+ ]/) {
+ $define_stmt .= substr($l, 1);
+ }
+ }
+ $define_stmt =~ s/$;//g;
+ $define_stmt =~ s/\s+/ /g;
+ $define_stmt = trim($define_stmt);
+
+# check if any macro arguments are reused (ignore '...' and 'type')
+ foreach my $arg (@def_args) {
+ 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/\#+\s*$arg\b//g;
+ $tmp_stmt =~ s/\b$arg\s*\#\#//g;
+ my $use_cnt = $tmp_stmt =~ s/\b$arg\b//g;
+ if ($use_cnt > 1) {
+ CHK("MACRO_ARG_REUSE",
+ "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx");
+ }
+# check if any macro arguments may have other precedence issues
+ if ($tmp_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m &&
+ ((defined($1) && $1 ne ',') ||
+ (defined($2) && $2 ne ','))) {
+ CHK("MACRO_ARG_PRECEDENCE",
+ "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx");
+ }
}
# check for macros with flow control, but without ## concatenation
@@ -4603,6 +5234,12 @@ sub process {
}
}
+# check for single line unbalanced braces
+ if ($sline =~ /^.\s*\}\s*else\s*$/ ||
+ $sline =~ /^.\s*else\s*\{\s*$/) {
+ CHK("BRACES", "Unbalanced braces around else statement\n" . $herecurr);
+ }
+
# check for unnecessary blank lines around braces
if (($line =~ /^.\s*}\s*$/ && $prevrawline =~ /^.\s*$/)) {
if (CHK("BRACES",
@@ -4623,14 +5260,14 @@ sub process {
my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
WARN("VOLATILE",
- "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
+ "Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst\n" . $herecurr);
}
# Check for user-visible strings broken across lines, which breaks the ability
# to grep for the string. Make exceptions when the previous string ends in a
# newline (multiple lines in one string constant) or '\t', '\r', ';', or '{'
# (common in inline assembly) or is a octal \123 or hexadecimal \xaf value
- if ($line =~ /^\+\s*"[X\t]*"/ &&
+ if ($line =~ /^\+\s*$String/ &&
$prevline =~ /"\s*$/ &&
$prevrawline !~ /(?:\\(?:[ntr]|[0-7]{1,3}|x[0-9a-fA-F]{1,2})|;\s*|\{\s*)"\s*$/) {
if (WARN("SPLIT_STRING",
@@ -4665,6 +5302,18 @@ sub process {
"break quoted strings at a space character\n" . $hereprev);
}
+# check for an embedded function name in a string when the function is known
+# This does not work very well for -f --file checking as it depends on patch
+# context providing the function name or a single line form for in-file
+# function declarations
+ if ($line =~ /^\+.*$String/ &&
+ defined($context_function) &&
+ get_quoted_string($line, $rawline) =~ /\b$context_function\b/ &&
+ length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) {
+ WARN("EMBEDDED_FUNCTION_NAME",
+ "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr);
+ }
+
# check for spaces before a quoted newline
if ($rawline =~ /^.*\".*\s\\n/) {
if (WARN("QUOTED_WHITESPACE_BEFORE_NEWLINE",
@@ -4676,31 +5325,44 @@ sub process {
}
# concatenated string without spaces between elements
- if ($line =~ /"X+"[A-Z_]+/ || $line =~ /[A-Z_]+"X+"/) {
+ if ($line =~ /$String[A-Z_]/ || $line =~ /[A-Za-z0-9_]$String/) {
CHK("CONCATENATED_STRING",
"Concatenated strings should use spaces between elements\n" . $herecurr);
}
# uncoalesced string fragments
- if ($line =~ /"X*"\s*"/) {
+ if ($line =~ /$String\s*"/) {
WARN("STRING_FRAGMENTS",
"Consecutive strings are generally better as a single string\n" . $herecurr);
}
-# check for %L{u,d,i} in strings
- my $string;
+# check for non-standard and hex prefixed decimal printf formats
+ my $show_L = 1; #don't show the same defect twice
+ my $show_Z = 1;
while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
- $string = substr($rawline, $-[1], $+[1] - $-[1]);
+ my $string = substr($rawline, $-[1], $+[1] - $-[1]);
$string =~ s/%%/__/g;
- if ($string =~ /(?<!%)%L[udi]/) {
+ # check for %L
+ if ($show_L && $string =~ /%[\*\d\.\$]*L([diouxX])/) {
WARN("PRINTF_L",
- "\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
- last;
+ "\%L$1 is non-standard C, use %ll$1\n" . $herecurr);
+ $show_L = 0;
+ }
+ # check for %Z
+ if ($show_Z && $string =~ /%[\*\d\.\$]*Z([diouxX])/) {
+ WARN("PRINTF_Z",
+ "%Z$1 is non-standard C, use %z$1\n" . $herecurr);
+ $show_Z = 0;
+ }
+ # check for 0x<decimal>
+ if ($string =~ /0x%[\*\d\.\$\Llzth]*[diou]/) {
+ ERROR("PRINTF_0XDECIMAL",
+ "Prefixing 0x with decimal output is defective\n" . $herecurr);
}
}
# check for line continuations in quoted strings with odd counts of "
- if ($rawline =~ /\\$/ && $rawline =~ tr/"/"/ % 2) {
+ if ($rawline =~ /\\$/ && $sline =~ tr/"/"/ % 2) {
WARN("LINE_CONTINUATIONS",
"Avoid line continuations in quoted strings\n" . $herecurr);
}
@@ -4714,10 +5376,34 @@ sub process {
# check for needless "if (<foo>) fn(<foo>)" uses
if ($prevline =~ /\bif\s*\(\s*($Lval)\s*\)/) {
- my $expr = '\s*\(\s*' . quotemeta($1) . '\s*\)\s*;';
- if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?)$expr/) {
- WARN('NEEDLESS_IF',
- "$1(NULL) is safe and this check is probably not required\n" . $hereprev);
+ my $tested = quotemeta($1);
+ my $expr = '\s*\(\s*' . $tested . '\s*\)\s*;';
+ if ($line =~ /\b(kfree|usb_free_urb|debugfs_remove(?:_recursive)?|(?:kmem_cache|mempool|dma_pool)_destroy)$expr/) {
+ my $func = $1;
+ if (WARN('NEEDLESS_IF',
+ "$func(NULL) is safe and this check is probably not required\n" . $hereprev) &&
+ $fix) {
+ my $do_fix = 1;
+ my $leading_tabs = "";
+ my $new_leading_tabs = "";
+ if ($lines[$linenr - 2] =~ /^\+(\t*)if\s*\(\s*$tested\s*\)\s*$/) {
+ $leading_tabs = $1;
+ } else {
+ $do_fix = 0;
+ }
+ if ($lines[$linenr - 1] =~ /^\+(\t+)$func\s*\(\s*$tested\s*\)\s*;\s*$/) {
+ $new_leading_tabs = $1;
+ if (length($leading_tabs) + 1 ne length($new_leading_tabs)) {
+ $do_fix = 0;
+ }
+ } else {
+ $do_fix = 0;
+ }
+ if ($do_fix) {
+ fix_delete_line($fixlinenr - 1, $prevrawline);
+ $fixed[$fixlinenr] =~ s/^\+$new_leading_tabs/\+$leading_tabs/;
+ }
+ }
}
}
@@ -4732,7 +5418,7 @@ 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 ($c =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|(?:dev_)?alloc_skb)/) {
+ 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)/) {
WARN("OOM_MESSAGE",
"Possible unnecessary 'out of memory' message\n" . $hereprev);
}
@@ -4749,6 +5435,12 @@ sub process {
}
}
+# check for logging continuations
+ if ($line =~ /\bprintk\s*\(\s*KERN_CONT\b|\bpr_cont\s*\(/) {
+ WARN("LOGGING_CONTINUATION",
+ "Avoid logging continuation uses where feasible\n" . $herecurr);
+ }
+
# check for mask then right shift without a parentheses
if ($^V && $^V ge 5.10.0 &&
$line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
@@ -4903,22 +5595,76 @@ sub process {
}
}
# check for memory barriers without a comment.
- if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
+
+ my $barriers = qr{
+ mb|
+ rmb|
+ wmb|
+ read_barrier_depends
+ }x;
+ my $barrier_stems = qr{
+ mb__before_atomic|
+ mb__after_atomic|
+ store_release|
+ load_acquire|
+ store_mb|
+ (?:$barriers)
+ }x;
+ my $all_barriers = qr{
+ (?:$barriers)|
+ smp_(?:$barrier_stems)|
+ virt_(?:$barrier_stems)
+ }x;
+
+ if ($line =~ /\b(?:$all_barriers)\s*\(/) {
if (!ctx_has_comment($first_line, $linenr)) {
WARN("MEMORY_BARRIER",
"memory barrier without comment\n" . $herecurr);
}
}
+
+ my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x;
+
+ if ($realfile !~ m@^include/asm-generic/@ &&
+ $realfile !~ m@/barrier\.h$@ &&
+ $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ &&
+ $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) {
+ WARN("MEMORY_BARRIER",
+ "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr);
+ }
+
+# check for waitqueue_active without a comment.
+ if ($line =~ /\bwaitqueue_active\s*\(/) {
+ if (!ctx_has_comment($first_line, $linenr)) {
+ WARN("WAITQUEUE_ACTIVE",
+ "waitqueue_active without comment\n" . $herecurr);
+ }
+ }
+
+# check for smp_read_barrier_depends and read_barrier_depends
+ if (!$file && $line =~ /\b(smp_|)read_barrier_depends\s*\(/) {
+ WARN("READ_BARRIER_DEPENDS",
+ "$1read_barrier_depends should only be used in READ_ONCE or DEC Alpha code\n" . $herecurr);
+ }
+
# check of hardware specific defines
if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m@include/asm-@) {
CHK("ARCH_DEFINES",
"architecture specific defines should be avoided\n" . $herecurr);
}
+# check that the storage class is not after a type
+ if ($line =~ /\b($Type)\s+($Storage)\b/) {
+ WARN("STORAGE_CLASS",
+ "storage class '$2' should be located before type '$1'\n" . $herecurr);
+ }
# Check that the storage class is at the beginning of a declaration
- if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
+ if ($line =~ /\b$Storage\b/ &&
+ $line !~ /^.\s*$Storage/ &&
+ $line =~ /^.\s*(.+?)\$Storage\s/ &&
+ $1 !~ /[\,\)]\s*$/) {
WARN("STORAGE_CLASS",
- "storage class should be at the beginning of the declaration\n" . $herecurr)
+ "storage class should be at the beginning of the declaration\n" . $herecurr);
}
# check the location of the inline attribute, that it is between
@@ -4984,6 +5730,45 @@ sub process {
"Using weak declarations can have unintended link defects\n" . $herecurr);
}
+# check for c99 types like uint8_t used outside of uapi/ and tools/
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $realfile !~ m@\btools/@ &&
+ $line =~ /\b($Declare)\s*$Ident\s*[=;,\[]/) {
+ my $type = $1;
+ if ($type =~ /\b($typeC99Typedefs)\b/) {
+ $type = $1;
+ my $kernel_type = 'u';
+ $kernel_type = 's' if ($type =~ /^_*[si]/);
+ $type =~ /(\d+)/;
+ $kernel_type .= $1;
+ if (CHK("PREFER_KERNEL_TYPES",
+ "Prefer kernel type '$kernel_type' over '$type'\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\b$type\b/$kernel_type/;
+ }
+ }
+ }
+
+# check for cast of C90 native int or longer types constants
+ if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) {
+ my $cast = $1;
+ my $const = $2;
+ if (WARN("TYPECAST_INT_CONSTANT",
+ "Unnecessary typecast of c90 int constant\n" . $herecurr) &&
+ $fix) {
+ my $suffix = "";
+ my $newconst = $const;
+ $newconst =~ s/${Int_type}$//;
+ $suffix .= 'U' if ($cast =~ /\bunsigned\b/);
+ if ($cast =~ /\blong\s+long\b/) {
+ $suffix .= 'LL';
+ } elsif ($cast =~ /\blong\b/) {
+ $suffix .= 'L';
+ }
+ $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/;
+ }
+ }
+
# check for sizeof(&)
if ($line =~ /\bsizeof\s*\(\s*\&/) {
WARN("SIZEOF_ADDRESS",
@@ -5018,10 +5803,43 @@ sub process {
}
}
+ # check for vsprintf extension %p<foo> misuses
+ if ($^V && $^V ge 5.10.0 &&
+ defined $stat &&
+ $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
+ $1 !~ /^_*volatile_*$/) {
+ my $bad_extension = "";
+ my $lc = $stat =~ tr@\n@@;
+ $lc = $lc + $linenr;
+ for (my $count = $linenr; $count <= $lc; $count++) {
+ 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);
+ }
+ if ($bad_extension =~ /p[Ff]/) {
+ $ext_type = "Deprecated";
+ $use = " - use %pS instead";
+ $use =~ s/pS/ps/ if ($bad_extension =~ /pf/);
+ }
+ 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 &&
defined $stat &&
- $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/s) {
+ $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*$FuncArg\s*\)/) {
my $ms_addr = $2;
my $ms_val = $7;
@@ -5036,6 +5854,48 @@ sub process {
}
}
+# Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar)
+# if ($^V && $^V ge 5.10.0 &&
+# defined $stat &&
+# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
+# if (WARN("PREFER_ETHER_ADDR_COPY",
+# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") &&
+# $fix) {
+# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/;
+# }
+# }
+
+# Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar)
+# if ($^V && $^V ge 5.10.0 &&
+# defined $stat &&
+# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
+# WARN("PREFER_ETHER_ADDR_EQUAL",
+# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n")
+# }
+
+# 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 &&
+# defined $stat &&
+# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) {
+#
+# my $ms_val = $7;
+#
+# if ($ms_val =~ /^(?:0x|)0+$/i) {
+# if (WARN("PREFER_ETH_ZERO_ADDR",
+# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") &&
+# $fix) {
+# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/;
+# }
+# } elsif ($ms_val =~ /^(?:0xff|255)$/i) {
+# if (WARN("PREFER_ETH_BROADCAST_ADDR",
+# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") &&
+# $fix) {
+# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/;
+# }
+# }
+# }
+
# typecasts on min/max could be min_t/max_t
if ($^V && $^V ge 5.10.0 &&
defined $stat &&
@@ -5154,13 +6014,50 @@ sub process {
"externs should be avoided in .c files\n" . $herecurr);
}
+# check for function declarations that have arguments without identifier names
+ 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);
+ 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$/) {
+ WARN("FUNCTION_ARGUMENTS",
+ "function definition argument '$arg' should also have an identifier name\n" . $herecurr);
+ }
+ }
+ }
+
+# check for function definitions
+ if ($^V && $^V ge 5.10.0 &&
+ defined $stat &&
+ $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) {
+ $context_function = $1;
+
+# check for multiline function definition with misplaced open brace
+ my $ok = 0;
+ my $cnt = statement_rawlines($stat);
+ my $herectx = $here . "\n";
+ for (my $n = 0; $n < $cnt; $n++) {
+ my $rl = raw_line($linenr, $n);
+ $herectx .= $rl . "\n";
+ $ok = 1 if ($rl =~ /^[ \+]\{/);
+ $ok = 1 if ($rl =~ /\{/ && $n == 0);
+ last if $rl =~ /^[ \+].*\{/;
+ }
+ if (!$ok) {
+ ERROR("OPEN_BRACE",
+ "open brace '{' following function definitions go on the next line\n" . $herectx);
+ }
+ }
+
# checks for new __setup's
if ($rawline =~ /\b__setup\("([^"]*)"/) {
my $name = $1;
if (!grep(/$name/, @setup_docs)) {
CHK("UNDOCUMENTED_SETUP",
- "__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
+ "__setup appears un-documented -- check Documentation/admin-guide/kernel-parameters.rst\n" . $herecurr);
}
}
@@ -5180,7 +6077,8 @@ sub process {
# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
if ($^V && $^V ge 5.10.0 &&
- $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
+ defined $stat &&
+ $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
my $oldfunc = $3;
my $a1 = $4;
my $a2 = $10;
@@ -5194,11 +6092,17 @@ 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";
+ }
if (WARN("ALLOC_WITH_MULTIPLY",
- "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) &&
+ "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
+ $cnt == 1 &&
$fix) {
$fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
-
}
}
}
@@ -5225,8 +6129,9 @@ sub process {
}
}
-# check for #defines like: 1 << <digit> that could be BIT(digit)
- if ($line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
+# check for #defines like: 1 << <digit> that could be BIT(digit), it is not exported to uapi
+ if ($realfile !~ m@^include/uapi/@ &&
+ $line =~ /#\s*define\s+\w+\s+\(?\s*1\s*([ulUL]*)\s*\<\<\s*(?:\d+|$Ident)\s*\)?/) {
my $ull = "";
$ull = "_ULL" if (defined($1) && $1 =~ /ll/i);
if (CHK("BIT_MACRO",
@@ -5236,6 +6141,16 @@ sub process {
}
}
+# check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE
+ if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(CONFIG_[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) {
+ my $config = $1;
+ if (WARN("PREFER_IS_ENABLED",
+ "Prefer IS_ENABLED(<FOO>) to CONFIG_<FOO> || CONFIG_<FOO>_MODULE\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)";
+ }
+ }
+
# check for case / default statements not preceded by break/fallthrough/switch
if ($line =~ /^.\s*(?:case\s+(?:$Ident|$Constant)\s*|default):/) {
my $has_break = 0;
@@ -5253,11 +6168,11 @@ sub process {
next if ($fline =~ /^.[\s$;]*$/);
$has_statement = 1;
$count++;
- $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|return\b|goto\b|continue\b)/);
+ $has_break = 1 if ($fline =~ /\bswitch\b|\b(?:break\s*;[\s$;]*$|exit\s*\(\b|return\b|goto\b|continue\b)/);
}
if (!$has_break && $has_statement) {
WARN("MISSING_BREAK",
- "Possible switch case/default not preceeded by break or fallthrough comment\n" . $herecurr);
+ "Possible switch case/default not preceded by break or fallthrough comment\n" . $herecurr);
}
}
@@ -5342,51 +6257,11 @@ sub process {
}
# check for various structs that are normally const (ops, kgdb, device_tree)
- my $const_structs = qr{
- acpi_dock_ops|
- address_space_operations|
- backlight_ops|
- block_device_operations|
- dentry_operations|
- dev_pm_ops|
- dma_map_ops|
- extent_io_ops|
- file_lock_operations|
- file_operations|
- hv_ops|
- ide_dma_ops|
- intel_dvo_dev_ops|
- item_operations|
- iwl_ops|
- kgdb_arch|
- kgdb_io|
- kset_uevent_ops|
- lock_manager_operations|
- microcode_ops|
- mtrr_ops|
- neigh_ops|
- nlmsvc_binding|
- of_device_id|
- pci_raw_ops|
- pipe_buf_operations|
- platform_hibernation_ops|
- platform_suspend_ops|
- proto_ops|
- rpc_pipe_ops|
- seq_operations|
- snd_ac97_build_ops|
- soc_pcmcia_socket_ops|
- stacktrace_ops|
- sysfs_ops|
- tty_operations|
- uart_ops|
- usb_mon_operations|
- wd_ops}x;
+# and avoid what seem like struct definitions 'struct foo {'
if ($line !~ /\bconst\b/ &&
- $line =~ /\bstruct\s+($const_structs)\b/) {
+ $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) {
WARN("CONST_STRUCT",
- "struct $1 should normally be const\n" .
- $herecurr);
+ "struct $1 should normally be const\n" . $herecurr);
}
# use of NR_CPUS is usually wrong
@@ -5426,6 +6301,12 @@ sub process {
}
}
+# check for mutex_trylock_recursive usage
+ if ($line =~ /mutex_trylock_recursive/) {
+ ERROR("LOCKING",
+ "recursive locking is bad, do not use this ever.\n" . $herecurr);
+ }
+
# check for lockdep_set_novalidate_class
if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
$line =~ /__lockdep_no_validate__\s*\)/ ) {
@@ -5443,36 +6324,134 @@ sub process {
"Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
}
+# 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 &&
+ 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;
+ my $perms = $2;
+ my $show = $3;
+ my $store = $4;
+ my $octal_perms = perms_to_octal($perms);
+ if ($show =~ /^${var}_show$/ &&
+ $store =~ /^${var}_store$/ &&
+ $octal_perms eq "0644") {
+ if (WARN("DEVICE_ATTR_RW",
+ "Use DEVICE_ATTR_RW\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*$store\s*\)/DEVICE_ATTR_RW(${var})/;
+ }
+ } elsif ($show =~ /^${var}_show$/ &&
+ $store =~ /^NULL$/ &&
+ $octal_perms eq "0444") {
+ if (WARN("DEVICE_ATTR_RO",
+ "Use DEVICE_ATTR_RO\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*$show\s*,\s*NULL\s*\)/DEVICE_ATTR_RO(${var})/;
+ }
+ } elsif ($show =~ /^NULL$/ &&
+ $store =~ /^${var}_store$/ &&
+ $octal_perms eq "0200") {
+ if (WARN("DEVICE_ATTR_WO",
+ "Use DEVICE_ATTR_WO\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\bDEVICE_ATTR\s*\(\s*$var\s*,\s*\Q$perms\E\s*,\s*NULL\s*,\s*$store\s*\)/DEVICE_ATTR_WO(${var})/;
+ }
+ } elsif ($octal_perms eq "0644" ||
+ $octal_perms eq "0444" ||
+ $octal_perms eq "0200") {
+ my $newshow = "$show";
+ $newshow = "${var}_show" if ($show ne "NULL" && $show ne "${var}_show");
+ my $newstore = $store;
+ $newstore = "${var}_store" if ($store ne "NULL" && $store ne "${var}_store");
+ my $rename = "";
+ if ($show ne $newshow) {
+ $rename .= " '$show' to '$newshow'";
+ }
+ if ($store ne $newstore) {
+ $rename .= " '$store' to '$newstore'";
+ }
+ WARN("DEVICE_ATTR_FUNCTIONS",
+ "Consider renaming function(s)$rename\n" . $herecurr);
+ } else {
+ WARN("DEVICE_ATTR_PERMS",
+ "DEVICE_ATTR unusual permissions '$perms' used\n" . $herecurr);
+ }
+ }
+
# Mode permission misuses where it seems decimal should be octal
# This uses a shortcut match to avoid unnecessary uses of a slow foreach loop
+# o Ignore module_param*(...) uses with a decimal 0 permission as that has a
+# 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 &&
+ defined $stat &&
$line =~ /$mode_perms_search/) {
foreach my $entry (@mode_permission_funcs) {
my $func = $entry->[0];
my $arg_pos = $entry->[1];
+ 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 $skip_args = "";
if ($arg_pos > 1) {
$arg_pos--;
$skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}";
}
- my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]";
- if ($line =~ /$test/) {
+ my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]";
+ if ($stat =~ /$test/) {
my $val = $1;
$val = $6 if ($skip_args ne "");
-
- if ($val !~ /^0$/ &&
+ if (!($func =~ /^(?:module_param|proc_create)/ && $val eq "0") &&
(($val =~ /^$Int$/ && $val !~ /^$Octal$/) ||
- length($val) ne 4)) {
+ ($val =~ /^$Octal$/ && length($val) ne 4))) {
ERROR("NON_OCTAL_PERMISSIONS",
- "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr);
- } elsif ($val =~ /^$Octal$/ && (oct($val) & 02)) {
+ "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real);
+ }
+ if ($val =~ /^$Octal$/ && (oct($val) & 02)) {
ERROR("EXPORTED_WORLD_WRITABLE",
- "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
+ "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real);
}
}
}
}
+
+# check for uses of S_<PERMS> that could be octal for readability
+ if ($line =~ /\b($multi_mode_perms_string_search)\b/) {
+ my $oval = $1;
+ my $octal = perms_to_octal($oval);
+ if (WARN("SYMBOLIC_PERMS",
+ "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\Q$oval\E/$octal/;
+ }
+ }
+
+# validate content of MODULE_LICENSE against list from include/linux/module.h
+ if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) {
+ my $extracted_string = get_quoted_string($line, $rawline);
+ my $valid_licenses = qr{
+ GPL|
+ GPL\ v2|
+ GPL\ and\ additional\ rights|
+ Dual\ BSD/GPL|
+ Dual\ MIT/GPL|
+ Dual\ MPL/GPL|
+ Proprietary
+ }x;
+ if ($extracted_string !~ /^"(?:$valid_licenses)"$/x) {
+ WARN("MODULE_LICENSE",
+ "unknown module license " . $extracted_string . "\n" . $herecurr);
+ }
+ }
}
# If we have no input at all, then there is nothing to report on
@@ -5493,11 +6472,11 @@ sub process {
exit(0);
}
- if (!$is_patch) {
+ if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
ERROR("NOT_UNIFIED_DIFF",
"Does not appear to be a unified-diff format patch\n");
}
- if ($is_patch && $chk_signoff && $signoff == 0) {
+ if ($is_patch && $has_commit_log && $chk_signoff && $signoff == 0) {
ERROR("MISSING_SIGN_OFF",
"Missing Signed-off-by: line(s)\n");
}
@@ -5508,28 +6487,29 @@ sub process {
print "total: $cnt_error errors, $cnt_warn warnings, " .
(($check)? "$cnt_chk checks, " : "") .
"$cnt_lines lines checked\n";
- print "\n" if ($quiet == 0);
}
if ($quiet == 0) {
+ # If there were any defects found and not already fixing them
+ if (!$clean and !$fix) {
+ print << "EOM"
- if ($^V lt 5.10.0) {
- print("NOTE: perl $^V is not modern enough to detect all possible issues.\n");
- print("An upgrade to at least perl v5.10.0 is suggested.\n\n");
+NOTE: For some of the reported defects, checkpatch may be able to
+ mechanically convert to the typical style using --fix or --fix-inplace.
+EOM
}
-
# If there were whitespace errors which cleanpatch can fix
# then suggest that.
if ($rpt_cleaners) {
- print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
- print " scripts/cleanfile\n\n";
$rpt_cleaners = 0;
+ print << "EOM"
+
+NOTE: Whitespace errors detected.
+ You may wish to use scripts/cleanpatch or scripts/cleanfile
+EOM
}
}
- hash_show_words(\%use_type, "Used");
- hash_show_words(\%ignore_type, "Ignored");
-
if ($clean == 0 && $fix &&
("@rawlines" ne "@fixed" ||
$#fixed_inserted >= 0 || $#fixed_deleted >= 0)) {
@@ -5557,6 +6537,7 @@ sub process {
if (!$quiet) {
print << "EOM";
+
Wrote EXPERIMENTAL --fix correction(s) to '$newfile'
Do _NOT_ trust the results written to this file.
@@ -5564,22 +6545,17 @@ Do _NOT_ submit these changes without inspecting them for correctness.
This EXPERIMENTAL file is simply a convenience to help rewrite patches.
No warranties, expressed or implied...
-
EOM
}
}
- if ($clean == 1 && $quiet == 0) {
- print "$vname has no obvious style problems and is ready for submission.\n"
- }
- if ($clean == 0 && $quiet == 0) {
- print << "EOM";
-$vname has style problems, please review.
-
-If any of these errors are false positives, please report
-them to the maintainer, see CHECKPATCH in MAINTAINERS.
-EOM
+ if ($quiet == 0) {
+ print "\n";
+ if ($clean == 1) {
+ print "$vname has no obvious style problems and is ready for submission.\n";
+ } else {
+ print "$vname has style problems, please review.\n";
+ }
}
-
return $clean;
}
diff --git a/test/performance/Makefile.am b/test/performance/Makefile.am
index 9c709e7..e50c840 100644
--- a/test/performance/Makefile.am
+++ b/test/performance/Makefile.am
@@ -34,6 +34,12 @@ odp_sched_latency_SOURCES = odp_sched_latency.c
odp_scheduling_SOURCES = odp_scheduling.c
odp_pktio_perf_SOURCES = odp_pktio_perf.c
+# l2fwd test depends on generator example
+EXTRA_odp_l2fwd_DEPENDENCIES = example-generator
+.PHONY: $(EXTRA_odp_l2fwd_DEPENDENCIES)
+example-generator:
+ $(MAKE) -C $(top_builddir)/example/generator odp_generator$(EXEEXT)
+
dist_check_SCRIPTS = $(TESTSCRIPTS)
dist_check_DATA = udp64.pcap
diff --git a/test/validation/api/classification/odp_classification_tests.c b/test/validation/api/classification/odp_classification_tests.c
index 7e15797..42d0c41 100644
--- a/test/validation/api/classification/odp_classification_tests.c
+++ b/test/validation/api/classification/odp_classification_tests.c
@@ -17,7 +17,14 @@ static odp_pool_t pool_list[CLS_ENTRIES];
static odp_pool_t pool_default;
static odp_pktio_t pktio_loop;
-
+static odp_cls_testcase_u tc;
+
+#define NUM_COS_PMR_CHAIN 2
+#define NUM_COS_DEFAULT 1
+#define NUM_COS_ERROR 1
+#define NUM_COS_L2_PRIO CLS_L2_QOS_MAX
+#define NUM_COS_PMR 1
+#define NUM_COS_COMPOSITE 1
/** sequence number of IP packets */
odp_atomic_u32_t seq;
@@ -30,6 +37,7 @@ int classification_suite_init(void)
int ret;
odp_pktio_param_t pktio_param;
odp_pktin_queue_param_t pktin_param;
+ tc.all_bits = 0;
pool_default = pool_create("classification_pool");
if (ODP_POOL_INVALID == pool_default) {
@@ -683,35 +691,60 @@ void test_pktio_pmr_composite_cos(void)
static void classification_test_pktio_configure(void)
{
+ odp_cls_capability_t capa;
+ int num_cos;
+
+ odp_cls_capability(&capa);
+ num_cos = capa.max_cos;
+
/* Configure the Different CoS for the pktio interface */
- if (TEST_DEFAULT)
+ if (num_cos >= NUM_COS_DEFAULT && TEST_DEFAULT) {
configure_pktio_default_cos();
- if (TEST_ERROR)
+ tc.default_cos = 1;
+ num_cos -= NUM_COS_DEFAULT;
+ }
+ if (num_cos >= NUM_COS_ERROR && TEST_ERROR) {
configure_pktio_error_cos();
- if (TEST_PMR_CHAIN)
+ tc.error_cos = 1;
+ num_cos -= NUM_COS_ERROR;
+ }
+ if (num_cos >= NUM_COS_PMR_CHAIN && TEST_PMR_CHAIN) {
configure_cls_pmr_chain();
- if (TEST_L2_QOS)
+ tc.pmr_chain = 1;
+ num_cos -= NUM_COS_PMR_CHAIN;
+ }
+ if (num_cos >= NUM_COS_L2_PRIO && TEST_L2_QOS) {
configure_cos_with_l2_priority();
- if (TEST_PMR)
+ tc.l2_priority = 1;
+ num_cos -= NUM_COS_L2_PRIO;
+ }
+ if (num_cos >= NUM_COS_PMR && TEST_PMR) {
configure_pmr_cos();
- if (TEST_PMR_SET)
+ tc.pmr_cos = 1;
+ num_cos -= NUM_COS_PMR;
+ }
+ if (num_cos >= NUM_COS_COMPOSITE && TEST_PMR_SET) {
configure_pktio_pmr_composite();
+ tc.pmr_composite_cos = 1;
+ num_cos -= NUM_COS_COMPOSITE;
+ }
+
}
static void classification_test_pktio_test(void)
{
/* Test Different CoS on the pktio interface */
- if (TEST_DEFAULT)
+ if (tc.default_cos && TEST_DEFAULT)
test_pktio_default_cos();
- if (TEST_ERROR)
+ if (tc.error_cos && TEST_ERROR)
test_pktio_error_cos();
- if (TEST_PMR_CHAIN)
+ if (tc.pmr_chain && TEST_PMR_CHAIN)
test_cls_pmr_chain();
- if (TEST_L2_QOS)
+ if (tc.l2_priority && TEST_L2_QOS)
test_cos_with_l2_priority();
- if (TEST_PMR)
+ if (tc.pmr_cos && TEST_PMR)
test_pmr_cos();
- if (TEST_PMR_SET)
+ if (tc.pmr_composite_cos && TEST_PMR_SET)
test_pktio_pmr_composite_cos();
}
diff --git a/test/validation/api/classification/odp_classification_testsuites.h b/test/validation/api/classification/odp_classification_testsuites.h
index 20f6b82..2c61536 100644
--- a/test/validation/api/classification/odp_classification_testsuites.h
+++ b/test/validation/api/classification/odp_classification_testsuites.h
@@ -22,6 +22,18 @@ typedef struct cls_packet_info {
uint32_t len;
} cls_packet_info_t;
+typedef union odp_cls_testcase {
+ struct {
+ uint32_t default_cos:1;
+ uint32_t error_cos:1;
+ uint32_t pmr_chain:1;
+ uint32_t l2_priority:1;
+ uint32_t pmr_cos:1;
+ uint32_t pmr_composite_cos:1;
+ };
+ uint32_t all_bits;
+} odp_cls_testcase_u;
+
extern odp_testinfo_t classification_suite[];
extern odp_testinfo_t classification_suite_basic[];
extern odp_testinfo_t classification_suite_pmr[];
diff --git a/test/validation/api/ipsec/ipsec.c b/test/validation/api/ipsec/ipsec.c
index 21eaf17..3e2e743 100644
--- a/test/validation/api/ipsec/ipsec.c
+++ b/test/validation/api/ipsec/ipsec.c
@@ -604,10 +604,15 @@ static int ipsec_send_out_one(const ipsec_test_part *part,
hdr_len = part->out[0].pkt_out->l3_offset;
CU_ASSERT_FATAL(hdr_len <= sizeof(hdr));
memcpy(hdr, part->out[0].pkt_out->data, hdr_len);
- } else {
+ } else if (part->pkt_in->l3_offset !=
+ ODP_PACKET_OFFSET_INVALID) {
hdr_len = part->pkt_in->l3_offset;
CU_ASSERT_FATAL(hdr_len <= sizeof(hdr));
memcpy(hdr, part->pkt_in->data, hdr_len);
+ } else {
+ /* Dummy header */
+ hdr_len = 14;
+ memset(hdr, 0xff, hdr_len);
}
inline_param.pktio = suite_context.pktio;
inline_param.outer_hdr.ptr = hdr;
diff --git a/test/validation/api/ipsec/ipsec_test_out.c b/test/validation/api/ipsec/ipsec_test_out.c
index 3db553b..5089dfa 100644
--- a/test/validation/api/ipsec/ipsec_test_out.c
+++ b/test/validation/api/ipsec/ipsec_test_out.c
@@ -997,6 +997,164 @@ static void test_out_ipv6_esp_udp_null_sha256(void)
ipsec_sa_destroy(sa);
}
+static void test_out_dummy_esp_null_sha256_tun_ipv4(void)
+{
+ uint32_t src = IPV4ADDR(10, 0, 111, 2);
+ uint32_t dst = IPV4ADDR(10, 0, 222, 2);
+ odp_ipsec_tunnel_param_t tunnel = {
+ .type = ODP_IPSEC_TUNNEL_IPV4,
+ .ipv4.src_addr = &src,
+ .ipv4.dst_addr = &dst,
+ .ipv4.ttl = 64,
+ };
+ odp_ipsec_sa_param_t param;
+ odp_ipsec_sa_t sa;
+ odp_ipsec_sa_t sa2;
+
+ /* This test will not work properly inbound inline mode.
+ * Packet might be dropped and we will not check for that. */
+ if (suite_context.inbound_op_mode == ODP_IPSEC_OP_MODE_INLINE)
+ return;
+
+ ipsec_sa_param_fill(&param,
+ false, false, 123, &tunnel,
+ ODP_CIPHER_ALG_NULL, NULL,
+ ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256,
+ NULL);
+
+ sa = odp_ipsec_sa_create(&param);
+
+ CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa);
+
+ ipsec_sa_param_fill(&param,
+ true, false, 123, &tunnel,
+ ODP_CIPHER_ALG_NULL, NULL,
+ ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256,
+ NULL);
+
+ sa2 = odp_ipsec_sa_create(&param);
+
+ CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa2);
+
+ ipsec_test_part test = {
+ .pkt_in = &pkt_test_nodata,
+ .num_opt = 1,
+ .opt = { .flag.tfc_dummy = 1,
+ .tfc_pad_len = 16, },
+ .out_pkt = 1,
+ .out = {
+ { .status.warn.all = 0,
+ .status.error.all = 0,
+ .l3_type = ODP_PROTO_L3_TYPE_IPV4,
+ .l4_type = ODP_PROTO_L4_TYPE_NO_NEXT,
+ .pkt_out = NULL },
+ },
+ };
+
+ ipsec_test_part test_empty = {
+ .pkt_in = &pkt_test_emtpy,
+ .num_opt = 1,
+ .opt = { .flag.tfc_dummy = 1,
+ .tfc_pad_len = 16, },
+ .out_pkt = 1,
+ .out = {
+ { .status.warn.all = 0,
+ .status.error.all = 0,
+ .l3_type = ODP_PROTO_L3_TYPE_IPV4,
+ .l4_type = ODP_PROTO_L4_TYPE_NO_NEXT,
+ .pkt_out = NULL },
+ },
+ };
+
+ ipsec_check_out_in_one(&test, sa, sa2);
+ ipsec_check_out_in_one(&test_empty, sa, sa2);
+
+ ipsec_sa_destroy(sa2);
+ ipsec_sa_destroy(sa);
+}
+
+static void test_out_dummy_esp_null_sha256_tun_ipv6(void)
+{
+ uint8_t src[16] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x11, 0x43, 0xff, 0xfe, 0x4a, 0xd7, 0x0a,
+ };
+ uint8_t dst[16] = {
+ 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+ };
+ odp_ipsec_tunnel_param_t tunnel = {
+ .type = ODP_IPSEC_TUNNEL_IPV6,
+ .ipv6.src_addr = src,
+ .ipv6.dst_addr = dst,
+ .ipv6.hlimit = 64,
+ };
+ odp_ipsec_sa_param_t param;
+ odp_ipsec_sa_t sa;
+ odp_ipsec_sa_t sa2;
+
+ /* This test will not work properly inbound inline mode.
+ * Packet might be dropped and we will not check for that. */
+ if (suite_context.inbound_op_mode == ODP_IPSEC_OP_MODE_INLINE)
+ return;
+
+ ipsec_sa_param_fill(&param,
+ false, false, 123, &tunnel,
+ ODP_CIPHER_ALG_NULL, NULL,
+ ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256,
+ NULL);
+
+ sa = odp_ipsec_sa_create(&param);
+
+ CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa);
+
+ ipsec_sa_param_fill(&param,
+ true, false, 123, &tunnel,
+ ODP_CIPHER_ALG_NULL, NULL,
+ ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256,
+ NULL);
+
+ sa2 = odp_ipsec_sa_create(&param);
+
+ CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa2);
+
+ ipsec_test_part test = {
+ .pkt_in = &pkt_test_nodata,
+ .num_opt = 1,
+ .opt = { .flag.tfc_dummy = 1,
+ .tfc_pad_len = 16, },
+ .out_pkt = 1,
+ .out = {
+ { .status.warn.all = 0,
+ .status.error.all = 0,
+ .l3_type = ODP_PROTO_L3_TYPE_IPV4,
+ .l4_type = ODP_PROTO_L4_TYPE_NO_NEXT,
+ .pkt_out = NULL },
+ },
+ };
+
+ ipsec_test_part test_empty = {
+ .pkt_in = &pkt_test_emtpy,
+ .num_opt = 1,
+ .opt = { .flag.tfc_dummy = 1,
+ .tfc_pad_len = 16, },
+ .out_pkt = 1,
+ .out = {
+ { .status.warn.all = 0,
+ .status.error.all = 0,
+ .l3_type = ODP_PROTO_L3_TYPE_IPV4,
+ .l4_type = ODP_PROTO_L4_TYPE_NO_NEXT,
+ .pkt_out = NULL },
+ },
+ };
+
+ ipsec_check_out_in_one(&test, sa, sa2);
+ ipsec_check_out_in_one(&test_empty, sa, sa2);
+
+ ipsec_sa_destroy(sa2);
+ ipsec_sa_destroy(sa);
+}
+
static void ipsec_test_capability(void)
{
odp_ipsec_capability_t capa;
@@ -1056,5 +1214,9 @@ odp_testinfo_t ipsec_out_suite[] = {
ipsec_check_esp_null_sha256),
ODP_TEST_INFO_CONDITIONAL(test_out_ipv6_esp_udp_null_sha256,
ipsec_check_esp_null_sha256),
+ ODP_TEST_INFO_CONDITIONAL(test_out_dummy_esp_null_sha256_tun_ipv4,
+ ipsec_check_esp_null_sha256),
+ ODP_TEST_INFO_CONDITIONAL(test_out_dummy_esp_null_sha256_tun_ipv6,
+ ipsec_check_esp_null_sha256),
ODP_TEST_INFO_NULL,
};
diff --git a/test/validation/api/ipsec/test_vectors.h b/test/validation/api/ipsec/test_vectors.h
index 4d5ab3b..5b357a1 100644
--- a/test/validation/api/ipsec/test_vectors.h
+++ b/test/validation/api/ipsec/test_vectors.h
@@ -1865,4 +1865,22 @@ static const ODP_UNUSED ipsec_test_packet
},
};
+static const ipsec_test_packet pkt_test_emtpy = {
+ .len = 0,
+ .l2_offset = ODP_PACKET_OFFSET_INVALID,
+ .l3_offset = ODP_PACKET_OFFSET_INVALID,
+ .l4_offset = ODP_PACKET_OFFSET_INVALID,
+ .data = { 0 },
+};
+
+static const ipsec_test_packet pkt_test_nodata = {
+ .len = 14,
+ .l2_offset = 0,
+ .l3_offset = ODP_PACKET_OFFSET_INVALID,
+ .l4_offset = ODP_PACKET_OFFSET_INVALID,
+ .data = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c, 0x0d,
+ },
+};
#endif
diff --git a/test/validation/api/pktio/pktio.c b/test/validation/api/pktio/pktio.c
index f5bb2e2..e82a968 100644
--- a/test/validation/api/pktio/pktio.c
+++ b/test/validation/api/pktio/pktio.c
@@ -1723,206 +1723,6 @@ static void pktio_test_start_stop(void)
odp_event_free(ev);
}
-/*
- * This is a pre-condition check that the pktio_test_send_failure()
- * test case can be run. If the TX interface max frame len is larger that the
- * biggest packet we can allocate then the test won't be able to
- * attempt to send packets larger than the max len, so skip the test.
- */
-static int pktio_check_send_failure(void)
-{
- odp_pktio_t pktio_tx;
- uint32_t maxlen;
- odp_pktio_param_t pktio_param;
- int iface_idx = 0;
- const char *iface = iface_name[iface_idx];
- odp_pool_capability_t pool_capa;
-
- if (odp_pool_capability(&pool_capa) < 0) {
- fprintf(stderr, "%s: pool capability failed\n", __func__);
- return ODP_TEST_INACTIVE;
- };
-
- memset(&pktio_param, 0, sizeof(pktio_param));
-
- pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT;
-
- pktio_tx = odp_pktio_open(iface, pool[iface_idx], &pktio_param);
- if (pktio_tx == ODP_PKTIO_INVALID) {
- fprintf(stderr, "%s: failed to open pktio\n", __func__);
- return ODP_TEST_INACTIVE;
- }
-
- /* read the maxlen from the transmit interface */
- maxlen = odp_pktout_maxlen(pktio_tx);
-
- odp_pktio_close(pktio_tx);
-
- /* Failure test supports only single segment */
- if (pool_capa.pkt.max_seg_len &&
- pool_capa.pkt.max_seg_len < maxlen + 32)
- return ODP_TEST_INACTIVE;
-
- return ODP_TEST_ACTIVE;
-}
-
-static void pktio_test_send_failure(void)
-{
- odp_pktio_t pktio_tx, pktio_rx;
- odp_packet_t pkt_tbl[TX_BATCH_LEN];
- uint32_t pkt_seq[TX_BATCH_LEN];
- int ret, i, alloc_pkts;
- uint32_t maxlen;
- odp_pool_param_t pool_params;
- odp_pool_t pkt_pool;
- int long_pkt_idx = TX_BATCH_LEN / 2;
- pktio_info_t info_rx;
- odp_pktout_queue_t pktout;
- odp_pool_capability_t pool_capa;
-
- pktio_tx = create_pktio(0, ODP_PKTIN_MODE_DIRECT,
- ODP_PKTOUT_MODE_DIRECT);
- if (pktio_tx == ODP_PKTIO_INVALID) {
- CU_FAIL("failed to open pktio");
- return;
- }
-
- CU_ASSERT_FATAL(odp_pktout_queue(pktio_tx, &pktout, 1) == 1);
-
- /* read maxlen from the transmit interface */
- maxlen = odp_pktout_maxlen(pktio_tx);
-
- ret = odp_pktio_start(pktio_tx);
- CU_ASSERT_FATAL(ret == 0);
-
- _pktio_wait_linkup(pktio_tx);
-
- CU_ASSERT_FATAL(odp_pool_capability(&pool_capa) == 0);
-
- if (pool_capa.pkt.max_seg_len &&
- pool_capa.pkt.max_seg_len < maxlen + 32) {
- CU_FAIL("Max packet seg length is too small.");
- return;
- }
-
- /* configure the pool so that we can generate test packets larger
- * than the interface max transmit length */
- odp_pool_param_init(&pool_params);
- pool_params.pkt.len = maxlen + 32;
- pool_params.pkt.seg_len = pool_params.pkt.len;
- pool_params.pkt.num = TX_BATCH_LEN + 1;
- pool_params.type = ODP_POOL_PACKET;
- pkt_pool = odp_pool_create("pkt_pool_oversize", &pool_params);
- CU_ASSERT_FATAL(pkt_pool != ODP_POOL_INVALID);
-
- if (num_ifaces > 1) {
- pktio_rx = create_pktio(1, ODP_PKTIN_MODE_DIRECT,
- ODP_PKTOUT_MODE_DIRECT);
- ret = odp_pktio_start(pktio_rx);
- CU_ASSERT_FATAL(ret == 0);
-
- _pktio_wait_linkup(pktio_rx);
- } else {
- pktio_rx = pktio_tx;
- }
-
- /* generate a batch of packets with a single overly long packet
- * in the middle */
- for (i = 0; i < TX_BATCH_LEN; ++i) {
- uint32_t pkt_len;
-
- if (i == long_pkt_idx)
- pkt_len = pool_params.pkt.len;
- else
- pkt_len = PKT_LEN_NORMAL;
-
- pkt_tbl[i] = odp_packet_alloc(pkt_pool, pkt_len);
- if (pkt_tbl[i] == ODP_PACKET_INVALID)
- break;
-
- pkt_seq[i] = pktio_init_packet(pkt_tbl[i]);
-
- pktio_pkt_set_macs(pkt_tbl[i], pktio_tx, pktio_rx);
- if (pktio_fixup_checksums(pkt_tbl[i]) != 0) {
- odp_packet_free(pkt_tbl[i]);
- break;
- }
-
- if (pkt_seq[i] == TEST_SEQ_INVALID) {
- odp_packet_free(pkt_tbl[i]);
- break;
- }
- }
- alloc_pkts = i;
-
- if (alloc_pkts == TX_BATCH_LEN) {
- /* try to send the batch with the long packet in the middle,
- * the initial short packets should be sent successfully */
- odp_errno_zero();
- ret = odp_pktout_send(pktout, pkt_tbl, TX_BATCH_LEN);
- CU_ASSERT(ret == long_pkt_idx);
- if (ret != long_pkt_idx)
- goto cleanup;
- CU_ASSERT(odp_errno() == 0);
-
- info_rx.id = pktio_rx;
- info_rx.inq = ODP_QUEUE_INVALID;
- info_rx.in_mode = ODP_PKTIN_MODE_DIRECT;
-
- i = wait_for_packets(&info_rx, pkt_tbl, pkt_seq, ret,
- TXRX_MODE_MULTI, ODP_TIME_SEC_IN_NS);
-
- if (i == ret) {
- /* now try to send starting with the too-long packet
- * and verify it fails */
- odp_errno_zero();
- ret = odp_pktout_send(pktout,
- &pkt_tbl[long_pkt_idx],
- TX_BATCH_LEN - long_pkt_idx);
- CU_ASSERT(ret == -1);
- CU_ASSERT(odp_errno() != 0);
- } else {
- CU_FAIL("failed to receive transmitted packets\n");
- }
-
- /* now reduce the size of the long packet and attempt to send
- * again - should work this time */
- i = long_pkt_idx;
- odp_packet_pull_tail(pkt_tbl[i],
- odp_packet_len(pkt_tbl[i]) -
- PKT_LEN_NORMAL);
- pkt_seq[i] = pktio_init_packet(pkt_tbl[i]);
-
- pktio_pkt_set_macs(pkt_tbl[i], pktio_tx, pktio_rx);
- ret = pktio_fixup_checksums(pkt_tbl[i]);
- CU_ASSERT_FATAL(ret == 0);
-
- CU_ASSERT_FATAL(pkt_seq[i] != TEST_SEQ_INVALID);
- ret = odp_pktout_send(pktout, &pkt_tbl[i], TX_BATCH_LEN - i);
- CU_ASSERT_FATAL(ret == (TX_BATCH_LEN - i));
-
- i = wait_for_packets(&info_rx, &pkt_tbl[i], &pkt_seq[i], ret,
- TXRX_MODE_MULTI, ODP_TIME_SEC_IN_NS);
- CU_ASSERT(i == ret);
- } else {
- CU_FAIL("failed to generate test packets\n");
- }
-
- for (i = 0; i < alloc_pkts; ++i) {
- if (pkt_tbl[i] != ODP_PACKET_INVALID)
- odp_packet_free(pkt_tbl[i]);
- }
-
-cleanup:
- if (pktio_rx != pktio_tx) {
- CU_ASSERT(odp_pktio_stop(pktio_rx) == 0);
- CU_ASSERT(odp_pktio_close(pktio_rx) == 0);
- }
- CU_ASSERT(odp_pktio_stop(pktio_tx) == 0);
- CU_ASSERT(odp_pktio_close(pktio_tx) == 0);
- CU_ASSERT(odp_pool_destroy(pkt_pool) == 0);
-}
-
static void pktio_test_recv_on_wonly(void)
{
odp_pktio_t pktio;
@@ -2221,8 +2021,6 @@ odp_testinfo_t pktio_suite_unsegmented[] = {
ODP_TEST_INFO(pktio_test_recv_tmo),
ODP_TEST_INFO(pktio_test_recv_mq_tmo),
ODP_TEST_INFO(pktio_test_recv_mtu),
- ODP_TEST_INFO_CONDITIONAL(pktio_test_send_failure,
- pktio_check_send_failure),
ODP_TEST_INFO(pktio_test_mtu),
ODP_TEST_INFO(pktio_test_promisc),
ODP_TEST_INFO(pktio_test_mac),
@@ -2247,8 +2045,6 @@ odp_testinfo_t pktio_suite_segmented[] = {
ODP_TEST_INFO(pktio_test_recv),
ODP_TEST_INFO(pktio_test_recv_multi),
ODP_TEST_INFO(pktio_test_recv_mtu),
- ODP_TEST_INFO_CONDITIONAL(pktio_test_send_failure,
- pktio_check_send_failure),
ODP_TEST_INFO_NULL
};
diff --git a/test/validation/api/scheduler/scheduler.c b/test/validation/api/scheduler/scheduler.c
index d5783b4..f1b61df 100644
--- a/test/validation/api/scheduler/scheduler.c
+++ b/test/validation/api/scheduler/scheduler.c
@@ -175,10 +175,8 @@ static void scheduler_test_wait_time(void)
/* check time correctness */
start_time = odp_time_local();
- for (i = 1; i < 6; i++) {
+ for (i = 1; i < 6; i++)
odp_schedule(&queue, wait_time);
- printf("%d..", i);
- }
end_time = odp_time_local();
diff = odp_time_diff(end_time, start_time);