From 246fd81f57f4ba90f9b49f6df7675da6ab4497ef Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Tue, 23 May 2023 15:24:42 +0200 Subject: [PATCH] Test: updated perf tests that have been broken for some time --- test/lib.sh | 1 + test/plot_perf.sh | 391 ++++++++++++++++++++++++------------- test/test_perf_cli.sh | 32 +-- test/test_perf_json.sh | 3 +- test/test_perf_restconf.sh | 17 +- 5 files changed, 284 insertions(+), 160 deletions(-) diff --git a/test/lib.sh b/test/lib.sh index 12f56ca6..4d161cf4 100755 --- a/test/lib.sh +++ b/test/lib.sh @@ -1040,6 +1040,7 @@ EOF # clixon tester read from file for large tests # Arguments: # - Command +# - expected retval # - Filename to pipe to stdin # - expected stdout outcome function expecteof_file(){ diff --git a/test/plot_perf.sh b/test/plot_perf.sh index 18869404..96f25eef 100755 --- a/test/plot_perf.sh +++ b/test/plot_perf.sh @@ -2,7 +2,7 @@ # Performance of large lists. See doc/scaling/large-lists.md # The parameters are shown below (under Default values) # Examples -# 1. run all measurements up to 10000 entris collect all results in /tmp/plots +# 1. run all measurements up to 10000 entries collect all results in /tmp/plots # run=true plot=false to=10000 resdir=/tmp/plots ./plot_perf.sh # 2. Use existing data plot and show on X11 # run=false plot=true resdir=/tmp/plots term=x11 ./plot_perf.sh @@ -10,6 +10,8 @@ # archs="i686 armv7l" run=false plot=true resdir=/tmp/plots term=png ./plot_perf.sh # Need gnuplot installed +set -u + # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi @@ -23,24 +25,24 @@ arch=$(arch) : ${resdir=$dir} # Result dir (both data and gnuplot) : ${plot=false} # Result dir (both data and gnuplot) : ${archs=$arch} # Plotting can be made for many architectures (not run) +: ${protos="netconf restconf"} +: ${state=true} # Generate state data and netconf get state plot # 0 prefix to protect against shell dynamic binding) to0=$to step0=$step reqs0=$reqs -ext=$term # gnuplot output file extenstion +ext=$term # gnuplot output file extension # Global variables APPNAME=example cfg=$dir/plot-conf.xml -fyang=$dir/plot.yang +fyang=$dir/scaling.yang +fstate=$dir/state.xml fxml=$dir/data.xml fjson=$dir/data.json -# Resultdir - if different from $dir that gets erased -#resdir=$dir - if [ ! -d $resdir ]; then mkdir $resdir fi @@ -66,38 +68,57 @@ module scaling{ } leaf b { description "payload data"; - type string; + type string; + } + leaf status { + description "state data"; + type string; + config false; } } } } EOF +RESTCONFIG=$(restconf_config none false) cat < $cfg $cfg + ietf-netconf:startup + clixon-restconf:allow-auth-none $dir /usr/local/share/clixon - scaling + $fyang /usr/local/var/example/example.sock /usr/local/var/example/example.pidfile $dir false + false + $RESTCONFIG EOF -# Generate file with n entries -# argument: -function genfile(){ - if [ $2 = netconf ]; then - echo -n "replace" > $fxml - for (( i=0; i<$1; i++ )); do - echo -n "$i$i" >> $fxml +# Generate file $fxml or $fjson with "nr" entries for PUT operations +# arguments: +# 1: +# 2: netconf(in xml) or json (for restconf) +function genfile() +{ + new "genfile" + nr=$1 + myproto=$2 + + if [ $myproto = netconf ]; then + rpc="replace" + for (( i=0; i<$nr; i++ )); do + rpc+="$i$i" done - echo "]]>]]>" >> $fxml - else # restconf + rpc+="" + echo -n "$DEFAULTHELLO" > $fxml + echo "$(chunked_framing "$rpc")" >> $fxml + else # json echo -n '{"scaling:x":{"y":[' > $fjson - for (( i=0; i<$1; i++ )); do + for (( i=0; i<$nr; i++ )); do if [ $i -ne 0 ]; then echo -n ',' >> $fjson fi @@ -107,49 +128,94 @@ function genfile(){ fi } -# Run netconffunction -# args: -# where proto is one of: -# netconf, restconf -# where op is one of: -# get put delete commit -function runnet(){ +# Generate state file with "nr" entries +# arguments: +# 1: Number of entries +# 2: File name +function genstate() +{ + nr=$1 + fstate=$2 + echo "" > $fstate + for (( i=0; i<$nr; i++ )); do + echo "$i$i" >> $fstate + done + echo "" >> $fstate +} + +# Run netconf function +# args: +# 1: put, get, commit, delete +# 2: Number of entries +# 3: =0 means all in one go +# 4: true: Also generate/get state data +function runnetconf() +{ op=$1 nr=$2 # Number of entries in DB (keep diff from n due to shell dynamic binding) reqs=$3 + st=$4 - file=$resdir/$op-netconf-$reqs-$arch + file=$resdir/$op-netconf-$reqs-$st-$arch + new "runnetconf $file $nr" echo -n "$nr " >> $file case $op in put) if [ $reqs = 0 ]; then # Write all in one go genfile $nr netconf; - { time -p cat $fxml | $clixon_netconf -qf $cfg -y $fyang ; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + { time -p cat $fxml | $clixon_netconf -qf $cfg; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file else # reqs != 0 { time -p for (( i=0; i<$reqs; i++ )); do - rnd=$(( ( RANDOM % $nr ) )); - echo "$rnd$rnd]]>]]>"; - done | $clixon_netconf -qf $cfg -y $fyang > /dev/null; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + rnd=$(( ( RANDOM % $nr ) )); + rpc=$(chunked_framing "$rnd$rnd") + if [ $i == 0 ]; then + echo -n "$DEFAULTHELLO"; + fi + echo "$rpc" + done | $clixon_netconf -qf $cfg > /dev/null; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file fi ;; get) + if $st; then + GET1="" + GET2="" + else + GET1="" + GET2="" + fi if [ $reqs = 0 ]; then # Read all in one go - { time -p echo "]]>]]>" | $clixon_netconf -qf $cfg -y $fyang > /dev/null ; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + rpc=$(chunked_framing "${GET1}${GET2}") + { time -p echo "$DEFAULTHELLO$rpc" | $clixon_netconf -qf $cfg > /dev/null ; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file else # reqs != 0 { time -p for (( i=0; i<$reqs; i++ )); do - rnd=$(( ( RANDOM % $nr ) )) - echo "$rnd$rnd]]>]]>" - done | $clixon_netconf -qf $cfg -y $fyang > /dev/null; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + rnd=$(( ( RANDOM % $nr ) )) + rpc=$(chunked_framing "${GET1}${GET2}") + if [ $i == 0 ]; then + echo -n "$DEFAULTHELLO"; + fi + echo "$rpc" + done | $clixon_netconf -qf $cfg > /dev/null; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + echo $file fi ;; delete) + if [ $reqs = 0 ]; then # Delete all in one go + rpc=$(chunked_framing "$rnd$rnd") + { time -p echo "$DEFAULTHELLO$rpc" | $clixon_netconf -qf $cfg > /dev/null ; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + else { time -p for (( i=0; i<$reqs; i++ )); do - rnd=$(( ( RANDOM % $nr ) )) - echo "$rnd$rnd]]>]]>" -done | $clixon_netconf -qf $cfg -y $fyang; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + rnd=$(( ( RANDOM % $nr ) )) + rpc=$(chunked_framing "$rnd$rnd") + if [ $i == 0 ]; then + echo -n "$DEFAULTHELLO"; + fi + echo "$rpc" + done | $clixon_netconf -qf $cfg; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + fi ;; commit) - { time -p echo "]]>]]>" | $clixon_netconf -qf $cfg -y $fyang > /dev/null ; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + rpc=$(chunked_framing "") + { time -p echo "$DEFAULTHELLO$rpc" | $clixon_netconf -qf $cfg > /dev/null ; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file ;; *) err "Operation not supported" "$op" @@ -159,46 +225,54 @@ done | $clixon_netconf -qf $cfg -y $fyang; } 2>&1 | awk '/real/ {print $2}' | tr } # Run restconf function -# args: -# where proto is one of: -# netconf, restconf -# where op is one of: -# get put delete -function runrest(){ +# args: +# 1: put, get, commit, delete +# 2: Number of entries +# 3: =0 means all in one go +# 4: true: Also generate/get state data +function runrestconf() +{ op=$1 nr=$2 # Number of entries in DB reqs=$3 + st=$4 - file=$resdir/$op-restconf-$reqs-$arch + file=$resdir/$op-restconf-$reqs-$st-$arch + new "runrestconf $file $nr" echo -n "$nr " >> $file case $op in put) if [ $reqs = 0 ]; then # Write all in one go - genfile $nr restconf + genfile $nr json # restconf @- means from stdin - { time -p curl $CURLOPTS -X PUT -d @$fjson http://localhost/restconf/data/scaling:x ; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + { time -p curl $CURLOPTS -X PUT -H 'Content-Type: application/yang-data+json' -d @$fjson $RCPROTO://localhost/restconf/data/scaling:x ; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file else # Small requests { time -p for (( i=0; i<$reqs; i++ )); do - rnd=$(( ( RANDOM % $nr ) )); - curl $CURLOPTS -X PUT http://localhost/restconf/data/scaling:x/y=$rnd -d "{\"scaling:y\":{\"a\":$rnd,\"b\":\"$rnd\"}}" - done ; } 2>&1 | awk '/real/ {print $2}' | tr , .>> $file + rnd=$(( ( RANDOM % $nr ) )); + curl $CURLOPTS -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/scaling:x/y=$rnd -d "{\"scaling:y\":{\"a\":$rnd,\"b\":\"$rnd\"}}" + done ; } 2>&1 | awk '/real/ {print $2}' | tr , .>> $file # fi ;; get) + if $st; then + CONTENT=all + else + CONTENT=config + fi if [ $reqs = 0 ]; then # Read all in one go - { time -p curl $CURLOPTS -X GET http://localhost/restconf/data/scaling:x > /dev/null; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file + { time -p curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/scaling:x?content=$CONTENT > /dev/null; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $file else # Small requests { time -p for (( i=0; i<$reqs; i++ )); do - rnd=$(( ( RANDOM % $nr ) )); - curl $CURLOPTS -X GET http://localhost/restconf/data/scaling:x/y=$rnd - done ; } 2>&1 | awk '/real/ {print $2}' | tr , .>> $file + rnd=$(( ( RANDOM % $nr ) )); + curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/scaling:x/y=$rnd?content=$CONTENT + done ; } 2>&1 | awk '/real/ {print $2}' | tr , .>> $file fi ;; delete) { time -p for (( i=0; i<$reqs; i++ )); do rnd=$(( ( RANDOM % $nr ) )); - curl $CURLOPTS -X GET http://localhost/restconf/data/scaling:x/y=$rnd + curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/scaling:x/y=$rnd done ; } 2>&1 | awk '/real/ {print $2}' | tr , .>> $file ;; *) @@ -208,63 +282,81 @@ function runrest(){ esac } - -function commit(){ +function commit() +{ # commit to running - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "]]>]]>" "^]]>]]>$" + new "commit" + expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" } -function reset(){ - # delete all in candidate - expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "none]]>]]>" '^]]>]]>$' +# Delete all in candidate and commit, and state file +function reset() +{ + new "reset" + expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "none" "" "" # commit to running commit + echo "" > $fstate } -# Load n entries into candidate -# Args: -function load(){ +# Load nr entries into candidate +# Args: +function load() +{ + new "load $1" + nr=$1 # Generate file ($fxml) - genfile $1 netconf + genfile $nr netconf # Write it to backend in one chunk - expecteof_file "$clixon_netconf -qf $cfg -y $fyang" 0 "$fxml" "^]]>]]>$" + new "generated netconf" + expecteof_file "$clixon_netconf -qef $cfg" 0 "$fxml" "^$" + new "load done" } # Run an operation, iterate from to in increment of # Each operation do times -# args: -# =0 means all in one go -# means a priori loaded into datastore -function plot(){ +# args: +# 1: put, get, commit, delete +# 2: netconf or restconf +# 3: Iterate from +# 4: in steps +# 5: Increment to +# 6: =0 means all in one go +# 7: Three values: "no", "candidate": prefill candidare, "running": also commit into running +# 8: false: no state, true: Also get state data +function genplot() +{ op=$1 proto=$2 from=$3 step=$4 to=$5 reqs=$6 - can=$7 - run=$8 + fill=$7 + st=$8 + new "genplot $proto" if [ $# -ne 8 ]; then exit "plot should be called with 8 arguments, got $#" fi - # reset file - new "Create file $resdir/$op-$proto-$reqs-$arch" - echo -n "" > $resdir/$op-$proto-$reqs-$arch - for (( n=$from; n<=$to; n=$n+$step )); do + new "Create file $resdir/$op-$proto-$reqs-$st-$arch" + echo -n "" > $resdir/$op-$proto-$reqs-$st-$arch + for (( nr=$from; nr<=$to; nr=$nr+$step )); do reset - if [ $can = n ]; then - load $n - if [ $run = n ]; then - commit - fi + if $st; then + genstate $nr $fstate + fi + if [ $fill = candidate ]; then + load $nr + elif [ $fill = running ]; then + load $nr + commit fi - new "$op-$proto-$reqs-$arch $n" if [ $proto = netconf ]; then - runnet $op $n $reqs + runnetconf $op $nr $reqs $st else - runrest $op $n $reqs + runrestconf $op $nr $reqs $st fi done echo # newline @@ -274,16 +366,17 @@ function plot(){ # Each operation do times # args: # =0 means all in one go -function startup(){ +function startup() +{ from=$1 step=$2 to=$3 mode=startup + new "startup" if [ $# -ne 3 ]; then - exit "plot should be called with 3 arguments, got $#" + exit "startup should be called with 3 arguments, got $#" fi - # gnuplot file gfile=$resdir/startup-$arch new "Create file $gfile" @@ -302,10 +395,9 @@ function startup(){ done echo "" >> $dbfile - new "Startup backend once -s $mode -f $cfg -y $fyang" + new "Startup backend once -s $mode -f $cfg" echo -n "$n " >> $gfile - { time -p sudo $clixon_backend -F1 -D $DBG -s $mode -f $cfg -y $fyang 2> /dev/null; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $gfile - + { time -p sudo $clixon_backend -F1 -D $DBG -s $mode -f $cfg 2> /dev/null; } 2>&1 | awk '/real/ {print $2}' | tr , . >> $gfile done echo # newline } @@ -316,58 +408,67 @@ if $run; then # backend a single time startup $step $step $to - new "test params: -f $cfg -y $fyang" + new "test params: -f $cfg" if [ $BE -ne 0 ]; then new "kill old backend" - sudo clixon_backend -zf $cfg -y $fyang + sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi - new "start backend -s init -f $cfg -y $fyang" - start_backend -s init -f $cfg -y $fyang + new "start backend -s init -f $cfg -- -sS $fstate" + start_backend -s init -f $cfg -- -sS $fstate + + new "wait backend" + wait_backend fi + if [ $RC -ne 0 ]; then + new "kill old restconf daemon" + stop_restconf_pre - new "kill old restconf daemon" - sudo pkill -u www-data -f "/www-data/clixon_restconf" + new "start restconf daemon" + start_restconf -f $cfg - new "start restconf daemon" - start_restconf -f $cfg -y $fyang - - new "waiting" - sleep $DEMWAIT + new "wait restconf" + wait_restconf + fi to=$to0 step=$step0 reqs=$reqs0 - # Put all tests - for proto in netconf restconf; do - new "$proto put all entries to candidate (restconf:running)" - plot put $proto $step $step $to 0 0 0 # all candidate 0 running 0 - done - - # Get all tests - for proto in netconf restconf; do - new "$proto get all entries from running" - plot get $proto $step $step $to 0 n n # start w full datastore + for pr in ${protos}; do + new "$pr put all entries to candidate (restconf:running)" + genplot put $pr $step $step $to 0 no false # all candidate 0 running 0 done # Netconf commit all new "Netconf commit all entries from candidate to running" - plot commit netconf $step $step $to 0 n 0 # candidate full running empty + genplot commit netconf $step $step $to 0 candidate false # candidate full running empty + # Get all tests + for pr in ${protos}; do + new "$pr get all config entries from running" + genplot get $pr $step $step $to 0 running false # start w full datastore + done + if $state; then + for pr in ${protos}; do + new "$pr get all state entries from running" + genplot get $pr $step $step $to 0 running true # start w full datastore + done + fi + # Transactions get/put/delete reqs=$reqs0 - for proto in netconf restconf; do - new "$proto get $reqs from full database" - plot get $proto $step $step $to $reqs n n + for pr in ${protos} ; do + new "$pr get $reqs from full database" + genplot get $pr $step $step $to $reqs running false + + new "$pr put $reqs to full database(replace / alter values)" + genplot put $pr $step $step $to $reqs running false - new "$proto put $reqs to full database(replace / alter values)" - plot put $proto $step $step $to $reqs n n - - new "$proto delete $reqs from full database(replace / alter values)" - plot delete $proto $step $step $to $reqs n n + new "$pr delete $reqs from full database(replace / alter values)" + genplot delete $pr $step $step $to $reqs running false done new "Kill restconf daemon" @@ -408,7 +509,7 @@ EOF # 1. Get config gplot="" for a in $archs; do - gplot="$gplot \"$resdir/get-restconf-0-$a\" title \"rc-$a\", \"$resdir/get-netconf-0-$a\" title \"nc-$a\"," + gplot="$gplot \"$resdir/get-restconf-0-false-$a\" title \"rc-$a\", \"$resdir/get-netconf-0-false-$a\" title \"nc-$a\"," done gnuplot -persist <" > $fconfig +rpc="" > $fconfig for (( i=0; i<$perfnr; i++ )); do - echo -n "$i$i" >> $fconfig + rpc+="$i$i" done -echo "]]>]]>" >> $fconfig +rpc+="" + +echo -n "$DEFAULTHELLO" > $fconfig +echo "$(chunked_framing "$rpc")" >> $fconfig # Now take large config file and write it via netconf to candidate new "test time exists" -expectpart "$(time -p ls)" 0 +expectpart "$(time -p ls)" 0 2>&1 | awk '/real/ {print $2}' new "netconf write large config" -expecteof_file "time -p $clixon_netconf -qef $cfg" 0 "$fconfig" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' +# One extra without time for potential error +expecteof_file "time -p $clixon_netconf -qef $cfg" 0 "$fconfig" "^$" 2>&1 | awk '/real/ {print $2}' # Here, there are $perfnr entries in candidate # Now commit it from candidate to running new "netconf commit large config" -expecteof "time -p $clixon_netconf -qef $cfg" 0 "]]>]]>" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' +rpc=$(chunked_framing "") +expecteof_netconf "time -p $clixon_netconf -qef $cfg" 0 "$DEFAULTHELLO" "$rpc" "" "" 2>&1 | awk '/real/ {print $2}' # CLI get. This takes a lot of time because expand_dbvar gets perfnr (eg 100000) entries # and loops over it. @@ -134,18 +139,21 @@ done } 2>&1 | awk '/real/ {print $2}' # Now do leaf-lists instead of leafs -#new "generate leaf-list config" -echo -n "replace" > $fconfig2 +new "generate leaf-list config" +rpc="replace" for (( i=0; i<$perfnr; i++ )); do - echo -n "$i" >> $fconfig2 + rpc+="$i" done -echo "]]>]]>" >> $fconfig2 +rpc+="" +echo -n "$DEFAULTHELLO" > $fconfig2 +echo "$(chunked_framing "$rpc")" >> $fconfig2 new "netconf replace large list-leaf config" -expecteof_file "time -p $clixon_netconf -qef $cfg" 0 "$fconfig2" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' +expecteof_file "time -p $clixon_netconf -qef $cfg" 0 "$fconfig2" "^$" 2>&1 | awk '/real/ {print $2}' new "netconf commit large leaf-list config" -expecteof "time -p $clixon_netconf -qef $cfg" 0 "]]>]]>" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' +rpc=$(chunked_framing "") +expecteof "time -p $clixon_netconf -qef $cfg" 0 "$rpc" "^$" 2>&1 | awk '/real/ {print $2}' # XXX No leafref cli tests diff --git a/test/test_perf_json.sh b/test/test_perf_json.sh index b8a35b4a..0024e050 100755 --- a/test/test_perf_json.sh +++ b/test/test_perf_json.sh @@ -21,7 +21,8 @@ echo '"}' >> $fjson echo "$fjson" new "json parse long string" -expecteof_file "time -p $clixon_util_json" 0 "$fjson" 2>&1 | awk '/real/ {print $2}' +#expecteof_file "$clixon_util_json" 0 "$fjson" +expecteof_file "time -p $clixon_util_json -j" 0 "$fjson" "$fjson" 2>&1 | awk '/real/ {print $2}' rm -rf $dir diff --git a/test/test_perf_restconf.sh b/test/test_perf_restconf.sh index 378f4dc0..787aca78 100755 --- a/test/test_perf_restconf.sh +++ b/test/test_perf_restconf.sh @@ -209,22 +209,7 @@ done echo -n "" >> $fdataxml2 # No CR new "restconf replace large list-leaf config" -expectpart "$(time -p curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+xml" $RCPROTO://localhost/restconf/data/scaling:x -d @$fdataxml2)" 0 "HTTP/$HVER 20" - -new "netconf add $perfreq small leaf-list config" -{ time -p for (( i=0; i<$perfreq; i++ )); do - rnd=$(( ( RANDOM % $perfnr ) )) - echo "$DEFAULTHELLO$rnd]]>]]>" -done | $clixon_netconf -qef $cfg > /dev/null; } 2>&1 | awk '/real/ {print $2}' - -new "netconf add small leaf-list config" -expecteof "time -p $clixon_netconf -qef $cfg" 0 "$DEFAULTHELLOx]]>]]>" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' - -new "netconf commit small leaf-list config" -expecteof "time -p $clixon_netconf -qef $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" 2>&1 | awk '/real/ {print $2}' - -new "netconf get large leaf-list config" -expecteof "time -p $clixon_netconf -qef $cfg" 0 "$DEFAULTHELLO]]>]]>" "^01" 2>&1 | awk '/real/ {print $2}' +expectpart "$(time -p curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+xml" $RCPROTO://localhost/restconf/data/scaling:x -d @$fdataxml2)" 0 "HTTP/$HVER 20" 2>&1 | awk '/real/ {print $2}' if [ $RC -ne 0 ]; then new "Kill restconf daemon"