summaryrefslogtreecommitdiffstats
path: root/src/spdk/dpdk/devtools
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdk/dpdk/devtools')
-rwxr-xr-xsrc/spdk/dpdk/devtools/build-tags.sh209
-rwxr-xr-xsrc/spdk/dpdk/devtools/check-dup-includes.sh18
-rwxr-xr-xsrc/spdk/dpdk/devtools/check-git-log.sh181
-rwxr-xr-xsrc/spdk/dpdk/devtools/check-includes.sh261
-rwxr-xr-xsrc/spdk/dpdk/devtools/check-maintainers.sh132
-rwxr-xr-xsrc/spdk/dpdk/devtools/check-symbol-change.sh159
-rwxr-xr-xsrc/spdk/dpdk/devtools/check-symbol-maps.sh30
-rwxr-xr-xsrc/spdk/dpdk/devtools/checkpatches.sh226
-rwxr-xr-xsrc/spdk/dpdk/devtools/cocci.sh64
-rw-r--r--src/spdk/dpdk/devtools/cocci/mtod-offset.cocci76
-rw-r--r--src/spdk/dpdk/devtools/cocci/strlcpy.cocci8
-rwxr-xr-xsrc/spdk/dpdk/devtools/get-maintainer.sh58
-rwxr-xr-xsrc/spdk/dpdk/devtools/git-log-fixes.sh112
-rw-r--r--src/spdk/dpdk/devtools/load-devel-config12
-rwxr-xr-xsrc/spdk/dpdk/devtools/test-build.sh244
-rwxr-xr-xsrc/spdk/dpdk/devtools/test-meson-builds.sh60
-rwxr-xr-xsrc/spdk/dpdk/devtools/test-null.sh17
-rwxr-xr-xsrc/spdk/dpdk/devtools/validate-abi.sh251
18 files changed, 2118 insertions, 0 deletions
diff --git a/src/spdk/dpdk/devtools/build-tags.sh b/src/spdk/dpdk/devtools/build-tags.sh
new file mode 100755
index 00000000..78001f04
--- /dev/null
+++ b/src/spdk/dpdk/devtools/build-tags.sh
@@ -0,0 +1,209 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Cavium, Inc
+#
+
+#
+# Generate tags or gtags or cscope or etags files
+#
+
+verbose=false
+linux=true
+bsd=true
+x86_32=true
+x86_64=true
+ppc_64=true
+arm_32=true
+arm_64=true
+
+print_usage()
+{
+ echo "Usage: $(basename $0) [-h] [-v] tags|cscope|gtags|etags [config]"
+ echo "Valid configs are:"
+ make showconfigs | sed 's,^,\t,'
+}
+
+# Move to the root of the git tree
+cd $(dirname $0)/..
+
+while getopts hv ARG ; do
+ case $ARG in
+ v ) verbose=true ;;
+ h ) print_usage; exit 0 ;;
+ ? ) print_usage; exit 1 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+#ignore version control files
+ignore="( -name .svn -o -name CVS -o -name .hg -o -name .git ) -prune -o"
+
+source_dirs="test app buildtools drivers examples lib"
+
+skip_bsd="( -name bsdapp ) -prune -o"
+skip_linux="( -name linuxapp ) -prune -o"
+skip_arch="( -name arch ) -prune -o"
+skip_sse="( -name *_sse*.[chS] ) -prune -o"
+skip_avx="( -name *_avx*.[chS] ) -prune -o"
+skip_neon="( -name *_neon*.[chS] ) -prune -o"
+skip_altivec="( -name *_altivec*.[chS] ) -prune -o"
+skip_arm64="( -name *arm64*.[chS] ) -prune -o"
+skip_x86="( -name *x86*.[chS] ) -prune -o"
+skip_32b_files="( -name *_32.h ) -prune -o"
+skip_64b_files="( -name *_64.h ) -prune -o"
+
+skiplist="$skip_bsd $skip_linux $skip_arch $skip_sse $skip_avx \
+ $skip_neon $skip_altivec $skip_x86 $skip_arm64"
+
+find_sources()
+{
+ find $1 $ignore $3 -name $2 -not -type l -print
+}
+
+common_sources()
+{
+ find_sources "$source_dirs" '*.[chS]' "$skiplist"
+}
+
+linux_sources()
+{
+ find_sources "lib/librte_eal/linuxapp" '*.[chS]'
+}
+
+bsd_sources()
+{
+ find_sources "lib/librte_eal/bsdapp" '*.[chS]'
+}
+
+arm_common()
+{
+ find_sources "lib/librte_eal/common/arch/arm" '*.[chS]'
+ find_sources "$source_dirs" '*neon*.[chS]'
+}
+
+arm_32_sources()
+{
+ arm_common
+ find_sources "lib/librte_eal/common/include/arch/arm" '*.[chS]' \
+ "$skip_64b_files"
+}
+
+arm_64_sources()
+{
+ arm_common
+ find_sources "lib/librte_eal/common/include/arch/arm" '*.[chS]' \
+ "$skip_32b_files"
+ find_sources "$source_dirs" '*arm64.[chS]'
+}
+
+x86_common()
+{
+ find_sources "lib/librte_eal/common/arch/x86" '*.[chS]'
+
+ find_sources "examples/performance-thread/common/arch/x86" '*.[chS]'
+ find_sources "$source_dirs" '*_sse*.[chS]'
+ find_sources "$source_dirs" '*_avx*.[chS]'
+ find_sources "$source_dirs" '*x86.[chS]'
+}
+
+x86_32_sources()
+{
+ x86_common
+ find_sources "lib/librte_eal/common/include/arch/x86" '*.[chS]' \
+ "$skip_64b_files"
+}
+
+x86_64_sources()
+{
+ x86_common
+ find_sources "lib/librte_eal/common/include/arch/x86" '*.[chS]' \
+ "$skip_32b_files"
+}
+
+ppc_64_sources()
+{
+ find_sources "lib/librte_eal/common/arch/ppc_64" '*.[chS]'
+ find_sources "lib/librte_eal/common/include/arch/ppc_64" '*.[chS]'
+ find_sources "$source_dirs" '*altivec*.[chS]'
+}
+
+check_valid_target()
+{
+ cfgfound=false
+ allconfigs=$(make showconfigs)
+ for cfg in $allconfigs ; do
+ if [ "$cfg" = "$1" ] ; then
+ cfgfound=true
+ fi
+ done
+ if ! $cfgfound ; then
+ echo "Invalid config: $1"
+ print_usage
+ exit 0
+ fi
+}
+
+if [ -n "$2" ]; then
+ check_valid_target $2
+
+ echo $2 | grep -q "linuxapp-" || linux=false
+ echo $2 | grep -q "bsdapp-" || bsd=false
+ echo $2 | grep -q "x86_64-" || x86_64=false
+ echo $2 | grep -q "arm-" || arm_32=false
+ echo $2 | grep -q "arm64-" || arm_64=false
+ echo $2 | grep -q "ppc_64-" || ppc_64=false
+ echo $2 | grep -q -e "i686-" -e "x32-" || x86_32=false
+fi
+
+all_sources()
+{
+ common_sources
+ if $linux ; then linux_sources ; fi
+ if $bsd ; then bsd_sources ; fi
+ if $x86_64 ; then x86_64_sources ; fi
+ if $x86_32 ; then x86_32_sources ; fi
+ if $ppc_64 ; then ppc_64_sources ; fi
+ if $arm_32 ; then arm_32_sources ; fi
+ if $arm_64 ; then arm_64_sources ; fi
+}
+
+show_flags()
+{
+ if $verbose ; then
+ echo "mode: $1"
+ echo "config: $2"
+ echo "linux: $linux"
+ echo "bsd: $bsd"
+ echo "x86_32: $x86_32"
+ echo "x86_64: $x86_64"
+ echo "ppc_64: $ppc_64"
+ echo "arm_32: $arm_32"
+ echo "arm_64: $arm_64"
+ fi
+}
+
+case "$1" in
+ "cscope")
+ show_flags $1 $2
+ all_sources > cscope.files
+ cscope -q -b -f cscope.out
+ ;;
+ "gtags")
+ show_flags $1 $2
+ all_sources | gtags -i -f -
+ ;;
+ "tags")
+ show_flags $1 $2
+ rm -f tags
+ all_sources | xargs ctags -a
+ ;;
+ "etags")
+ show_flags $1 $2
+ rm -f TAGS
+ all_sources | xargs etags -a
+ ;;
+ *)
+ echo "Invalid mode: $1"
+ print_usage
+ ;;
+esac
diff --git a/src/spdk/dpdk/devtools/check-dup-includes.sh b/src/spdk/dpdk/devtools/check-dup-includes.sh
new file mode 100755
index 00000000..e4c2748c
--- /dev/null
+++ b/src/spdk/dpdk/devtools/check-dup-includes.sh
@@ -0,0 +1,18 @@
+#! /bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017 Mellanox Technologies, Ltd
+
+# Check C files in git repository for duplicated includes.
+# Usage: devtools/check-dup-includes.sh [directory]
+
+dir=${1:-$(dirname $(readlink -m $0))/..}
+cd $dir
+
+# speed up by ignoring Unicode details
+export LC_ALL=C
+
+for file in $(git ls-files '*.[ch]') ; do
+ sed -rn 's,^[[:space:]]*#include[[:space:]]*[<"](.*)[>"].*,\1,p' $file |
+ sort | uniq -d |
+ sed "s,^,$file: duplicated include: ,"
+done
diff --git a/src/spdk/dpdk/devtools/check-git-log.sh b/src/spdk/dpdk/devtools/check-git-log.sh
new file mode 100755
index 00000000..97dae4be
--- /dev/null
+++ b/src/spdk/dpdk/devtools/check-git-log.sh
@@ -0,0 +1,181 @@
+#! /bin/sh
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016 6WIND S.A.
+
+# Check commit logs (headlines and references)
+#
+# If any doubt about the formatting, please check in the most recent history:
+# git log --format='%>|(15)%cr %s' --reverse | grep -i <pattern>
+
+if [ "$1" = '-h' -o "$1" = '--help' ] ; then
+ cat <<- END_OF_HELP
+ usage: $(basename $0) [-h] [range]
+
+ Check commit log formatting.
+ The git range can be specified as a "git log" option,
+ e.g. -1 to check only the latest commit.
+ The default range starts from origin/master to HEAD.
+ END_OF_HELP
+ exit
+fi
+
+selfdir=$(dirname $(readlink -f $0))
+range=${1:-origin/master..}
+# convert -N to HEAD~N.. in order to comply with git-log-fixes.sh getopts
+if printf -- $range | grep -q '^-[0-9]\+' ; then
+ range="HEAD$(printf -- $range | sed 's,^-,~,').."
+fi
+
+commits=$(git log --format='%h' --reverse $range)
+headlines=$(git log --format='%s' --reverse $range)
+bodylines=$(git log --format='%b' --reverse $range)
+fixes=$(git log --format='%h %s' --reverse $range | grep -i ': *fix' | cut -d' ' -f1)
+stablefixes=$($selfdir/git-log-fixes.sh $range | sed '/(N\/A)$/d' | cut -d' ' -f2)
+tags=$(git log --format='%b' --reverse $range | grep -i -e 'by *:' -e 'fix.*:')
+bytag='\(Reported\|Suggested\|Signed-off\|Acked\|Reviewed\|Tested\)-by:'
+
+# check headline format (spacing, no punctuation, no code)
+bad=$(echo "$headlines" | grep --color=always \
+ -e ' ' \
+ -e '^ ' \
+ -e ' $' \
+ -e '\.$' \
+ -e '[,;!?&|]' \
+ -e ':.*_' \
+ -e '^[^:]\+$' \
+ -e ':[^ ]' \
+ -e ' :' \
+ | sed 's,^,\t,')
+[ -z "$bad" ] || printf "Wrong headline format:\n$bad\n"
+
+# check headline prefix when touching only drivers, e.g. net/<driver name>
+bad=$(for commit in $commits ; do
+ headline=$(git log --format='%s' -1 $commit)
+ files=$(git diff-tree --no-commit-id --name-only -r $commit)
+ [ -z "$(echo "$files" | grep -v '^\(drivers\|doc\|config\)/')" ] ||
+ continue
+ drv=$(echo "$files" | grep '^drivers/' | cut -d "/" -f 2,3 | sort -u)
+ drvgrp=$(echo "$drv" | cut -d "/" -f 1 | uniq)
+ if [ $(echo "$drvgrp" | wc -l) -gt 1 ] ; then
+ echo "$headline" | grep -v '^drivers:'
+ elif [ $(echo "$drv" | wc -l) -gt 1 ] ; then
+ echo "$headline" | grep -v "^drivers/$drvgrp"
+ else
+ echo "$headline" | grep -v "^$drv"
+ fi
+done | sed 's,^,\t,')
+[ -z "$bad" ] || printf "Wrong headline prefix:\n$bad\n"
+
+# check headline label for common typos
+bad=$(echo "$headlines" | grep --color=always \
+ -e '^example[:/]' \
+ -e '^apps/' \
+ -e '^testpmd' \
+ -e 'test-pmd' \
+ -e '^bond:' \
+ | sed 's,^,\t,')
+[ -z "$bad" ] || printf "Wrong headline label:\n$bad\n"
+
+# check headline lowercase for first words
+bad=$(echo "$headlines" | grep --color=always \
+ -e '^.*[[:upper:]].*:' \
+ -e ': *[[:upper:]]' \
+ | sed 's,^,\t,')
+[ -z "$bad" ] || printf "Wrong headline uppercase:\n$bad\n"
+
+# check headline uppercase (Rx/Tx, VF, L2, MAC, Linux, ARM...)
+bad=$(echo "$headlines" | grep -E --color=always \
+ -e ':.*\<(rx|tx|RX|TX)\>' \
+ -e ':.*\<[pv]f\>' \
+ -e ':.*\<[hsf]w\>' \
+ -e ':.*\<l[234]\>' \
+ -e ':.*\<api\>' \
+ -e ':.*\<arm\>' \
+ -e ':.*\<armv7\>' \
+ -e ':.*\<armv8\>' \
+ -e ':.*\<crc\>' \
+ -e ':.*\<dma\>' \
+ -e ':.*\<eeprom\>' \
+ -e ':.*\<freebsd\>' \
+ -e ':.*\<iova\>' \
+ -e ':.*\<linux\>' \
+ -e ':.*\<lro\>' \
+ -e ':.*\<lsc\>' \
+ -e ':.*\<mac\>' \
+ -e ':.*\<mss\>' \
+ -e ':.*\<mtu\>' \
+ -e ':.*\<nic\>' \
+ -e ':.*\<nvm\>' \
+ -e ':.*\<numa\>' \
+ -e ':.*\<pci\>' \
+ -e ':.*\<pmd\>' \
+ -e ':.*\<rss\>' \
+ -e ':.*\<sctp\>' \
+ -e ':.*\<tso\>' \
+ -e ':.*\<udp\>' \
+ -e ':.*\<[Vv]lan\>' \
+ -e ':.*\<vdpa\>' \
+ -e ':.*\<vsi\>' \
+ | sed 's,^,\t,')
+[ -z "$bad" ] || printf "Wrong headline lowercase:\n$bad\n"
+
+# special case check for VMDq to give good error message
+bad=$(echo "$headlines" | grep -E --color=always \
+ -e '\<(vmdq|VMDQ)\>' \
+ | sed 's,^,\t,')
+[ -z "$bad" ] || printf "Wrong headline capitalization, use 'VMDq':\n$bad\n"
+
+# check headline length (60 max)
+bad=$(echo "$headlines" |
+ awk 'length>60 {print}' |
+ sed 's,^,\t,')
+[ -z "$bad" ] || printf "Headline too long:\n$bad\n"
+
+# check body lines length (75 max)
+bad=$(echo "$bodylines" | grep -v '^Fixes:' |
+ awk 'length>75 {print}' |
+ sed 's,^,\t,')
+[ -z "$bad" ] || printf "Line too long:\n$bad\n"
+
+# check starting commit message with "It"
+bad=$(for commit in $commits ; do
+ firstbodyline=$(git log --format='%b' -1 $commit | head -n1)
+ echo "$firstbodyline" | grep --color=always -ie '^It '
+done | sed 's,^,\t,')
+[ -z "$bad" ] || printf "Wrong beginning of commit message:\n$bad\n"
+
+# check tags spelling
+bad=$(echo "$tags" |
+ grep -v "^$bytag [^,]* <.*@.*>$" |
+ grep -v '^Fixes: [0-9a-f]\{7\}[0-9a-f]* (".*")$' |
+ sed 's,^.,\t&,')
+[ -z "$bad" ] || printf "Wrong tag:\n$bad\n"
+
+# check missing Fixes: tag
+bad=$(for fix in $fixes ; do
+ git log --format='%b' -1 $fix | grep -q '^Fixes: ' ||
+ git log --format='\t%s' -1 $fix
+done)
+[ -z "$bad" ] || printf "Missing 'Fixes' tag:\n$bad\n"
+
+# check Fixes: reference
+IFS='
+'
+fixtags=$(echo "$tags" | grep '^Fixes: ')
+bad=$(for fixtag in $fixtags ; do
+ hash=$(echo "$fixtag" | sed 's,^Fixes: \([0-9a-f]*\).*,\1,')
+ if git branch --contains $hash 2>&- | grep -q '^\*' ; then
+ good="Fixes: $hash "$(git log --format='("%s")' -1 $hash 2>&-)
+ else
+ good="reference not in current branch"
+ fi
+ printf "$fixtag" | grep -v "^$good$"
+done | sed 's,^,\t,')
+[ -z "$bad" ] || printf "Wrong 'Fixes' reference:\n$bad\n"
+
+# check Cc: stable@dpdk.org for fixes
+bad=$(for fix in $stablefixes ; do
+ git log --format='%b' -1 $fix | grep -qi '^Cc: *stable@dpdk.org' ||
+ git log --format='\t%s' -1 $fix
+done)
+[ -z "$bad" ] || printf "Is it candidate for Cc: stable@dpdk.org backport?\n$bad\n"
diff --git a/src/spdk/dpdk/devtools/check-includes.sh b/src/spdk/dpdk/devtools/check-includes.sh
new file mode 100755
index 00000000..9057633e
--- /dev/null
+++ b/src/spdk/dpdk/devtools/check-includes.sh
@@ -0,0 +1,261 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016 6WIND S.A.
+
+# This script checks that header files in a given directory do not miss
+# dependencies when included on their own, do not conflict and accept being
+# compiled with the strictest possible flags.
+#
+# Files are looked up in the directory provided as the first argument,
+# otherwise build/include by default.
+#
+# Recognized environment variables:
+#
+# VERBOSE=1 is the same as -v.
+#
+# QUIET=1 is the same as -q.
+#
+# SUMMARY=1 is the same as -s.
+#
+# CC, CPPFLAGS, CFLAGS, EXTRA_CPPFLAGS, EXTRA_CFLAGS, CXX, CXXFLAGS and
+# EXTRA_CXXFLAGS are taken into account.
+#
+# PEDANTIC_CFLAGS, PEDANTIC_CXXFLAGS and PEDANTIC_CPPFLAGS provide strict
+# C/C++ compilation flags.
+#
+# IGNORE contains a list of shell patterns matching files (relative to the
+# include directory) to avoid. It is set by default to known DPDK headers
+# which must not be included on their own.
+#
+# IGNORE_CXX provides additional files for C++.
+
+while getopts hqvs arg; do
+ case $arg in
+ h)
+ cat <<EOF
+usage: $0 [-h] [-q] [-v] [-s] [DIR]
+
+This script checks that header files in a given directory do not miss
+dependencies when included on their own, do not conflict and accept being
+compiled with the strictest possible flags.
+
+ -h display this help and exit
+ -q quiet mode, disable normal output
+ -v show command lines being executed
+ -s show summary
+
+With no DIR, default to build/include.
+
+Any failed header check yields a nonzero exit status.
+EOF
+ exit
+ ;;
+ q)
+ QUIET=1
+ ;;
+ v)
+ VERBOSE=1
+ ;;
+ s)
+ SUMMARY=1
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+include_dir=${1:-build/include}
+
+: ${PEDANTIC_CFLAGS=-std=c99 -pedantic -Wall -Wextra -Werror}
+: ${PEDANTIC_CXXFLAGS=}
+: ${PEDANTIC_CPPFLAGS=-D_XOPEN_SOURCE=600}
+: ${CC:=cc}
+: ${CXX:=c++}
+: ${IGNORE= \
+ 'rte_atomic_32.h' \
+ 'rte_atomic_64.h' \
+ 'rte_byteorder_32.h' \
+ 'rte_byteorder_64.h' \
+ 'generic/*' \
+ 'exec-env/*' \
+ 'rte_vhost.h' \
+ 'rte_eth_vhost.h' \
+ 'rte_eal_interrupts.h' \
+}
+: ${IGNORE_CXX= \
+ 'rte_vhost.h' \
+ 'rte_eth_vhost.h' \
+}
+
+temp_cc=/tmp/${0##*/}.$$.c
+pass_cc=
+failures_cc=0
+
+temp_cxx=/tmp/${0##*/}.$$.cc
+pass_cxx=
+failures_cxx=0
+
+# Process output parameters.
+
+[ "$QUIET" = 1 ] &&
+exec 1> /dev/null
+
+[ "$VERBOSE" = 1 ] &&
+output ()
+{
+ local CCV
+ local CXXV
+
+ shift
+ CCV=$CC
+ CXXV=$CXX
+ CC="echo $CC" CXX="echo $CXX" "$@"
+ CC=$CCV
+ CXX=$CXXV
+
+ "$@"
+} ||
+output ()
+{
+
+ printf ' %s\n' "$1"
+ shift
+ "$@"
+}
+
+trap 'rm -f "$temp_cc" "$temp_cxx"' EXIT
+
+compile_cc ()
+{
+ ${CC} -I"$include_dir" \
+ ${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \
+ ${PEDANTIC_CFLAGS} ${CFLAGS} ${EXTRA_CFLAGS} \
+ -c -o /dev/null "${temp_cc}"
+}
+
+compile_cxx ()
+{
+ ${CXX} -I"$include_dir" \
+ ${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \
+ ${PEDANTIC_CXXFLAGS} ${CXXFLAGS} ${EXTRA_CXXFLAGS} \
+ -c -o /dev/null "${temp_cxx}"
+}
+
+ignore ()
+{
+ file="$1"
+ shift
+ while [ $# -ne 0 ]; do
+ case "$file" in
+ $1)
+ return 0
+ ;;
+ esac
+ shift
+ done
+ return 1
+}
+
+# Check C/C++ compilation for each header file.
+
+while read -r path
+do
+ file=${path#$include_dir}
+ file=${file##/}
+ if ignore "$file" $IGNORE; then
+ output "SKIP $file" :
+ continue
+ fi
+ if printf "\
+#include <%s>
+
+int main(void)
+{
+ return 0;
+}
+" "$file" > "$temp_cc" &&
+ output "CC $file" compile_cc
+ then
+ pass_cc="$pass_cc $file"
+ else
+ failures_cc=$(($failures_cc + 1))
+ fi
+ if ignore "$file" $IGNORE_CXX; then
+ output "SKIP CXX $file" :
+ continue
+ fi
+ if printf "\
+#include <%s>
+
+int main()
+{
+}
+" "$file" > "$temp_cxx" &&
+ output "CXX $file" compile_cxx
+ then
+ pass_cxx="$pass_cxx $file"
+ else
+ failures_cxx=$(($failures_cxx + 1))
+ fi
+done <<EOF
+$(find "$include_dir" -name '*.h')
+EOF
+
+# Check C compilation with all includes.
+
+: > "$temp_cc" &&
+for file in $pass_cc; do
+ printf "\
+#include <%s>
+" "$file" >> $temp_cc
+done
+if printf "\
+int main(void)
+{
+ return 0;
+}
+" >> "$temp_cc" &&
+ output "CC (all includes that did not fail)" compile_cc
+then
+ :
+else
+ failures_cc=$(($failures_cc + 1))
+fi
+
+# Check C++ compilation with all includes.
+
+: > "$temp_cxx" &&
+for file in $pass_cxx; do
+ printf "\
+#include <%s>
+" "$file" >> $temp_cxx
+done
+if printf "\
+int main()
+{
+}
+" >> "$temp_cxx" &&
+ output "CXX (all includes that did not fail)" compile_cxx
+then
+ :
+else
+ failures_cxx=$(($failures_cxx + 1))
+fi
+
+# Report results.
+
+if [ "$SUMMARY" = 1 ]; then
+ printf "\
+Summary:
+ %u failure(s) for C using '%s'.
+ %u failure(s) for C++ using '%s'.
+" $failures_cc "$CC" $failures_cxx "$CXX" 1>&2
+fi
+
+# Exit with nonzero status if there are failures.
+
+[ $failures_cc -eq 0 ] &&
+[ $failures_cxx -eq 0 ]
diff --git a/src/spdk/dpdk/devtools/check-maintainers.sh b/src/spdk/dpdk/devtools/check-maintainers.sh
new file mode 100755
index 00000000..85a300f0
--- /dev/null
+++ b/src/spdk/dpdk/devtools/check-maintainers.sh
@@ -0,0 +1,132 @@
+#! /bin/sh
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2015 6WIND S.A.
+
+# Do some basic checks in MAINTAINERS file
+
+cd $(dirname $0)/..
+
+# speed up by ignoring Unicode details
+export LC_ALL=C
+
+# Get files matching paths with wildcards and / meaning recursing
+files () # <path> [<path> ...]
+{
+ if [ -z "$1" ] ; then
+ return
+ fi
+ if [ -d .git ] ; then
+ git ls-files "$1"
+ else
+ find "$1" -type f |
+ sed 's,^\./,,'
+ fi |
+ # if not ended by /
+ if ! echo "$1" | grep -q '/[[:space:]]*$' ; then
+ # filter out deeper directories
+ sed "/\(\/[^/]*\)\{$(($(echo "$1" | grep -o / | wc -l) + 1))\}/d"
+ else
+ cat
+ fi
+ # next path
+ shift
+ files "$@"
+}
+
+# Get all files matching F: and X: fields
+parse_fx () # <index file>
+{
+ IFS='
+'
+ # parse each line excepted underlining
+ for line in $( (sed '/^-\+$/d' $1 ; echo) | sed 's,^$,§,') ; do
+ if echo "$line" | grep -q '^§$' ; then
+ # empty line delimit end of section
+ whitelist=$(files $flines)
+ blacklist=$(files $xlines)
+ match=$(aminusb "$whitelist" "$blacklist")
+ if [ -n "$whitelist" ] ; then
+ printf "# $title "
+ maintainers=$(echo "$maintainers" | sed -r 's,.*<(.*)>.*,\1,')
+ maintainers=$(printf "$maintainers" | sed -e 's,^,<,' -e 's,$,>,')
+ echo $maintainers
+ fi
+ if [ -n "$match" ] ; then
+ echo "$match"
+ fi
+ # flush section
+ unset maintainers
+ unset flines
+ unset xlines
+ elif echo "$line" | grep -q '^[A-Z]: ' ; then
+ # maintainer
+ maintainers=$(add_line_to_if "$line" "$maintainers" 'M: ')
+ # file matching pattern
+ flines=$(add_line_to_if "$line" "$flines" 'F: ')
+ # file exclusion pattern
+ xlines=$(add_line_to_if "$line" "$xlines" 'X: ')
+ else # assume it is a title
+ title="$line"
+ fi
+ done
+}
+
+# Check patterns in F: and X:
+check_fx () # <index file>
+{
+ IFS='
+'
+ for line in $(sed -n 's,^[FX]: ,,p' $1 | tr '*' '#') ; do
+ line=$(printf "$line" | tr '#' '*')
+ match=$(files "$line")
+ if [ -z "$match" ] ; then
+ echo "$line"
+ fi
+ done
+}
+
+# Add a line to a set of lines if it begins with right pattern
+add_line_to_if () # <new line> <lines> <head pattern>
+{
+ (
+ echo "$2"
+ echo "$1" | sed -rn "s,^$3(.*),\1,p"
+ ) |
+ sed '/^$/d'
+}
+
+# Subtract two sets of lines
+aminusb () # <lines a> <lines b>
+{
+ printf "$1\n$2\n$2" | sort | uniq -u | sed '/^$/d'
+}
+
+printf 'sections: '
+parsed=$(parse_fx MAINTAINERS)
+echo "$parsed" | grep -c '^#'
+printf 'with maintainer: '
+echo "$parsed" | grep -c '^#.*@'
+printf 'maintainers: '
+grep '^M:.*<' MAINTAINERS | sort -u | wc -l
+
+echo
+echo '##########'
+echo '# orphan areas'
+echo '##########'
+echo "$parsed" | sed -rn 's,^#([^@]*)$,\1,p' | uniq
+
+echo
+echo '##########'
+echo '# files not listed'
+echo '##########'
+all=$(files ./)
+listed=$(echo "$parsed" | sed '/^#/d' | sort -u)
+aminusb "$all" "$listed"
+
+echo
+echo '##########'
+echo '# wrong patterns'
+echo '##########'
+check_fx MAINTAINERS
+
+# TODO: check overlaps
diff --git a/src/spdk/dpdk/devtools/check-symbol-change.sh b/src/spdk/dpdk/devtools/check-symbol-change.sh
new file mode 100755
index 00000000..daaf45e1
--- /dev/null
+++ b/src/spdk/dpdk/devtools/check-symbol-change.sh
@@ -0,0 +1,159 @@
+#!/bin/sh
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Neil Horman <nhorman@tuxdriver.com>
+
+build_map_changes()
+{
+ local fname="$1"
+ local mapdb="$2"
+
+ cat "$fname" | awk '
+ # Initialize our variables
+ BEGIN {map="";sym="";ar="";sec=""; in_sec=0; in_map=0}
+
+ # Anything that starts with + or -, followed by an a
+ # and ends in the string .map is the name of our map file
+ # This may appear multiple times in a patch if multiple
+ # map files are altered, and all section/symbol names
+ # appearing between a triggering of this rule and the
+ # next trigger of this rule are associated with this file
+ /[-+] a\/.*\.map/ {map=$2; in_map=1}
+
+ # Same pattern as above, only it matches on anything that
+ # does not end in 'map', indicating we have left the map chunk.
+ # When we hit this, turn off the in_map variable, which
+ # supresses the subordonate rules below
+ /[-+] a\/.*\.^(map)/ {in_map=0}
+
+ # Triggering this rule, which starts a line with a + and ends it
+ # with a { identifies a versioned section. The section name is
+ # the rest of the line with the + and { symbols remvoed.
+ # Triggering this rule sets in_sec to 1, which actives the
+ # symbol rule below
+ /+.*{/ {gsub("+","");
+ if (in_map == 1) {
+ sec=$1; in_sec=1;
+ }
+ }
+
+ # This rule idenfies the end of a section, and disables the
+ # symbol rule
+ /.*}/ {in_sec=0}
+
+ # This rule matches on a + followed by any characters except a :
+ # (which denotes a global vs local segment), and ends with a ;.
+ # The semicolon is removed and the symbol is printed with its
+ # association file name and version section, along with an
+ # indicator that the symbol is a new addition. Note this rule
+ # only works if we have found a version section in the rule
+ # above (hence the in_sec check) And found a map file (the
+ # in_map check). If we are not in a map chunk, do nothing. If
+ # we are in a map chunk but not a section chunk, record it as
+ # unknown.
+ /^+[^}].*[^:*];/ {gsub(";","");sym=$2;
+ if (in_map == 1) {
+ if (in_sec == 1) {
+ print map " " sym " " sec " add"
+ } else {
+ print map " " sym " unknown add"
+ }
+ }
+ }
+
+ # This is the same rule as above, but the rule matches on a
+ # leading - rather than a +, denoting that the symbol is being
+ # removed.
+ /^-[^}].*[^:*];/ {gsub(";","");sym=$2;
+ if (in_map == 1) {
+ if (in_sec == 1) {
+ print map " " sym " " sec " del"
+ } else {
+ print map " " sym " unknown del"
+ }
+ }
+ }' > "$mapdb"
+
+ sort -u "$mapdb" > "$mapdb.2"
+ mv -f "$mapdb.2" "$mapdb"
+
+}
+
+check_for_rule_violations()
+{
+ local mapdb="$1"
+ local mname
+ local symname
+ local secname
+ local ar
+ local ret=0
+
+ while read mname symname secname ar
+ do
+ if [ "$ar" = "add" ]
+ then
+
+ if [ "$secname" = "unknown" ]
+ then
+ # Just inform the user of this occurrence, but
+ # don't flag it as an error
+ echo -n "INFO: symbol $syname is added but "
+ echo -n "patch has insuficient context "
+ echo -n "to determine the section name "
+ echo -n "please ensure the version is "
+ echo "EXPERIMENTAL"
+ continue
+ fi
+
+ if [ "$secname" != "EXPERIMENTAL" ]
+ then
+ # Symbols that are getting added in a section
+ # other than the experimental section
+ # to be moving from an already supported
+ # section or its a violation
+ grep -q \
+ "$mname $symname [^EXPERIMENTAL] del" "$mapdb"
+ if [ $? -ne 0 ]
+ then
+ echo -n "ERROR: symbol $symname "
+ echo -n "is added in a section "
+ echo -n "other than the EXPERIMENTAL "
+ echo "section of the version map"
+ ret=1
+ fi
+ fi
+ else
+
+ if [ "$secname" != "EXPERIMENTAL" ]
+ then
+ # Just inform users that non-experimenal
+ # symbols need to go through a deprecation
+ # process
+ echo -n "INFO: symbol $symname is being "
+ echo -n "removed, ensure that it has "
+ echo "gone through the deprecation process"
+ fi
+ fi
+ done < "$mapdb"
+
+ return $ret
+}
+
+trap clean_and_exit_on_sig EXIT
+
+mapfile=`mktemp mapdb.XXXXXX`
+patch=$1
+exit_code=1
+
+clean_and_exit_on_sig()
+{
+ rm -f "$mapfile"
+ exit $exit_code
+}
+
+build_map_changes "$patch" "$mapfile"
+check_for_rule_violations "$mapfile"
+exit_code=$?
+
+rm -f "$mapfile"
+
+exit $exit_code
diff --git a/src/spdk/dpdk/devtools/check-symbol-maps.sh b/src/spdk/dpdk/devtools/check-symbol-maps.sh
new file mode 100755
index 00000000..e137d48a
--- /dev/null
+++ b/src/spdk/dpdk/devtools/check-symbol-maps.sh
@@ -0,0 +1,30 @@
+#! /bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2018 Mellanox Technologies, Ltd
+
+cd $(dirname $0)/..
+
+# speed up by ignoring Unicode details
+export LC_ALL=C
+
+find_orphan_symbols ()
+{
+ for map in $(find lib drivers -name '*.map') ; do
+ for sym in $(sed -rn 's,^([^}]*_.*);,\1,p' $map) ; do
+ if echo $sym | grep -q '^per_lcore_' ; then
+ continue
+ fi
+ if ! grep -q -r --exclude=$(basename $map) \
+ -w $sym $(dirname $map) ; then
+ echo "$map: $sym"
+ fi
+ done
+ done
+}
+
+orphan_symbols=$(find_orphan_symbols)
+if [ -n "$orphan_symbols" ] ; then
+ echo "Found only in symbol map file:"
+ echo "$orphan_symbols" | sed 's,^,\t,'
+ exit 1
+fi
diff --git a/src/spdk/dpdk/devtools/checkpatches.sh b/src/spdk/dpdk/devtools/checkpatches.sh
new file mode 100755
index 00000000..ba795ad1
--- /dev/null
+++ b/src/spdk/dpdk/devtools/checkpatches.sh
@@ -0,0 +1,226 @@
+#! /bin/sh
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2015 6WIND S.A.
+
+# Load config options:
+# - DPDK_CHECKPATCH_PATH
+# - DPDK_CHECKPATCH_LINE_LENGTH
+. $(dirname $(readlink -e $0))/load-devel-config
+
+VALIDATE_NEW_API=$(dirname $(readlink -e $0))/check-symbol-change.sh
+
+length=${DPDK_CHECKPATCH_LINE_LENGTH:-80}
+
+# override default Linux options
+options="--no-tree"
+options="$options --max-line-length=$length"
+options="$options --show-types"
+options="$options --ignore=LINUX_VERSION_CODE,\
+FILE_PATH_CHANGES,MAINTAINERS_STYLE,SPDX_LICENSE_TAG,\
+VOLATILE,PREFER_PACKED,PREFER_ALIGNED,PREFER_PRINTF,\
+PREFER_KERNEL_TYPES,BIT_MACRO,CONST_STRUCT,\
+SPLIT_STRING,LONG_LINE_STRING,\
+LINE_SPACING,PARENTHESIS_ALIGNMENT,NETWORKING_BLOCK_COMMENT_STYLE,\
+NEW_TYPEDEFS,COMPARISON_TO_NULL"
+
+clean_tmp_files() {
+ if echo $tmpinput | grep -q '^checkpatches\.' ; then
+ rm -f "$tmpinput"
+ fi
+}
+
+trap "clean_tmp_files" INT
+
+print_usage () {
+ cat <<- END_OF_HELP
+ usage: $(basename $0) [-q] [-v] [-nX|patch1 [patch2] ...]]
+
+ Run Linux kernel checkpatch.pl with DPDK options.
+ The environment variable DPDK_CHECKPATCH_PATH must be set.
+
+ The patches to check can be from stdin, files specified on the command line,
+ or latest git commits limited with -n option (default limit: origin/master).
+ END_OF_HELP
+}
+
+check_forbidden_additions() {
+ # This awk script receives a list of expressions to monitor
+ # and a list of folders to search these expressions in
+ # - No search is done inside comments
+ # - Both additions and removals of the expressions are checked
+ # A positive balance of additions fails the check
+ read -d '' awk_script << 'EOF'
+ BEGIN {
+ split(FOLDERS,deny_folders," ");
+ split(EXPRESSIONS,deny_expr," ");
+ in_file=0;
+ in_comment=0;
+ count=0;
+ comment_start="/*"
+ comment_end="*/"
+ }
+ # search for add/remove instances in current file
+ # state machine assumes the comments structure is enforced by
+ # checkpatches.pl
+ (in_file) {
+ # comment start
+ if (index($0,comment_start) > 0) {
+ in_comment = 1
+ }
+ # non comment code
+ if (in_comment == 0) {
+ for (i in deny_expr) {
+ forbidden_added = "^\+.*" deny_expr[i];
+ forbidden_removed="^-.*" deny_expr[i];
+ current = expressions[deny_expr[i]]
+ if ($0 ~ forbidden_added) {
+ count = count + 1;
+ expressions[deny_expr[i]] = current + 1
+ }
+ if ($0 ~ forbidden_removed) {
+ count = count - 1;
+ expressions[deny_expr[i]] = current - 1
+ }
+ }
+ }
+ # comment end
+ if (index($0,comment_end) > 0) {
+ in_comment = 0
+ }
+ }
+ # switch to next file , check if the balance of add/remove
+ # of previous filehad new additions
+ ($0 ~ "^\+\+\+ b/") {
+ in_file = 0;
+ if (count > 0) {
+ exit;
+ }
+ for (i in deny_folders) {
+ re = "^\+\+\+ b/" deny_folders[i];
+ if ($0 ~ deny_folders[i]) {
+ in_file = 1
+ last_file = $0
+ }
+ }
+ }
+ END {
+ if (count > 0) {
+ print "Warning in " substr(last_file,6) ":"
+ print "are you sure you want to add the following:"
+ for (key in expressions) {
+ if (expressions[key] > 0) {
+ print key
+ }
+ }
+ exit RET_ON_FAIL
+ }
+ }
+EOF
+ # ---------------------------------
+ # refrain from new additions of rte_panic() and rte_exit()
+ # multiple folders and expressions are separated by spaces
+ awk -v FOLDERS="lib drivers" \
+ -v EXPRESSIONS="rte_panic\\\( rte_exit\\\(" \
+ -v RET_ON_FAIL=1 \
+ "$awk_script" -
+}
+
+number=0
+quiet=false
+verbose=false
+while getopts hn:qv ARG ; do
+ case $ARG in
+ n ) number=$OPTARG ;;
+ q ) quiet=true ;;
+ v ) verbose=true ;;
+ h ) print_usage ; exit 0 ;;
+ ? ) print_usage ; exit 1 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+if [ ! -f "$DPDK_CHECKPATCH_PATH" ] || [ ! -x "$DPDK_CHECKPATCH_PATH" ] ; then
+ print_usage >&2
+ echo
+ echo 'Cannot execute DPDK_CHECKPATCH_PATH' >&2
+ exit 1
+fi
+
+total=0
+status=0
+
+check () { # <patch> <commit> <title>
+ local ret=0
+
+ total=$(($total + 1))
+ ! $verbose || printf '\n### %s\n\n' "$3"
+ if [ -n "$1" ] ; then
+ tmpinput=$1
+ elif [ -n "$2" ] ; then
+ tmpinput=$(mktemp checkpatches.XXXXXX)
+ git format-patch --find-renames \
+ --no-stat --stdout -1 $commit > "$tmpinput"
+ else
+ tmpinput=$(mktemp checkpatches.XXXXXX)
+ cat > "$tmpinput"
+ fi
+
+ report=$($DPDK_CHECKPATCH_PATH $options "$tmpinput" 2>/dev/null)
+ if [ $? -ne 0 ] ; then
+ $verbose || printf '\n### %s\n\n' "$3"
+ printf '%s\n' "$report" | sed -n '1,/^total:.*lines checked$/p'
+ ret=1
+ fi
+
+ ! $verbose || printf '\nChecking API additions/removals:\n'
+ report=$($VALIDATE_NEW_API "$tmpinput")
+ if [ $? -ne 0 ] ; then
+ printf '%s\n' "$report"
+ ret=1
+ fi
+
+ ! $verbose || printf '\nChecking forbidden tokens additions:\n'
+ report=$(check_forbidden_additions <"$tmpinput")
+ if [ $? -ne 0 ] ; then
+ printf '%s\n' "$report"
+ ret=1
+ fi
+
+ clean_tmp_files
+ [ $ret -eq 0 ] && return 0
+
+ status=$(($status + 1))
+}
+
+if [ -n "$1" ] ; then
+ for patch in "$@" ; do
+ # Subject can be on 2 lines
+ subject=$(sed '/^Subject: */!d;s///;N;s,\n[[:space:]]\+, ,;s,\n.*,,;q' "$patch")
+ check "$patch" '' "$subject"
+ done
+elif [ ! -t 0 ] ; then # stdin
+ subject=$(while read header value ; do
+ if [ "$header" = 'Subject:' ] ; then
+ IFS= read next
+ continuation=$(echo "$next" | sed -n 's,^[[:space:]]\+, ,p')
+ echo $value$continuation
+ break
+ fi
+ done)
+ check '' '' "$subject"
+else
+ if [ $number -eq 0 ] ; then
+ commits=$(git rev-list --reverse origin/master..)
+ else
+ commits=$(git rev-list --reverse --max-count=$number HEAD)
+ fi
+ for commit in $commits ; do
+ subject=$(git log --format='%s' -1 $commit)
+ check '' $commit "$subject"
+ done
+fi
+pass=$(($total - $status))
+$quiet || printf '\n%d/%d valid patch' $pass $total
+$quiet || [ $pass -le 1 ] || printf 'es'
+$quiet || printf '\n'
+exit $status
diff --git a/src/spdk/dpdk/devtools/cocci.sh b/src/spdk/dpdk/devtools/cocci.sh
new file mode 100755
index 00000000..4ca5025f
--- /dev/null
+++ b/src/spdk/dpdk/devtools/cocci.sh
@@ -0,0 +1,64 @@
+#! /bin/sh
+
+# BSD LICENSE
+#
+# Copyright 2015 EZchip Semiconductor Ltd.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of EZchip Semiconductor nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Apply coccinelle transforms.
+
+SRCTREE=$(readlink -f $(dirname $0)/..)
+COCCI=$SRCTREE/devtools/cocci
+[ -n "$SPATCH" ] || SPATCH=$(which spatch)
+
+PATCH_LIST="$@"
+[ -n "$PATCH_LIST" ] || PATCH_LIST=$(echo $COCCI/*.cocci)
+
+[ -x "$SPATCH" ] || (
+ echo "Coccinelle tools not installed."
+ exit 1
+)
+
+tmp=$(mktemp)
+
+for c in $PATCH_LIST; do
+ while true; do
+ echo -n "Applying $c..."
+ $SPATCH --sp-file $c -c --linux-spacing --very-quiet \
+ --include-headers --preprocess \
+ --in-place --dir $SRCTREE > $tmp
+ if [ -s $tmp ]; then
+ echo " changes applied, retrying."
+ else
+ echo " no change."
+ break;
+ fi
+ done
+done
+
+rm -f $tmp
diff --git a/src/spdk/dpdk/devtools/cocci/mtod-offset.cocci b/src/spdk/dpdk/devtools/cocci/mtod-offset.cocci
new file mode 100644
index 00000000..3f83f322
--- /dev/null
+++ b/src/spdk/dpdk/devtools/cocci/mtod-offset.cocci
@@ -0,0 +1,76 @@
+//
+// Replace explicit packet offset computations with rte_pktmbuf_mtod_offset().
+//
+@disable paren@
+typedef uint8_t;
+expression M, O;
+@@
+(
+- rte_pktmbuf_mtod(M, char *) + O
++ rte_pktmbuf_mtod_offset(M, char *, O)
+|
+- rte_pktmbuf_mtod(M, char *) - O
++ rte_pktmbuf_mtod_offset(M, char *, -O)
+|
+- rte_pktmbuf_mtod(M, unsigned char *) + O
++ rte_pktmbuf_mtod_offset(M, unsigned char *, O)
+|
+- rte_pktmbuf_mtod(M, unsigned char *) - O
++ rte_pktmbuf_mtod_offset(M, unsigned char *, -O)
+|
+- rte_pktmbuf_mtod(M, uint8_t *) + O
++ rte_pktmbuf_mtod_offset(M, uint8_t *, O)
+|
+- rte_pktmbuf_mtod(M, uint8_t *) - O
++ rte_pktmbuf_mtod_offset(M, uint8_t *, -O)
+)
+
+
+//
+// Fold subsequent offset terms into pre-existing offset used in
+// rte_pktmbuf_mtod_offset().
+//
+@disable paren@
+expression M, O1, O2;
+@@
+(
+- rte_pktmbuf_mtod_offset(M, char *, O1) + O2
++ rte_pktmbuf_mtod_offset(M, char *, O1 + O2)
+|
+- rte_pktmbuf_mtod_offset(M, char *, O1) - O2
++ rte_pktmbuf_mtod_offset(M, char *, O1 - O2)
+|
+- rte_pktmbuf_mtod_offset(M, unsigned char *, O1) + O2
++ rte_pktmbuf_mtod_offset(M, unsigned char *, O1 + O2)
+|
+- rte_pktmbuf_mtod_offset(M, unsigned char *, O1) - O2
++ rte_pktmbuf_mtod_offset(M, unsigned char *, O1 - O2)
+|
+- rte_pktmbuf_mtod_offset(M, uint8_t *, O1) + O2
++ rte_pktmbuf_mtod_offset(M, uint8_t *, O1 + O2)
+|
+- rte_pktmbuf_mtod_offset(M, uint8_t *, O1) - O2
++ rte_pktmbuf_mtod_offset(M, uint8_t *, O1 - O2)
+)
+
+
+//
+// Cleanup rules. Fold in double casts, remove unnecessary parenthesis, etc.
+//
+@disable paren@
+expression M, O;
+type C, T;
+@@
+(
+- (C)rte_pktmbuf_mtod_offset(M, T, O)
++ rte_pktmbuf_mtod_offset(M, C, O)
+|
+- (rte_pktmbuf_mtod_offset(M, T, O))
++ rte_pktmbuf_mtod_offset(M, T, O)
+|
+- (C)rte_pktmbuf_mtod(M, T)
++ rte_pktmbuf_mtod(M, C)
+|
+- (rte_pktmbuf_mtod(M, T))
++ rte_pktmbuf_mtod(M, T)
+)
diff --git a/src/spdk/dpdk/devtools/cocci/strlcpy.cocci b/src/spdk/dpdk/devtools/cocci/strlcpy.cocci
new file mode 100644
index 00000000..335e2712
--- /dev/null
+++ b/src/spdk/dpdk/devtools/cocci/strlcpy.cocci
@@ -0,0 +1,8 @@
+@use_strlcpy@
+identifier src, dst;
+expression size;
+@@
+(
+- snprintf(dst, size, "%s", src)
++ strlcpy(dst, src, size)
+)
diff --git a/src/spdk/dpdk/devtools/get-maintainer.sh b/src/spdk/dpdk/devtools/get-maintainer.sh
new file mode 100755
index 00000000..b9160486
--- /dev/null
+++ b/src/spdk/dpdk/devtools/get-maintainer.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+
+# Load config options:
+# - DPDK_GETMAINTAINER_PATH
+. $(dirname $(readlink -e $0))/load-devel-config
+
+options="--no-git-fallback"
+options="$options --no-rolestats"
+
+print_usage () {
+ cat <<- END_OF_HELP
+ usage: $(basename $0) <patch>
+
+ The DPDK_GETMAINTAINER_PATH variable should be set to the full path to
+ the get_maintainer.pl script located in Linux kernel sources. Example:
+ DPDK_GETMAINTAINER_PATH=~/linux/scripts/get_maintainer.pl
+
+ Also refer to devtools/load-devel-config to store your configuration.
+ END_OF_HELP
+}
+
+# Requires DPDK_GETMAINTAINER_PATH devel config option set
+if [ ! -f "$DPDK_GETMAINTAINER_PATH" ] ||
+ [ ! -x "$DPDK_GETMAINTAINER_PATH" ] ; then
+ print_usage >&2
+ echo
+ echo 'Cannot execute DPDK_GETMAINTAINER_PATH' >&2
+ exit 1
+fi
+
+FILES="COPYING CREDITS Kbuild"
+FOLDERS="Documentation arch include fs init ipc scripts"
+
+# Kernel script checks for some files and folders to run
+workaround () {
+ for f in $FILES; do
+ if [ ! -f $f ]; then touch $f; fi
+ done
+
+ for d in $FOLDERS; do
+ if [ ! -d $d ]; then mkdir $d; fi
+ done
+}
+
+fix_workaround () {
+ for f in $FILES; do if [ -f $f ]; then rm -f $f; fi; done
+ for d in $FOLDERS; do if [ -d $d ]; then rmdir $d; fi; done
+}
+
+# clean workaround on exit
+trap fix_workaround EXIT
+
+workaround
+$DPDK_GETMAINTAINER_PATH $options $@
+# fix_workaround called on exit by trap
diff --git a/src/spdk/dpdk/devtools/git-log-fixes.sh b/src/spdk/dpdk/devtools/git-log-fixes.sh
new file mode 100755
index 00000000..e37ee226
--- /dev/null
+++ b/src/spdk/dpdk/devtools/git-log-fixes.sh
@@ -0,0 +1,112 @@
+#! /bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016 6WIND S.A.
+
+print_usage ()
+{
+ echo "usage: $(basename $0) [-h] <git_range>"
+}
+
+print_help ()
+{
+ print_usage
+ cat <<- END_OF_HELP
+
+ Find fixes to backport on previous versions.
+ It looks for the word "fix" in the headline or a tag "Fixes" or "Reverts".
+ The oldest bug origin is printed as well as partially fixed versions.
+ END_OF_HELP
+}
+
+usage_error () # <message>
+{
+ echo "$*" >&2
+ print_usage >&2
+ exit 1
+}
+
+while getopts h ARG ; do
+ case $ARG in
+ h ) print_help ; exit 0 ;;
+ ? ) print_usage >&2 ; exit 1 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+[ $# -ge 1 ] || usage_error 'range argument required'
+range="$*"
+
+# get major release version of a commit
+commit_version () # <hash>
+{
+ # use current branch as history reference
+ local refbranch=$(git rev-parse --abbrev-ref HEAD)
+ local tag=$( (git tag -l --contains $1 --merged $refbranch 2>&- ||
+ # tag --merged option has been introduced in git 2.7.0
+ # below is a fallback in case of old git version
+ for t in $(git tag -l --contains $1) ; do
+ git branch $refbranch --contains $t |
+ sed "s,.\+,$t,"
+ done) |
+ head -n1)
+ if [ -z "$tag" ] ; then
+ # before -rc1 tag of release in progress
+ make showversion | cut -d'.' -f-2
+ else
+ echo $tag | sed 's,^v,,' | sed 's,-rc.*,,'
+ fi
+}
+
+# get bug origin hashes of a fix
+origin_filter () # <hash>
+{
+ git log --format='%b' -1 $1 |
+ sed -n 's,^ *\([Ff]ixes\|[Rr]everts\): *\([0-9a-f]*\).*,\2,p'
+}
+
+# get oldest major release version of bug origins
+origin_version () # <origin_hash> ...
+{
+ for origin in $* ; do
+ # check hash is valid
+ git rev-parse -q --verify $1 >&- || continue
+ # get version of this bug origin
+ local origver=$(commit_version $origin)
+ local roothashes="$(origin_filter $origin)"
+ if [ -n "$roothashes" ] ; then
+ # look chained fix of fix recursively
+ local rootver="$(origin_version $roothashes)"
+ [ -n "$rootver" ] || continue
+ echo "$rootver (partially fixed in $origver)"
+ else
+ echo "$origver"
+ fi
+ # filter the oldest origin
+ done | sort -uV | head -n1
+}
+
+# print a marker for stable tag presence
+stable_tag () # <hash>
+{
+ if git log --format='%b' -1 $1 | grep -qi '^Cc: *stable@dpdk.org' ; then
+ echo 'S'
+ else
+ echo '-'
+ fi
+}
+
+git log --oneline --reverse $range |
+while read id headline ; do
+ origins=$(origin_filter $id)
+ stable=$(stable_tag $id)
+ [ "$stable" = "S" ] || [ -n "$origins" ] || echo "$headline" | grep -q fix || continue
+ version=$(commit_version $id)
+ if [ -n "$origins" ] ; then
+ origver="$(origin_version $origins)"
+ [ -n "$origver" ] || continue
+ # ignore fix of bug introduced in the same release
+ ! echo "$origver" | grep -q "^$version" || continue
+ else
+ origver='N/A'
+ fi
+ printf '%s %7s %s %s (%s)\n' $version $id $stable "$headline" "$origver"
+done
diff --git a/src/spdk/dpdk/devtools/load-devel-config b/src/spdk/dpdk/devtools/load-devel-config
new file mode 100644
index 00000000..4f43cb35
--- /dev/null
+++ b/src/spdk/dpdk/devtools/load-devel-config
@@ -0,0 +1,12 @@
+# Load DPDK devel config and allow override
+# from system file
+test ! -r /etc/dpdk/devel.config ||
+ . /etc/dpdk/devel.config
+# from user file
+test ! -r ~/.config/dpdk/devel.config ||
+ . ~/.config/dpdk/devel.config
+# from local file
+test ! -r $(dirname $(readlink -m $0))/../.develconfig ||
+ . $(dirname $(readlink -m $0))/../.develconfig
+
+# The config files must export variables in the shell style
diff --git a/src/spdk/dpdk/devtools/test-build.sh b/src/spdk/dpdk/devtools/test-build.sh
new file mode 100755
index 00000000..1eee2417
--- /dev/null
+++ b/src/spdk/dpdk/devtools/test-build.sh
@@ -0,0 +1,244 @@
+#! /bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2015 6WIND S.A.
+
+default_path=$PATH
+
+# Load config options:
+# - ARMV8_CRYPTO_LIB_PATH
+# - DPDK_BUILD_TEST_CONFIGS (defconfig1+option1+option2 defconfig2)
+# - DPDK_DEP_ARCHIVE
+# - DPDK_DEP_CFLAGS
+# - DPDK_DEP_ISAL (y/[n])
+# - DPDK_DEP_LDFLAGS
+# - DPDK_DEP_MLX (y/[n])
+# - DPDK_DEP_NUMA ([y]/n)
+# - DPDK_DEP_PCAP (y/[n])
+# - DPDK_DEP_SSL (y/[n])
+# - DPDK_DEP_IPSEC_MB (y/[n])
+# - DPDK_DEP_SZE (y/[n])
+# - DPDK_DEP_ZLIB (y/[n])
+# - DPDK_MAKE_JOBS (int)
+# - DPDK_NOTIFY (notify-send)
+# - FLEXRAN_SDK
+# - LIBMUSDK_PATH
+# - LIBSSO_SNOW3G_PATH
+# - LIBSSO_KASUMI_PATH
+# - LIBSSO_ZUC_PATH
+. $(dirname $(readlink -e $0))/load-devel-config
+
+print_usage () {
+ echo "usage: $(basename $0) [-h] [-jX] [-s] [config1 [config2] ...]]"
+}
+
+print_help () {
+ echo 'Test building several targets with different options'
+ echo
+ print_usage
+ cat <<- END_OF_HELP
+
+ options:
+ -h this help
+ -jX use X parallel jobs in "make"
+ -s short test only first config without tests|examples|doc
+ -v verbose build
+
+ config: defconfig[[~][+]option1[[~][+]option2...]]
+ Example: x86_64-native-linuxapp-gcc+debug~RXTX_CALLBACKS
+ The lowercase options are defined inside $(basename $0).
+ The uppercase options can be the end of a defconfig option
+ to enable if prefixed with '+' or to disable if prefixed with '~'.
+ Default is to automatically enable most of the options.
+ The external dependencies are setup with DPDK_DEP_* variables.
+ If no config on command line, DPDK_BUILD_TEST_CONFIGS is used.
+ END_OF_HELP
+}
+
+J=$DPDK_MAKE_JOBS
+short=false
+unset verbose
+maxerr=-Wfatal-errors
+while getopts hj:sv ARG ; do
+ case $ARG in
+ j ) J=$OPTARG ;;
+ s ) short=true ;;
+ v ) verbose='V=1' ;;
+ h ) print_help ; exit 0 ;;
+ ? ) print_usage ; exit 1 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+configs=${*:-$DPDK_BUILD_TEST_CONFIGS}
+
+success=false
+on_exit ()
+{
+ if $success ; then
+ [ "$DPDK_NOTIFY" != notify-send ] || \
+ notify-send -u low --icon=dialog-information 'DPDK build' 'finished'
+ elif [ -z "$signal" ] ; then
+ [ -z "$dir" ] || echo "failed to build $dir" >&2
+ [ "$DPDK_NOTIFY" != notify-send ] || \
+ notify-send -u low --icon=dialog-error 'DPDK build' 'failed'
+ fi
+}
+# catch manual interrupt to ignore notification
+trap "signal=INT ; trap - INT ; kill -INT $$" INT
+# notify result on exit
+trap on_exit EXIT
+
+cd $(dirname $(readlink -m $0))/..
+
+reset_env ()
+{
+ export PATH=$default_path
+ unset CROSS
+ unset DPDK_DEP_ARCHIVE
+ unset DPDK_DEP_CFLAGS
+ unset DPDK_DEP_ISAL
+ unset DPDK_DEP_LDFLAGS
+ unset DPDK_DEP_MLX
+ unset DPDK_DEP_NUMA
+ unset DPDK_DEP_PCAP
+ unset DPDK_DEP_SSL
+ unset DPDK_DEP_IPSEC_MB
+ unset DPDK_DEP_SZE
+ unset DPDK_DEP_ZLIB
+ unset ARMV8_CRYPTO_LIB_PATH
+ unset FLEXRAN_SDK
+ unset LIBMUSDK_PATH
+ unset LIBSSO_SNOW3G_PATH
+ unset LIBSSO_KASUMI_PATH
+ unset LIBSSO_ZUC_PATH
+ unset PQOS_INSTALL_PATH
+}
+
+config () # <directory> <target> <options>
+{
+ reconfig=false
+ if git rev-parse 2>&- && [ -n "$(git diff HEAD~ -- config)" ] ; then
+ echo 'Default config may have changed'
+ reconfig=true
+ fi
+ if [ ! -e $1/.config ] || $reconfig ; then
+ echo "================== Configure $1"
+ make T=$2 O=$1 config
+
+ echo 'Customize configuration'
+ # Built-in options (lowercase)
+ ! echo $3 | grep -q '+default' || \
+ sed -ri 's,(RTE_MACHINE=")native,\1default,' $1/.config
+ echo $3 | grep -q '+next' || \
+ sed -ri 's,(NEXT_ABI=)y,\1n,' $1/.config
+ ! echo $3 | grep -q '+shared' || \
+ sed -ri 's,(SHARED_LIB=)n,\1y,' $1/.config
+ ! echo $3 | grep -q '+debug' || ( \
+ sed -ri 's,(RTE_LOG_DP_LEVEL=).*,\1RTE_LOG_DEBUG,' $1/.config
+ sed -ri 's,(_DEBUG.*=)n,\1y,' $1/.config
+ sed -ri 's,(_STAT.*=)n,\1y,' $1/.config
+ sed -ri 's,(TEST_PMD_RECORD_.*=)n,\1y,' $1/.config )
+
+ # Automatic configuration
+ test "$DPDK_DEP_NUMA" != n || \
+ sed -ri 's,(NUMA.*=)y,\1n,' $1/.config
+ sed -ri 's,(LIBRTE_IEEE1588=)n,\1y,' $1/.config
+ sed -ri 's,(BYPASS=)n,\1y,' $1/.config
+ test "$DPDK_DEP_ARCHIVE" != y || \
+ sed -ri 's,(RESOURCE_TAR=)n,\1y,' $1/.config
+ test "$DPDK_DEP_ISAL" != y || \
+ sed -ri 's,(ISAL_PMD=)n,\1y,' $1/.config
+ test "$DPDK_DEP_MLX" != y || \
+ sed -ri 's,(MLX._PMD=)n,\1y,' $1/.config
+ test "$DPDK_DEP_SZE" != y || \
+ sed -ri 's,(PMD_SZEDATA2=)n,\1y,' $1/.config
+ test "$DPDK_DEP_ZLIB" != y || \
+ sed -ri 's,(BNX2X_PMD=)n,\1y,' $1/.config
+ test "$DPDK_DEP_ZLIB" != y || \
+ sed -ri 's,(COMPRESSDEV_TEST=)n,\1y,' $1/.config
+ test "$DPDK_DEP_PCAP" != y || \
+ sed -ri 's,(PCAP=)n,\1y,' $1/.config
+ test -z "$ARMV8_CRYPTO_LIB_PATH" || \
+ sed -ri 's,(PMD_ARMV8_CRYPTO=)n,\1y,' $1/.config
+ test "$DPDK_DEP_IPSEC_MB" != y || \
+ sed -ri 's,(PMD_AESNI_MB=)n,\1y,' $1/.config
+ test "$DPDK_DEP_IPSEC_MB" != y || \
+ sed -ri 's,(PMD_AESNI_GCM=)n,\1y,' $1/.config
+ test -z "$LIBSSO_SNOW3G_PATH" || \
+ sed -ri 's,(PMD_SNOW3G=)n,\1y,' $1/.config
+ test -z "$LIBSSO_KASUMI_PATH" || \
+ sed -ri 's,(PMD_KASUMI=)n,\1y,' $1/.config
+ test -z "$LIBSSO_ZUC_PATH" || \
+ sed -ri 's,(PMD_ZUC=)n,\1y,' $1/.config
+ test "$DPDK_DEP_SSL" != y || \
+ sed -ri 's,(PMD_CCP=)n,\1y,' $1/.config
+ test "$DPDK_DEP_SSL" != y || \
+ sed -ri 's,(PMD_OPENSSL=)n,\1y,' $1/.config
+ test "$DPDK_DEP_SSL" != y || \
+ sed -ri 's,(PMD_QAT=)n,\1y,' $1/.config
+ test -z "$FLEXRAN_SDK" || \
+ sed -ri 's,(BBDEV_TURBO_SW=)n,\1y,' $1/.config
+ sed -ri 's,(SCHED_.*=)n,\1y,' $1/.config
+ test -z "$LIBMUSDK_PATH" || \
+ sed -ri 's,(PMD_MVSAM_CRYPTO=)n,\1y,' $1/.config
+ test -z "$LIBMUSDK_PATH" || \
+ sed -ri 's,(MVPP2_PMD=)n,\1y,' $1/.config
+ build_config_hook $1 $2 $3
+
+ # Explicit enabler/disabler (uppercase)
+ for option in $(echo $3 | sed 's,[~+], &,g') ; do
+ pattern=$(echo $option | cut -c2-)
+ if echo $option | grep -q '^~' ; then
+ sed -ri "s,($pattern=)y,\1n," $1/.config
+ elif echo $option | grep -q '^+' ; then
+ sed -ri "s,($pattern=)n,\1y," $1/.config
+ fi
+ done
+ fi
+}
+
+# default empty hook to override in devel config
+build_config_hook () # <directory> <target> <options>
+{
+ :
+}
+
+for conf in $configs ; do
+ target=$(echo $conf | sed 's,[~+].*,,')
+ # reload config with DPDK_TARGET set
+ DPDK_TARGET=$target
+ reset_env
+ . $(dirname $(readlink -e $0))/load-devel-config
+
+ options=$(echo $conf | sed 's,[^~+]*,,')
+ dir=$conf
+ config $dir $target $options
+
+ echo "================== Build $dir"
+ make -j$J EXTRA_CFLAGS="$maxerr $DPDK_DEP_CFLAGS" \
+ EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose O=$dir
+ ! $short || break
+ echo "================== Build tests for $dir"
+ make test-build -j$J EXTRA_CFLAGS="$maxerr $DPDK_DEP_CFLAGS" \
+ EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose O=$dir
+ echo "================== Build examples for $dir"
+ export RTE_SDK=$(pwd)
+ export RTE_TARGET=$dir
+ make -j$J -sC examples \
+ EXTRA_LDFLAGS="$DPDK_DEP_LDFLAGS" $verbose \
+ O=$(readlink -m $dir/examples)
+ unset RTE_TARGET
+ echo "################## $dir done."
+ unset dir
+done
+
+if ! $short ; then
+ mkdir -p .check
+ echo "================== Build doxygen HTML API"
+ make doc-api-html >/dev/null 2>.check/doc.txt
+ echo "================== Build sphinx HTML guides"
+ make doc-guides-html >/dev/null 2>>.check/doc.txt
+ echo "================== Check docs"
+ diff -u /dev/null .check/doc.txt
+fi
+
+success=true
diff --git a/src/spdk/dpdk/devtools/test-meson-builds.sh b/src/spdk/dpdk/devtools/test-meson-builds.sh
new file mode 100755
index 00000000..951c9067
--- /dev/null
+++ b/src/spdk/dpdk/devtools/test-meson-builds.sh
@@ -0,0 +1,60 @@
+#! /bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2018 Intel Corporation
+
+# Run meson to auto-configure the various builds.
+# * all builds get put in a directory whose name starts with "build-"
+# * if a build-directory already exists we assume it was properly configured
+# Run ninja after configuration is done.
+
+srcdir=$(dirname $(readlink -m $0))/..
+MESON=${MESON:-meson}
+
+if command -v ninja >/dev/null 2>&1 ; then
+ ninja_cmd=ninja
+elif command -v ninja-build >/dev/null 2>&1 ; then
+ ninja_cmd=ninja-build
+else
+ echo "ERROR: ninja is not found" >&2
+ exit 1
+fi
+
+build () # <directory> <meson options>
+{
+ builddir=$1
+ shift
+ if [ ! -d "$builddir" ] ; then
+ options="--werror -Dexamples=all $*"
+ echo "$MESON $options $srcdir $builddir"
+ $MESON $options $srcdir $builddir
+ unset CC
+ fi
+ echo "$ninja_cmd -C $builddir"
+ $ninja_cmd -C $builddir
+}
+
+# shared and static linked builds with gcc and clang
+for c in gcc clang ; do
+ for s in static shared ; do
+ export CC="ccache $c"
+ build build-$c-$s --default-library=$s
+ done
+done
+
+# test compilation with minimal x86 instruction set
+build build-x86-default -Dmachine=nehalem
+
+# enable cross compilation if gcc cross-compiler is found
+c=aarch64-linux-gnu-gcc
+if command -v $c >/dev/null 2>&1 ; then
+ # compile the general v8a also for clang to increase coverage
+ export CC="ccache clang"
+ build build-arm64-host-clang --cross-file \
+ config/arm/arm64_armv8_linuxapp_gcc
+
+ for f in config/arm/arm*gcc ; do
+ export CC="ccache gcc"
+ build build-$(basename $f | tr '_' '-' | cut -d'-' -f-2) \
+ --cross-file $f
+ done
+fi
diff --git a/src/spdk/dpdk/devtools/test-null.sh b/src/spdk/dpdk/devtools/test-null.sh
new file mode 100755
index 00000000..61879e3e
--- /dev/null
+++ b/src/spdk/dpdk/devtools/test-null.sh
@@ -0,0 +1,17 @@
+#! /bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2015 6WIND S.A.
+
+# Run a quick testpmd forwarding with null PMD without hugepage
+
+build=${1:-build}
+coremask=${2:-3} # default using cores 0 and 1
+
+if grep -q SHARED_LIB=y $build/.config; then
+ pmd='-d librte_pmd_null.so'
+fi
+
+(sleep 1 && echo stop) |
+$build/app/testpmd -c $coremask -n 1 --no-huge \
+ $pmd --vdev net_null1 --vdev net_null2 -- \
+ --total-num-mbufs=2048 -ia
diff --git a/src/spdk/dpdk/devtools/validate-abi.sh b/src/spdk/dpdk/devtools/validate-abi.sh
new file mode 100755
index 00000000..138436d9
--- /dev/null
+++ b/src/spdk/dpdk/devtools/validate-abi.sh
@@ -0,0 +1,251 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2015 Neil Horman. All rights reserved.
+# Copyright(c) 2017 6WIND S.A.
+# All rights reserved
+
+set -e
+
+abicheck=abi-compliance-checker
+abidump=abi-dumper
+default_dst=abi-check
+default_target=x86_64-native-linuxapp-gcc
+
+# trap on error
+err_report() {
+ echo "$0: error at line $1"
+}
+trap 'err_report $LINENO' ERR
+
+print_usage () {
+ cat <<- END_OF_HELP
+ $(basename $0) [options] <rev1> <rev2>
+
+ This script compares the ABI of 2 git revisions of the current
+ workspace. The output is a html report and a compilation log.
+
+ The objective is to make sure that applications built against
+ DSOs from the first revision can still run when executed using
+ the DSOs built from the second revision.
+
+ <rev1> and <rev2> are git commit id or tags.
+
+ Options:
+ -h show this help
+ -j <num> enable parallel compilation with <num> threads
+ -v show compilation logs on the console
+ -d <dir> change working directory (default is ${default_dst})
+ -t <target> the dpdk target to use (default is ${default_target})
+ -f overwrite existing files in destination directory
+
+ The script returns 0 on success, or the value of last failing
+ call of ${abicheck} (incompatible abi or the tool has run with errors).
+ The errors returned by ${abidump} are ignored.
+
+ END_OF_HELP
+}
+
+# log in the file, and on stdout if verbose
+# $1: level string
+# $2: string to be logged
+log() {
+ echo "$1: $2"
+ if [ "${verbose}" != "true" ]; then
+ echo "$1: $2" >&3
+ fi
+}
+
+# launch a command and log it, taking care of surrounding spaces with quotes
+cmd() {
+ local i s whitespace ret
+ s=""
+ whitespace="[[:space:]]"
+ for i in "$@"; do
+ if [[ $i =~ $whitespace ]]; then
+ i=\"$i\"
+ fi
+ if [ -z "$s" ]; then
+ s="$i"
+ else
+ s="$s $i"
+ fi
+ done
+
+ ret=0
+ log "CMD" "$s"
+ "$@" || ret=$?
+ if [ "$ret" != "0" ]; then
+ log "CMD" "previous command returned $ret"
+ fi
+
+ return $ret
+}
+
+# redirect or copy stderr/stdout to a file
+# the syntax is unfamiliar, but it makes the rest of the
+# code easier to read, avoiding the use of pipes
+set_log_file() {
+ # save original stdout and stderr in fd 3 and 4
+ exec 3>&1
+ exec 4>&2
+ # create a new fd 5 that send to a file
+ exec 5> >(cat > $1)
+ # send stdout and stderr to fd 5
+ if [ "${verbose}" = "true" ]; then
+ exec 1> >(tee /dev/fd/5 >&3)
+ exec 2> >(tee /dev/fd/5 >&4)
+ else
+ exec 1>&5
+ exec 2>&5
+ fi
+}
+
+# Make sure we configure SHARED libraries
+# Also turn off IGB and KNI as those require kernel headers to build
+fixup_config() {
+ local conf=config/defconfig_$target
+ cmd sed -i -e"$ a\CONFIG_RTE_BUILD_SHARED_LIB=y" $conf
+ cmd sed -i -e"$ a\CONFIG_RTE_NEXT_ABI=n" $conf
+ cmd sed -i -e"$ a\CONFIG_RTE_EAL_IGB_UIO=n" $conf
+ cmd sed -i -e"$ a\CONFIG_RTE_LIBRTE_KNI=n" $conf
+ cmd sed -i -e"$ a\CONFIG_RTE_KNI_KMOD=n" $conf
+}
+
+# build dpdk for the given tag and dump abi
+# $1: hash of the revision
+gen_abi() {
+ local i
+
+ cmd git clone ${dpdkroot} ${dst}/${1}
+ cmd cd ${dst}/${1}
+
+ log "INFO" "Checking out version ${1} of the dpdk"
+ # Move to the old version of the tree
+ cmd git checkout ${1}
+
+ fixup_config
+
+ # Now configure the build
+ log "INFO" "Configuring DPDK ${1}"
+ cmd make config T=$target O=$target
+
+ # Checking abi compliance relies on using the dwarf information in
+ # the shared objects. Build with -g to include them.
+ log "INFO" "Building DPDK ${1}. This might take a moment"
+ cmd make -j$parallel O=$target V=1 EXTRA_CFLAGS="-g -Og -Wno-error" \
+ EXTRA_LDFLAGS="-g" || log "INFO" "The build failed"
+
+ # Move to the lib directory
+ cmd cd ${PWD}/$target/lib
+ log "INFO" "Collecting ABI information for ${1}"
+ for i in *.so; do
+ [ -e "$i" ] || break
+ cmd $abidump ${i} -o $dst/${1}/${i}.dump -lver ${1} || true
+ # hack to ignore empty SymbolsInfo section (no public ABI)
+ if grep -q "'SymbolInfo' => {}," $dst/${1}/${i}.dump \
+ 2> /dev/null; then
+ log "INFO" "${i} has no public ABI, remove dump file"
+ cmd rm -f $dst/${1}/${i}.dump
+ fi
+ done
+}
+
+verbose=false
+parallel=1
+dst=${default_dst}
+target=${default_target}
+force=0
+while getopts j:vd:t:fh ARG ; do
+ case $ARG in
+ j ) parallel=$OPTARG ;;
+ v ) verbose=true ;;
+ d ) dst=$OPTARG ;;
+ t ) target=$OPTARG ;;
+ f ) force=1 ;;
+ h ) print_usage ; exit 0 ;;
+ ? ) print_usage ; exit 1 ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+if [ $# != 2 ]; then
+ print_usage
+ exit 1
+fi
+
+tag1=$1
+tag2=$2
+
+# convert path to absolute
+case "${dst}" in
+ /*) ;;
+ *) dst=${PWD}/${dst} ;;
+esac
+dpdkroot=$(readlink -e $(dirname $0)/..)
+
+if [ -e "${dst}" -a "$force" = 0 ]; then
+ echo "The ${dst} directory is not empty. Remove it, use another"
+ echo "one (-d <dir>), or force overriding (-f)"
+ exit 1
+fi
+
+rm -rf ${dst}
+mkdir -p ${dst}
+set_log_file ${dst}/abi-check.log
+log "INFO" "Logs available in ${dst}/abi-check.log"
+
+command -v ${abicheck} || log "INFO" "Can't find ${abicheck} utility"
+command -v ${abidump} || log "INFO" "Can't find ${abidump} utility"
+
+hash1=$(git show -s --format=%h "$tag1" -- 2> /dev/null | tail -1)
+hash2=$(git show -s --format=%h "$tag2" -- 2> /dev/null | tail -1)
+
+# Make hashes available in output for non-local reference
+tag1="$tag1 ($hash1)"
+tag2="$tag2 ($hash2)"
+
+if [ "$hash1" = "$hash2" ]; then
+ log "ERROR" "$tag1 and $tag2 are the same revisions"
+ exit 1
+fi
+
+cmd mkdir -p ${dst}
+
+# dump abi for each revision
+gen_abi ${hash1}
+gen_abi ${hash2}
+
+# compare the abi dumps
+cmd cd ${dst}
+ret=0
+list=""
+for i in ${hash2}/*.dump; do
+ name=`basename $i`
+ libname=${name%.dump}
+
+ if [ ! -f ${hash1}/$name ]; then
+ log "INFO" "$NAME does not exist in $tag1. skipping..."
+ continue
+ fi
+
+ local_ret=0
+ cmd $abicheck -l $libname \
+ -old ${hash1}/$name -new ${hash2}/$name || local_ret=$?
+ if [ $local_ret != 0 ]; then
+ log "NOTICE" "$abicheck returned $local_ret"
+ ret=$local_ret
+ list="$list $libname"
+ fi
+done
+
+if [ $ret != 0 ]; then
+ log "NOTICE" "ABI may be incompatible, check reports/logs for details."
+ log "NOTICE" "Incompatible list: $list"
+else
+ log "NOTICE" "No error detected, ABI is compatible."
+fi
+
+log "INFO" "Logs are in ${dst}/abi-check.log"
+log "INFO" "HTML reports are in ${dst}/compat_reports directory"
+
+exit $ret