Revision 40db178a5600ef50c518628cbe0328b8a1d058a6 authored by Martynas Pumputis on 03 November 2020, 10:23:05 UTC, committed by Martynas Pumputis on 03 November 2020, 10:23:05 UTC
Signed-off-by: Martynas Pumputis <m@lambda.lt>
1 parent 6ee319d
verifier-test.sh
#!/bin/bash
#
# Copyright 2018-2020 Authors of Cilium
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -eo pipefail
DEV="cilium-probe"
DIR=$(dirname $0)/../../bpf
MAPTOOL=$(dirname $0)/../../tools/maptool/maptool
ALL_TC_PROGS="bpf_lxc bpf_host bpf_network bpf_overlay"
TC_PROGS=${TC_PROGS:-$ALL_TC_PROGS}
ALL_CG_PROGS="bpf_sock sockops/bpf_sockops sockops/bpf_redir"
CG_PROGS=${CG_PROGS:-$ALL_CG_PROGS}
ALL_XDP_PROGS="bpf_xdp"
XDP_PROGS=${XDP_PROGS:-$ALL_XDP_PROGS}
IGNORED_PROGS="bpf_alignchecker"
ALL_PROGS="${IGNORED_PROGS} ${ALL_CG_PROGS} ${ALL_TC_PROGS} ${ALL_XDP_PROGS}"
VERBOSE=false
RUN_ALL_TESTS=false
BPFFS=${BPFFS:-"/sys/fs/bpf"}
TESTMOUNT=$BPFFS/test
BPFTOOL=${BPFTOOL:-"bpftool"}
TC=${TC:-"tc"}
IPROUTE2=${IPROUTE2:-"ip"}
FEATURES=""
# The following arrays are used for loading cgroups programs, and are
# initialized in cg_prog_type_init().
#
# prog_types is keyed by a section in a bpf/*{,/*}.c source file, with
# the value as the TC prog_type argument.
declare -A prog_types
# attach_types is keyed by a section in a bpf/*{,/*}.c source file,
# with the value as the tc or bpftool attach_type argument.
declare -A attach_types
function clean_maps {
for f in $BPFFS/tc/globals/test_*; do
rm -f $f
done
}
function cleanup {
$IPROUTE2 link del ${DEV} 2>/dev/null || true
clean_maps
rm -rf ${TESTMOUNT}
}
function get_section {
grep "__section(" $DIR/$1 | sed 's/__sec[^\"]*\"\([0-9A-Za-z_-]*\).*/\1/'
}
function load_prog {
loader=$1
args=$2
name=$3
echo "=> Loading ${name}..."
if $VERBOSE; then
# Redirect stderr to stdout to assist caller parsing
${loader} $args verbose 2>&1
else
# Only run verbose mode if loading fails.
${loader} $args 2>/dev/null \
|| ${loader} $args verbose
fi
}
function load_prog_dev {
loader=$1
mode=$2
prog=$3
for section in $(get_section ${prog}.c); do
local args="dev ${DEV} ${mode} obj ${DIR}/${prog}.o sec $section"
load_prog "$loader" "$args" "$prog.c:$section"
done
}
function load_tc {
for p in ${TC_PROGS}; do
load_prog_dev "$TC filter replace" "ingress bpf da" ${p}
done
}
# $1 - Partial macro to check
function check_macro {
# $FEATURES here is deliberately unquoted to ensure the correct
# grepping behaviour, otherwise we get issues with exit code 141
$RUN_ALL_TESTS || echo $FEATURES | grep -q " HAVE_[^ ]*$1"
}
function cg_prog_type_init {
FEATURES="$($BPFTOOL feature probe macros)"
mkdir -p ${TESTMOUNT}
# These show up in sockops progs; skip them quietly.
prog_types["int"]="SKIP"
prog_types["_version"]="SKIP"
prog_types["version"]="SKIP"
if $BPFTOOL help 2>&1 | grep -q feature; then
if check_macro SOCK_OPS; then
prog_types["sockops"]="sock_ops"
attach_types["sockops"]="sock_ops"
fi
if check_macro SK_MSG; then
prog_types["sk_msg"]="sock_ops"
attach_types["sk_msg"]="msg_verdict"
fi
if check_macro CGROUP_INET4_CONNECT; then
prog_types["from-sock4"]="sockaddr"
attach_types["from-sock4"]="connect4"
fi
if check_macro CGROUP_INET6_CONNECT; then
prog_types["from-sock6"]="sockaddr"
attach_types["from-sock6"]="connect6"
fi
if check_macro UDP4_RECVMSG; then
prog_types["snd-sock4"]="sockaddr"
prog_types["rcv-sock4"]="sockaddr"
attach_types["snd-sock4"]="sendmsg4"
attach_types["rcv-sock4"]="recvmsg4"
fi
if check_macro UDP6_RECVMSG; then
prog_types["snd-sock6"]="sockaddr"
prog_types["rcv-sock6"]="sockaddr"
attach_types["snd-sock6"]="sendmsg6"
attach_types["rcv-sock6"]="recvmsg6"
fi
fi
# Hack: Get the eppolicymap and sockmap pinned
#
# Basically none of the loaders support arbitrarily creating a map
# of type 'hash_of_maps' right now, so we have a little tool in the
# repo that allows creation of this map type from the commandline.
#
# Only set it up if we determined kernel support above!
if [ "${#attach_types[@]}" -gt 1 ]; then
$MAPTOOL eppolicymap "test_cilium_ep_to_policy" 2>/dev/null
$MAPTOOL sockmap "test_sock_ops_map" 2>/dev/null
fi
}
function load_sock_prog {
prog=$1
pinpath=$2
prog_type=$3
attach_type=$4
section=$5
local args="pin $pinpath obj ${prog}.o type $prog_type \
attach_type $attach_type sec $section"
if $VERBOSE; then
$TC exec bpf $args verbose 2>&1
else
$TC exec bpf $args 2>/dev/null \
|| $TC exec bpf $args verbose
fi
}
function load_sockops_prog {
prog="$1"
pinpath="$2"
# cilium_signals is omitted from this list, because the sockops progs
# don't support BPF_MAP_TYPE_PERF_EVENT_ARRAY for now.
ALL_MAPS="cilium_ipcache cilium_ep_to_policy cilium_lxc sock_ops_map \
cilium_metrics cilium_tunnel_map cilium_encrypt_state \
cilium_lb6_reverse_nat cilium_lb6_services cilium_lb6_backends \
cilium_lb4_reverse_nat cilium_lb4_services cilium_lb4_backends \
cilium_events"
map_args=""
for map in $ALL_MAPS; do
map_args="$map_args map name test_$map pinned /sys/fs/bpf/tc/globals/test_$map"
done
echo "=> Loading ${p}.c:${section}..."
if $VERBOSE; then
$BPFTOOL -m prog load "$prog.o" "$pinpath" $map_args 2>&1
else
$BPFTOOL -m prog load "$prog.o" "$pinpath" $map_args 2>/dev/null \
|| $BPFTOOL -m prog load "$prog.o" "$pinpath" $map_args
fi
}
function load_cg {
cg_prog_type_init
mkdir -p $TESTMOUNT/sockops
for p in ${CG_PROGS}; do
ELF_SECTIONS="$(readelf -S $DIR/${p}.o)"
for section in $(get_section ${p}.c); do
if [ "${prog_types[$section]}" == "" ]; then
echo "=> Skipping ${p}.c:$section"
continue
elif [ "${prog_types[$section]}" == "SKIP" ]; then
continue
elif ! echo $ELF_SECTIONS | grep -q $section; then
echo "=> Skipping ${p}.c:$section (not found in ELF)"
continue
fi
local prog_type=${prog_types[$section]}
local attach_type=${attach_types[$section]}
if [ "$prog_type" = "sockaddr" ]; then
local args="exec bpf pin $TESTMOUNT/$p obj $DIR/${p}.o \
type $prog_type \
attach_type $attach_type sec $section"
load_prog "$TC" "$args" "${p}.o:$section"
else
load_sockops_prog "$DIR/$p" "$TESTMOUNT/$p"
fi
rm -f $TESTMOUNT/$p
done
done
}
function load_xdp {
if $IPROUTE2 link set dev ${DEV} xdpgeneric off 2>/dev/null; then
for p in ${XDP_PROGS}; do
load_prog_dev "$IPROUTE2 link set" "xdpgeneric" ${p}
done
else
echo "=> Skipping ${DIR}/bpf_xdp.c."
echo "Ensure you have linux >= 4.12 and recent iproute2 to test XDP." 1>&2
fi
}
function handle_args {
if [ $(id -u) -ne 0 ]; then
echo "Must be run as root" 1>&2
exit 1
fi
# If first argument is "-v", always set verbose
while [ $# -gt 0 ]; do
key="$1"
case "$key" in
-a|--all)
echo "Running all tests even if support detection fails" 1>&2
RUN_ALL_TESTS=true
shift;;
-v|--verbose)
VERBOSE=true
shift;;
*)
echo "Unrecognized argument '$1'" 1>&2
exit 1
;;
esac
done
}
function handle_developers {
set +e
PROG_DIFF=$(diff -u \
<(find ${DIR}/ -name "bpf*.c" | sed 's/^.*bpf\/\([^.]*\).*$/\1/' | sort) \
<(for p in ${ALL_PROGS}; do echo $p; done | sort))
PROGS_NOT_COVERED=$?
set -e
if [ $PROGS_NOT_COVERED -ne 0 ]; then
echo "This script doesn't verify all BPF programs:" 1>&2
echo "${PROG_DIFF}" | tail -n +4 1>&2
exit 1
fi
}
function main {
handle_args "$@"
handle_developers
trap cleanup EXIT
if [ "$TC_PROGS" != "" ] || [ "$XDP_PROGS" != "" ]; then
$IPROUTE2 link add ${DEV} type dummy
$TC qdisc replace dev ${DEV} clsact
fi
load_tc
load_cg
load_xdp
}
main "$@"
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...