mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
This commit introduces "check-xl-vcpupin-parse" for helping
verifying and debugging the (v)CPU bitmap parsing code in xl.
The script runs "xl -N vcpu-pin 0 all <some strings>"
repeatedly, with various input strings, and checks that the
output is as expected.
This is what the script can do:
# ./check-xl-vcpupin-parse -h
usage: ./check-xl-vcpupin-parse [options]
Tests various vcpu-pinning strings. If run without arguments acts
as follows:
- generates some test data and saves them in
check-xl-vcpupin-parse.data;
- tests all the generated configurations (reading them back from
check-xl-vcpupin-parse.data).
An example of a test vector file is provided in
check-xl-vcpupin-parse.data-example.
Options:
-h prints this message
-r seed uses seed for initializing the rundom number generator
(default: the script PID)
-s string tries using string as a vcpu pinning configuration and
reports whether that succeeds or not
-o ofile save the test data in ofile
(default: check-xl-vcpupin-parse.data)
-i ifile read test data from ifile
An example test data file (generated on a 2 NUMA nodes, 16 CPUs
host) is being provided in check-xl-vcpupin-parse.data-example.
Signed-off-by: Dario Faggioli <dario.faggioli@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
295 lines
9.0 KiB
Bash
Executable File
295 lines
9.0 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
if [ -x ./xl ] ; then
|
|
export LD_LIBRARY_PATH=.:../libxc:../xenstore:
|
|
XL=./xl
|
|
else
|
|
XL=xl
|
|
fi
|
|
|
|
fprefix=tmp.check-xl-vcpupin-parse
|
|
outfile=check-xl-vcpupin-parse.data
|
|
|
|
usage () {
|
|
cat <<END
|
|
usage: $0 [options]
|
|
|
|
Tests various vcpu-pinning strings. If run without arguments acts
|
|
as follows:
|
|
- generates some test data and saves them in $outfile;
|
|
- tests all the generated configurations (reading them back from
|
|
$outfile).
|
|
|
|
An example of a test vector file is provided in ${outfile}-example.
|
|
|
|
Options:
|
|
-h prints this message
|
|
-r seed uses seed for initializing the rundom number generator
|
|
(default: the script PID)
|
|
-s string tries using string as a vcpu pinning configuration and
|
|
reports whether that succeeds or not
|
|
-o ofile save the test data in ofile (default: $outfile)
|
|
-i ifile read test data from ifile
|
|
END
|
|
}
|
|
|
|
expected () {
|
|
cat >$fprefix.expected
|
|
}
|
|
|
|
# by default, re-seed with our PID
|
|
seed=$$
|
|
failures=0
|
|
|
|
# Execute one test and check the result against the provided
|
|
# rc value and output
|
|
one () {
|
|
expected_rc=$1; shift
|
|
printf "test case %s...\n" "$*"
|
|
set +e
|
|
${XL} -N vcpu-pin 0 all "$@" </dev/null >$fprefix.actual 2>/dev/null
|
|
actual_rc=$?
|
|
if [ $actual_rc != $expected_rc ]; then
|
|
diff -u $fprefix.expected $fprefix.actual
|
|
echo >&2 "test case \`$*' failed ($actual_rc $diff_rc)"
|
|
failures=$(( $failures + 1 ))
|
|
fi
|
|
set -e
|
|
}
|
|
|
|
# Write an entry in the test vector file. Format is as follows:
|
|
# test-string*expected-rc*expected-output
|
|
write () {
|
|
printf "$1*$2*$3\n" >> $outfile
|
|
}
|
|
|
|
complete () {
|
|
if [ "$failures" = 0 ]; then
|
|
echo all ok.; exit 0
|
|
else
|
|
echo "$failures tests failed."; exit 1
|
|
fi
|
|
}
|
|
|
|
# Test a specific pinning string
|
|
string () {
|
|
expected_rc=$1; shift
|
|
printf "test case %s...\n" "$*"
|
|
set +e
|
|
${XL} -N vcpu-pin 0 all "$@" &> /dev/null
|
|
actual_rc=$?
|
|
set -e
|
|
|
|
if [ $actual_rc != $expected_rc ]; then
|
|
echo >&2 "test case \`$*' failed ($actual_rc)"
|
|
else
|
|
echo >&2 "test case \`$*' succeeded"
|
|
fi
|
|
|
|
exit 0
|
|
}
|
|
|
|
# Read a test vector file (provided as $1) line by line and
|
|
# test all the entries it contains
|
|
run ()
|
|
{
|
|
while read line
|
|
do
|
|
if [ ${line:0:1} != '#' ]; then
|
|
test_string="`echo $line | cut -f1 -d'*'`"
|
|
exp_rc="`echo $line | cut -f2 -d'*'`"
|
|
exp_output="`echo $line | cut -f3 -d'*'`"
|
|
|
|
expected <<END
|
|
$exp_output
|
|
END
|
|
one $exp_rc "$test_string"
|
|
fi
|
|
done < $1
|
|
|
|
complete
|
|
|
|
exit 0
|
|
}
|
|
|
|
while getopts "hr:s:o:i:" option
|
|
do
|
|
case $option in
|
|
h)
|
|
usage
|
|
exit 0
|
|
;;
|
|
r)
|
|
seed=$OPTARG
|
|
;;
|
|
s)
|
|
string 0 "$OPTARG"
|
|
;;
|
|
o)
|
|
outfile=$OPTARG
|
|
;;
|
|
i)
|
|
run $OPTARG
|
|
;;
|
|
esac
|
|
done
|
|
|
|
#---------- test data ----------
|
|
#
|
|
nr_cpus=`xl info | grep nr_cpus | cut -f2 -d':'`
|
|
nr_nodes=`xl info | grep nr_nodes | cut -f2 -d':'`
|
|
nr_cpus_per_node=`xl info -n | sed '/cpu:/,/numa_info/!d' | head -n -1 | \
|
|
awk '{print $4}' | uniq -c | tail -1 | awk '{print $1}'`
|
|
cat >$outfile <<END
|
|
# WARNING: some of these tests are topology based tests.
|
|
# Expect failures if the topology is not detected correctly
|
|
# detected topology: $nr_cpus CPUs, $nr_nodes nodes, $nr_cpus_per_node CPUs per node.
|
|
#
|
|
# seed used for random number generation: seed=${seed}.
|
|
#
|
|
# Format is as follows:
|
|
# test-string*expected-return-code*expected-output
|
|
#
|
|
END
|
|
|
|
# Re-seed the random number generator
|
|
RANDOM=$seed
|
|
|
|
echo "# Testing a wrong configuration" >> $outfile
|
|
write foo 255 ""
|
|
|
|
echo "# Testing the 'all' syntax" >> $outfile
|
|
write "all" 0 "cpumap: all"
|
|
write "nodes:all" 0 "cpumap: all"
|
|
write "all,nodes:all" 0 "cpumap: all"
|
|
write "all,^nodes:0,all" 0 "cpumap: all"
|
|
|
|
echo "# Testing the empty cpumap case" >> $outfile
|
|
write "^0" 0 "cpumap: none"
|
|
|
|
echo "# A few attempts of pinning to just one random cpu" >> $outfile
|
|
if [ $nr_cpus -gt 1 ]; then
|
|
for i in `seq 0 3`; do
|
|
cpu=$(($RANDOM % nr_cpus))
|
|
write "$cpu" 0 "cpumap: $cpu"
|
|
done
|
|
fi
|
|
|
|
echo "# A few attempts of pinning to all but one random cpu" >> $outfile
|
|
if [ $nr_cpus -gt 2 ]; then
|
|
for i in `seq 0 3`; do
|
|
cpu=$(($RANDOM % nr_cpus))
|
|
if [ $cpu -eq 0 ]; then
|
|
expected_range="1-$((nr_cpus - 1))"
|
|
elif [ $cpu -eq 1 ]; then
|
|
expected_range="0,2-$((nr_cpus - 1))"
|
|
elif [ $cpu -eq $((nr_cpus - 2)) ]; then
|
|
expected_range="0-$((cpu - 1)),$((nr_cpus - 1))"
|
|
elif [ $cpu -eq $((nr_cpus - 1)) ]; then
|
|
expected_range="0-$((nr_cpus - 2))"
|
|
else
|
|
expected_range="0-$((cpu - 1)),$((cpu + 1))-$((nr_cpus - 1))"
|
|
fi
|
|
write "all,^$cpu" 0 "cpumap: $expected_range"
|
|
done
|
|
fi
|
|
|
|
echo "# A few attempts of pinning to a random range of cpus" >> $outfile
|
|
if [ $nr_cpus -gt 2 ]; then
|
|
for i in `seq 0 3`; do
|
|
cpua=$(($RANDOM % nr_cpus))
|
|
range=$((nr_cpus - cpua))
|
|
cpub=$(($RANDOM % range))
|
|
cpubb=$((cpua + cpub))
|
|
if [ $cpua -eq $cpubb ]; then
|
|
expected_range="$cpua"
|
|
else
|
|
expected_range="$cpua-$cpubb"
|
|
fi
|
|
write "$expected_range" 0 "cpumap: $expected_range"
|
|
done
|
|
fi
|
|
|
|
echo "# A few attempts of pinning to just one random node" >> $outfile
|
|
if [ $nr_nodes -gt 1 ]; then
|
|
for i in `seq 0 3`; do
|
|
node=$(($RANDOM % nr_nodes))
|
|
# this assumes that the first $nr_cpus_per_node (from cpu
|
|
# 0 to cpu $nr_cpus_per_node-1) are assigned to the first node
|
|
# (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node
|
|
# to 2*$nr_cpus_per_node-1) are assigned to the second node (node
|
|
# 1), etc. Expect failures if that is not the case.
|
|
write "nodes:$node" 0 "cpumap: $((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1)-1))"
|
|
done
|
|
fi
|
|
|
|
echo "# A few attempts of pinning to all but one random node" >> $outfile
|
|
if [ $nr_nodes -gt 1 ]; then
|
|
for i in `seq 0 3`; do
|
|
node=$(($RANDOM % nr_nodes))
|
|
# this assumes that the first $nr_cpus_per_node (from cpu
|
|
# 0 to cpu $nr_cpus_per_node-1) are assigned to the first node
|
|
# (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node
|
|
# to 2*$nr_cpus_per_node-1) are assigned to the second node (node
|
|
# 1), etc. Expect failures if that is not the case.
|
|
if [ $node -eq 0 ]; then
|
|
expected_range="$nr_cpus_per_node-$((nr_cpus - 1))"
|
|
elif [ $node -eq $((nr_nodes - 1)) ]; then
|
|
expected_range="0-$((nr_cpus - nr_cpus_per_node - 1))"
|
|
else
|
|
expected_range="0-$((nr_cpus_per_node*node-1)),$((nr_cpus_per_node*(node+1)))-$nr_cpus"
|
|
fi
|
|
write "all,^nodes:$node" 0 "cpumap: $expected_range"
|
|
done
|
|
fi
|
|
|
|
echo "# A few attempts of pinning to a random range of nodes" >> $outfile
|
|
if [ $nr_nodes -gt 1 ]; then
|
|
for i in `seq 0 3`; do
|
|
nodea=$(($RANDOM % nr_nodes))
|
|
range=$((nr_nodes - nodea))
|
|
nodeb=$(($RANDOM % range))
|
|
nodebb=$((nodea + nodeb))
|
|
# this assumes that the first $nr_cpus_per_node (from cpu
|
|
# 0 to cpu $nr_cpus_per_node-1) are assigned to the first node
|
|
# (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node
|
|
# to 2*$nr_cpus_per_node-1) are assigned to the second node (node
|
|
# 1), etc. Expect failures if that is not the case.
|
|
if [ $nodea -eq 0 ] && [ $nodebb -eq $((nr_nodes - 1)) ]; then
|
|
expected_range="all"
|
|
else
|
|
expected_range="$((nr_cpus_per_node*nodea))-$((nr_cpus_per_node*(nodebb+1) - 1))"
|
|
fi
|
|
write "nodes:$nodea-$nodebb" 0 "cpumap: $expected_range"
|
|
done
|
|
fi
|
|
|
|
echo "# A few attempts of pinning to a node but excluding one random cpu" >> $outfile
|
|
if [ $nr_nodes -gt 1 ]; then
|
|
for i in `seq 0 3`; do
|
|
node=$(($RANDOM % nr_nodes))
|
|
# this assumes that the first $nr_cpus_per_node (from cpu
|
|
# 0 to cpu $nr_cpus_per_node-1) are assigned to the first node
|
|
# (node 0), the second $nr_cpus_per_node (from $nr_cpus_per_node
|
|
# to 2*$nr_cpus_per_node-1) are assigned to the second node (node
|
|
# 1), etc. Expect failures if that is not the case.
|
|
cpu=$(($RANDOM % nr_cpus_per_node + nr_cpus_per_node*node))
|
|
if [ $cpu -eq $((nr_cpus_per_node*node)) ]; then
|
|
expected_range="$((nr_cpus_per_node*node + 1))-$((nr_cpus_per_node*(node+1) - 1))"
|
|
elif [ $cpu -eq $((nr_cpus_per_node*node + 1)) ]; then
|
|
expected_range="$((nr_cpus_per_node*node)),$((nr_cpus_per_node*node + 2))-$((nr_cpus_per_node*(node+1) - 1))"
|
|
elif [ $cpu -eq $((nr_cpus_per_node*(node+1) - 2)) ]; then
|
|
expected_range="$((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1) - 3)),$((nr_cpus_per_node*(node+1) - 1))"
|
|
elif [ $cpu -eq $((nr_cpus_per_node*(node+1) - 1)) ]; then
|
|
expected_range="$((nr_cpus_per_node*node))-$((nr_cpus_per_node*(node+1) - 2))"
|
|
else
|
|
expected_range="$((nr_cpus_per_node*node))-$((cpu - 1)),$((cpu + 1))-$((nr_cpus_per_node*(node+1) - 1))"
|
|
fi
|
|
write "nodes:$node,^$cpu" 0 "cpumap: $expected_range"
|
|
done
|
|
fi
|
|
|
|
run $outfile
|