|
Packit |
9c3e7e |
# Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
|
|
Packit |
9c3e7e |
#
|
|
Packit |
9c3e7e |
# This program is free software; you can redistribute it and/or modify
|
|
Packit |
9c3e7e |
# it under the terms of the GNU General Public License as published by
|
|
Packit |
9c3e7e |
# the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
9c3e7e |
# (at your option) any later version.
|
|
Packit |
9c3e7e |
#
|
|
Packit |
9c3e7e |
# This program is distributed in the hope that it will be useful,
|
|
Packit |
9c3e7e |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
9c3e7e |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
9c3e7e |
# GNU General Public License for more details.
|
|
Packit |
9c3e7e |
#
|
|
Packit |
9c3e7e |
# You should have received a copy of the GNU General Public License
|
|
Packit |
9c3e7e |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
export LC_ALL=C
|
|
Packit |
9c3e7e |
export PATH=$(pwd):$PATH
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
if [ ! -e clknetsim ]; then
|
|
Packit |
9c3e7e |
git clone https://github.com/mlichvar/clknetsim.git || exit 1
|
|
Packit |
9c3e7e |
fi
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
if [ ! -x clknetsim/clknetsim -o ! -e clknetsim/clknetsim.so ]; then
|
|
Packit |
9c3e7e |
pushd clknetsim
|
|
Packit |
9c3e7e |
make || exit 1
|
|
Packit |
9c3e7e |
popd
|
|
Packit |
9c3e7e |
fi
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
export CLKNETSIM_PATH=clknetsim
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
. $CLKNETSIM_PATH/clknetsim.bash
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
default_limit=500
|
|
Packit |
9c3e7e |
default_time_offset=1e-1
|
|
Packit |
9c3e7e |
default_freq_offset=1e-4
|
|
Packit |
9c3e7e |
default_base_delay=1e-7
|
|
Packit |
9c3e7e |
default_jitter=1e-7
|
|
Packit |
9c3e7e |
default_wander=1e-9
|
|
Packit |
9c3e7e |
default_time_rms_limit=1e-6
|
|
Packit |
9c3e7e |
default_freq_rms_limit=1e-6
|
|
Packit |
9c3e7e |
default_time_max_limit=2e-6
|
|
Packit |
9c3e7e |
default_freq_max_limit=2e-6
|
|
Packit |
9c3e7e |
default_min_sync_time=10
|
|
Packit |
9c3e7e |
default_max_sync_time=40
|
|
Packit |
9c3e7e |
default_max_ptp4l_delay_limit=1e-4
|
|
Packit |
9c3e7e |
default_nodes=3
|
|
Packit |
9c3e7e |
default_subnets=""
|
|
Packit |
9c3e7e |
default_master_node=1
|
|
Packit |
9c3e7e |
default_transparent_nodes=""
|
|
Packit |
9c3e7e |
default_free_running_nodes=""
|
|
Packit |
9c3e7e |
default_pmc_node=0
|
|
Packit |
9c3e7e |
default_nsm_node=0
|
|
Packit |
9c3e7e |
default_master_start=0.0
|
|
Packit |
9c3e7e |
default_slave_start=9.0
|
|
Packit |
9c3e7e |
default_pmc_start=50.0
|
|
Packit |
9c3e7e |
default_nsm_start=50.0
|
|
Packit |
9c3e7e |
default_master_step=""
|
|
Packit |
9c3e7e |
default_slave_step=""
|
|
Packit |
9c3e7e |
default_update_interval=0
|
|
Packit |
9c3e7e |
default_log_packets=0
|
|
Packit |
9c3e7e |
default_master_conf=""
|
|
Packit |
9c3e7e |
default_slave_conf=""
|
|
Packit |
9c3e7e |
default_transparent_conf=""
|
|
Packit |
9c3e7e |
default_pmc_conf=""
|
|
Packit |
9c3e7e |
default_nsm_conf=""
|
|
Packit |
9c3e7e |
default_extra_ptp4l_options=""
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
for defopt in $(declare | grep '^default_'); do
|
|
Packit |
9c3e7e |
defoptname=${defopt%%=*}
|
|
Packit |
9c3e7e |
optname=${defoptname#default_}
|
|
Packit |
9c3e7e |
eval "[ -z \"\${$optname:+a}\" ] && $optname=\"\$$defoptname\""
|
|
Packit |
9c3e7e |
done
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_start() {
|
|
Packit |
9c3e7e |
rm -f tmp/*
|
|
Packit |
9c3e7e |
echo "Testing $@:"
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_pass() {
|
|
Packit |
9c3e7e |
echo "PASS"
|
|
Packit |
9c3e7e |
exit 0
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_fail() {
|
|
Packit |
9c3e7e |
echo "FAIL"
|
|
Packit |
9c3e7e |
exit 1
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_ok() {
|
|
Packit |
9c3e7e |
pad_line
|
|
Packit |
9c3e7e |
echo -e "\tOK"
|
|
Packit |
9c3e7e |
return 0
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_bad() {
|
|
Packit |
9c3e7e |
pad_line
|
|
Packit |
9c3e7e |
echo -e "\tBAD"
|
|
Packit |
9c3e7e |
return 1
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_error() {
|
|
Packit |
9c3e7e |
pad_line
|
|
Packit |
9c3e7e |
echo -e "\tERROR"
|
|
Packit |
9c3e7e |
return 1
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
msg_length=0
|
|
Packit |
9c3e7e |
pad_line() {
|
|
Packit |
9c3e7e |
local line_length=56
|
|
Packit |
9c3e7e |
[ $msg_length -lt $line_length ] && \
|
|
Packit |
9c3e7e |
printf "%$[$line_length - $msg_length]s" ""
|
|
Packit |
9c3e7e |
msg_length=0
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message() {
|
|
Packit |
9c3e7e |
local level=$1 eol=$2
|
|
Packit |
9c3e7e |
shift 2
|
|
Packit |
9c3e7e |
local msg="$*"
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
while [ $level -gt 0 ]; do
|
|
Packit |
9c3e7e |
echo -n " "
|
|
Packit |
9c3e7e |
level=$[$level - 1]
|
|
Packit |
9c3e7e |
msg_length=$[$msg_length + 2]
|
|
Packit |
9c3e7e |
done
|
|
Packit |
9c3e7e |
echo -n "$msg"
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
msg_length=$[$msg_length + ${#msg}]
|
|
Packit |
9c3e7e |
if [ $eol -ne 0 ]; then
|
|
Packit |
9c3e7e |
echo
|
|
Packit |
9c3e7e |
msg_length=0
|
|
Packit |
9c3e7e |
fi
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
check_sync() {
|
|
Packit |
9c3e7e |
local i sync_time max_time_error max_freq_error ret=0
|
|
Packit |
9c3e7e |
local rms_time_error rms_freq_error
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 2 1 "checking clock sync time, max/rms time/freq error:"
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
for i in $(seq 1 $nodes); do
|
|
Packit |
9c3e7e |
[ $i -eq $master_node ] && continue
|
|
Packit |
9c3e7e |
[ $i -eq $pmc_node ] && continue
|
|
Packit |
9c3e7e |
[ $i -eq $nsm_node ] && continue
|
|
Packit |
9c3e7e |
[[ " $free_running_nodes " =~ [^0-9]$i[^0-9] ]] && continue
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
sync_time=$(find_sync tmp/log.offset tmp/log.freq $i \
|
|
Packit |
9c3e7e |
$time_max_limit $freq_max_limit 1.0)
|
|
Packit |
9c3e7e |
max_time_error=$(get_stat 'Maximum absolute offset' $i)
|
|
Packit |
9c3e7e |
max_freq_error=$(get_stat 'Maximum absolute frequency' $i)
|
|
Packit |
9c3e7e |
rms_time_error=$(get_stat 'RMS offset' $i)
|
|
Packit |
9c3e7e |
rms_freq_error=$(get_stat 'RMS frequency' $i)
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 3 0 "node $i: $sync_time $(printf '%.2e %.2e %.2e %.2e' \
|
|
Packit |
9c3e7e |
$max_time_error $max_freq_error $rms_time_error $rms_freq_error)"
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
check_stat $sync_time $min_sync_time $max_sync_time && \
|
|
Packit |
9c3e7e |
check_stat $max_time_error 0.0 $time_max_limit && \
|
|
Packit |
9c3e7e |
check_stat $max_freq_error 0.0 $freq_max_limit && \
|
|
Packit |
9c3e7e |
check_stat $rms_time_error 0.0 $time_rms_limit && \
|
|
Packit |
9c3e7e |
check_stat $rms_freq_error 0.0 $freq_rms_limit && \
|
|
Packit |
9c3e7e |
test_ok || test_bad
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
[ $? -eq 0 ] || ret=1
|
|
Packit |
9c3e7e |
done
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
return $ret
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
check_ptp4l_delay() {
|
|
Packit |
9c3e7e |
local i max_delay ret=0
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 2 1 "checking max abs path delay measured by ptp4l:"
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
for i in $(seq 1 $nodes); do
|
|
Packit |
9c3e7e |
[ $i -eq $master_node ] && continue
|
|
Packit |
9c3e7e |
[ $i -eq $pmc_node ] && continue
|
|
Packit |
9c3e7e |
[ $i -eq $nsm_node ] && continue
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
max_delay=$(grep -oE 'path delay *[-0-9]+ +[-0-9]+$' tmp/log.$i | awk '
|
|
Packit |
9c3e7e |
BEGIN {
|
|
Packit |
9c3e7e |
max = 0.0
|
|
Packit |
9c3e7e |
} {
|
|
Packit |
9c3e7e |
abs = $4 < 0 ? -$4 : $4
|
|
Packit |
9c3e7e |
if (max < abs)
|
|
Packit |
9c3e7e |
max = abs
|
|
Packit |
9c3e7e |
} END {
|
|
Packit |
9c3e7e |
print max / 1e9
|
|
Packit |
9c3e7e |
}')
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 3 0 "node $i: $(printf '%.2e' $max_delay)"
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
check_stat $max_delay 0.0 $max_ptp4l_delay_limit && test_ok || test_bad
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
[ $? -eq 0 ] || ret=1
|
|
Packit |
9c3e7e |
done
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
return $ret
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
check_pmc_output() {
|
|
Packit |
9c3e7e |
local pattern=$1
|
|
Packit |
9c3e7e |
test_message 2 0 "checking pmc output:"
|
|
Packit |
9c3e7e |
[[ "$(cat tmp/log.$pmc_node)" =~ $pattern ]] && test_ok || test_bad
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
check_nsm_output() {
|
|
Packit |
9c3e7e |
local pattern=$1
|
|
Packit |
9c3e7e |
test_message 2 0 "checking nsm output:"
|
|
Packit |
9c3e7e |
[[ "$(cat tmp/log.$nsm_node)" =~ $pattern ]] && test_ok || test_bad
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
print_nondefaults() {
|
|
Packit |
9c3e7e |
local defopt defoptname optname
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 2 1 "non-default settings:"
|
|
Packit |
9c3e7e |
declare | grep '^default_*' | while read defopt; do
|
|
Packit |
9c3e7e |
defoptname=${defopt%%=*}
|
|
Packit |
9c3e7e |
optname=${defoptname#default_}
|
|
Packit |
9c3e7e |
eval "[ \"\$$optname\" = \"\$$defoptname\" ]" || \
|
|
Packit |
9c3e7e |
test_message 3 1 $(eval "echo $optname=\$$optname")
|
|
Packit |
9c3e7e |
done
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
get_wander_expr() {
|
|
Packit |
9c3e7e |
local scaled_wander
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
scaled_wander=$(awk "BEGIN {print $wander / \
|
|
Packit |
9c3e7e |
sqrt($update_interval < 0 ? 2^-($update_interval) : 1)}")
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
echo "(+ $freq_offset (sum (* $scaled_wander (normal))))"
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
run_simulation() {
|
|
Packit |
9c3e7e |
test_message 2 0 "running simulation:"
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
start_server $nodes \
|
|
Packit |
9c3e7e |
-n $[$(echo "$subnets" | tr -cd '|' | wc -c) + 1] \
|
|
Packit |
9c3e7e |
-o tmp/log.offset -f tmp/log.freq \
|
|
Packit |
9c3e7e |
$([ $log_packets -ne 0 ] && echo -p tmp/log.packets) \
|
|
Packit |
9c3e7e |
-R $(awk "BEGIN {print $update_interval < 0 ? 2^-($update_interval) : 1}") \
|
|
Packit |
9c3e7e |
-r $(awk "BEGIN {print $max_sync_time * 2^$update_interval}") \
|
|
Packit |
9c3e7e |
-l $(awk "BEGIN {print $limit * 2^$update_interval}") && test_ok || test_error
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
run_ptp4l() {
|
|
Packit |
9c3e7e |
local i s subnet ifaces test_subnets conf start
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 1 1 "ptp4l test with $nodes nodes:"
|
|
Packit |
9c3e7e |
print_nondefaults
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
[ -z "$subnets" ] && test_subnets=$(seq -s ' ' 1 $nodes) || test_subnets=$subnets
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
generate_config4 "$master_node $pmc_node $nsm_node" "$test_subnets" $time_offset \
|
|
Packit |
9c3e7e |
"$(get_wander_expr)" \
|
|
Packit |
9c3e7e |
"(+ $base_delay (* $jitter (exponential)))"
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
for i in $(seq 1 $nodes); do
|
|
Packit |
9c3e7e |
ifaces="" subnet=0
|
|
Packit |
9c3e7e |
for s in $test_subnets; do
|
|
Packit |
9c3e7e |
[ $s = "|" ] && subnet=$[$subnet + 1] && continue
|
|
Packit |
9c3e7e |
[ $s -eq $i ] && ifaces="$ifaces -i eth$subnet"
|
|
Packit |
9c3e7e |
done
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 2 0 "starting node $i:"
|
|
Packit |
9c3e7e |
if [ $i -eq $pmc_node ]; then
|
|
Packit |
9c3e7e |
echo "node${i}_start = $pmc_start" >> tmp/conf
|
|
Packit |
9c3e7e |
start_client $i pmc "$pmc_conf" "" "-b 0 $ifaces" && \
|
|
Packit |
9c3e7e |
test_ok || test_error
|
|
Packit |
9c3e7e |
elif [ $i -eq $nsm_node ]; then
|
|
Packit |
9c3e7e |
echo "node${i}_start = $nsm_start" >> tmp/conf
|
|
Packit |
9c3e7e |
start_client $i nsm "$nsm_conf" "" "$ifaces" && \
|
|
Packit |
9c3e7e |
test_ok || test_error
|
|
Packit |
9c3e7e |
else
|
|
Packit |
9c3e7e |
if [[ " $transparent_nodes " =~ [^0-9]$i[^0-9] ]]; then
|
|
Packit |
9c3e7e |
start=$slave_start
|
|
Packit |
9c3e7e |
conf=$transparent_conf
|
|
Packit |
9c3e7e |
step=$slave_step
|
|
Packit |
9c3e7e |
elif [ $i -eq $master_node ]; then
|
|
Packit |
9c3e7e |
start=$master_start
|
|
Packit |
9c3e7e |
conf=$master_conf
|
|
Packit |
9c3e7e |
step=$master_step
|
|
Packit |
9c3e7e |
else
|
|
Packit |
9c3e7e |
start=$slave_start
|
|
Packit |
9c3e7e |
conf=$slave_conf
|
|
Packit |
9c3e7e |
step=$slave_step
|
|
Packit |
9c3e7e |
fi
|
|
Packit |
9c3e7e |
[ -z "$step" ] || echo "node${i}_step = $step" >> tmp/conf
|
|
Packit |
9c3e7e |
echo "node${i}_start = $start" >> tmp/conf
|
|
Packit |
9c3e7e |
start_client $i ptp4l "$conf" "" "$ifaces $extra_ptp4l_options" && \
|
|
Packit |
9c3e7e |
test_ok || test_error
|
|
Packit |
9c3e7e |
fi
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
[ $? -ne 0 ] && return 1
|
|
Packit |
9c3e7e |
done
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
run_simulation
|
|
Packit |
9c3e7e |
}
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
run_phc2sys() {
|
|
Packit |
9c3e7e |
local i
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 1 1 "phc2sys test with $nodes nodes:"
|
|
Packit |
9c3e7e |
print_nondefaults
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
for i in $(seq 1 $nodes); do
|
|
Packit |
9c3e7e |
cat >> tmp/conf <<-EOF
|
|
Packit |
9c3e7e |
node${i}_freq = $(get_wander_expr)
|
|
Packit |
9c3e7e |
node${i}_refclock = (* $jitter (normal))
|
|
Packit |
9c3e7e |
node${i}_offset = $time_offset
|
|
Packit |
9c3e7e |
node${i}_start = $slave_start
|
|
Packit |
9c3e7e |
EOF
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
test_message 2 0 "starting node $i:"
|
|
Packit |
9c3e7e |
start_client $i phc2sys "$slave_conf" && test_ok || test_error
|
|
Packit |
9c3e7e |
[ $? -ne 0 ] && return 1
|
|
Packit |
9c3e7e |
done
|
|
Packit |
9c3e7e |
|
|
Packit |
9c3e7e |
run_simulation
|
|
Packit |
9c3e7e |
}
|