This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "".
The branch, master has been updated via 57df98eca15fe64a716f9f555714ef5fb9cd25e9 (commit) via 674ea087fba016e55f03e3966fe64fc908141f8f (commit) via a9584da4284c04e45a9584a58c6dbeb404871119 (commit) via 63123149319eb0e379dc52a3f4691993d026f3bf (commit) via 9a5a18af733c07109224e328ca0ac640ff49f845 (commit) via 06321dc028b83ea78b39eb9673859a40f9da37f7 (commit) via d6de4dfcf1a3a6c861c87d47990f793c71328eda (commit) via fc0a57306aa68a782e8611a9bd08ae10aaa5274a (commit) via 2eaf47b69ea5f2095e26e0ea597d3e8702b0da06 (commit) via 9f3311f92d28ef9fdf6ef3d8ec8b90efe7a832d6 (commit) via 68b1a52611e6ac9be306e5a17d009a6fd46c455e (commit) via 59d636481fd1771107f3eb4632c2a9fc868afc11 (commit) via 0225a8a396ddc7168be096f28b0a711184a48ef9 (commit) via 72febbae5ea55a5fd051978fbfa0f669cf0e99fc (commit) via f80f28c4046b650c180bcb9b41c859c0c8e2564e (commit) via b08aa94548163ae4d4bac2724e68ca9102667f6a (commit) via 4aacfd4d72b80a22d449d865a6c4f063afa823ab (commit) via 71ca38c00c11ebb6b4dede6d09ebdd28eb45d890 (commit) via 7e0c523ad6f209f238277e4116c21ba696edb7f4 (commit) via 12d238d96318cc9d46dd5a2893894824a633805b (commit) via bcd246e3a9948a631eb8eb77886ac1b369b13dba (commit) via c57da8ddc80e0e314957c6d11db288ef11fc1805 (commit) via 535ad269bfc6581a048d3e844576063be5d19501 (commit) via d8dd54f2325cf859703721e7a17b6cbe734d857a (commit) via edc9616a1bbc0fbc2d7f84ddafeb119d689f3f70 (commit) via 31d3492b50b057df853ad51c909ac21d6e95a4ca (commit) via 74f7b6d1a003175f1cddf979212631a0d7832399 (commit) via 3c5cc8070d3bc8b7429f0410de6ef3009ff6a28f (commit) via 4665f6d2987fb26ad006cb56b02b3ef4c170f371 (commit) via d3690d4115441dc69d9571cb5261dd005a112d39 (commit) via 364887331875180c498abb8b7681a228ca21181e (commit) via eca5df13cf7987d6e3cd3cc930851671b071e4b3 (commit) via c8dc27d1fb5c890143338439f1cdbe3b2719174c (commit) via 62ef9d5c92e0f56f45767f4c73df214d4393e158 (commit) via 41fd242a0685e79cb6f1b1e1826e6734bea2f359 (commit) via 35a90a547466db90c00d6375d8d9a3573e84e99b (commit) via 9a1d48b1262d88e55922c4e1ed9f91ed2e3376d7 (commit) via 1e70adc3ae54b0c4518bdb51d94301f1dafe4ebf (commit) via 91282a4c578716f157aa8a5e0a9bf9bd25b19a17 (commit) via e009051a0166fa25e601190354e0333aa30ad58d (commit) via 36f589b5a84804ce246bcd9a3eb9352801aaf41d (commit) via 2bbd7ace9e236d27dcfb52acfef991bd5ce39354 (commit) via 196d8f518071cc8c37dde0835cb7559d6cdd55da (commit) via 42fc5ebdcd5a1e5fbb7a19a2756a310f23a0cdd5 (commit) via bb8015d15ca4b0e2033eeca09906032a88e74bff (commit) via 3e61be54a77ed8ccc2030e88b9a26372d3f76e2c (commit) via c0da87688187c81039cf81790fed3d6ed00a956e (commit) via c2a1c48f5fc17cf4dd870057d17059ad668d29ad (commit) via c67dcec1c034a0c75c093b49e2a172bbd3d50def (commit) via 80b9a1e4d6a297ac916cbaf360e7b2114ef86a7a (commit) via 7135eda6854ba60d6379ca5799b4b58959e998b5 (commit) via 017969502cd0247c9b25e80e002ac563860f5a5d (commit) via 3a4f369fb2019761af5d4d7ad09d48f1e5d44f82 (commit) via 962600ecdbe44d386f95a57ac5a91365af0b6c39 (commit) from 6ea708c0f9f36b9a90f463dd1f7e0332f82e079b (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit 57df98eca15fe64a716f9f555714ef5fb9cd25e9 Author: Bogdan Pricope bogdan.pricope@linaro.org Date: Thu Mar 29 11:47:02 2018 +0300
linux-gen: dpdk: fix runtime/default config read order
Signed-off-by: Bogdan Pricope bogdan.pricope@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_libconfig_internal.h b/platform/linux-generic/include/odp_libconfig_internal.h index 04291775..727f6886 100644 --- a/platform/linux-generic/include/odp_libconfig_internal.h +++ b/platform/linux-generic/include/odp_libconfig_internal.h @@ -22,6 +22,11 @@ int _odp_libconfig_term_global(void);
int _odp_libconfig_lookup_int(const char *path, int *value);
+int _odp_libconfig_lookup_ext_int(const char *base_path, + const char *local_path, + const char *name, + int *value); + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/odp_libconfig.c b/platform/linux-generic/odp_libconfig.c index 85acc572..316ed067 100644 --- a/platform/linux-generic/odp_libconfig.c +++ b/platform/linux-generic/odp_libconfig.c @@ -95,3 +95,41 @@ int _odp_libconfig_lookup_int(const char *path, int *value)
return (ret_def == CONFIG_TRUE || ret_rt == CONFIG_TRUE) ? 1 : 0; } + +static int lookup_int(config_t *cfg, + const char *base_path, + const char *local_path, + const char *name, + int *value) +{ + char path[256]; + + if (local_path) { + snprintf(path, sizeof(path), "%s.%s.%s", base_path, + local_path, name); + if (config_lookup_int(cfg, path, value) == CONFIG_TRUE) + return 1; + } + + snprintf(path, sizeof(path), "%s.%s", base_path, name); + if (config_lookup_int(cfg, path, value) == CONFIG_TRUE) + return 1; + + return 0; +} + +int _odp_libconfig_lookup_ext_int(const char *base_path, + const char *local_path, + const char *name, + int *value) +{ + if (lookup_int(&odp_global_data.libconfig_runtime, + base_path, local_path, name, value)) + return 1; + + if (lookup_int(&odp_global_data.libconfig_default, + base_path, local_path, name, value)) + return 1; + + return 0; +} diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index d40ad954..7bccab87 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -95,22 +95,16 @@ void refer_constructors(void) } #endif
-static int lookup_opt(const char *path, const char *drv_name, int *val) +static int lookup_opt(const char *opt_name, 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); + int ret;
+ ret = _odp_libconfig_lookup_ext_int(base, drv_name, opt_name, val); if (ret == 0) - ODP_ERR("Unable to find DPDK configuration option: %s\n", path); + ODP_ERR("Unable to find DPDK configuration option: %s\n", + opt_name); + return ret; }
commit 674ea087fba016e55f03e3966fe64fc908141f8f Author: Maxim Uvarov maxim.uvarov@linaro.org Date: Fri Mar 30 19:09:07 2018 +0300
add odp_ipsec to .gitignore
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/performance/.gitignore b/test/performance/.gitignore index 259f690c..4c4ab6ed 100644 --- a/test/performance/.gitignore +++ b/test/performance/.gitignore @@ -3,6 +3,7 @@ odp_atomic odp_bench_packet odp_crypto +odp_ipsec odp_l2fwd odp_pktio_ordered odp_pktio_perf
commit a9584da4284c04e45a9584a58c6dbeb404871119 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Wed Mar 28 17:14:28 2018 +0300
build: fix autoconf error caused by double-registering config item
Autoconf uses provided tag as is, when registering config command. Require platform code to pass platform argument, so that different config commands will be registered.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-and-tested-by: Matias Elo matias.elo@nokia.com Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/m4/odp_libconfig.m4 b/m4/odp_libconfig.m4 index c9d770bb..302dc506 100644 --- a/m4/odp_libconfig.m4 +++ b/m4/odp_libconfig.m4 @@ -1,5 +1,5 @@ -# ODP_LIBCONFIG -# ------------- +# ODP_LIBCONFIG(PLATFORM) +# ----------------------- AC_DEFUN([ODP_LIBCONFIG], [dnl ########################################################################## @@ -18,12 +18,12 @@ AS_IF([test -z "$OD"], [AC_MSG_ERROR([Could not find 'od'])]) # Create a header file odp_libconfig_config.h which containins null # terminated hex dump of odp-linux.conf ########################################################################## -AC_CONFIG_COMMANDS([platform/${with_platform}/include/odp_libconfig_config.h], -[mkdir -p platform/${with_platform}/include +AC_CONFIG_COMMANDS([platform/$1/include/odp_libconfig_config.h], +[mkdir -p platform/$1/include (echo "static const char config_builtin[[]] = {"; \ - $OD -An -v -tx1 < ${srcdir}/config/odp-${with_platform}.conf | \ + $OD -An -v -tx1 < ${srcdir}/config/odp-$1.conf | \ $SED -e 's/[[0-9a-f]]+/0x\0,/g' ; \ echo "0x00 };") > \ - platform/${with_platform}/include/odp_libconfig_config.h], + platform/$1/include/odp_libconfig_config.h], [with_platform=$with_platform OD=$OD SED=$SED]) ]) # ODP_LIBCONFIG diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4 index d4aa9cd0..7cf0a9b6 100644 --- a/platform/linux-generic/m4/configure.m4 +++ b/platform/linux-generic/m4/configure.m4 @@ -6,7 +6,7 @@ ODP_ATOMIC ODP_PTHREAD ODP_TIMER ODP_OPENSSL -ODP_LIBCONFIG +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])
commit 63123149319eb0e379dc52a3f4691993d026f3bf Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Mar 23 04:36:41 2018 +0300
build: don't use xxd to hexdump config file
Use standard od and sed programs to hexdump config file, removing dependency on xxd.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/DEPENDENCIES b/DEPENDENCIES index f328e787..48f5a839 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -21,8 +21,6 @@ Prerequisites for building the OpenDataPlane (ODP) API
Libraries currently required to link: openssl, libatomic, libconfig
- Required tools: xxd - 3.1 OpenSSL native compile
For native compilation, simply load the necessary libraries using the appropriate diff --git a/m4/odp_libconfig.m4 b/m4/odp_libconfig.m4 index 632c271e..c9d770bb 100644 --- a/m4/odp_libconfig.m4 +++ b/m4/odp_libconfig.m4 @@ -8,12 +8,11 @@ AC_DEFUN([ODP_LIBCONFIG], PKG_CHECK_MODULES([LIBCONFIG], [libconfig])
########################################################################## -# Check for xxd availability +# Check for od availability ########################################################################## -AC_CHECK_PROGS([XXD], [xxd]) -if test -z "$XXD"; - then AC_MSG_ERROR([Could not find 'xxd']) -fi +AC_CHECK_PROGS([OD], [od]) +AC_PROG_SED +AS_IF([test -z "$OD"], [AC_MSG_ERROR([Could not find 'od'])])
########################################################################## # Create a header file odp_libconfig_config.h which containins null @@ -21,8 +20,10 @@ fi ########################################################################## AC_CONFIG_COMMANDS([platform/${with_platform}/include/odp_libconfig_config.h], [mkdir -p platform/${with_platform}/include - (cd ${srcdir}/config ; xxd -i odp-${with_platform}.conf) | \ - sed 's/([[0-9a-f]])$/\0, 0x00/' > \ + (echo "static const char config_builtin[[]] = {"; \ + $OD -An -v -tx1 < ${srcdir}/config/odp-${with_platform}.conf | \ + $SED -e 's/[[0-9a-f]]+/0x\0,/g' ; \ + echo "0x00 };") > \ platform/${with_platform}/include/odp_libconfig_config.h], - [with_platform=$with_platform]) + [with_platform=$with_platform OD=$OD SED=$SED]) ]) # ODP_LIBCONFIG diff --git a/platform/linux-generic/odp_libconfig.c b/platform/linux-generic/odp_libconfig.c index 3b3b3170..85acc572 100644 --- a/platform/linux-generic/odp_libconfig.c +++ b/platform/linux-generic/odp_libconfig.c @@ -16,8 +16,6 @@ #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) @@ -33,7 +31,7 @@ int _odp_libconfig_init_global(void) config_init(config); config_init(config_rt);
- if (!config_read_string(config, CONF_STR_NAME)) { + if (!config_read_string(config, config_builtin)) { ODP_ERR("Failed to read default config: %s(%d): %s\n", config_error_file(config), config_error_line(config), config_error_text(config));
commit 9a5a18af733c07109224e328ca0ac640ff49f845 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Sat Mar 24 05:42:25 2018 +0300
build: another DPDK-linking fix
Try our best to link with DPDK, if we are doing static linking of examples and tests and we detected shared DPDK library. Build the list of static libraries, in hope they are present on the system (like in Debian/Ubuntu DPDK packages). Linking can still fail, as we have warned during configure time.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/example/Makefile.inc b/example/Makefile.inc index 3c8060da..083c537f 100644 --- a/example/Makefile.inc +++ b/example/Makefile.inc @@ -6,6 +6,8 @@ LDADD = $(LIB)/libodp-linux.la $(LIB)/libodphelper.la
# Do not link to DPDK twice in case of dynamic linking with ODP if STATIC_APPS +LDADD += $(DPDK_LIBS_LT_STATIC) +else LDADD += $(DPDK_LIBS_LT) endif
diff --git a/m4/odp_dpdk.m4 b/m4/odp_dpdk.m4 index dccc6569..ec248e76 100644 --- a/m4/odp_dpdk.m4 +++ b/m4/odp_dpdk.m4 @@ -21,20 +21,22 @@ AS_VAR_APPEND([DPDK_PMDS], [--no-whole-archive]) # -------------------- # Set DPDK_LIBS/DPDK_LIBS_LT/DPDK_LIBS_LIBODP depending on DPDK setup AC_DEFUN([_ODP_DPDK_SET_LIBS], [dnl +ODP_DPDK_PMDS([$DPDK_PMD_PATH]) AS_IF([test "x$DPDK_SHARED" = "xyes"], [dnl # applications don't need to be linked to anything, just rpath DPDK_LIBS_LT="$DPDK_RPATH_LT" # static linking flags will need -ldpdk + DPDK_LIBS_LT_STATIC="$DPDK_LDFLAGS $DPDK_PMDS $DPDK_LIBS" DPDK_LIBS="-Wl,--no-as-needed,-ldpdk,--as-needed,`echo $DPDK_LIBS | sed -e 's/ /,/g'`" DPDK_LIBS="$DPDK_LDFLAGS $DPDK_RPATH $DPDK_LIBS" # link libodp-linux with -ldpdk DPDK_LIBS_LIBODP="$DPDK_LIBS" ], [dnl - ODP_DPDK_PMDS([$DPDK_PMD_PATH]) # build long list of libraries for applications, which should not be # rearranged by libtool DPDK_LIBS_LT="`echo $DPDK_LIBS | sed -e 's/^/-Wc,/' -e 's/ /,/g'`" DPDK_LIBS_LT="$DPDK_LDFLAGS $DPDK_PMDS $DPDK_LIBS_LT $DPDK_LIBS" + DPDK_LIBS_LT_STATIC="$DPDK_LIBS_LT" # static linking flags follow the suite DPDK_LIBS="$DPDK_LDFLAGS $DPDK_PMDS $DPDK_LIBS" # link libodp-linux with libtool linking flags @@ -43,6 +45,7 @@ AS_IF([test "x$DPDK_SHARED" = "xyes"], [dnl AC_SUBST([DPDK_LIBS]) AC_SUBST([DPDK_LIBS_LIBODP]) AC_SUBST([DPDK_LIBS_LT]) +AC_SUBST([DPDK_LIBS_LT_STATIC]) ])
# _ODP_DPDK_CHECK_LIB(LDFLAGS, [LIBS]) diff --git a/test/Makefile.inc b/test/Makefile.inc index 55a493a8..0706cac8 100644 --- a/test/Makefile.inc +++ b/test/Makefile.inc @@ -21,6 +21,8 @@ AM_CPPFLAGS = \
# Do not link to DPDK twice in case of dynamic linking with ODP if STATIC_APPS +LDADD += $(DPDK_LIBS_LT_STATIC) +else LDADD += $(DPDK_LIBS_LT) endif
commit 06321dc028b83ea78b39eb9673859a40f9da37f7 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Sat Mar 24 04:54:37 2018 +0300
build: move odp scheduler setting to common m4 file
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/m4/odp_schedule.m4 b/m4/odp_scheduler.m4 similarity index 73% rename from platform/linux-generic/m4/odp_schedule.m4 rename to m4/odp_scheduler.m4 index 70be5a7d..23cc7da3 100644 --- a/platform/linux-generic/m4/odp_schedule.m4 +++ b/m4/odp_scheduler.m4 @@ -1,6 +1,11 @@ +# ODP_SCHEDULER +# ------------- +# Select default scheduler +AC_DEFUN([ODP_SCHEDULER], [dnl AC_ARG_ENABLE([scheduler-default], [AS_HELP_STRING([enable-scheduler-default], [Choose default scheduler (default is basic)])], [], [enable_scheduler_default=basic]) AC_DEFINE_UNQUOTED([ODP_SCHEDULE_DEFAULT], ["$enable_scheduler_default"], [Define to name default scheduler]) +]) # ODP_SCHEDULER diff --git a/platform/linux-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4 index e3f276af..d4aa9cd0 100644 --- a/platform/linux-generic/m4/configure.m4 +++ b/platform/linux-generic/m4/configure.m4 @@ -10,7 +10,7 @@ ODP_LIBCONFIG 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]) -m4_include([platform/linux-generic/m4/odp_schedule.m4]) +ODP_SCHEDULER
m4_include([platform/linux-generic/m4/performance.m4])
commit d6de4dfcf1a3a6c861c87d47990f793c71328eda Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Mar 23 18:56:59 2018 +0300
linux-gen: ipsec: add proper support for AES-CCM
Make linux-generic's IPsec actually support AES-CCM algorithm.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_ipsec_sad.c b/platform/linux-generic/odp_ipsec_sad.c index 05865eb3..8dab489c 100644 --- a/platform/linux-generic/odp_ipsec_sad.c +++ b/platform/linux-generic/odp_ipsec_sad.c @@ -220,6 +220,8 @@ uint32_t _odp_ipsec_cipher_iv_len(odp_cipher_alg_t cipher) #endif case ODP_CIPHER_ALG_AES_GCM: return 12; + case ODP_CIPHER_ALG_AES_CCM: + return 11; case ODP_CIPHER_ALG_CHACHA20_POLY1305: return 12; default: @@ -252,6 +254,8 @@ uint32_t _odp_ipsec_auth_digest_len(odp_auth_alg_t auth) case ODP_AUTH_ALG_AES_GCM: case ODP_AUTH_ALG_AES_GMAC: return 16; + case ODP_AUTH_ALG_AES_CCM: + return 16; case ODP_AUTH_ALG_CHACHA20_POLY1305: return 16; default: @@ -411,6 +415,7 @@ odp_ipsec_sa_t odp_ipsec_sa_create(const odp_ipsec_sa_param_t *param) case ODP_CIPHER_ALG_AES128_GCM: #endif case ODP_CIPHER_ALG_AES_GCM: + case ODP_CIPHER_ALG_AES_CCM: ipsec_sa->use_counter_iv = 1; ipsec_sa->esp_iv_len = 8; ipsec_sa->esp_block_len = 16;
commit fc0a57306aa68a782e8611a9bd08ae10aaa5274a Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Mar 23 18:55:54 2018 +0300
linux-gen: crypto: add IV length checks
Check IV length on crypto session creation, fixing possible issues later, during en/decryption.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c index a7fddb5b..21449cfe 100644 --- a/platform/linux-generic/odp_crypto.c +++ b/platform/linux-generic/odp_crypto.c @@ -661,9 +661,8 @@ static int process_cipher_param(odp_crypto_generic_session_t *session, return -1;
/* Verify IV len is correct */ - if (!((0 == session->p.cipher_iv.length) || - ((uint32_t)EVP_CIPHER_iv_length(cipher) == - session->p.cipher_iv.length))) + if ((uint32_t)EVP_CIPHER_iv_length(cipher) != + session->p.cipher_iv.length) return -1;
session->cipher.evp_cipher = cipher; @@ -791,6 +790,10 @@ static int process_aes_gcm_param(odp_crypto_generic_session_t *session, session->p.cipher_key.length) return -1;
+ /* Verify IV len is correct */ + if (12 != session->p.cipher_iv.length) + return -1; + memcpy(session->cipher.key_data, session->p.cipher_key.data, session->p.cipher_key.length);
@@ -902,6 +905,10 @@ static int process_aes_gmac_param(odp_crypto_generic_session_t *session, session->p.auth_key.length) return -1;
+ /* Verify IV len is correct */ + if (12 != session->p.auth_iv.length) + return -1; + memcpy(session->auth.key, session->p.auth_key.data, session->p.auth_key.length);
@@ -1058,6 +1065,11 @@ static int process_aes_ccm_param(odp_crypto_generic_session_t *session, session->p.cipher_key.length) return -1;
+ /* Verify IV len is correct */ + if (11 != session->p.cipher_iv.length && + 13 != session->p.cipher_iv.length) + return -1; + memcpy(session->cipher.key_data, session->p.cipher_key.data, session->p.cipher_key.length);
@@ -1078,6 +1090,10 @@ static int process_aes_ccm_param(odp_crypto_generic_session_t *session, static int process_auth_hmac_param(odp_crypto_generic_session_t *session, const EVP_MD *evp_md) { + /* Verify IV len is correct */ + if (0 != session->p.auth_iv.length) + return -1; + /* Set function */ if (ODP_CRYPTO_OP_ENCODE == session->p.op) session->auth.func = auth_hmac_gen; @@ -1106,6 +1122,9 @@ static int process_auth_cmac_param(odp_crypto_generic_session_t *session, session->p.auth_key.length) return -1;
+ if (0 != session->p.auth_iv.length) + return -1; + /* Set function */ if (ODP_CRYPTO_OP_ENCODE == session->p.op) session->auth.func = auth_cmac_gen;
commit 2eaf47b69ea5f2095e26e0ea597d3e8702b0da06 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Mar 23 18:42:42 2018 +0300
performance: crypto: add more algorithms
Run more performance tests on crypto transformation.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/performance/odp_crypto.c b/test/performance/odp_crypto.c index e4f49fb7..8841c127 100644 --- a/test/performance/odp_crypto.c +++ b/test/performance/odp_crypto.c @@ -51,6 +51,30 @@ static uint8_t test_key24[24] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x15, 0x16, 0x17, 0x18 };
+static uint8_t test_key32[32] = { 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, +}; + +static uint8_t test_key64[64] = { 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x4b, 0x2c, 0x2d, + 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x55, 0x36, 0x37, + 0x38, 0x39, 0x5a, 0x3b, 0x3c, + 0x3d, 0x3e, 0x5f, 0x40, +}; + /** * Structure that holds template for session create call * for different algorithms supported by test @@ -279,6 +303,81 @@ static crypto_alg_config_t algs_config[] = { .auth_digest_len = 12, }, }, + { + .name = "aes-ctr-null", + .session = { + .cipher_alg = ODP_CIPHER_ALG_AES_CTR, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .cipher_iv = { + .data = test_iv, + .length = 16, + }, + .auth_alg = ODP_AUTH_ALG_NULL + }, + }, + { + .name = "aes-ctr-hmac-sha1-96", + .session = { + .cipher_alg = ODP_CIPHER_ALG_AES_CTR, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .cipher_iv = { + .data = test_iv, + .length = 16, + }, + .auth_alg = ODP_AUTH_ALG_SHA1_HMAC, + .auth_key = { + .data = test_key20, + .length = sizeof(test_key20) + }, + .auth_digest_len = 12, + }, + }, + { + .name = "null-hmac-sha256-128", + .session = { + .cipher_alg = ODP_CIPHER_ALG_NULL, + .auth_alg = ODP_AUTH_ALG_SHA256_HMAC, + .auth_key = { + .data = test_key32, + .length = sizeof(test_key32) + }, + .auth_digest_len = 16, + }, + }, + { + .name = "null-hmac-sha512-256", + .session = { + .cipher_alg = ODP_CIPHER_ALG_NULL, + .auth_alg = ODP_AUTH_ALG_SHA512_HMAC, + .auth_key = { + .data = test_key64, + .length = sizeof(test_key64) + }, + .auth_digest_len = 32, + }, + }, + { + .name = "null-aes-gmac", + .session = { + .cipher_alg = ODP_CIPHER_ALG_NULL, + .auth_alg = ODP_AUTH_ALG_AES_GMAC, + .auth_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .auth_iv = { + .data = test_iv, + .length = 12, + }, + .auth_digest_len = 16, + }, + }, { .name = "aes-gcm", .session = { @@ -295,6 +394,38 @@ static crypto_alg_config_t algs_config[] = { .auth_digest_len = 16, }, }, + { + .name = "aes-ccm", + .session = { + .cipher_alg = ODP_CIPHER_ALG_AES_CCM, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .cipher_iv = { + .data = test_iv, + .length = 11, + }, + .auth_alg = ODP_AUTH_ALG_AES_CCM, + .auth_digest_len = 16, + }, + }, + { + .name = "chacha20-poly1305", + .session = { + .cipher_alg = ODP_CIPHER_ALG_CHACHA20_POLY1305, + .cipher_key = { + .data = test_key32, + .length = sizeof(test_key32) + }, + .cipher_iv = { + .data = test_iv, + .length = 12, + }, + .auth_alg = ODP_AUTH_ALG_CHACHA20_POLY1305, + .auth_digest_len = 16, + }, + }, };
/**
commit 9f3311f92d28ef9fdf6ef3d8ec8b90efe7a832d6 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Mar 23 18:42:42 2018 +0300
performance: ipsec: add more algorithms
Run more performance tests on IPsec transformation.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/performance/odp_ipsec.c b/test/performance/odp_ipsec.c index 6fdd033c..587293db 100644 --- a/test/performance/odp_ipsec.c +++ b/test/performance/odp_ipsec.c @@ -51,6 +51,30 @@ static uint8_t test_key24[24] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x15, 0x16, 0x17, 0x18 };
+static uint8_t test_key32[32] = { 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, +}; + +static uint8_t test_key64[64] = { 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x4b, 0x2c, 0x2d, + 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0x33, 0x34, 0x55, 0x36, 0x37, + 0x38, 0x39, 0x5a, 0x3b, 0x3c, + 0x3d, 0x3e, 0x5f, 0x40, +}; + /** * Structure that holds template for sa create call * for different algorithms supported by test @@ -245,6 +269,32 @@ static ipsec_alg_config_t algs_config[] = { }, }, }, + { + .name = "aes-ctr-null", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_AES_CTR, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .auth_alg = ODP_AUTH_ALG_NULL + }, + }, + { + .name = "aes-ctr-hmac-sha1-96", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_AES_CTR, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .auth_alg = ODP_AUTH_ALG_SHA1_HMAC, + .auth_key = { + .data = test_key20, + .length = sizeof(test_key20) + }, + }, + }, { .name = "null-hmac-sha1-96", .crypto = { @@ -256,6 +306,43 @@ static ipsec_alg_config_t algs_config[] = { }, }, }, + { + .name = "null-hmac-sha256-128", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_NULL, + .auth_alg = ODP_AUTH_ALG_SHA256_HMAC, + .auth_key = { + .data = test_key32, + .length = sizeof(test_key32) + }, + }, + }, + { + .name = "null-hmac-sha512-256", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_NULL, + .auth_alg = ODP_AUTH_ALG_SHA512_HMAC, + .auth_key = { + .data = test_key64, + .length = sizeof(test_key64) + }, + }, + }, + { + .name = "null-aes-gmac", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_NULL, + .auth_alg = ODP_AUTH_ALG_AES_GMAC, + .auth_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .cipher_key_extra = { + .data = test_salt, + .length = 4, + }, + }, + }, { .name = "aes-gcm", .crypto = { @@ -271,6 +358,36 @@ static ipsec_alg_config_t algs_config[] = { .auth_alg = ODP_AUTH_ALG_AES_GCM, }, }, + { + .name = "aes-ccm", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_AES_CCM, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .cipher_key_extra = { + .data = test_salt, + .length = 3, + }, + .auth_alg = ODP_AUTH_ALG_AES_CCM, + }, + }, + { + .name = "chacha20-poly1305", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_CHACHA20_POLY1305, + .cipher_key = { + .data = test_key32, + .length = sizeof(test_key32) + }, + .cipher_key_extra = { + .data = test_salt, + .length = 4, + }, + .auth_alg = ODP_AUTH_ALG_CHACHA20_POLY1305, + }, + }, };
/**
commit 68b1a52611e6ac9be306e5a17d009a6fd46c455e Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Mar 23 18:19:48 2018 +0300
performance: ipsec: add AH measurements
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/performance/odp_ipsec.c b/test/performance/odp_ipsec.c index 6552c0e0..6fdd033c 100644 --- a/test/performance/odp_ipsec.c +++ b/test/performance/odp_ipsec.c @@ -122,6 +122,12 @@ typedef struct { * Specified through -t argument. */ int tunnel; + + /* + * Use AH transformation. + * Specified through -u argument. + */ + int ah; } ipsec_args_t;
/* @@ -778,6 +784,7 @@ static void usage(char *progname) " -s, --schedule Use scheduler for completion events.\n" " -p, --poll Poll completion queue for completion events.\n" " -t, --tunnel Use tunnel-mode IPsec transformation.\n" + " -u, --ah Use AH transformation instead of ESP.\n" " -h, --help Display help and exit.\n" "\n"); } @@ -798,10 +805,11 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs) {"poll", no_argument, NULL, 'p'}, {"schedule", no_argument, NULL, 's'}, {"tunnel", no_argument, NULL, 't'}, + {"ah", no_argument, NULL, 'u'}, {NULL, 0, NULL, 0} };
- static const char *shortopts = "+a:c:df:hi:m:nl:spt"; + static const char *shortopts = "+a:c:df:hi:m:nl:sptu";
/* let helper collect its own arguments (e.g. --odph_proc) */ odph_parse_options(argc, argv, shortopts, longopts); @@ -813,6 +821,7 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs) cargs->payload_length = 0; cargs->alg_config = NULL; cargs->schedule = 0; + cargs->ah = 0;
opterr = 0; /* do not issue errors on helper options */
@@ -860,6 +869,9 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs) case 't': cargs->tunnel = 1; break; + case 'u': + cargs->ah = 1; + break; default: break; } @@ -1011,6 +1023,10 @@ int main(int argc, char *argv[]) for (i = 0; i < (sizeof(algs_config) / sizeof(ipsec_alg_config_t)); i++) { + if (cargs.ah && + algs_config[i].crypto.cipher_alg != + ODP_CIPHER_ALG_NULL) + continue; run_measure_one_config(&cargs, algs_config + i); } }
commit 59d636481fd1771107f3eb4632c2a9fc868afc11 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Thu Mar 15 15:50:22 2018 +0300
tests: add IPsec performance test
Use this tool to measure IPsec performance with different algorithms For now only outbound direction is supported.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/performance/Makefile.am b/test/performance/Makefile.am index 458c8fb0..c8f0bdec 100644 --- a/test/performance/Makefile.am +++ b/test/performance/Makefile.am @@ -4,6 +4,7 @@ TESTS_ENVIRONMENT += TEST_DIR=${builddir}
EXECUTABLES = odp_bench_packet \ odp_crypto \ + odp_ipsec \ odp_pktio_perf
COMPILE_ONLY = odp_l2fwd \ @@ -30,6 +31,7 @@ bin_PROGRAMS = $(EXECUTABLES) $(COMPILE_ONLY)
odp_bench_packet_SOURCES = odp_bench_packet.c odp_crypto_SOURCES = odp_crypto.c +odp_ipsec_SOURCES = odp_ipsec.c odp_pktio_ordered_SOURCES = odp_pktio_ordered.c dummy_crc.h odp_sched_latency_SOURCES = odp_sched_latency.c odp_sched_pktio_SOURCES = odp_sched_pktio.c diff --git a/test/performance/odp_ipsec.c b/test/performance/odp_ipsec.c new file mode 100644 index 00000000..6552c0e0 --- /dev/null +++ b/test/performance/odp_ipsec.c @@ -0,0 +1,1037 @@ +/* Copyright (c) 2018, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "config.h" + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif /* _GNU_SOURCE */ + +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/time.h> +#include <sys/resource.h> + +#include <odp_api.h> +#include <odp/helper/odph_api.h> + +#define app_err(fmt, ...) \ + fprintf(stderr, "%s:%d:%s(): Error: " fmt, __FILE__, \ + __LINE__, __func__, ##__VA_ARGS__) + +/** @def POOL_NUM_PKT + * Number of packets in the pool + */ +#define POOL_NUM_PKT 64 + +static uint8_t test_salt[16] = "0123456789abcdef"; + +static uint8_t test_key16[16] = { 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, +}; + +static uint8_t test_key20[20] = { 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, +}; + +static uint8_t test_key24[24] = { 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18 +}; + +/** + * Structure that holds template for sa create call + * for different algorithms supported by test + */ +typedef struct { + const char *name; /**< Algorithm name */ + odp_ipsec_crypto_param_t crypto; /**< Prefilled SA crypto param */ +} ipsec_alg_config_t; + +/** + * Parsed command line crypto arguments. Describes test configuration. + */ +typedef struct { + /** + * If non zero prints content of packets. Enabled by -d or + * --debug option. + */ + int debug_packets; + + /** + * If non zero Try to run crypto operation in place. Note some + * implementation may not support such mode. Enabled by -n or + * --inplace option. + */ + int in_place; + + /** + * Maximum number of outstanding encryption requests. Note code + * poll for results over queue and if nothing is available it can + * submit more encryption requests up to maximum number specified by + * this option. Specified through -f or --flight option. + */ + int in_flight; + + /** + * Number of iteration to repeat crypto operation to get good + * average number. Specified through -i or --terations option. + * Default is 10000. + */ + int iteration_count; + + /** + * Payload size to test. If 0 set of predefined payload sizes + * is tested. Specified through -p or --payload option. + */ + unsigned int payload_length; + + /** + * Pointer to selected algorithm to test. If NULL all available + * alogorthims are tested. Name of algorithm is passed through + * -a or --algorithm option. + */ + ipsec_alg_config_t *alg_config; + + /** + * Use scheduler to get completion events from crypto operation. + * Specified through -s argument. + * */ + int schedule; + + /* + * Poll completion queue for crypto completion events. + * Specified through -p argument. + */ + int poll; + + /* + * Use tunnel instead of transport mode. + * Specified through -t argument. + */ + int tunnel; +} ipsec_args_t; + +/* + * Helper structure that holds averages for test of one algorithm + * for given payload size. + */ +typedef struct { + /** + * Elapsed time for one crypto operation. + */ + double elapsed; + + /** + * CPU time spent pre one crypto operation by whole process + * i.e include current and all other threads in process. + * It is filled with 'getrusage(RUSAGE_SELF, ...)' call. + */ + double rusage_self; + + /** + * CPU time spent per one crypto operation by current thread + * only. It is filled with 'getrusage(RUSAGE_THREAD, ...)' + * call. + */ + double rusage_thread; +} ipsec_run_result_t; + +/** + * Structure holds one snap to misc times of current process. + */ +typedef struct { + struct timeval tv; /**< Elapsed time */ + struct rusage ru_self; /**< Rusage value for whole process */ + struct rusage ru_thread; /**< Rusage value for current thread */ +} time_record_t; + +/** + * Set of predefined payloads. + */ +static unsigned int global_payloads[] = { + 64, + 256, + 1024, + 8192, + 16384 +}; + +/** Number of payloads used in the test */ +static unsigned int global_num_payloads; + +/** + * Set of known algorithms to test + */ +static ipsec_alg_config_t algs_config[] = { + { + .name = "3des-cbc-null", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_3DES_CBC, + .cipher_key = { + .data = test_key24, + .length = sizeof(test_key24) + }, + .auth_alg = ODP_AUTH_ALG_NULL + }, + }, + { + .name = "3des-cbc-hmac-md5-96", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_3DES_CBC, + .cipher_key = { + .data = test_key24, + .length = sizeof(test_key24) + }, + .auth_alg = ODP_AUTH_ALG_MD5_HMAC, + .auth_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + }, + }, + { + .name = "null-hmac-md5-96", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_NULL, + .auth_alg = ODP_AUTH_ALG_MD5_HMAC, + .auth_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + }, + }, + { + .name = "aes-cbc-null", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_AES_CBC, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .auth_alg = ODP_AUTH_ALG_NULL + }, + }, + { + .name = "aes-cbc-hmac-sha1-96", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_AES_CBC, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .auth_alg = ODP_AUTH_ALG_SHA1_HMAC, + .auth_key = { + .data = test_key20, + .length = sizeof(test_key20) + }, + }, + }, + { + .name = "null-hmac-sha1-96", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_NULL, + .auth_alg = ODP_AUTH_ALG_SHA1_HMAC, + .auth_key = { + .data = test_key20, + .length = sizeof(test_key20) + }, + }, + }, + { + .name = "aes-gcm", + .crypto = { + .cipher_alg = ODP_CIPHER_ALG_AES_GCM, + .cipher_key = { + .data = test_key16, + .length = sizeof(test_key16) + }, + .cipher_key_extra = { + .data = test_salt, + .length = 4, + }, + .auth_alg = ODP_AUTH_ALG_AES_GCM, + }, + }, +}; + +/** + * Find corresponding config for given name. Returns NULL + * if config for given name is not found. + */ +static ipsec_alg_config_t * +find_config_by_name(const char *name) +{ + unsigned int i; + ipsec_alg_config_t *ret = NULL; + + for (i = 0; i < (sizeof(algs_config) / sizeof(ipsec_alg_config_t)); + i++) { + if (strcmp(algs_config[i].name, name) == 0) { + ret = algs_config + i; + break; + } + } + return ret; +} + +/** + * Helper function that prints list of algorithms that this + * test understands. + */ +static void +print_config_names(const char *prefix) +{ + unsigned int i; + + for (i = 0; i < (sizeof(algs_config) / sizeof(ipsec_alg_config_t)); + i++) { + printf("%s %s\n", prefix, algs_config[i].name); + } +} + +/** + * Snap current time values and put them into 'rec'. + */ +static void +fill_time_record(time_record_t *rec) +{ + gettimeofday(&rec->tv, NULL); + getrusage(RUSAGE_SELF, &rec->ru_self); + getrusage(RUSAGE_THREAD, &rec->ru_thread); +} + +/** + * Calculated CPU time difference for given two rusage structures. + * Note it adds user space and system time together. + */ +static unsigned long long +get_rusage_diff(struct rusage *start, struct rusage *end) +{ + unsigned long long rusage_diff; + unsigned long long rusage_start; + unsigned long long rusage_end; + + rusage_start = (start->ru_utime.tv_sec * 1000000) + + (start->ru_utime.tv_usec); + rusage_start += (start->ru_stime.tv_sec * 1000000) + + (start->ru_stime.tv_usec); + + rusage_end = (end->ru_utime.tv_sec * 1000000) + + (end->ru_utime.tv_usec); + rusage_end += (end->ru_stime.tv_sec * 1000000) + + (end->ru_stime.tv_usec); + + rusage_diff = rusage_end - rusage_start; + + return rusage_diff; +} + +/** + * Get diff for RUSAGE_SELF (whole process) between two time snap + * records. + */ +static unsigned long long +get_rusage_self_diff(time_record_t *start, time_record_t *end) +{ + return get_rusage_diff(&start->ru_self, &end->ru_self); +} + +/** + * Get diff for RUSAGE_THREAD (current thread only) between two + * time snap records. + */ +static unsigned long long +get_rusage_thread_diff(time_record_t *start, time_record_t *end) +{ + return get_rusage_diff(&start->ru_thread, &end->ru_thread); +} + +/** + * Get diff of elapsed time between two time snap records + */ +static unsigned long long +get_elapsed_usec(time_record_t *start, time_record_t *end) +{ + unsigned long long s; + unsigned long long e; + + s = (start->tv.tv_sec * 1000000) + (start->tv.tv_usec); + e = (end->tv.tv_sec * 1000000) + (end->tv.tv_usec); + + return e - s; +} + +/** + * Print header line for our report. + */ +static void +print_result_header(void) +{ + printf("\n%30.30s %15s %15s %15s %15s %15s %15s\n", + "algorithm", "avg over #", "payload (bytes)", "elapsed (us)", + "rusg self (us)", "rusg thrd (us)", "throughput (Kb)"); +} + +/** + * Print one line of our report. + */ +static void +print_result(ipsec_args_t *cargs, + unsigned int payload_length, + ipsec_alg_config_t *config, + ipsec_run_result_t *result) +{ + unsigned int throughput; + + throughput = (1000000.0 / result->elapsed) * payload_length / 1024; + printf("%30.30s %15d %15d %15.3f %15.3f %15.3f %15d\n", + config->name, cargs->iteration_count, payload_length, + result->elapsed, result->rusage_self, result->rusage_thread, + throughput); +} + +#define IPV4ADDR(a, b, c, d) odp_cpu_to_be_32((a << 24) | \ + (b << 16) | \ + (c << 8) | \ + (d << 0)) + +/** + * Create ODP IPsec SA for given config. + */ +static odp_ipsec_sa_t +create_sa_from_config(ipsec_alg_config_t *config, + ipsec_args_t *cargs) +{ + odp_ipsec_sa_param_t param; + odp_queue_t out_queue; + + odp_ipsec_sa_param_init(¶m); + memcpy(¶m.crypto, &config->crypto, + sizeof(odp_ipsec_crypto_param_t)); + + param.proto = ODP_IPSEC_ESP; + param.dir = ODP_IPSEC_DIR_OUTBOUND; + + if (cargs->tunnel) { + uint32_t src = IPV4ADDR(10, 0, 111, 2); + uint32_t dst = IPV4ADDR(10, 0, 222, 2); + odp_ipsec_tunnel_param_t tunnel; + + memset(&tunnel, 0, sizeof(tunnel)); + tunnel.type = ODP_IPSEC_TUNNEL_IPV4; + tunnel.ipv4.src_addr = &src; + tunnel.ipv4.dst_addr = &dst; + tunnel.ipv4.ttl = 64; + + param.mode = ODP_IPSEC_MODE_TUNNEL; + param.outbound.tunnel = tunnel; + } else { + param.mode = ODP_IPSEC_MODE_TRANSPORT; + } + + if (cargs->schedule || cargs->poll) { + out_queue = odp_queue_lookup("ipsec-out"); + if (out_queue == ODP_QUEUE_INVALID) { + app_err("ipsec-out queue not found\n"); + return ODP_IPSEC_SA_INVALID; + } + param.dest_queue = out_queue; + } else { + param.dest_queue = ODP_QUEUE_INVALID; + } + + return odp_ipsec_sa_create(¶m); +} + +static uint8_t test_data[] = { + /* IP */ + 0x45, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x01, 0xac, 0x27, 0xc0, 0xa8, 0x6f, 0x02, + 0xc0, 0xa8, 0xde, 0x02, + + /* ICMP */ + 0x08, 0x00, 0xfb, 0x37, 0x12, 0x34, 0x00, 0x00 +}; + +static odp_packet_t +make_packet(odp_pool_t pkt_pool, unsigned int payload_length) +{ + odp_packet_t pkt; + + if (payload_length < sizeof(test_data)) + return ODP_PACKET_INVALID; + + pkt = odp_packet_alloc(pkt_pool, payload_length); + if (pkt == ODP_PACKET_INVALID) { + app_err("failed to allocate buffer\n"); + return pkt; + } + + odp_packet_copy_from_mem(pkt, 0, sizeof(test_data), test_data); + odp_packet_l3_offset_set(pkt, 0); + + uint8_t *mem = odp_packet_data(pkt); + ((odph_ipv4hdr_t *)mem)->tot_len = odp_cpu_to_be_16(payload_length); + memset(mem + sizeof(test_data), 1, payload_length - sizeof(test_data)); + + return pkt; +} + +/** + * Run measurement iterations for given config and payload size. + * Result of run returned in 'result' out parameter. + */ +static int +run_measure_one(ipsec_args_t *cargs, + odp_ipsec_sa_t sa, + unsigned int payload_length, + time_record_t *start, + time_record_t *end) +{ + odp_ipsec_out_param_t param; + odp_pool_t pkt_pool; + odp_packet_t pkt = ODP_PACKET_INVALID; + int rc = 0; + + pkt_pool = odp_pool_lookup("packet_pool"); + if (pkt_pool == ODP_POOL_INVALID) { + app_err("pkt_pool not found\n"); + return -1; + } + + int packets_sent = 0; + int packets_received = 0; + + /* Initialize parameters block */ + memset(¶m, 0, sizeof(param)); + param.num_sa = 1; + param.num_opt = 0; + param.sa = &sa; + + fill_time_record(start); + + while ((packets_sent < cargs->iteration_count) || + (packets_received < cargs->iteration_count)) { + if ((packets_sent < cargs->iteration_count) && + (packets_sent - packets_received < + cargs->in_flight)) { + odp_packet_t out_pkt; + int num_out = 1; + + pkt = make_packet(pkt_pool, payload_length); + if (ODP_PACKET_INVALID == pkt) + return -1; + + out_pkt = cargs->in_place ? pkt : ODP_PACKET_INVALID; + + if (cargs->debug_packets) + odp_packet_print_data(pkt, 0, + odp_packet_len(pkt)); + + rc = odp_ipsec_out(&pkt, 1, + &out_pkt, &num_out, + ¶m); + if (rc <= 0) { + app_err("failed odp_ipsec_out: rc = %d\n", + rc); + odp_packet_free(pkt); + break; + } + if (odp_packet_has_error(out_pkt)) { + odp_ipsec_packet_result_t result; + + odp_ipsec_result(&result, out_pkt); + app_err("Received error packet: %d\n", + result.status.error.all); + } + packets_sent += rc; + packets_received += num_out; + if (cargs->debug_packets) + odp_packet_print_data(out_pkt, 0, + odp_packet_len(out_pkt)); + odp_packet_free(out_pkt); + } + } + + fill_time_record(end); + + return rc < 0 ? rc : 0; +} + +static int +run_measure_one_async(ipsec_args_t *cargs, + odp_ipsec_sa_t sa, + unsigned int payload_length, + time_record_t *start, + time_record_t *end) +{ + odp_ipsec_out_param_t param; + odp_pool_t pkt_pool; + odp_queue_t out_queue; + odp_packet_t pkt = ODP_PACKET_INVALID; + int rc = 0; + + pkt_pool = odp_pool_lookup("packet_pool"); + if (pkt_pool == ODP_POOL_INVALID) { + app_err("pkt_pool not found\n"); + return -1; + } + + out_queue = odp_queue_lookup("ipsec-out"); + if (out_queue == ODP_QUEUE_INVALID) { + app_err("ipsec-out queue not found\n"); + return -1; + } + + int packets_sent = 0; + int packets_received = 0; + + /* Initialize parameters block */ + memset(¶m, 0, sizeof(param)); + param.num_sa = 1; + param.num_opt = 0; + param.sa = &sa; + + fill_time_record(start); + + while ((packets_sent < cargs->iteration_count) || + (packets_received < cargs->iteration_count)) { + odp_event_t ev; + + if ((packets_sent < cargs->iteration_count) && + (packets_sent - packets_received < + cargs->in_flight)) { + pkt = make_packet(pkt_pool, payload_length); + if (ODP_PACKET_INVALID == pkt) + return -1; + + if (cargs->debug_packets) + odp_packet_print_data(pkt, 0, + odp_packet_len(pkt)); + + rc = odp_ipsec_out_enq(&pkt, 1, + ¶m); + if (rc <= 0) { + app_err("failed odp_crypto_packet_op_enq: rc = %d\n", + rc); + odp_packet_free(pkt); + break; + } + packets_sent += rc; + } + + if (cargs->schedule) + ev = odp_schedule(NULL, + ODP_SCHED_NO_WAIT); + else + ev = odp_queue_deq(out_queue); + + while (ev != ODP_EVENT_INVALID) { + odp_packet_t out_pkt; + odp_ipsec_packet_result_t result; + + out_pkt = odp_ipsec_packet_from_event(ev); + odp_ipsec_result(&result, out_pkt); + + if (cargs->debug_packets) + odp_packet_print_data(out_pkt, 0, + odp_packet_len(out_pkt)); + odp_packet_free(out_pkt); + packets_received++; + if (cargs->schedule) + ev = odp_schedule(NULL, + ODP_SCHED_NO_WAIT); + else + ev = odp_queue_deq(out_queue); + } + } + + fill_time_record(end); + + return rc < 0 ? rc : 0; +} + +/** + * Process one algorithm. Note if paload size is specicified it is + * only one run. Or iterate over set of predefined payloads. + */ +static int +run_measure_one_config(ipsec_args_t *cargs, + ipsec_alg_config_t *config) +{ + odp_ipsec_sa_t sa; + int rc = 0; + unsigned int num_payloads = global_num_payloads; + unsigned int *payloads = global_payloads; + unsigned int i; + + sa = create_sa_from_config(config, cargs); + if (sa == ODP_IPSEC_SA_INVALID) { + app_err("IPsec SA create failed.\n"); + return -1; + } + + print_result_header(); + if (cargs->payload_length) { + num_payloads = 1; + payloads = &cargs->payload_length; + } + + for (i = 0; i < num_payloads; i++) { + double count; + ipsec_run_result_t result; + time_record_t start, end; + + if (cargs->schedule || cargs->poll) + rc = run_measure_one_async(cargs, sa, + payloads[i], + &start, &end); + else + rc = run_measure_one(cargs, sa, + payloads[i], + &start, &end); + if (rc) + break; + + count = get_elapsed_usec(&start, &end); + result.elapsed = count / cargs->iteration_count; + + count = get_rusage_self_diff(&start, &end); + result.rusage_self = count / cargs->iteration_count; + + count = get_rusage_thread_diff(&start, &end); + result.rusage_thread = count / cargs->iteration_count; + + print_result(cargs, payloads[i], + config, &result); + } + + odp_ipsec_sa_disable(sa); + if (cargs->schedule || cargs->poll) { + odp_queue_t out_queue = odp_queue_lookup("ipsec-out"); + odp_ipsec_status_t status; + + while (1) { + odp_event_t event = odp_queue_deq(out_queue); + + if (event != ODP_EVENT_INVALID && + odp_event_type(event) == ODP_EVENT_IPSEC_STATUS && + odp_ipsec_status(&status, event) == ODP_IPSEC_OK && + status.id == ODP_IPSEC_STATUS_SA_DISABLE && + status.sa == sa) + break; + } + } + odp_ipsec_sa_destroy(sa); + + return rc; +} + +typedef struct thr_arg { + ipsec_args_t ipsec_args; + ipsec_alg_config_t *ipsec_alg_config; +} thr_arg_t; + +static int run_thr_func(void *arg) +{ + thr_arg_t *thr_args = (thr_arg_t *)arg; + + run_measure_one_config(&thr_args->ipsec_args, + thr_args->ipsec_alg_config); + return 0; +} + +/** + * Prinf usage information + */ +static void usage(char *progname) +{ + printf("\n" + "Usage: %s OPTIONS\n" + " E.g. %s -i 100000\n" + "\n" + "OpenDataPlane crypto speed measure.\n" + "Optional OPTIONS\n" + " -a, --algorithm <name> Specify algorithm name (default all)\n" + " Supported values are:\n", + progname, progname); + + print_config_names(" "); + printf(" -d, --debug Enable dump of processed packets.\n" + " -f, --flight <number> Max number of packet processed in parallel (default 1)\n" + " -i, --iterations <number> Number of iterations.\n" + " -n, --inplace Encrypt on place.\n" + " -l, --payload Payload length.\n" + " -s, --schedule Use scheduler for completion events.\n" + " -p, --poll Poll completion queue for completion events.\n" + " -t, --tunnel Use tunnel-mode IPsec transformation.\n" + " -h, --help Display help and exit.\n" + "\n"); +} + +static void parse_args(int argc, char *argv[], ipsec_args_t *cargs) +{ + int opt; + int long_index; + static const struct option longopts[] = { + {"algorithm", optional_argument, NULL, 'a'}, + {"debug", no_argument, NULL, 'd'}, + {"flight", optional_argument, NULL, 'f'}, + {"help", no_argument, NULL, 'h'}, + {"iterations", optional_argument, NULL, 'i'}, + {"inplace", no_argument, NULL, 'n'}, + {"payload", optional_argument, NULL, 'l'}, + {"sessions", optional_argument, NULL, 'm'}, + {"poll", no_argument, NULL, 'p'}, + {"schedule", no_argument, NULL, 's'}, + {"tunnel", no_argument, NULL, 't'}, + {NULL, 0, NULL, 0} + }; + + static const char *shortopts = "+a:c:df:hi:m:nl:spt"; + + /* let helper collect its own arguments (e.g. --odph_proc) */ + odph_parse_options(argc, argv, shortopts, longopts); + + cargs->in_place = 0; + cargs->in_flight = 1; + cargs->debug_packets = 0; + cargs->iteration_count = 10000; + cargs->payload_length = 0; + cargs->alg_config = NULL; + cargs->schedule = 0; + + opterr = 0; /* do not issue errors on helper options */ + + while (1) { + opt = getopt_long(argc, argv, shortopts, longopts, &long_index); + + if (opt == -1) + break; /* No more options */ + + switch (opt) { + case 'a': + cargs->alg_config = find_config_by_name(optarg); + if (!cargs->alg_config) { + printf("cannot test crypto '%s' configuration\n", + optarg); + usage(argv[0]); + exit(-1); + } + break; + case 'd': + cargs->debug_packets = 1; + break; + case 'i': + cargs->iteration_count = atoi(optarg); + break; + case 'f': + cargs->in_flight = atoi(optarg); + break; + case 'h': + usage(argv[0]); + exit(EXIT_SUCCESS); + break; + case 'n': + cargs->in_place = 1; + break; + case 'l': + cargs->payload_length = atoi(optarg); + break; + case 's': + cargs->schedule = 1; + break; + case 'p': + cargs->poll = 1; + break; + case 't': + cargs->tunnel = 1; + break; + default: + break; + } + } + + optind = 1; /* reset 'extern optind' from the getopt lib */ + + if (cargs->schedule && cargs->poll) { + printf("-s (schedule) and -p (poll) options are not compatible\n"); + usage(argv[0]); + exit(-1); + } +} + +int main(int argc, char *argv[]) +{ + ipsec_args_t cargs; + odp_pool_t pool; + odp_queue_param_t qparam; + odp_pool_param_t param; + odp_queue_t out_queue = ODP_QUEUE_INVALID; + thr_arg_t thr_arg; + odp_cpumask_t cpumask; + char cpumaskstr[ODP_CPUMASK_STR_SIZE]; + int num_workers = 1; + odph_odpthread_t thr[num_workers]; + odp_instance_t instance; + odp_pool_capability_t capa; + odp_ipsec_config_t config; + uint32_t max_seg_len; + unsigned int i; + + memset(&cargs, 0, sizeof(cargs)); + + /* Parse and store the application arguments */ + parse_args(argc, argv, &cargs); + + /* Init ODP before calling anything else */ + if (odp_init_global(&instance, NULL, NULL)) { + app_err("ODP global init failed.\n"); + exit(EXIT_FAILURE); + } + + /* Init this thread */ + if (odp_init_local(instance, ODP_THREAD_WORKER)) { + app_err("ODP local init failed.\n"); + exit(EXIT_FAILURE); + } + + if (odp_pool_capability(&capa)) { + app_err("Pool capability request failed.\n"); + exit(EXIT_FAILURE); + } + + max_seg_len = capa.pkt.max_seg_len; + + for (i = 0; i < sizeof(global_payloads) / sizeof(unsigned int); i++) { + if (global_payloads[i] > max_seg_len) + break; + } + + global_num_payloads = i; + + /* Create packet pool */ + odp_pool_param_init(¶m); + param.pkt.seg_len = max_seg_len; + param.pkt.len = max_seg_len; + param.pkt.num = POOL_NUM_PKT; + param.type = ODP_POOL_PACKET; + pool = odp_pool_create("packet_pool", ¶m); + + if (pool == ODP_POOL_INVALID) { + app_err("packet pool create failed.\n"); + exit(EXIT_FAILURE); + } + odp_pool_print(pool); + + odp_ipsec_config_init(&config); + config.max_num_sa = 2; + config.inbound.chksums.all_chksum = 0; + config.outbound.all_chksum = 0; + + odp_queue_param_init(&qparam); + if (cargs.schedule) { + qparam.type = ODP_QUEUE_TYPE_SCHED; + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; + qparam.sched.sync = ODP_SCHED_SYNC_PARALLEL; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + out_queue = odp_queue_create("ipsec-out", &qparam); + } else if (cargs.poll) { + qparam.type = ODP_QUEUE_TYPE_PLAIN; + out_queue = odp_queue_create("ipsec-out", &qparam); + } + if (cargs.schedule || cargs.poll) { + if (out_queue == ODP_QUEUE_INVALID) { + app_err("ipsec-out queue create failed.\n"); + exit(EXIT_FAILURE); + } + config.inbound_mode = ODP_IPSEC_OP_MODE_ASYNC; + config.outbound_mode = ODP_IPSEC_OP_MODE_ASYNC; + config.inbound.default_queue = out_queue; + } else { + config.inbound_mode = ODP_IPSEC_OP_MODE_SYNC; + config.outbound_mode = ODP_IPSEC_OP_MODE_SYNC; + config.inbound.default_queue = ODP_QUEUE_INVALID; + } + + if (cargs.schedule) { + printf("Run in async scheduled mode\n"); + + thr_arg.ipsec_args = cargs; + thr_arg.ipsec_alg_config = cargs.alg_config; + num_workers = odp_cpumask_default_worker(&cpumask, + num_workers); + (void)odp_cpumask_to_str(&cpumask, cpumaskstr, + sizeof(cpumaskstr)); + printf("num worker threads: %i\n", + num_workers); + printf("first CPU: %i\n", + odp_cpumask_first(&cpumask)); + printf("cpu mask: %s\n", + cpumaskstr); + } else if (cargs.poll) { + printf("Run in async poll mode\n"); + } else { + printf("Run in sync mode\n"); + } + + memset(thr, 0, sizeof(thr)); + + if (cargs.alg_config) { + odph_odpthread_params_t thr_param; + + memset(&thr_param, 0, sizeof(thr_param)); + thr_param.start = run_thr_func; + thr_param.arg = &thr_arg; + thr_param.thr_type = ODP_THREAD_WORKER; + thr_param.instance = instance; + + if (cargs.schedule) { + odph_odpthreads_create(&thr[0], &cpumask, &thr_param); + odph_odpthreads_join(&thr[0]); + } else { + run_measure_one_config(&cargs, cargs.alg_config); + } + } else { + unsigned int i; + + for (i = 0; + i < (sizeof(algs_config) / sizeof(ipsec_alg_config_t)); + i++) { + run_measure_one_config(&cargs, algs_config + i); + } + } + + if (cargs.schedule || cargs.poll) + odp_queue_destroy(out_queue); + if (odp_pool_destroy(pool)) { + app_err("Error: pool destroy\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_local()) { + app_err("Error: term local\n"); + exit(EXIT_FAILURE); + } + + if (odp_term_global(instance)) { + app_err("Error: term global\n"); + exit(EXIT_FAILURE); + } + + return 0; +} +
commit 0225a8a396ddc7168be096f28b0a711184a48ef9 Author: Bogdan Pricope bogdan.pricope@linaro.org Date: Thu Mar 22 08:51:27 2018 +0200
linux-gen: pktio: dpdk: fix IPv4 csum calculation when l4 offset is not set
IPv4 header contains length of the header and options in IHL field. It can be used to replace L3 length calculation based on offsets. This patch fixes bug: https://bugs.linaro.org/show_bug.cgi?id=3686.
Signed-off-by: Bogdan Pricope bogdan.pricope@linaro.org Reviewed-and-tested-by: Matias Elo matias.elo@nokia.com Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index 83dbec4f..d40ad954 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -656,11 +656,7 @@ static inline void pkt_set_ol_tx(odp_pktout_config_opt_t *pktout_cfg, if (!ipv4_chksum_pkt && !udp_chksum_pkt && !tcp_chksum_pkt) return;
- if (pkt_p->l4_offset == ODP_PACKET_OFFSET_INVALID) - return; - mbuf->l2_len = pkt_p->l3_offset - pkt_p->l2_offset; - mbuf->l3_len = pkt_p->l4_offset - pkt_p->l3_offset;
if (l3_proto_v4) mbuf->ol_flags = PKT_TX_IPV4; @@ -671,8 +667,14 @@ static inline void pkt_set_ol_tx(odp_pktout_config_opt_t *pktout_cfg, mbuf->ol_flags |= PKT_TX_IP_CKSUM;
((struct ipv4_hdr *)l3_hdr)->hdr_checksum = 0; + mbuf->l3_len = _ODP_IPV4HDR_IHL(*(uint8_t *)l3_hdr) * 4; }
+ if (pkt_p->l4_offset == ODP_PACKET_OFFSET_INVALID) + return; + + mbuf->l3_len = pkt_p->l4_offset - pkt_p->l3_offset; + l4_hdr = (void *)(mbuf_data + pkt_p->l4_offset);
if (udp_chksum_pkt) {
commit 72febbae5ea55a5fd051978fbfa0f669cf0e99fc Author: Bogdan Pricope bogdan.pricope@linaro.org Date: Thu Mar 22 16:57:49 2018 +0200
linux-gen: pktio: dpdk: accept UDPv4 packets with all-zero csum
Accept IPv4 UDP packets with all-zero checksum field even if DPDK reported it as bad checksum value. This patch fixes bug: https://bugs.linaro.org/show_bug.cgi?id=3685.
Signed-off-by: Bogdan Pricope bogdan.pricope@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index 7b9fed72..83dbec4f 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -27,6 +27,7 @@ #include <odp_libconfig_internal.h>
#include <protocols/eth.h> +#include <protocols/udp.h>
#include <rte_config.h> #include <rte_malloc.h> @@ -419,6 +420,7 @@ MEMPOOL_REGISTER_OPS(ops_stack); #define IP4_CSUM_RESULT(m) (m->ol_flags & PKT_RX_IP_CKSUM_MASK) #define L4_CSUM_RESULT(m) (m->ol_flags & PKT_RX_L4_CKSUM_MASK) #define HAS_L4_PROTO(m, proto) ((m->packet_type & RTE_PTYPE_L4_MASK) == proto) +#define UDP4_CSUM(_p) (((_odp_udphdr_t *)_odp_packet_l4_ptr(_p, NULL))->chksum)
#define PKTIN_CSUM_BITS 0x1C
@@ -451,6 +453,12 @@ static inline int pkt_set_ol_rx(odp_pktin_config_opt_t *pktin_cfg, if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) { pkt_hdr->p.input_flags.l4_chksum_done = 1; } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) { + if (pkt_hdr->p.input_flags.ipv4 && + pkt_hdr->p.input_flags.udp && + !UDP4_CSUM(packet_handle(pkt_hdr))) { + pkt_hdr->p.input_flags.l4_chksum_done = 1; + return 0; + } if (pktin_cfg->bit.drop_udp_err) return -1;
commit f80f28c4046b650c180bcb9b41c859c0c8e2564e Author: Petri Savolainen petri.savolainen@linaro.org Date: Thu Mar 15 16:43:55 2018 +0200
test: sched_pktio: new scheduler performance test with pktio
Added new test which can be used to test scheduler performance with packet IO. Future development includes multiple application pipeline stages through queues.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/performance/.gitignore b/test/performance/.gitignore index 72035e00..259f690c 100644 --- a/test/performance/.gitignore +++ b/test/performance/.gitignore @@ -7,4 +7,5 @@ odp_l2fwd odp_pktio_ordered odp_pktio_perf odp_sched_latency +odp_sched_pktio odp_scheduling diff --git a/test/performance/Makefile.am b/test/performance/Makefile.am index e50c840b..458c8fb0 100644 --- a/test/performance/Makefile.am +++ b/test/performance/Makefile.am @@ -9,6 +9,7 @@ EXECUTABLES = odp_bench_packet \ COMPILE_ONLY = odp_l2fwd \ odp_pktio_ordered \ odp_sched_latency \ + odp_sched_pktio \ odp_scheduling
TESTSCRIPTS = odp_l2fwd_run.sh \ @@ -31,6 +32,7 @@ odp_bench_packet_SOURCES = odp_bench_packet.c odp_crypto_SOURCES = odp_crypto.c odp_pktio_ordered_SOURCES = odp_pktio_ordered.c dummy_crc.h odp_sched_latency_SOURCES = odp_sched_latency.c +odp_sched_pktio_SOURCES = odp_sched_pktio.c odp_scheduling_SOURCES = odp_scheduling.c odp_pktio_perf_SOURCES = odp_pktio_perf.c
diff --git a/test/performance/odp_sched_pktio.c b/test/performance/odp_sched_pktio.c new file mode 100644 index 00000000..cf6e17f4 --- /dev/null +++ b/test/performance/odp_sched_pktio.c @@ -0,0 +1,722 @@ +/* Copyright (c) 2018, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <stdlib.h> + +#include <odp_api.h> +#include <odp/helper/odph_api.h> + +#define MAX_WORKERS 64 +#define MAX_PKTIOS 32 +#define MAX_PKTIO_NAME 31 +#define MAX_PKTIO_QUEUES MAX_WORKERS +#define MAX_PKT_LEN 1514 +#define MAX_PKT_NUM (16 * 1024) +#define MIN_PKT_SEG_LEN 64 +#define BURST_SIZE 32 +#define CHECK_PERIOD 10000 +#define MAX_PKTIO_INDEXES 256 + +typedef struct { + int worker_id; + void *test_global_ptr; +} worker_arg_t; + +typedef struct { + volatile int stop_workers; + odp_barrier_t worker_start; + + struct { + int num_worker; + int num_pktio; + } opt; + + int max_workers; + odp_cpumask_t cpumask; + odp_instance_t instance; + + int worker_cpu[MAX_WORKERS]; + + odp_pool_t pool; + uint32_t pkt_len; + uint32_t pkt_num; + + unsigned int num_input_queues; + unsigned int num_output_queues; + + struct { + char name[MAX_PKTIO_NAME + 1]; + odp_pktio_t pktio; + int pktio_index; + int started; + odph_ethaddr_t my_addr; + odp_queue_t input_queue[MAX_PKTIO_QUEUES]; + odp_pktout_queue_t pktout[MAX_PKTIO_QUEUES]; + + } pktio[MAX_PKTIOS]; + + worker_arg_t worker_arg[MAX_WORKERS]; + + /* Maps pktio input index to pktio[] index for output */ + uint8_t pktio_map[MAX_PKTIO_INDEXES]; + +} test_global_t; + +static test_global_t *test_global; + +static inline void set_dst_eth_addr(odph_ethaddr_t *eth_addr, int index) +{ + eth_addr->addr[0] = 0x02; + eth_addr->addr[1] = 0; + eth_addr->addr[2] = 0; + eth_addr->addr[3] = 0; + eth_addr->addr[4] = 0; + eth_addr->addr[5] = index; +} + +static inline void fill_eth_addr(odp_packet_t pkt[], int num, + test_global_t *test_global, int out) +{ + odph_ethhdr_t *eth; + int i; + + for (i = 0; i < num; ++i) { + eth = odp_packet_data(pkt[i]); + + eth->src = test_global->pktio[out].my_addr; + set_dst_eth_addr(ð->dst, out); + } +} + +static int worker_thread(void *arg) +{ + odp_event_t ev[BURST_SIZE]; + int num, sent, drop, in, out; + odp_pktout_queue_t pktout; + worker_arg_t *worker_arg = arg; + test_global_t *test_global = worker_arg->test_global_ptr; + int worker_id = worker_arg->worker_id; + uint32_t polls = 0; + + printf("Worker %i started\n", worker_id); + + /* Wait for other workers to start */ + odp_barrier_wait(&test_global->worker_start); + + while (1) { + odp_packet_t pkt[BURST_SIZE]; + + num = odp_schedule_multi(NULL, ODP_SCHED_NO_WAIT, + ev, BURST_SIZE); + + polls++; + + if (polls == CHECK_PERIOD) { + polls = 0; + if (test_global->stop_workers) + break; + } + + if (num <= 0) + continue; + + odp_packet_from_event_multi(pkt, ev, num); + + in = odp_packet_input_index(pkt[0]); + out = test_global->pktio_map[in]; + pktout = test_global->pktio[out].pktout[worker_id]; + + fill_eth_addr(pkt, num, test_global, out); + + sent = odp_pktout_send(pktout, pkt, num); + + if (odp_unlikely(sent < 0)) + sent = 0; + + drop = num - sent; + + if (odp_unlikely(drop)) + odp_packet_free_multi(&pkt[sent], drop); + } + + printf("Worker %i stopped\n", worker_id); + + return 0; +} + +static void sig_handler(int signo) +{ + (void)signo; + + if (test_global) { + test_global->stop_workers = 1; + odp_mb_full(); + } +} + +/* Get rid of path in filename - only for unix-type paths using '/' */ +#define NO_PATH(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x)) + +static void print_usage(const char *progname) +{ + printf("\n" + "Scheduler with packet IO test application.\n" + "\n" + "Usage: %s [options]\n" + "\n" + "OPTIONS:\n" + " -i, --interface <name> Packet IO interfaces (comma-separated, no spaces)\n" + " -c, --count Worker thread count. Default: 1\n" + " -h, --help Display help and exit.\n\n", + NO_PATH(progname)); +} + +static int parse_options(int argc, char *argv[], test_global_t *test_global) +{ + int i, opt, long_index; + char *name, *str; + int len, str_len; + const struct option longopts[] = { + {"interface", required_argument, NULL, 'i'}, + {"count", required_argument, NULL, 'c'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + const char *shortopts = "+i:c:h"; + int ret = 0; + + test_global->opt.num_worker = 1; + + /* let helper collect its own arguments (e.g. --odph_proc) */ + odph_parse_options(argc, argv, shortopts, longopts); + + while (1) { + opt = getopt_long(argc, argv, shortopts, longopts, &long_index); + + if (opt == -1) + break; /* No more options */ + + switch (opt) { + case 'i': + i = 0; + str = optarg; + str_len = strlen(str); + + while (str_len > 0) { + len = strcspn(str, ","); + str_len -= len + 1; + + if (i == MAX_PKTIOS) { + printf("Error: Too many interfaces\n"); + ret = -1; + break; + } + + if (len > MAX_PKTIO_NAME) { + printf("Error: Too long interface name %s\n", + str); + ret = -1; + break; + } + + name = test_global->pktio[i].name; + memcpy(name, str, len); + str += len + 1; + i++; + } + + test_global->opt.num_pktio = i; + + break; + case 'c': + test_global->opt.num_worker = atoi(optarg); + break; + case 'h': + print_usage(argv[0]); + ret = -1; + break; + default: + ret = -1; + break; + } + } + + return ret; +} + +static int config_setup(test_global_t *test_global) +{ + int i, cpu; + odp_pool_capability_t pool_capa; + uint32_t pkt_len, pkt_num; + odp_cpumask_t *cpumask = &test_global->cpumask; + + test_global->max_workers = odp_cpumask_default_worker(cpumask, 0); + + if (test_global->opt.num_worker > test_global->max_workers || + test_global->opt.num_worker > MAX_WORKERS) { + printf("Error: Too many workers %i.\n", + test_global->opt.num_worker); + return -1; + } + + cpu = odp_cpumask_first(cpumask); + for (i = 0; i < test_global->opt.num_worker; ++i) { + test_global->worker_cpu[i] = cpu; + cpu = odp_cpumask_next(cpumask, cpu); + } + + if (test_global->opt.num_pktio == 0) { + printf("Error: At least one pktio interface needed.\n"); + return -1; + } + + if (MAX_PKTIO_INDEXES <= odp_pktio_max_index()) { + printf("Error: Larger pktio_map[] table needed: %u\n", + odp_pktio_max_index()); + return -1; + } + + if (odp_pool_capability(&pool_capa)) { + printf("Error: Pool capability failed.\n"); + return -1; + } + + pkt_len = MAX_PKT_LEN; + pkt_num = MAX_PKT_NUM; + + if (pool_capa.pkt.max_len && pkt_len > pool_capa.pkt.max_len) + pkt_len = pool_capa.pkt.max_len; + + if (pool_capa.pkt.max_num && pkt_num > pool_capa.pkt.max_num) + pkt_num = pool_capa.pkt.max_num; + + test_global->pkt_len = pkt_len; + test_global->pkt_num = pkt_num; + + if (test_global->num_input_queues == 0) + test_global->num_input_queues = test_global->opt.num_worker; + + if (test_global->num_output_queues == 0) + test_global->num_output_queues = test_global->opt.num_worker; + + return 0; +} + +static void print_config(test_global_t *test_global) +{ + char cpumask_str[ODP_CPUMASK_STR_SIZE]; + int i; + + odp_cpumask_to_str(&test_global->cpumask, cpumask_str, + ODP_CPUMASK_STR_SIZE); + + printf("\n" + "Test configuration:\n" + " max workers: %i\n" + " available worker cpus: %s\n" + " num workers: %i\n" + " worker cpus: ", + test_global->max_workers, + cpumask_str, + test_global->opt.num_worker); + + for (i = 0; i < test_global->opt.num_worker; i++) + printf(" %i", test_global->worker_cpu[i]); + + printf("\n" + " num interfaces: %i\n" + " interface names: ", test_global->opt.num_pktio); + + for (i = 0; i < test_global->opt.num_pktio; i++) + printf(" %s", test_global->pktio[i].name); + + printf("\n" + " num input queues: %i\n" + " num output queues: %i\n", + test_global->num_input_queues, test_global->num_output_queues); + + printf("\n"); +} + +static int open_pktios(test_global_t *test_global) +{ + odp_pool_param_t pool_param; + odp_pktio_param_t pktio_param; + odp_pool_t pool; + odp_pktio_t pktio; + odp_pktio_capability_t pktio_capa; + odp_pktio_config_t pktio_config; + odp_pktin_queue_param_t pktin_param; + odp_pktout_queue_param_t pktout_param; + odp_schedule_sync_t sched_sync; + unsigned int num_input, num_output; + char *name; + int i, num_pktio, ret; + + num_pktio = test_global->opt.num_pktio; + num_input = test_global->num_input_queues; + num_output = test_global->num_output_queues; + + odp_pool_param_init(&pool_param); + pool_param.pkt.seg_len = MIN_PKT_SEG_LEN; + pool_param.pkt.len = test_global->pkt_len; + pool_param.pkt.num = test_global->pkt_num; + pool_param.type = ODP_POOL_PACKET; + + pool = odp_pool_create("packet pool", &pool_param); + + test_global->pool = pool; + + if (pool == ODP_POOL_INVALID) { + printf("Error: Pool create.\n"); + return -1; + } + + odp_pktio_param_init(&pktio_param); + pktio_param.in_mode = ODP_PKTIN_MODE_SCHED; + pktio_param.out_mode = ODP_PKTOUT_MODE_DIRECT; + + sched_sync = ODP_SCHED_SYNC_ATOMIC; + + for (i = 0; i < num_pktio; i++) + test_global->pktio[i].pktio = ODP_PKTIO_INVALID; + + /* Open and configure interfaces */ + for (i = 0; i < num_pktio; i++) { + name = test_global->pktio[i].name; + pktio = odp_pktio_open(name, pool, &pktio_param); + + if (pktio == ODP_PKTIO_INVALID) { + printf("Error (%s): Pktio open failed.\n", name); + return -1; + } + + test_global->pktio[i].pktio = pktio; + test_global->pktio[i].pktio_index = odp_pktio_index(pktio); + + ret = odp_pktio_mac_addr(pktio, + test_global->pktio[i].my_addr.addr, + ODPH_ETHADDR_LEN); + if (ret != ODPH_ETHADDR_LEN) { + printf("Error (%s): Bad MAC address len.\n", name); + return -1; + } + + odp_pktio_print(pktio); + + if (odp_pktio_capability(pktio, &pktio_capa)) { + printf("Error (%s): Pktio capa failed.\n", name); + return -1; + } + + if (num_input > pktio_capa.max_input_queues) { + printf("Error (%s): Too many input queues: %u\n", + name, num_input); + return -1; + } + + if (num_output > pktio_capa.max_output_queues) { + printf("Error (%s): Too many output queues: %u\n", + name, num_output); + return -1; + } + + odp_pktio_config_init(&pktio_config); + pktio_config.parser.layer = ODP_PROTO_LAYER_NONE; + + odp_pktio_config(pktio, &pktio_config); + + odp_pktin_queue_param_init(&pktin_param); + + pktin_param.queue_param.sched.prio = ODP_SCHED_PRIO_DEFAULT; + pktin_param.queue_param.sched.sync = sched_sync; + pktin_param.queue_param.sched.group = ODP_SCHED_GROUP_ALL; + + if (num_input > 1) { + pktin_param.hash_enable = 1; + pktin_param.hash_proto.proto.ipv4_udp = 1; + } + + pktin_param.num_queues = num_input; + + if (odp_pktin_queue_config(pktio, &pktin_param)) { + printf("Error (%s): Pktin config failed.\n", name); + return -1; + } + + if (odp_pktin_event_queue(pktio, + test_global->pktio[i].input_queue, + num_input) != (int)num_input) { + printf("Error (%s): Input queue query failed.\n", name); + return -1; + } + + odp_pktout_queue_param_init(&pktout_param); + pktout_param.num_queues = num_output; + pktout_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE; + + if (odp_pktout_queue_config(pktio, &pktout_param)) { + printf("Error (%s): Pktout config failed.\n", name); + return -1; + } + + if (odp_pktout_queue(pktio, + test_global->pktio[i].pktout, + num_output) != (int)num_output) { + printf("Error (%s): Output queue query failed.\n", + name); + return -1; + } + } + + return 0; +} + +static void link_pktios(test_global_t *test_global) +{ + int i, num_pktio, input, output; + + num_pktio = test_global->opt.num_pktio; + + printf("Forwarding table (pktio indexes)\n"); + + /* If single interface loopback, otherwise forward to the next + * interface. */ + for (i = 0; i < num_pktio; i++) { + input = test_global->pktio[i].pktio_index; + output = (i + 1) % num_pktio; + test_global->pktio_map[input] = output; + printf(" input %i, output %i\n", + input, + test_global->pktio[output].pktio_index); + } + + printf("\n"); +} + +static int start_pktios(test_global_t *test_global) +{ + int i; + + for (i = 0; i < test_global->opt.num_pktio; i++) { + if (odp_pktio_start(test_global->pktio[i].pktio)) { + printf("Error (%s): Pktio start failed.\n", + test_global->pktio[i].name); + + return -1; + } + + test_global->pktio[i].started = 1; + } + + return 0; +} + +static int stop_pktios(test_global_t *test_global) +{ + odp_pktio_t pktio; + int i, ret = 0; + + for (i = 0; i < test_global->opt.num_pktio; i++) { + pktio = test_global->pktio[i].pktio; + + if (pktio == ODP_PKTIO_INVALID || + test_global->pktio[i].started == 0) + continue; + + if (odp_pktio_stop(pktio)) { + printf("Error (%s): Pktio stop failed.\n", + test_global->pktio[i].name); + ret = -1; + } + } + + return ret; +} + +static void empty_queues(void) +{ + odp_event_t ev; + uint64_t wait_time = odp_schedule_wait_time(ODP_TIME_SEC_IN_NS / 2); + + /* Drop all events from all queues */ + while (1) { + ev = odp_schedule(NULL, wait_time); + + if (ev == ODP_EVENT_INVALID) + break; + + odp_event_free(ev); + } +} + +static int close_pktios(test_global_t *test_global) +{ + odp_pktio_t pktio; + odp_pool_t pool; + int i, ret = 0; + + for (i = 0; i < test_global->opt.num_pktio; i++) { + pktio = test_global->pktio[i].pktio; + + if (pktio == ODP_PKTIO_INVALID) + continue; + + if (odp_pktio_close(pktio)) { + printf("Error (%s): Pktio close failed.\n", + test_global->pktio[i].name); + ret = -1; + } + } + + pool = test_global->pool; + + if (pool == ODP_POOL_INVALID) + return ret; + + if (odp_pool_destroy(pool)) { + printf("Error: Pool destroy failed.\n"); + ret = -1; + } + + return ret; +} + +static void start_workers(odph_odpthread_t thread[], + test_global_t *test_global) +{ + int i; + odp_cpumask_t cpumask; + odph_odpthread_params_t param; + int num = test_global->opt.num_worker; + + memset(¶m, 0, sizeof(odph_odpthread_params_t)); + param.start = worker_thread; + param.thr_type = ODP_THREAD_WORKER; + param.instance = test_global->instance; + + memset(thread, 0, num * sizeof(odph_odpthread_t)); + + for (i = 0; i < num; i++) { + odp_cpumask_zero(&cpumask); + odp_cpumask_set(&cpumask, test_global->worker_cpu[i]); + test_global->worker_arg[i].worker_id = i; + test_global->worker_arg[i].test_global_ptr = test_global; + param.arg = &test_global->worker_arg[i]; + + odph_odpthreads_create(&thread[i], &cpumask, ¶m); + } +} + +static void wait_workers(odph_odpthread_t thread[], test_global_t *test_global) +{ + int i; + + for (i = 0; i < test_global->opt.num_worker; ++i) + odph_odpthreads_join(&thread[i]); +} + +int main(int argc, char *argv[]) +{ + odp_instance_t instance; + odp_init_t init; + odp_shm_t shm; + odph_odpthread_t thread[MAX_WORKERS]; + + signal(SIGINT, sig_handler); + + /* List features not to be used (may optimize performance) */ + odp_init_param_init(&init); + init.not_used.feat.cls = 1; + init.not_used.feat.crypto = 1; + init.not_used.feat.ipsec = 1; + init.not_used.feat.timer = 1; + init.not_used.feat.tm = 1; + + /* Init ODP before calling anything else */ + if (odp_init_global(&instance, &init, NULL)) { + printf("Error: Global init failed.\n"); + return -1; + } + + /* Init this thread */ + if (odp_init_local(instance, ODP_THREAD_CONTROL)) { + printf("Error: Local init failed.\n"); + return -1; + } + + /* Reserve memory for args from shared mem */ + shm = odp_shm_reserve("test_global", sizeof(test_global_t), + ODP_CACHE_LINE_SIZE, 0); + + if (shm == ODP_SHM_INVALID) { + printf("Error: shm reserve failed.\n"); + return -1; + } + + test_global = odp_shm_addr(shm); + memset(test_global, 0, sizeof(test_global_t)); + + test_global->instance = instance; + test_global->pool = ODP_POOL_INVALID; + + if (parse_options(argc, argv, test_global)) + goto quit; + + odp_sys_info_print(); + + if (config_setup(test_global)) + goto quit; + + print_config(test_global); + + if (open_pktios(test_global)) + goto quit; + + link_pktios(test_global); + + odp_barrier_init(&test_global->worker_start, + test_global->opt.num_worker + 1); + + start_workers(thread, test_global); + + /* Synchronize pktio configuration with workers. Worker are now ready + * to process packets. */ + odp_barrier_wait(&test_global->worker_start); + + if (start_pktios(test_global)) { + test_global->stop_workers = 1; + odp_mb_full(); + } + + wait_workers(thread, test_global); + +quit: + stop_pktios(test_global); + empty_queues(); + close_pktios(test_global); + + if (odp_shm_free(shm)) { + printf("Error: shm free failed.\n"); + return -1; + } + + if (odp_term_local()) { + printf("Error: term local failed.\n"); + return -1; + } + + if (odp_term_global(instance)) { + printf("Error: term global failed.\n"); + return -1; + } + + return 0; +}
commit b08aa94548163ae4d4bac2724e68ca9102667f6a Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Mar 16 11:37:20 2018 +0200
linux-gen: pktio: add index to pktio print
Print also pktio index. It is often more useful information to the user than handle (which may be e.g. a pointer).
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index 5b019579..bf7aef14 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -1169,13 +1169,15 @@ void odp_pktio_print(odp_pktio_t hdl)
len += snprintf(&str[len], n - len, "pktio\n"); - len += snprintf(&str[len], n - len, - " handle %" PRIu64 "\n", - odp_pktio_to_u64(hdl)); len += snprintf(&str[len], n - len, " name %s\n", entry->s.name); len += snprintf(&str[len], n - len, " type %s\n", entry->s.ops->name); + len += snprintf(&str[len], n - len, + " index %i\n", _odp_pktio_index(hdl)); + len += snprintf(&str[len], n - len, + " handle (u64) %" PRIu64 "\n", + odp_pktio_to_u64(hdl)); len += snprintf(&str[len], n - len, " state %s\n", entry->s.state == PKTIO_STATE_STARTED ? "start" :
commit 4aacfd4d72b80a22d449d865a6c4f063afa823ab Author: Petri Savolainen petri.savolainen@linaro.org Date: Thu Mar 15 16:47:09 2018 +0200
linux-gen: pktio: add error prints
Added error prints for failures due to a bad handle.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index 56e9f686..5b019579 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -376,8 +376,10 @@ int odp_pktio_close(odp_pktio_t hdl) int res;
entry = get_pktio_entry(hdl); - if (entry == NULL) + if (entry == NULL) { + ODP_ERR("Bad handle\n"); return -1; + }
if (entry->s.state == PKTIO_STATE_STARTED) { ODP_DBG("Missing odp_pktio_stop() before close.\n"); @@ -416,8 +418,10 @@ int odp_pktio_config(odp_pktio_t hdl, const odp_pktio_config_t *config) int res = 0;
entry = get_pktio_entry(hdl); - if (!entry) + if (!entry) { + ODP_ERR("Bad handle\n"); return -1; + }
if (config == NULL) { odp_pktio_config_init(&default_config); @@ -466,12 +470,15 @@ int odp_pktio_start(odp_pktio_t hdl) int res = 0;
entry = get_pktio_entry(hdl); - if (!entry) + if (!entry) { + ODP_ERR("Bad handle\n"); return -1; + }
lock_entry(entry); if (entry->s.state == PKTIO_STATE_STARTED) { unlock_entry(entry); + ODP_ERR("Already started\n"); return -1; } if (entry->s.ops->start) @@ -513,8 +520,10 @@ static int _pktio_stop(pktio_entry_t *entry) int res = 0; odp_pktin_mode_t mode = entry->s.param.in_mode;
- if (entry->s.state != PKTIO_STATE_STARTED) + if (entry->s.state != PKTIO_STATE_STARTED) { + ODP_ERR("Not started\n"); return -1; + }
if (entry->s.ops->stop) res = entry->s.ops->stop(entry); @@ -536,8 +545,10 @@ int odp_pktio_stop(odp_pktio_t hdl) int res;
entry = get_pktio_entry(hdl); - if (!entry) + if (!entry) { + ODP_ERR("Bad handle\n"); return -1; + }
lock_entry(entry); res = _pktio_stop(entry);
commit 71ca38c00c11ebb6b4dede6d09ebdd28eb45d890 Author: Matias Elo matias.elo@nokia.com Date: Tue Mar 13 08:44:50 2018 +0200
linux-gen: dpdk: bump supported dpdk version to v17.11
Bump supported DPDK version to LTS version 17.11. Also adds dependecies for optional Mellanox PMD drivers.
Signed-off-by: Matias Elo matias.elo@nokia.com Reviewed-by: Bogdan Pricope bogdan.pricope@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/.travis.yml b/.travis.yml index 1f5ef42e..2f47ed79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,7 +49,7 @@ env: # for individual commit validation. But you you want to track tests history # you need generated new one at https://codecov.io specific for your repo. - CODECOV_TOKEN=a733c34c-5f5c-4ff1-af4b-e9f5edb1ab5e - - DPDK_VERS="17.08" + - DPDK_VERS="17.11" matrix: - CONF="" - CONF="--disable-abi-compat" @@ -59,8 +59,6 @@ env: - CONF="--disable-host-optimization" - CONF="--disable-host-optimization --disable-abi-compat" - DPDK_SHARED="y" CONF="--disable-static-applications" - - DPDK_VERS="17.11" CONF="" - - DPDK_VERS="17.11" DPDK_SHARED="y" CONF="--disable-static-applications"
compiler: - gcc @@ -196,7 +194,7 @@ install: fi DPDK_TARGET="${DPDK_TARGET}gcc" if [ ! -f "dpdk/${TARGET}/usr/local/lib/libdpdk.$LIBDPDKEXT" ]; then - git -c advice.detachedHead=false clone -q --depth=1 --single-branch --branch=v${DPDK_VERS} http://dpdk.org/git/dpdk dpdk + git -c advice.detachedHead=false clone -q --depth=1 --single-branch --branch=${DPDK_VERS} http://dpdk.org/git/dpdk-stable dpdk pushd dpdk git log --oneline --decorate # AArch64 && ARMv7 fixup @@ -207,6 +205,10 @@ install: make config T=${DPDK_TARGET} O=${TARGET} pushd ${TARGET} sed -ri 's,(CONFIG_RTE_LIBRTE_PMD_PCAP=).*,\1y,' .config + # OCTEON TX driver includes ARM v8.1 instructions + sed -ri 's,(CONFIG_RTE_LIBRTE_OCTEONTX_PMD=).*,\1n,' .config + sed -ri 's,(CONFIG_RTE_LIBRTE_PMD_OCTEONTX_SSOVF=).*,\1n,' .config + sed -ri 's,(CONFIG_RTE_LIBRTE_OCTEONTX_MEMPOOL=).*,\1n,' .config if test -n "${DPDK_MACHINE}" ; then sed -ri 's,(CONFIG_RTE_MACHINE=).*,\1"'${DPDK_MACHINE}'",' .config fi diff --git a/DEPENDENCIES b/DEPENDENCIES index 2cd8ccb4..f328e787 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -174,7 +174,7 @@ Prerequisites for building the OpenDataPlane (ODP) API
3.4.1 Building DPDK and ODP with DPDK pktio support
- DPDK packet I/O has been tested to work with DPDK v17.08. + DPDK packet I/O has been tested to work with DPDK v17.11.
Follow steps in ./scripts/build-pktio-dpdk
diff --git a/m4/odp_dpdk.m4 b/m4/odp_dpdk.m4 index b94c9b55..dccc6569 100644 --- a/m4/odp_dpdk.m4 +++ b/m4/odp_dpdk.m4 @@ -9,6 +9,8 @@ cur_driver=`basename "$filename" .a | sed -e 's/^lib//'` AS_VAR_APPEND([DPDK_PMDS], [-l$cur_driver,]) AS_CASE([$cur_driver], [rte_pmd_nfp], [AS_VAR_APPEND([DPDK_LIBS], [" -lm"])], + [rte_pmd_mlx4], [AS_VAR_APPEND([DPDK_LIBS], [" -lmlx4 -libverbs"])], + [rte_pmd_mlx5], [AS_VAR_APPEND([DPDK_LIBS], [" -lmlx5 -libverbs"])], [rte_pmd_pcap], [AS_VAR_APPEND([DPDK_LIBS], [" -lpcap"])], [rte_pmd_openssl], [AS_VAR_APPEND([DPDK_LIBS], [" -lcrypto"])]) done diff --git a/scripts/build-pktio-dpdk b/scripts/build-pktio-dpdk index 26afd97c..b0c0a4d0 100755 --- a/scripts/build-pktio-dpdk +++ b/scripts/build-pktio-dpdk @@ -16,7 +16,7 @@ if [ "$?" != "0" ]; then exit 1 fi
-git -c advice.detachedHead=false clone -q --depth=1 --single-branch --branch=v17.08 http://dpdk.org/git/dpdk dpdk +git -c advice.detachedHead=false clone -q --depth=1 --single-branch --branch=17.11 http://dpdk.org/git/dpdk-stable dpdk pushd dpdk git log --oneline --decorate
commit 7e0c523ad6f209f238277e4116c21ba696edb7f4 Author: Petri Savolainen petri.savolainen@linaro.org Date: Mon Mar 12 17:05:32 2018 +0200
linux-gen: sched: increase max spread
Allow user to configure larger than the default spread value.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c index 3bcafdb4..b50462a5 100644 --- a/platform/linux-generic/odp_schedule_basic.c +++ b/platform/linux-generic/odp_schedule_basic.c @@ -46,7 +46,7 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) && #define GRP_WEIGHT_TBL_SIZE NUM_SCHED_GRPS
/* Maximum priority queue spread */ -#define MAX_SPREAD 4 +#define MAX_SPREAD 8
/* Minimum priority queue spread */ #define MIN_SPREAD 1
commit 12d238d96318cc9d46dd5a2893894824a633805b Author: Petri Savolainen petri.savolainen@linaro.org Date: Mon Mar 12 16:54:41 2018 +0200
linux-gen: sched: decouple spread and group table sizes
Only thing common between these tables were the shared round counter. With separate counters, tables can have different sizes. Especially, spread table size needs to be increased and support also sizes not power of two (configurable spread values).
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c index e6d28c6d..3bcafdb4 100644 --- a/platform/linux-generic/odp_schedule_basic.c +++ b/platform/linux-generic/odp_schedule_basic.c @@ -42,6 +42,9 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) && /* Number of scheduling groups */ #define NUM_SCHED_GRPS 32
+/* Group weight table size */ +#define GRP_WEIGHT_TBL_SIZE NUM_SCHED_GRPS + /* Maximum priority queue spread */ #define MAX_SPREAD 4
@@ -52,8 +55,8 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) && * of the prefer queue. */ #define PREFER_RATIO 64
-/* Size of poll weight table */ -#define WEIGHT_TBL_SIZE ((MAX_SPREAD - 1) * PREFER_RATIO) +/* Spread weight table */ +#define SPREAD_TBL_SIZE ((MAX_SPREAD - 1) * PREFER_RATIO)
/* Maximum number of packet IO interfaces */ #define NUM_PKTIO ODP_CONFIG_PKTIO_ENTRIES @@ -116,17 +119,18 @@ typedef struct { int thr; uint16_t stash_num; uint16_t stash_index; - uint16_t pause; - uint16_t round; + uint16_t grp_round; + uint16_t spread_round; uint32_t stash_qi; odp_queue_t stash_queue; odp_event_t stash_ev[MAX_DEQ];
uint32_t grp_epoch; - int num_grp; + uint16_t num_grp; + uint16_t pause; uint8_t grp[NUM_SCHED_GRPS]; - uint8_t weight_tbl[WEIGHT_TBL_SIZE]; - uint8_t grp_weight[WEIGHT_TBL_SIZE]; + uint8_t spread_tbl[SPREAD_TBL_SIZE]; + uint8_t grp_weight[GRP_WEIGHT_TBL_SIZE];
struct { /* Source queue index */ @@ -182,6 +186,7 @@ typedef struct { odp_spinlock_t grp_lock; odp_atomic_u32_t grp_epoch; uint32_t ring_mask; + uint16_t max_spread;
struct { char name[ODP_SCHED_GROUP_NAME_LEN]; @@ -216,6 +221,7 @@ ODP_STATIC_ASSERT(MAX_SPREAD <= 256, "Spread_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"); +ODP_STATIC_ASSERT(CHECK_IS_POWER2(GRP_WEIGHT_TBL_SIZE), "Not_power_of_2");
/* Global scheduler context */ static sched_global_t *sched; @@ -271,11 +277,11 @@ static void sched_local_init(void)
spread = prio_spread_index(sched_local.thr);
- for (i = 0; i < WEIGHT_TBL_SIZE; i++) { - sched_local.weight_tbl[i] = spread; + for (i = 0; i < SPREAD_TBL_SIZE; i++) { + sched_local.spread_tbl[i] = spread;
if (num_spread > 1 && (i % PREFER_RATIO) == 0) { - sched_local.weight_tbl[i] = prio_spread_index(spread + + sched_local.spread_tbl[i] = prio_spread_index(spread + offset); offset++; if (offset == num_spread) @@ -309,6 +315,8 @@ static int schedule_init_global(void) return -1; }
+ /* When num_spread == 1, only spread_tbl[0] is used. */ + sched->max_spread = (sched->config.num_spread - 1) * PREFER_RATIO; sched->shm = shm; odp_spinlock_init(&sched->mask_lock);
@@ -442,7 +450,7 @@ static inline int grp_update_tbl(void) odp_spinlock_unlock(&sched->grp_lock);
/* Update group weights. Round robin over all thread's groups. */ - for (i = 0; i < WEIGHT_TBL_SIZE; i++) + for (i = 0; i < GRP_WEIGHT_TBL_SIZE; i++) sched_local.grp_weight[i] = i % num;
sched_local.num_grp = num; @@ -961,7 +969,7 @@ static inline int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], int i, num_grp; int ret; int first, grp_id; - uint16_t round; + uint16_t spread_round, grp_round; uint32_t epoch;
if (sched_local.stash_num) { @@ -978,15 +986,17 @@ static inline int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], if (odp_unlikely(sched_local.pause)) return 0;
- /* Each thread prefers a priority queue. Poll weight table avoids + /* Each thread prefers a priority queue. Spread weight table avoids * starvation of other priority queues on low thread counts. */ - round = sched_local.round + 1; + spread_round = sched_local.spread_round; + grp_round = (sched_local.grp_round++) & (GRP_WEIGHT_TBL_SIZE - 1);
- if (odp_unlikely(round == WEIGHT_TBL_SIZE)) - round = 0; + if (odp_unlikely(spread_round + 1 >= sched->max_spread)) + sched_local.spread_round = 0; + else + sched_local.spread_round = spread_round + 1;
- sched_local.round = round; - first = sched_local.weight_tbl[round]; + first = sched_local.spread_tbl[spread_round];
epoch = odp_atomic_load_acq_u32(&sched->grp_epoch); num_grp = sched_local.num_grp; @@ -996,7 +1006,7 @@ static inline int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], sched_local.grp_epoch = epoch; }
- grp_id = sched_local.grp_weight[round]; + grp_id = sched_local.grp_weight[grp_round];
/* Schedule queues per group and priority */ for (i = 0; i < num_grp; i++) {
commit bcd246e3a9948a631eb8eb77886ac1b369b13dba Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Mar 9 16:49:48 2018 +0200
linux-gen: sched: configurable priority spread
Use configuration file to enable user to change priority queue spreading.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf index 91605886..0034c64b 100644 --- a/config/odp-linux-generic.conf +++ b/config/odp-linux-generic.conf @@ -38,3 +38,12 @@ queue_basic: { # Default queue size. Value must be a power of two. default_queue_size = 4096 } + +sched_basic: { + # Priority level spread. Each priority level is spread into multiple + # scheduler internal queues. A higher spread value typically improves + # parallelism and thus is better for high thread counts, but causes + # uneven service level for low thread counts. Typically, optimal + # value is the number of threads using the scheduler. + prio_spread = 4 +} diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c index cd20b39d..e6d28c6d 100644 --- a/platform/linux-generic/odp_schedule_basic.c +++ b/platform/linux-generic/odp_schedule_basic.c @@ -27,6 +27,7 @@ #include <odp_timer_internal.h> #include <odp_queue_internal.h> #include <odp_buffer_inlines.h> +#include <odp_libconfig_internal.h>
/* Number of priority levels */ #define NUM_PRIO 8 @@ -41,15 +42,18 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) && /* Number of scheduling groups */ #define NUM_SCHED_GRPS 32
-/* Priority queues per priority */ -#define QUEUES_PER_PRIO 4 +/* Maximum priority queue spread */ +#define MAX_SPREAD 4 + +/* Minimum priority queue spread */ +#define MIN_SPREAD 1
/* A thread polls a non preferred sched queue every this many polls * of the prefer queue. */ #define PREFER_RATIO 64
/* Size of poll weight table */ -#define WEIGHT_TBL_SIZE ((QUEUES_PER_PRIO - 1) * PREFER_RATIO) +#define WEIGHT_TBL_SIZE ((MAX_SPREAD - 1) * PREFER_RATIO)
/* Maximum number of packet IO interfaces */ #define NUM_PKTIO ODP_CONFIG_PKTIO_ENTRIES @@ -60,14 +64,10 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) && /* Not a valid index */ #define NULL_INDEX ((uint32_t)-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 - * queues in the worst case. */ -#define PRIO_QUEUE_RING_SIZE (ODP_CONFIG_QUEUES / QUEUES_PER_PRIO) - -/* Mask for wrapping around priority queue index */ -#define RING_MASK (PRIO_QUEUE_RING_SIZE - 1) +/* Maximum priority queue ring size. A ring must be large enough to store all + * queues in the worst case (all queues are scheduled, have the same priority + * and no spreading). */ +#define MAX_RING_SIZE ODP_CONFIG_QUEUES
/* Priority queue empty, not a valid queue index. */ #define PRIO_QUEUE_EMPTY NULL_INDEX @@ -76,14 +76,14 @@ ODP_STATIC_ASSERT((ODP_SCHED_PRIO_NORMAL > 0) && ODP_STATIC_ASSERT(CHECK_IS_POWER2(ODP_CONFIG_QUEUES), "Number_of_queues_is_not_power_of_two");
-/* Ring size must be power of two, so that MAX_QUEUE_IDX_MASK can be used. */ -ODP_STATIC_ASSERT(CHECK_IS_POWER2(PRIO_QUEUE_RING_SIZE), +/* Ring size must be power of two, so that mask can be used. */ +ODP_STATIC_ASSERT(CHECK_IS_POWER2(MAX_RING_SIZE), "Ring_size_is_not_power_of_two");
/* Mask of queues per priority */ typedef uint8_t pri_mask_t;
-ODP_STATIC_ASSERT((8 * sizeof(pri_mask_t)) >= QUEUES_PER_PRIO, +ODP_STATIC_ASSERT((8 * sizeof(pri_mask_t)) >= MAX_SPREAD, "pri_mask_t_is_too_small");
/* Start of named groups in group mask arrays */ @@ -147,7 +147,7 @@ typedef struct ODP_ALIGNED_CACHE { ring_t ring;
/* Ring data: queue indexes */ - uint32_t queue_index[PRIO_QUEUE_RING_SIZE]; + uint32_t queue_index[MAX_RING_SIZE];
} prio_queue_t;
@@ -168,14 +168,20 @@ typedef struct { pri_mask_t pri_mask[NUM_PRIO]; odp_spinlock_t mask_lock;
- prio_queue_t prio_q[NUM_SCHED_GRPS][NUM_PRIO][QUEUES_PER_PRIO]; + prio_queue_t prio_q[NUM_SCHED_GRPS][NUM_PRIO][MAX_SPREAD];
odp_shm_t shm; - uint32_t pri_count[NUM_PRIO][QUEUES_PER_PRIO]; + + struct { + uint8_t num_spread; + } config; + + uint32_t pri_count[NUM_PRIO][MAX_SPREAD];
odp_thrmask_t mask_all; odp_spinlock_t grp_lock; odp_atomic_u32_t grp_epoch; + uint32_t ring_mask;
struct { char name[ODP_SCHED_GROUP_NAME_LEN]; @@ -186,7 +192,7 @@ typedef struct { struct { uint8_t grp; uint8_t prio; - uint8_t queue_per_prio; + uint8_t spread; uint8_t sync; uint8_t order_lock_count; uint8_t poll_pktin; @@ -206,8 +212,7 @@ typedef struct { /* 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(MAX_SPREAD <= 256, "Spread_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"); @@ -221,11 +226,41 @@ static __thread sched_local_t sched_local; /* Function prototypes */ static inline void schedule_release_context(void);
+static int read_config_file(sched_global_t *sched) +{ + const char *str; + int val = 0; + + ODP_PRINT("Scheduler config:\n"); + + str = "sched_basic.prio_spread"; + if (!_odp_libconfig_lookup_int(str, &val)) { + ODP_ERR("Config option '%s' not found.\n", str); + return -1; + } + + if (val > MAX_SPREAD || val < MIN_SPREAD) { + ODP_ERR("Bad value %s = %u\n", str, val); + return -1; + } + + sched->config.num_spread = val; + ODP_PRINT(" %s: %i\n\n", str, val); + + return 0; +} + +static inline uint8_t prio_spread_index(uint32_t index) +{ + return index % sched->config.num_spread; +} + static void sched_local_init(void) { int i; - uint8_t id; - uint8_t offset = 0; + uint8_t spread; + uint8_t num_spread = sched->config.num_spread; + uint8_t offset = 1;
memset(&sched_local, 0, sizeof(sched_local_t));
@@ -234,17 +269,17 @@ static void sched_local_init(void) sched_local.stash_qi = PRIO_QUEUE_EMPTY; sched_local.ordered.src_queue = NULL_INDEX;
- id = sched_local.thr & (QUEUES_PER_PRIO - 1); + spread = prio_spread_index(sched_local.thr);
for (i = 0; i < WEIGHT_TBL_SIZE; i++) { - sched_local.weight_tbl[i] = id; + sched_local.weight_tbl[i] = spread;
- if (i % PREFER_RATIO == 0) { + if (num_spread > 1 && (i % PREFER_RATIO) == 0) { + sched_local.weight_tbl[i] = prio_spread_index(spread + + offset); offset++; - sched_local.weight_tbl[i] = (id + offset) & - (QUEUES_PER_PRIO - 1); - if (offset == QUEUES_PER_PRIO - 1) - offset = 0; + if (offset == num_spread) + offset = 1; } } } @@ -269,19 +304,24 @@ static int schedule_init_global(void)
memset(sched, 0, sizeof(sched_global_t));
+ if (read_config_file(sched)) { + odp_shm_free(shm); + return -1; + } + sched->shm = shm; odp_spinlock_init(&sched->mask_lock);
for (grp = 0; grp < NUM_SCHED_GRPS; grp++) { for (i = 0; i < NUM_PRIO; i++) { - for (j = 0; j < QUEUES_PER_PRIO; j++) { + for (j = 0; j < MAX_SPREAD; j++) { prio_queue_t *prio_q; int k;
prio_q = &sched->prio_q[grp][i][j]; ring_init(&prio_q->ring);
- for (k = 0; k < PRIO_QUEUE_RING_SIZE; k++) { + for (k = 0; k < MAX_RING_SIZE; k++) { prio_q->queue_index[k] = PRIO_QUEUE_EMPTY; } @@ -322,14 +362,15 @@ static int schedule_term_global(void) int ret = 0; int rc = 0; int i, j, grp; + uint32_t ring_mask = sched->ring_mask;
for (grp = 0; grp < NUM_SCHED_GRPS; grp++) { for (i = 0; i < NUM_PRIO; i++) { - for (j = 0; j < QUEUES_PER_PRIO; j++) { + for (j = 0; j < MAX_SPREAD; j++) { ring_t *ring = &sched->prio_q[grp][i][j].ring; uint32_t qi;
- while ((qi = ring_deq(ring, RING_MASK)) != + while ((qi = ring_deq(ring, ring_mask)) != RING_EMPTY) { odp_event_t events[1]; int num; @@ -413,11 +454,6 @@ static uint32_t schedule_max_ordered_locks(void) return CONFIG_QUEUE_MAX_ORD_LOCKS; }
-static inline int queue_per_prio(uint32_t queue_index) -{ - return ((QUEUES_PER_PRIO - 1) & queue_index); -} - static void pri_set(int id, int prio) { odp_spinlock_lock(&sched->mask_lock); @@ -441,33 +477,39 @@ static void pri_clr(int id, int prio)
static void pri_set_queue(uint32_t queue_index, int prio) { - int id = queue_per_prio(queue_index); + uint8_t id = prio_spread_index(queue_index);
return pri_set(id, prio); }
static void pri_clr_queue(uint32_t queue_index, int prio) { - int id = queue_per_prio(queue_index); + uint8_t id = prio_spread_index(queue_index); pri_clr(id, prio); }
static int schedule_init_queue(uint32_t queue_index, const odp_schedule_param_t *sched_param) { + uint32_t ring_size; int i; int prio = sched_param->prio;
pri_set_queue(queue_index, prio); sched->queue[queue_index].grp = sched_param->group; sched->queue[queue_index].prio = prio; - sched->queue[queue_index].queue_per_prio = queue_per_prio(queue_index); + sched->queue[queue_index].spread = prio_spread_index(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;
+ ring_size = MAX_RING_SIZE / sched->config.num_spread; + ring_size = ROUNDUP_POWER2_U32(ring_size); + ODP_ASSERT(ring_size <= MAX_RING_SIZE); + sched->ring_mask = ring_size - 1; + odp_atomic_init_u64(&sched->order[queue_index].ctx, 0); odp_atomic_init_u64(&sched->order[queue_index].next_ctx, 0);
@@ -492,9 +534,9 @@ static void schedule_destroy_queue(uint32_t queue_index) int prio = sched->queue[queue_index].prio;
pri_clr_queue(queue_index, prio); - sched->queue[queue_index].grp = 0; - sched->queue[queue_index].prio = 0; - sched->queue[queue_index].queue_per_prio = 0; + sched->queue[queue_index].grp = 0; + sched->queue[queue_index].prio = 0; + sched->queue[queue_index].spread = 0;
if (queue_is_ordered(queue_index) && odp_atomic_load_u64(&sched->order[queue_index].ctx) != @@ -504,12 +546,12 @@ static void schedule_destroy_queue(uint32_t queue_index)
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; + int grp = sched->queue[queue_index].grp; + int prio = sched->queue[queue_index].prio; + int spread = sched->queue[queue_index].spread; + ring_t *ring = &sched->prio_q[grp][prio][spread].ring;
- ring_enq(ring, RING_MASK, queue_index); + ring_enq(ring, sched->ring_mask, queue_index); return 0; }
@@ -540,13 +582,14 @@ static void schedule_release_atomic(void) uint32_t qi = sched_local.stash_qi;
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; + int grp = sched->queue[qi].grp; + int prio = sched->queue[qi].prio; + int spread = sched->queue[qi].spread; + ring_t *ring = &sched->prio_q[grp][prio][spread].ring;
/* Release current atomic queue */ - ring_enq(ring, RING_MASK, qi); + ring_enq(ring, sched->ring_mask, qi); + sched_local.stash_qi = PRIO_QUEUE_EMPTY; } } @@ -773,8 +816,10 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], int prio, i; int ret; int id; - unsigned int max_deq = MAX_DEQ; uint32_t qi; + unsigned int max_deq = MAX_DEQ; + int num_spread = sched->config.num_spread; + uint32_t ring_mask = sched->ring_mask;
/* Schedule events */ for (prio = 0; prio < NUM_PRIO; prio++) { @@ -785,14 +830,14 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], /* Select the first ring based on weights */ id = first;
- for (i = 0; i < QUEUES_PER_PRIO;) { + for (i = 0; i < num_spread;) { int num; int ordered; odp_queue_t handle; ring_t *ring; int pktin;
- if (id >= QUEUES_PER_PRIO) + if (id >= num_spread) id = 0;
/* No queues created for this priority queue */ @@ -805,7 +850,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, RING_MASK); + qi = ring_deq(ring, ring_mask);
/* Priority queue empty */ if (qi == RING_EMPTY) { @@ -854,7 +899,7 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], continue;
if (num_pkt == 0 || !stash) { - ring_enq(ring, RING_MASK, qi); + ring_enq(ring, ring_mask, qi); break; }
@@ -880,14 +925,14 @@ 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, RING_MASK, qi); + ring_enq(ring, ring_mask, qi);
} else if (queue_is_atomic(qi)) { /* Hold queue during atomic access */ sched_local.stash_qi = qi; } else { /* Continue scheduling the queue */ - ring_enq(ring, RING_MASK, qi); + ring_enq(ring, ring_mask, qi); }
handle = queue_from_index(qi);
commit c57da8ddc80e0e314957c6d11db288ef11fc1805 Author: Petri Savolainen petri.savolainen@linaro.org Date: Thu Mar 8 14:55:14 2018 +0200
linux-gen: queue: configurable max size
Use configuration file to enable user to change the maximum queue size. Ring memory for all queues is reserved based on the max size.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf index 306ee197..91605886 100644 --- a/config/odp-linux-generic.conf +++ b/config/odp-linux-generic.conf @@ -32,6 +32,9 @@ pktio_dpdk: { }
queue_basic: { + # Maximum queue size. Value must be a power of two. + max_queue_size = 8192 + # Default queue size. Value must be a power of two. default_queue_size = 4096 } diff --git a/platform/linux-generic/include/odp_queue_internal.h b/platform/linux-generic/include/odp_queue_internal.h index 386d804e..98e86fa0 100644 --- a/platform/linux-generic/include/odp_queue_internal.h +++ b/platform/linux-generic/include/odp_queue_internal.h @@ -63,19 +63,17 @@ 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_entry_t queue[ODP_CONFIG_QUEUES]; + uint32_t *ring_data; + uint32_t queue_lf_num; + uint32_t queue_lf_size; + queue_lf_func_t queue_lf_func; + odp_shm_t queue_gbl_shm; + odp_shm_t queue_ring_shm;
struct { + uint32_t max_queue_size; uint32_t default_queue_size; } config;
diff --git a/platform/linux-generic/odp_queue_basic.c b/platform/linux-generic/odp_queue_basic.c index bbd12fe8..89a0cd90 100644 --- a/platform/linux-generic/odp_queue_basic.c +++ b/platform/linux-generic/odp_queue_basic.c @@ -38,7 +38,7 @@ #include <inttypes.h>
#define MIN_QUEUE_SIZE 8 -#define MAX_QUEUE_SIZE CONFIG_QUEUE_SIZE +#define MAX_QUEUE_SIZE (1 * 1024 * 1024)
static int queue_init(queue_entry_t *queue, const char *name, const odp_queue_param_t *param); @@ -64,11 +64,11 @@ static int queue_capa(odp_queue_capability_t *capa, int sched) /* 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 = MAX_QUEUE_SIZE; + capa->plain.max_size = queue_glb->config.max_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 = MAX_QUEUE_SIZE; + capa->sched.max_size = queue_glb->config.max_queue_size;
if (sched) { capa->max_ordered_locks = sched_fn->max_ordered_locks(); @@ -87,7 +87,7 @@ static int read_config_file(queue_global_t *queue_glb)
ODP_PRINT("Queue config:\n");
- str = "queue_basic.default_queue_size"; + str = "queue_basic.max_queue_size"; if (!_odp_libconfig_lookup_int(str, &val)) { ODP_ERR("Config option '%s' not found.\n", str); return -1; @@ -101,6 +101,24 @@ static int read_config_file(queue_global_t *queue_glb) return -1; }
+ queue_glb->config.max_queue_size = val_u32; + ODP_PRINT(" %s: %u\n", str, val_u32); + + str = "queue_basic.default_queue_size"; + if (!_odp_libconfig_lookup_int(str, &val)) { + ODP_ERR("Config option '%s' not found.\n", str); + return -1; + } + + val_u32 = val; + + if (val_u32 > queue_glb->config.max_queue_size || + val_u32 < MIN_QUEUE_SIZE || + !CHECK_IS_POWER2(val_u32)) { + ODP_ERR("Bad value %s = %u\n", str, val_u32); + return -1; + } + queue_glb->config.default_queue_size = val_u32; ODP_PRINT(" %s: %u\n\n", str, val_u32);
@@ -114,10 +132,11 @@ static int queue_init_global(void) uint32_t lf_size = 0; queue_lf_func_t *lf_func; odp_queue_capability_t capa; + uint64_t mem_size;
ODP_DBG("Starts...\n");
- shm = odp_shm_reserve("odp_queues", + shm = odp_shm_reserve("_odp_queue_gbl", sizeof(queue_global_t), sizeof(queue_entry_t), 0);
@@ -141,6 +160,21 @@ static int queue_init_global(void) return -1; }
+ queue_glb->queue_gbl_shm = shm; + mem_size = sizeof(uint32_t) * ODP_CONFIG_QUEUES * + (uint64_t)queue_glb->config.max_queue_size; + + shm = odp_shm_reserve("_odp_queue_rings", mem_size, + ODP_CACHE_LINE_SIZE, 0); + + if (shm == ODP_SHM_INVALID) { + odp_shm_free(queue_glb->queue_gbl_shm); + return -1; + } + + queue_glb->queue_ring_shm = shm; + queue_glb->ring_data = odp_shm_addr(shm); + lf_func = &queue_glb->queue_lf_func; queue_glb->queue_lf_num = queue_lf_init_global(&lf_size, lf_func); queue_glb->queue_lf_size = lf_size; @@ -170,7 +204,6 @@ static int queue_term_local(void) static int queue_term_global(void) { int ret = 0; - int rc = 0; queue_entry_t *queue; int i;
@@ -179,20 +212,24 @@ static int queue_term_global(void) LOCK(queue); if (queue->s.status != QUEUE_STATUS_FREE) { ODP_ERR("Not destroyed queue: %s\n", queue->s.name); - rc = -1; + ret = -1; } UNLOCK(queue); }
queue_lf_term_global();
- ret = odp_shm_free(odp_shm_lookup("odp_queues")); - if (ret < 0) { - ODP_ERR("shm free failed for odp_queues"); - rc = -1; + if (odp_shm_free(queue_glb->queue_ring_shm)) { + ODP_ERR("shm free failed"); + ret = -1; + } + + if (odp_shm_free(queue_glb->queue_gbl_shm)) { + ODP_ERR("shm free failed"); + ret = -1; }
- return rc; + return ret; }
static int queue_capability(odp_queue_capability_t *capa) @@ -244,7 +281,7 @@ static odp_queue_t queue_create(const char *name, }
if (param->nonblocking == ODP_BLOCKING) { - if (param->size > MAX_QUEUE_SIZE) + if (param->size > queue_glb->config.max_queue_size) return ODP_QUEUE_INVALID; } else if (param->nonblocking == ODP_NONBLOCKING_LF) { /* Only plain type lock-free queues supported */ @@ -623,6 +660,7 @@ static odp_event_t queue_deq(odp_queue_t handle) static int queue_init(queue_entry_t *queue, const char *name, const odp_queue_param_t *param) { + uint64_t offset; uint32_t queue_size;
if (name == NULL) { @@ -657,13 +695,15 @@ static int queue_init(queue_entry_t *queue, const char *name, /* Round up if not already a power of two */ queue_size = ROUNDUP_POWER2_U32(queue_size);
- if (queue_size > MAX_QUEUE_SIZE) { + if (queue_size > queue_glb->config.max_queue_size) { ODP_ERR("Too large queue size %u\n", queue_size); return -1; }
- ring_st_init(&queue->s.ring_st, - queue_glb->ring_data[queue->s.index].data, queue_size); + offset = queue->s.index * (uint64_t)queue_glb->config.max_queue_size; + + ring_st_init(&queue->s.ring_st, &queue_glb->ring_data[offset], + queue_size);
return 0; }
commit 535ad269bfc6581a048d3e844576063be5d19501 Author: Petri Savolainen petri.savolainen@linaro.org Date: Wed Mar 7 15:33:55 2018 +0200
linux-gen: queue: configurable default size
Use configuration file to enable user to change default queue size. Queue size parameter from application is used for larger queues than the default size.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/config/odp-linux-generic.conf b/config/odp-linux-generic.conf index 15e65d00..306ee197 100644 --- a/config/odp-linux-generic.conf +++ b/config/odp-linux-generic.conf @@ -30,3 +30,8 @@ pktio_dpdk: { rx_drop_en = 1 } } + +queue_basic: { + # Default queue size. Value must be a power of two. + default_queue_size = 4096 +} diff --git a/platform/linux-generic/include/odp_queue_internal.h b/platform/linux-generic/include/odp_queue_internal.h index 3aec3fe9..386d804e 100644 --- a/platform/linux-generic/include/odp_queue_internal.h +++ b/platform/linux-generic/include/odp_queue_internal.h @@ -75,6 +75,10 @@ typedef struct queue_global_t { uint32_t queue_lf_size; queue_lf_func_t queue_lf_func;
+ struct { + uint32_t default_queue_size; + } config; + } queue_global_t;
extern queue_global_t *queue_glb; diff --git a/platform/linux-generic/odp_queue_basic.c b/platform/linux-generic/odp_queue_basic.c index 1218987b..bbd12fe8 100644 --- a/platform/linux-generic/odp_queue_basic.c +++ b/platform/linux-generic/odp_queue_basic.c @@ -25,6 +25,7 @@ #include <odp/api/hints.h> #include <odp/api/sync.h> #include <odp/api/traffic_mngr.h> +#include <odp_libconfig_internal.h>
#define NUM_INTERNAL_QUEUES 64
@@ -36,6 +37,9 @@ #include <string.h> #include <inttypes.h>
+#define MIN_QUEUE_SIZE 8 +#define MAX_QUEUE_SIZE CONFIG_QUEUE_SIZE + static int queue_init(queue_entry_t *queue, const char *name, const odp_queue_param_t *param);
@@ -60,11 +64,11 @@ static int queue_capa(odp_queue_capability_t *capa, int sched) /* 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.max_size = MAX_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; + capa->sched.max_size = MAX_QUEUE_SIZE;
if (sched) { capa->max_ordered_locks = sched_fn->max_ordered_locks(); @@ -75,6 +79,34 @@ static int queue_capa(odp_queue_capability_t *capa, int sched) return 0; }
+static int read_config_file(queue_global_t *queue_glb) +{ + const char *str; + uint32_t val_u32; + int val = 0; + + ODP_PRINT("Queue config:\n"); + + str = "queue_basic.default_queue_size"; + if (!_odp_libconfig_lookup_int(str, &val)) { + ODP_ERR("Config option '%s' not found.\n", str); + return -1; + } + + val_u32 = val; + + if (val_u32 > MAX_QUEUE_SIZE || val_u32 < MIN_QUEUE_SIZE || + !CHECK_IS_POWER2(val_u32)) { + ODP_ERR("Bad value %s = %u\n", str, val_u32); + return -1; + } + + queue_glb->config.default_queue_size = val_u32; + ODP_PRINT(" %s: %u\n\n", str, val_u32); + + return 0; +} + static int queue_init_global(void) { uint32_t i; @@ -104,6 +136,11 @@ static int queue_init_global(void) queue->s.handle = queue_from_index(i); }
+ if (read_config_file(queue_glb)) { + odp_shm_free(shm); + return -1; + } + lf_func = &queue_glb->queue_lf_func; queue_glb->queue_lf_num = queue_lf_init_global(&lf_size, lf_func); queue_glb->queue_lf_size = lf_size; @@ -207,7 +244,7 @@ static odp_queue_t queue_create(const char *name, }
if (param->nonblocking == ODP_BLOCKING) { - if (param->size > CONFIG_QUEUE_SIZE) + if (param->size > MAX_QUEUE_SIZE) return ODP_QUEUE_INVALID; } else if (param->nonblocking == ODP_NONBLOCKING_LF) { /* Only plain type lock-free queues supported */ @@ -586,6 +623,8 @@ static odp_event_t queue_deq(odp_queue_t handle) static int queue_init(queue_entry_t *queue, const char *name, const odp_queue_param_t *param) { + uint32_t queue_size; + if (name == NULL) { queue->s.name[0] = 0; } else { @@ -609,9 +648,22 @@ static int queue_init(queue_entry_t *queue, const char *name, queue->s.pktin = PKTIN_INVALID; queue->s.pktout = PKTOUT_INVALID;
+ /* Use default size for all small queues to quarantee performance + * level. */ + queue_size = queue_glb->config.default_queue_size; + if (param->size > queue_glb->config.default_queue_size) + queue_size = param->size; + + /* Round up if not already a power of two */ + queue_size = ROUNDUP_POWER2_U32(queue_size); + + if (queue_size > MAX_QUEUE_SIZE) { + ODP_ERR("Too large queue size %u\n", queue_size); + return -1; + } + ring_st_init(&queue->s.ring_st, - queue_glb->ring_data[queue->s.index].data, - CONFIG_QUEUE_SIZE); + queue_glb->ring_data[queue->s.index].data, queue_size);
return 0; }
commit d8dd54f2325cf859703721e7a17b6cbe734d857a Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Sat Feb 10 03:57:24 2018 +0300
test: misc: use C++ I/O instead of C
To verify that this test is really compiled using C++ compiler use cout instead of printf.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/miscellaneous/odp_api_from_cpp.cpp b/test/miscellaneous/odp_api_from_cpp.cpp index 4578ae4b..7ed72ff1 100644 --- a/test/miscellaneous/odp_api_from_cpp.cpp +++ b/test/miscellaneous/odp_api_from_cpp.cpp @@ -1,11 +1,11 @@ -#include <cstdio> +#include <iostream> #include <odp_api.h> #include <odp/helper/odph_api.h>
int main(int argc ODP_UNUSED, const char *argv[] ODP_UNUSED) { - printf("\tODP API version: %s\n", odp_version_api_str()); - printf("\tODP implementation version: %s\n", odp_version_impl_str()); + std::cout << "\tODP API version: " << odp_version_api_str() << std::endl; + std::cout << "\tODP implementation version: " << odp_version_impl_str() << std::endl;
return 0; }
commit edc9616a1bbc0fbc2d7f84ddafeb119d689f3f70 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Sat Mar 17 00:05:24 2018 +0300
shippable: reenable non-ABI-compat build for GCC
Non-ABI-compat build is broken only for Clang, so disable it only for that compiler, rather than disabling it completely.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/.shippable.yml b/.shippable.yml index 86556441..6ef5cab7 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" @@ -16,7 +16,7 @@ env: # - CROSS_ARCH="i386"
matrix: - allow_failures: + exclude: - compiler: clang env: CONF="--disable-abi-compat --disable-test-perf --disable-test-perf-proc"
commit 31d3492b50b057df853ad51c909ac21d6e95a4ca Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Tue Mar 20 08:08:03 2018 +0000
performance: fix sched_latency test with huge cpu count
odp_sched_latency has off-by-one error in accessing cpu stats: worker thread id do not start from 0. Instead of fixing just off-by-one, use ODP_THREAD_COUNT_MAX directly to allocate proper amount of cpu stats structures.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/performance/odp_sched_latency.c b/test/performance/odp_sched_latency.c index d49a212a..ca720119 100644 --- a/test/performance/odp_sched_latency.c +++ b/test/performance/odp_sched_latency.c @@ -27,7 +27,6 @@ /* GNU lib C */ #include <getopt.h>
-#define MAX_WORKERS 64 /**< Maximum number of worker threads */ #define MAX_QUEUES 4096 /**< Maximum number of queues */ #define EVENT_POOL_SIZE (1024 * 1024) /**< Event pool size */ #define TEST_ROUNDS (4 * 1024 * 1024) /**< Test rounds for each thread */ @@ -105,7 +104,8 @@ typedef union ODP_ALIGNED_CACHE {
/** Test global variables */ typedef struct { - core_stat_t core_stat[MAX_WORKERS]; /**< Core specific stats */ + /** Core specific stats */ + core_stat_t core_stat[ODP_THREAD_COUNT_MAX]; odp_barrier_t barrier; /**< Barrier for thread synchronization */ odp_pool_t pool; /**< Pool for allocating test events */ test_args_t args; /**< Parsed command line arguments */ @@ -617,8 +617,9 @@ static void parse_args(int argc, char *argv[], test_args_t *args) }
/* Make sure arguments are valid */ - if (args->cpu_count > MAX_WORKERS) - args->cpu_count = MAX_WORKERS; + /* -1 for main thread */ + if (args->cpu_count > ODP_THREAD_COUNT_MAX - 1) + args->cpu_count = ODP_THREAD_COUNT_MAX - 1; if (args->prio[LO_PRIO].queues > MAX_QUEUES) args->prio[LO_PRIO].queues = MAX_QUEUES; if (args->prio[HI_PRIO].queues > MAX_QUEUES)
commit 74f7b6d1a003175f1cddf979212631a0d7832399 Author: Maxim Uvarov maxim.uvarov@linaro.org Date: Tue Mar 20 09:01:36 2018 +0300
shippable: simplify test execution
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org
diff --git a/.shippable.yml b/.shippable.yml index 82960a39..86556441 100644 --- a/.shippable.yml +++ b/.shippable.yml @@ -34,17 +34,19 @@ build:
ci: - mkdir -p $HOME/odp-shmdir + - export CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes - ./bootstrap - if [ "${CC#clang}" != "${CC}" ] ; then export CXX="${CC/clang/clang++}"; fi + - echo ./configure $CONF - ./configure $CONF - make -j $(nproc) - - sudo env CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes ODP_SCHEDULER=basic make check + - ODP_SCHEDULER=basic make check - ./scripts/shippable-post.sh basic - - sudo env CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes ODP_SCHEDULER=sp make check + - ODP_SCHEDULER=sp make check - ./scripts/shippable-post.sh sp - - sudo env CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes ODP_SCHEDULER=iquery make check + - ODP_SCHEDULER=iquery make check - ./scripts/shippable-post.sh iquery - - sudo env CI=true ODP_SHM_DIR=$HOME/odp-shmdir ODP_TEST_OUT_XML=yes ODP_SCHEDULER=scalable make check + - ODP_SCHEDULER=scalable make check - ./scripts/shippable-post.sh scalable - rm -rf $HOME/odp-shmdir
commit 3c5cc8070d3bc8b7429f0410de6ef3009ff6a28f Author: Maxim Uvarov maxim.uvarov@linaro.org Date: Thu Mar 8 23:49:26 2018 +0300
configure.ac: update version to v1.18.0.1
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org
diff --git a/configure.ac b/configure.ac index 08086d44..904e8197 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])
commit 4665f6d2987fb26ad006cb56b02b3ef4c170f371 Author: Bill Fischofer bill.fischofer@linaro.org Date: Wed Mar 7 11:02:06 2018 -0600
changelog: updates for odp v1.18.0.1
Add updates for V1.18.0.1 (Tiger Moth RC2 fix level)
Signed-off-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/CHANGELOG b/CHANGELOG index cfebbbdc..1dfdd0e7 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
commit d3690d4115441dc69d9571cb5261dd005a112d39 Author: Maxim Uvarov maxim.uvarov@linaro.org Date: Thu Mar 15 16:51:45 2018 +0300
shippable: disable abi compat mode tests on aarch64
disable tests which fails under our docker runs with native clang 4.0
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/.shippable.yml b/.shippable.yml index 6a6a5974..82960a39 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"
commit 364887331875180c498abb8b7681a228ca21181e Author: Matias Elo matias.elo@nokia.com Date: Tue Mar 13 12:58:53 2018 +0200
test: mmap_vlan_ins: wait before removing test interfaces
Removing the test interfaces while the applications are still running may cause a test application instance to not close properly.
Signed-off-by: Matias Elo matias.elo@nokia.com Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
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 91f78311..ae263ee3 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
commit eca5df13cf7987d6e3cd3cc930851671b071e4b3 Author: Balasubramanian Manoharan bala.manoharan@linaro.org Date: Mon Mar 12 18:41:50 2018 +0530
validation: cls: add cls capability check
check for max_cos supported in odp_cls_capability_t before creating odp_cos_t
Signed-off-by: Balasubramanian Manoharan bala.manoharan@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/validation/api/classification/odp_classification_tests.c b/test/validation/api/classification/odp_classification_tests.c index 7e157970..42d0c412 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 20f6b82d..2c615367 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[];
commit c8dc27d1fb5c890143338439f1cdbe3b2719174c Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Wed Feb 21 20:19:32 2018 +0300
build: change order of subdirectories
Descend into examples after building/running tests. It is quite logical that first we build validation & performance tests, then we build platform tests, helper tests and only after that descend into examples.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/Makefile.am b/Makefile.am index 89388a19..4f3e0020 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,11 +12,11 @@ SUBDIRS = \ include \ $(PLATFORM_DIR) \ helper \ + test \ + $(PLATFORM_TEST_DIR) \ helper/test \ doc \ - example . \ - test \ - $(PLATFORM_TEST_DIR) + example
@DX_RULES@
commit 62ef9d5c92e0f56f45767f4c73df214d4393e158 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Fri Mar 9 13:47:25 2018 +0300
test: l2fwd: enforce dependency between l2fwd test and generator
Test l2fwd depends on the generator example. Enforce build order.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/performance/Makefile.am b/test/performance/Makefile.am index 9c709e79..e50c840b 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
commit 41fd242a0685e79cb6f1b1e1826e6734bea2f359 Author: Yi He yi.he@linaro.org Date: Mon Mar 12 16:38:37 2018 +0800
validation: scheduler: fix test_wait_time failure
Resolve Bug https://bugs.linaro.org/show_bug.cgi?id=3675, the elapsed time measurement could be enlarged unpredictably by inner printf calls and exceed the upper limit of tolerance.
Signed-off-by: Yi He yi.he@linaro.org Reviewed-by: Ola Liljedahl ola.liljedahl@arm.com Reviewed-by: Brian Brooks brian.brooks@arm.com Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/validation/api/scheduler/scheduler.c b/test/validation/api/scheduler/scheduler.c index d5783b4d..f1b61dfd 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);
commit 35a90a547466db90c00d6375d8d9a3573e84e99b Author: Maxim Uvarov maxim.uvarov@linaro.org Date: Wed Mar 14 00:58:58 2018 +0300
shippable: do not use huge pages
huge pages under docker are trickly also /dev/shm/ is limited to 64Mb. Use different folder for shared memory files.
Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org
diff --git a/.shippable.yml b/.shippable.yml index 9828ed52..6a6a5974 100644 --- a/.shippable.yml +++ b/.shippable.yml @@ -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
commit 9a1d48b1262d88e55922c4e1ed9f91ed2e3376d7 Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Fri Mar 9 16:58:15 2018 +0100
odp_dpdk.m4: use correct installation directory
We are currently using the include path used when building DPDK, however when installing DPDK, the headers are put in ${prefix}/include/dpdk. We should use the latter in our include path.
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/.travis.yml b/.travis.yml index a03b2904..1f5ef42e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -195,7 +195,7 @@ install: LIBDPDKEXT=a fi DPDK_TARGET="${DPDK_TARGET}gcc" - if [ ! -f "dpdk/${TARGET}/lib/libdpdk.$LIBDPDKEXT" ]; then + if [ ! -f "dpdk/${TARGET}/usr/local/lib/libdpdk.$LIBDPDKEXT" ]; then git -c advice.detachedHead=false clone -q --depth=1 --single-branch --branch=v${DPDK_VERS} http://dpdk.org/git/dpdk dpdk pushd dpdk git log --oneline --decorate @@ -222,10 +222,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
# Netmap pktio @@ -293,7 +294,7 @@ jobs: - ./bootstrap - ./configure --prefix=$HOME/odp-install --enable-user-guides - --with-dpdk-path=`pwd`/dpdk/${TARGET} + --with-dpdk-path=`pwd`/dpdk/${TARGET}/usr/local --with-netmap-path=`pwd`/netmap CFLAGS="-O0 -coverage" CXXFLAGS="-O0 -coverage" LDFLAGS="--coverage" --enable-debug=full diff --git a/m4/odp_dpdk.m4 b/m4/odp_dpdk.m4 index 6e2a914b..b94c9b55 100644 --- a/m4/odp_dpdk.m4 +++ b/m4/odp_dpdk.m4 @@ -120,7 +120,7 @@ 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 diff --git a/scripts/build-pktio-dpdk b/scripts/build-pktio-dpdk index 97916c1e..26afd97c 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
commit 1e70adc3ae54b0c4518bdb51d94301f1dafe4ebf Author: Josep Puigdemont josep.puigdemont@linaro.org Date: Fri Mar 9 15:59:52 2018 +0100
odp_dpdk.m4: check for DPDK static libraries
Signed-off-by: Josep Puigdemont josep.puigdemont@linaro.org Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/m4/odp_dpdk.m4 b/m4/odp_dpdk.m4 index 0050fc4b..6e2a914b 100644 --- a/m4/odp_dpdk.m4 +++ b/m4/odp_dpdk.m4 @@ -127,6 +127,8 @@ AS_IF([test "x$1" = "xsystem"], [dnl 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"
commit 91282a4c578716f157aa8a5e0a9bf9bd25b19a17 Author: Matias Elo matias.elo@nokia.com Date: Mon Mar 12 14:07:27 2018 +0200
configure: add check for 'xxd' tool
Add check for 'xxd' tool and list it in DEPENDENCIES file.
Signed-off-by: Matias Elo matias.elo@nokia.com Reviewed-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/DEPENDENCIES b/DEPENDENCIES index b6765fec..2cd8ccb4 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -17,10 +17,12 @@ 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, libconfig
+ Required tools: xxd + 3.1 OpenSSL native compile
For native compilation, simply load the necessary libraries using the appropriate diff --git a/m4/odp_libconfig.m4 b/m4/odp_libconfig.m4 index 18275f07..632c271e 100644 --- a/m4/odp_libconfig.m4 +++ b/m4/odp_libconfig.m4 @@ -7,6 +7,14 @@ AC_DEFUN([ODP_LIBCONFIG], ########################################################################## 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
commit e009051a0166fa25e601190354e0333aa30ad58d Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Mon Mar 5 17:55:52 2018 +0300
build: make so numbering to be tied to ODP versions
We do not make any promises on ABI backwards compatibility, we have been using -version-number instead of -version-info for ages, so affirm this approach. Drop misleading comment and tie SO version numbers to ODP relase numbers.
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/configure.ac b/configure.ac index 31f24aa8..08086d44 100644 --- a/configure.ac +++ b/configure.ac @@ -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.... -# 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.
commit 36f589b5a84804ce246bcd9a3eb9352801aaf41d Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Mar 2 16:34:07 2018 +0200
linux-gen: sched: optimize local variable layout
Pack local variables struct and bring commonly used variables into the head of the struct.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c index b3c913bb..cd20b39d 100644 --- a/platform/linux-generic/odp_schedule_basic.c +++ b/platform/linux-generic/odp_schedule_basic.c @@ -114,14 +114,20 @@ ODP_STATIC_ASSERT(sizeof(lock_called_t) == sizeof(uint32_t), /* Scheduler local data */ typedef struct { int thr; - int stash_num; - int stash_index; - int pause; + uint16_t stash_num; + uint16_t stash_index; + uint16_t pause; uint16_t round; 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; @@ -133,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 */
commit 2bbd7ace9e236d27dcfb52acfef991bd5ce39354 Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Mar 2 15:28:12 2018 +0200
linux-gen: sched: use stash prefix
Use consistently stash_ prefix for thread local variables related to event stashing.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c index d662bd6a..b3c913bb 100644 --- a/platform/linux-generic/odp_schedule_basic.c +++ b/platform/linux-generic/odp_schedule_basic.c @@ -114,13 +114,14 @@ ODP_STATIC_ASSERT(sizeof(lock_called_t) == sizeof(uint32_t), /* Scheduler local data */ typedef struct { int thr; - int num; - int index; + int stash_num; + int stash_index; int pause; uint16_t round; - 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]; + struct { /* Source queue index */ uint32_t src_queue; @@ -228,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); @@ -364,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; } @@ -536,9 +537,9 @@ static void schedule_pktio_start(int pktio_index, int num_pktin,
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; @@ -546,7 +547,7 @@ static void schedule_release_atomic(void)
/* Release current atomic queue */ ring_enq(ring, RING_MASK, qi); - sched_local.queue_index = PRIO_QUEUE_EMPTY; + sched_local.stash_qi = PRIO_QUEUE_EMPTY; } }
@@ -634,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(); @@ -648,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++; } @@ -743,7 +744,7 @@ static inline int poll_pktin(uint32_t qi, int stash)
if (stash) { for (i = 0; i < num; i++) - sched_local.ev_stash[i] = event_from_buf_hdr(b_hdr[i]); + sched_local.stash_ev[i] = event_from_buf_hdr(b_hdr[i]);
return num; } @@ -829,7 +830,7 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[],
pktin = queue_is_pktin(qi);
- num = sched_cb_queue_deq_multi(qi, sched_local.ev_stash, + num = sched_cb_queue_deq_multi(qi, sched_local.stash_ev, max_deq, !pktin);
if (num < 0) { @@ -883,17 +884,17 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[],
} 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, RING_MASK, qi); }
- handle = queue_from_index(qi); - sched_local.num = num; - sched_local.index = 0; - sched_local.queue = handle; - ret = copy_events(out_ev, max_num); + 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) @@ -918,11 +919,11 @@ static inline int do_schedule(odp_queue_t *out_queue, odp_event_t out_ev[], 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; }
commit 196d8f518071cc8c37dde0835cb7559d6cdd55da Author: Petri Savolainen petri.savolainen@linaro.org Date: Fri Mar 2 14:27:22 2018 +0200
linux-gen: sched: optimize parallel packet input queue throughput
Extend direct packet input processing to parallel queues. Parallel queues do not quarantee ordering, so also those can pass packets directly to application and (potentially) stash some per thread.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c index 3ea261fa..d662bd6a 100644 --- a/platform/linux-generic/odp_schedule_basic.c +++ b/platform/linux-generic/odp_schedule_basic.c @@ -846,19 +846,19 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], * priorities. Stop scheduling queue when pktio * has been stopped. */ if (pktin) { - int atomic = queue_is_atomic(qi); - int num_pkt = poll_pktin(qi, atomic); + int stash = !ordered; + int num_pkt = poll_pktin(qi, stash);
if (odp_unlikely(num_pkt < 0)) continue;
- if (num_pkt == 0 || !atomic) { + if (num_pkt == 0 || !stash) { ring_enq(ring, RING_MASK, qi); break; }
- /* Process packets from an atomic queue - * right away */ + /* Process packets from an atomic or + * parallel queue right away. */ num = num_pkt; } else { /* Remove empty queue from scheduling. @@ -868,12 +868,6 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], } }
- 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; @@ -895,6 +889,12 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], ring_enq(ring, RING_MASK, qi); }
+ handle = queue_from_index(qi); + sched_local.num = num; + sched_local.index = 0; + sched_local.queue = handle; + ret = copy_events(out_ev, max_num); + /* Output the source queue handle */ if (out_queue) *out_queue = handle;
commit 42fc5ebdcd5a1e5fbb7a19a2756a310f23a0cdd5 Author: Petri Savolainen petri.savolainen@linaro.org Date: Thu Mar 1 17:22:21 2018 +0200
linux-gen: queue: enqueue may fail
Drop events when queue enqueue fails. Enqueue failure is more likely now when queue has limited size.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index 8b599e96..56e9f686 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -657,8 +657,22 @@ static odp_buffer_hdr_t *pktin_dequeue(queue_t q_int) 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; } @@ -695,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; }
@@ -782,6 +809,7 @@ int sched_cb_pktin_poll_old(int pktio_index, int num_queue, int index[])
for (idx = 0; idx < num_queue; idx++) { queue_t q_int; + int num_enq;
num = pktin_recv_buf(entry, index[idx], hdr_tbl, QUEUE_MULTI_MAX); @@ -795,7 +823,16 @@ int sched_cb_pktin_poll_old(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_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c index b251bdee..3ea261fa 100644 --- a/platform/linux-generic/odp_schedule_basic.c +++ b/platform/linux-generic/odp_schedule_basic.c @@ -581,13 +581,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; } diff --git a/platform/linux-generic/odp_schedule_iquery.c b/platform/linux-generic/odp_schedule_iquery.c index ddd97bea..40f2e9fc 100644 --- a/platform/linux-generic/odp_schedule_iquery.c +++ b/platform/linux-generic/odp_schedule_iquery.c @@ -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; }
commit bb8015d15ca4b0e2033eeca09906032a88e74bff Author: Petri Savolainen petri.savolainen@linaro.org Date: Thu Mar 1 16:03:39 2018 +0200
linux-gen: sched: optimize atomic packet input queue throughput
When packet input queue is atomic, packets received from packet input are passed directly to the application. Other queue types may have events stashed on other threads, so for those incoming packets are always enqueued (to maintain packet order).
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_buffer_inlines.h b/platform/linux-generic/include/odp_buffer_inlines.h index 9abe79fc..9e3b6ef7 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_queue_internal.h b/platform/linux-generic/include/odp_queue_internal.h index 0540bf72..3aec3fe9 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 ef178e07..8a973a85 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 dd2097bf..4bd127a4 100644 --- a/platform/linux-generic/include/odp_schedule_if.h +++ b/platform/linux-generic/include/odp_schedule_if.h @@ -77,7 +77,9 @@ 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); diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index f8792b66..8b599e96 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -578,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; @@ -589,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]; @@ -643,13 +643,16 @@ 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; @@ -665,6 +668,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)) @@ -676,8 +683,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;
@@ -739,12 +746,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)) { @@ -758,9 +782,9 @@ 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;
- 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; diff --git a/platform/linux-generic/odp_queue_basic.c b/platform/linux-generic/odp_queue_basic.c index 4371fd90..1218987b 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) { diff --git a/platform/linux-generic/odp_queue_lf.c b/platform/linux-generic/odp_queue_lf.c index 74f52946..066e6a67 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 b3847ab9..b251bdee 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 @@ -699,14 +700,20 @@ 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) +static inline int poll_pktin(uint32_t qi, int stash) { - int pktio_index, pktin_index, num, num_pktin; + 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, 1, &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. */ @@ -720,9 +727,33 @@ static inline int poll_pktin(uint32_t qi)
if (num_pktin == 0) sched_cb_pktio_stop_finalize(pktio_index); + + return num; }
- return num; + if (stash) { + for (i = 0; i < num; i++) + sched_local.ev_stash[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[], @@ -805,17 +836,26 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], * priorities. Stop scheduling queue when pktio * has been stopped. */ if (pktin) { - int num_pkt = poll_pktin(qi); + int atomic = queue_is_atomic(qi); + int num_pkt = poll_pktin(qi, atomic);
- if (odp_likely(num_pkt >= 0)) { + if (odp_unlikely(num_pkt < 0)) + continue; + + if (num_pkt == 0 || !atomic) { ring_enq(ring, RING_MASK, qi); break; } - }
- /* Remove empty queue from scheduling. Continue - * scheduling the same priority queue. */ - continue; + /* Process packets from an atomic queue + * right away */ + num = num_pkt; + } else { + /* Remove empty queue from scheduling. + * Continue scheduling the same priority + * queue. */ + continue; + } }
handle = queue_from_index(qi); diff --git a/platform/linux-generic/odp_schedule_iquery.c b/platform/linux-generic/odp_schedule_iquery.c index 1a82f48d..ddd97bea 100644 --- a/platform/linux-generic/odp_schedule_iquery.c +++ b/platform/linux-generic/odp_schedule_iquery.c @@ -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. diff --git a/platform/linux-generic/odp_schedule_sp.c b/platform/linux-generic/odp_schedule_sp.c index 50390274..84d16d3c 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 {
commit 3e61be54a77ed8ccc2030e88b9a26372d3f76e2c Author: Petri Savolainen petri.savolainen@linaro.org Date: Tue Feb 27 16:27:39 2018 +0200
linux-gen: sched: optimize packet input polling
Optimize scheduler throughput with packet IO interfaces. Special pktio poll commands are removed and event queue is used instead to trigger packet input polling. Packet input is polled when those queues are empty. Thus, these queues connected to packet input are not removed from scheduling when empty.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/include/odp_schedule_if.h b/platform/linux-generic/include/odp_schedule_if.h index 66e05043..dd2097bf 100644 --- a/platform/linux-generic/include/odp_schedule_if.h +++ b/platform/linux-generic/include/odp_schedule_if.h @@ -82,7 +82,9 @@ 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/odp_queue_basic.c b/platform/linux-generic/odp_queue_basic.c index f87c2876..4371fd90 100644 --- a/platform/linux-generic/odp_queue_basic.c +++ b/platform/linux-generic/odp_queue_basic.c @@ -309,6 +309,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; @@ -503,7 +514,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; @@ -525,7 +536,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) @@ -552,7 +563,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) @@ -561,7 +572,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; @@ -671,11 +682,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_schedule_basic.c b/platform/linux-generic/odp_schedule_basic.c index e5e1fe60..b3847ab9 100644 --- a/platform/linux-generic/odp_schedule_basic.c +++ b/platform/linux-generic/odp_schedule_basic.c @@ -50,39 +50,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 +66,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 +79,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;
@@ -150,7 +117,6 @@ typedef struct { int index; int pause; uint16_t round; - uint16_t pktin_polls; uint32_t queue_index; odp_queue_t queue; odp_event_t ev_stash[MAX_DEQ]; @@ -183,24 +149,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 +168,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 +182,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;
@@ -337,16 +287,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 +327,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); @@ -519,6 +462,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,88 +500,39 @@ 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"); - - idx = poll_cmd_queue_idx(pktio_index, pktin_idx[i]); + ODP_ASSERT(pktin_idx[i] <= MAX_PKTIN_INDEX);
- 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; @@ -647,7 +544,7 @@ static void schedule_release_atomic(void) ring_t *ring = &sched->prio_q[grp][prio][queue_per_prio].ring;
/* Release current atomic queue */ - ring_enq(ring, PRIO_QUEUE_MASK, qi); + ring_enq(ring, RING_MASK, qi); sched_local.queue_index = PRIO_QUEUE_EMPTY; } } @@ -797,6 +694,37 @@ 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 pktio_index, pktin_index, num, num_pktin; + + pktio_index = sched->queue[qi].pktio_index; + pktin_index = sched->queue[qi].pktin_index; + + num = sched_cb_pktin_poll(pktio_index, 1, &pktin_index); + + /* 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; +} + 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 +748,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 +763,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 +786,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;
+ pktin = queue_is_pktin(qi); + num = sched_cb_queue_deq_multi(qi, sched_local.ev_stash, - max_deq); + max_deq, !pktin);
if (num < 0) { /* Destroyed queue. Continue scheduling the same @@ -868,6 +799,20 @@ static inline int do_schedule_grp(odp_queue_t *out_queue, odp_event_t out_ev[], }
if (num == 0) { + /* 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 num_pkt = poll_pktin(qi); + + if (odp_likely(num_pkt >= 0)) { + ring_enq(ring, RING_MASK, qi); + break; + } + } + /* Remove empty queue from scheduling. Continue * scheduling the same priority queue. */ continue; @@ -890,14 +835,14 @@ 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; } else { /* Continue scheduling the queue */ - ring_enq(ring, PRIO_QUEUE_MASK, qi); + ring_enq(ring, RING_MASK, qi); }
/* Output the source queue handle */ @@ -919,7 +864,7 @@ 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;
@@ -972,66 +917,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 +1277,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 ea62c364..1a82f48d 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); @@ -1527,7 +1527,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 007d673f..50390274 100644 --- a/platform/linux-generic/odp_schedule_sp.c +++ b/platform/linux-generic/odp_schedule_sp.c @@ -559,7 +559,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;
commit c0da87688187c81039cf81790fed3d6ed00a956e Author: Petri Savolainen petri.savolainen@linaro.org Date: Tue Mar 6 13:38:30 2018 +0200
linux-gen: queue: improve debug print
Print max number of queues and max queue size in global init.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_queue_basic.c b/platform/linux-generic/odp_queue_basic.c index e4f6fd82..f87c2876 100644 --- a/platform/linux-generic/odp_queue_basic.c +++ b/platform/linux-generic/odp_queue_basic.c @@ -68,14 +68,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 +123,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 +175,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)
commit c2a1c48f5fc17cf4dd870057d17059ad668d29ad Author: Petri Savolainen petri.savolainen@linaro.org Date: Tue Mar 6 12:46:33 2018 +0200
linux-gen: pktio: add debug prints
Print interface name on open, start, stop and close calls. Also print driver name and number of queues to ease check of correct configuration.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index ae8e390b..f8792b66 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; }
commit c67dcec1c034a0c75c093b49e2a172bbd3d50def Author: Petri Savolainen petri.savolainen@linaro.org Date: Tue Mar 6 10:46:57 2018 +0200
linux-gen: sysinfo: add content to info string print
Added implementation details string and cpu mask to system info print out.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c index d460a198..d1cda1ea 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);
commit 80b9a1e4d6a297ac916cbaf360e7b2114ef86a7a Author: Petri Savolainen petri.savolainen@linaro.org Date: Tue Mar 6 10:40:06 2018 +0200
linux-gen: version: implementation name content
Removed quotes from implementation name (from "odp-linux" to odp_linux). Added ODP_ prefix to name and build version macros.
Signed-off-by: Petri Savolainen petri.savolainen@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Reviewed-by: Balasubramanian Manoharan bala.manoharan@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/configure.ac b/configure.ac index f9e7f73b..31f24aa8 100644 --- a/configure.ac +++ b/configure.ac @@ -240,7 +240,7 @@ AS_IF([test "${with_platform}" = "linux-generic"], [m4_include([./platform/linux-generic/m4/configure.m4])], [AC_MSG_ERROR([UNSUPPORTED PLATFORM: ${with_platform}])])
-AC_DEFINE_UNQUOTED([IMPLEMENTATION_NAME], ["$IMPLEMENTATION_NAME"], +AC_DEFINE_UNQUOTED([ODP_IMPLEMENTATION_NAME], ["$ODP_IMPLEMENTATION_NAME"], [Define to the name of the implementation])
########################################################################## @@ -385,7 +385,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/platform/Makefile.inc b/platform/Makefile.inc index 9df96b12..ae4d52f2 100644 --- a/platform/Makefile.inc +++ b/platform/Makefile.inc @@ -17,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-generic/m4/configure.m4 b/platform/linux-generic/m4/configure.m4 index d2ddd495..e3f276af 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 diff --git a/platform/linux-generic/odp_impl.c b/platform/linux-generic/odp_impl.c index b6994295..227d5000 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
commit 7135eda6854ba60d6379ca5799b4b58959e998b5 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Wed Feb 21 19:01:01 2018 +0300
validation: ipsec: verify TFC dummy packet generation
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/test/validation/api/ipsec/ipsec.c b/test/validation/api/ipsec/ipsec.c index 21eaf17b..3e2e743d 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 3db553b6..5089dfa7 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(¶m, + false, false, 123, &tunnel, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256, + NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_sa_param_fill(¶m, + true, false, 123, &tunnel, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256, + NULL); + + sa2 = odp_ipsec_sa_create(¶m); + + 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(¶m, + false, false, 123, &tunnel, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256, + NULL); + + sa = odp_ipsec_sa_create(¶m); + + CU_ASSERT_NOT_EQUAL_FATAL(ODP_IPSEC_SA_INVALID, sa); + + ipsec_sa_param_fill(¶m, + true, false, 123, &tunnel, + ODP_CIPHER_ALG_NULL, NULL, + ODP_AUTH_ALG_SHA256_HMAC, &key_5a_256, + NULL); + + sa2 = odp_ipsec_sa_create(¶m); + + 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 4d5ab3bd..5b357a16 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
commit 017969502cd0247c9b25e80e002ac563860f5a5d Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Wed Feb 21 19:00:30 2018 +0300
linux-gen: ipsec: support TFC dummy packet generation
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index 78814eeb..1e90cea0 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; @@ -1070,13 +1080,20 @@ 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->tfc_pad_len : 0; + 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; @@ -1131,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 + @@ -1167,6 +1199,8 @@ 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, @@ -1176,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 - @@ -1327,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) @@ -1346,9 +1401,6 @@ static ipsec_sa_t *ipsec_out_single(odp_packet_t pkt, /* Initialize parameters block */ memset(¶m, 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); @@ -1364,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; @@ -1745,9 +1802,14 @@ int odp_ipsec_out_inline(const odp_packet_t pkt_in[], int num_in, else opt = ¶m->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) @@ -1766,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));
commit 3a4f369fb2019761af5d4d7ad09d48f1e5d44f82 Author: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Date: Wed Feb 21 16:33:30 2018 +0300
linux-gen: ipsec: support tfc_pad_len IPsec option
Signed-off-by: Dmitry Eremin-Solenikov dmitry.ereminsolenikov@linaro.org Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c index fb852e70..78814eeb 100644 --- a/platform/linux-generic/odp_ipsec.c +++ b/platform/linux-generic/odp_ipsec.c @@ -1061,7 +1061,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,6 +1070,7 @@ 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->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; @@ -1079,7 +1081,7 @@ static int ipsec_out_esp(odp_packet_t *pkt, 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 +1122,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); @@ -1165,6 +1167,8 @@ 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); + _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); @@ -1384,7 +1388,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, ¶m, status, mtu); + rc = ipsec_out_esp(&pkt, &state, ipsec_sa, ¶m, status, mtu, + opt); } else if (ODP_IPSEC_AH == ipsec_sa->proto) { rc = ipsec_out_ah(&pkt, &state, ipsec_sa, ¶m, status, mtu); } else {
commit 962600ecdbe44d386f95a57ac5a91365af0b6c39 Author: Matias Elo matias.elo@nokia.com Date: Fri Mar 2 15:17:22 2018 +0200
checkpatch: update to the latest version
Update checkpatch script to the latest version (2d453e3b41c80d1a2c02b02d672f5dcd73f95a12). Ignores some new unnecessary checks. PRIu8 and PRIu16 camel case warnings are also ignored.
Signed-off-by: Matias Elo matias.elo@nokia.com Reviewed-by: Bill Fischofer bill.fischofer@linaro.org Signed-off-by: Maxim Uvarov maxim.uvarov@linaro.org
diff --git a/.checkpatch.conf b/.checkpatch.conf index 990a54d2..7195642f 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/scripts/checkpatch.pl b/scripts/checkpatch.pl index d366f257..d5ffd1dd 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%5Cn"); +# 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%5Cn"); - } - # 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; }
-----------------------------------------------------------------------
Summary of changes: .checkpatch.conf | 5 + .shippable.yml | 18 +- .travis.yml | 17 +- CHANGELOG | 49 + DEPENDENCIES | 4 +- Makefile.am | 6 +- config/odp-linux-generic.conf | 17 + configure.ac | 21 +- example/Makefile.inc | 2 + m4/odp_dpdk.m4 | 11 +- m4/odp_libconfig.m4 | 25 +- .../m4/odp_schedule.m4 => m4/odp_scheduler.m4 | 5 + platform/Makefile.inc | 2 +- .../linux-generic/include/odp_buffer_inlines.h | 5 + .../linux-generic/include/odp_libconfig_internal.h | 5 + .../linux-generic/include/odp_queue_internal.h | 24 + platform/linux-generic/include/odp_queue_lf.h | 1 - platform/linux-generic/include/odp_schedule_if.h | 8 +- platform/linux-generic/m4/configure.m4 | 6 +- platform/linux-generic/odp_crypto.c | 25 +- platform/linux-generic/odp_impl.c | 30 +- platform/linux-generic/odp_ipsec.c | 108 +- platform/linux-generic/odp_ipsec_sad.c | 5 + platform/linux-generic/odp_libconfig.c | 42 +- platform/linux-generic/odp_packet_io.c | 145 +- platform/linux-generic/odp_queue_basic.c | 213 ++- platform/linux-generic/odp_queue_lf.c | 2 +- platform/linux-generic/odp_schedule_basic.c | 633 ++++---- platform/linux-generic/odp_schedule_iquery.c | 23 +- platform/linux-generic/odp_schedule_sp.c | 7 +- platform/linux-generic/odp_system_info.c | 26 +- platform/linux-generic/pktio/dpdk.c | 36 +- .../test/mmap_vlan_ins/mmap_vlan_ins.sh | 3 + scripts/build-pktio-dpdk | 7 +- scripts/checkpatch.pl | 1552 ++++++++++++++++---- test/Makefile.inc | 2 + test/miscellaneous/odp_api_from_cpp.cpp | 6 +- test/performance/.gitignore | 2 + test/performance/Makefile.am | 10 + test/performance/odp_crypto.c | 131 ++ test/performance/{odp_crypto.c => odp_ipsec.c} | 1035 +++++++------ test/performance/odp_sched_latency.c | 9 +- test/performance/odp_sched_pktio.c | 722 +++++++++ .../api/classification/odp_classification_tests.c | 59 +- .../classification/odp_classification_testsuites.h | 12 + test/validation/api/ipsec/ipsec.c | 7 +- test/validation/api/ipsec/ipsec_test_out.c | 162 ++ test/validation/api/ipsec/test_vectors.h | 18 + test/validation/api/scheduler/scheduler.c | 4 +- 49 files changed, 3945 insertions(+), 1322 deletions(-) rename platform/linux-generic/m4/odp_schedule.m4 => m4/odp_scheduler.m4 (73%) copy test/performance/{odp_crypto.c => odp_ipsec.c} (56%) create mode 100644 test/performance/odp_sched_pktio.c
hooks/post-receive