os-ken/ryu/tests/mininet/run_mnet-test.sh
HIYAMA Manabu 24d894bc95 test: add mininet-test suite
This patch adds a test framework using mininet. The following tests
can be performed.

- Set the flow for the OVS-switch from Ryu-app, we test the actual
  packet is to be handled properly in accordance with the flow; The
  packet that generated by "mz" or replayed by "tcpreplay" is routed
  through the ovs-switch, are processed according to the flow, then
  compare test conditions and the results captured by "tshark".

- Create a packet with ryu using the packet-lib, we test the packet
  and response are correct; to compare test conditions and the results
  captured by "tshark".

  $ ./run_mnet-test.sh [OPTION] [TEST DIR or FILE]...
  $ ./run_mnet-test.sh l2 l3/icmp packet_lib/arp/ARP_gratuitous.mn
  $ ./run_mnet-test.sh --help

Requirements package:
 - mininet: git://github.com/mininet/mininet.git
 - openvswitch: git://openvswitch.org/openvswitch
 - Mausezahn 0.40: http://www.perihel.at/sec/mz/
 - TShark 1.6.2: http://www.wireshark.org/
 - tcpreplay 3.4: http://tcpreplay.synfin.net/

Signed-off-by: HIYAMA Manabu <hiyama.manabu@po.ntts.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
2013-01-29 18:35:01 +09:00

275 lines
6.7 KiB
Bash
Executable File

#!/bin/sh
RUN_DIR=`dirname $0`
CMD_NAME=`basename $0 .sh`
CMD_PATH=`readlink -f $0`
CMD_DIR=`dirname $CMD_PATH`
DUMP_SEC=10
DUMP_DELAY=2
DUMP_DIR=/tmp/test-mn/dump
TEST_LIST=
TEST_SUFFIX=.mn
MN_PRE_FILE=/tmp/test-mn/mn-pre
MN_POST_FILE=/tmp/test-mn/mn-post
PKG_LIST="tshark tcpreplay mz"
RTN=0
# usage
usage() {
echo "Usage: $0 [OPTION] [TEST DIR or FILE]..."
echo ""
echo "Run Ryu's test in mininet"
echo "ex.) $ $0 l2 l3/icmp/ICMP_ping.mn"
echo ""
echo "Options:"
echo " -h, --help show this help message and exit"
exit 0
}
# set default environment
set_env() {
POST_IF=h1-eth0
DUMP_HOST=h2
DUMP_IF=h2-eth0
TEST_NAME=
DUMP_FILE=
RYU_APP=
RYU_LOG=
PCAP_MZ=
PCAP_FILE=
PCAP_FILTER=
PCAP_COM=
CACHE_HIT=
}
# making mininet-test-pre-file
mn_pre() {
exec 3>&1
exec >$MN_PRE_FILE
echo "sh echo '----------------------------------'"
echo "sh echo '(pre) mininet topology dump.'"
echo "sh echo '----------------------------------'"
echo "dump"
echo "net"
echo "sh echo '----------------------------------'"
echo "sh echo '(pre) tshark start.'"
echo "sh echo '----------------------------------'"
echo "$DUMP_HOST tshark -i $DUMP_IF -a duration:$DUMP_SEC -w $DUMP_FILE &"
echo "sh sleep $DUMP_DELAY"
echo "sh echo '----------------------------------'"
exec 1>&3
}
# making mininet-test-post-file
mn_post() {
exec 3>&1
exec >$MN_POST_FILE
echo "sh ovs-vsctl del-controller s1"
echo "sh ovs-vsctl set bridge s1 protocols='[OpenFlow10,OpenFlow12]'"
echo "sh ovs-vsctl set-controller s1 tcp:127.0.0.1"
echo "sh echo '----------------------------------'"
echo "sh echo '(post) packet sending...'"
echo "sh echo '----------------------------------'"
echo $PCAP_COM
echo "sh sleep 1"
echo "sh echo '----------------------------------'"
echo "sh echo '(post) dump flows.'"
echo "sh echo '----------------------------------'"
echo "sh ovs-ofctl dump-flows s1"
echo "sh echo '----------------------------------'"
exec 1>&3
}
# ovs cache-hit incremental check
ovs_cache_hit() {
expr `sudo ovs-dpctl show|sed -n 's|lookups: hit:||gp'|awk '{print $1}'` - ${1:-0}
}
# starting ryu-manager
run_ryu() {
ERRSTAT=0
ERRTAG="run_ryu() :"
echo "Inf: RYU_APP=$RYU_APP"
echo "Inf: ryu-manager starting..."
ryu-manager --verbose $RYU_APP 2>$DUMP_DIR/$RYU_LOG &
PID_RYU=$!
sleep 1
[ -d /proc/$PID_RYU ] || err $ERRTAG "failed to start ryu-manager."
return $ERRSTAT
}
# starting mininet and test-script
run_mn() {
echo "Info: mininet starting..."
sudo mn --mac --test none --pre $MN_PRE_FILE --post $MN_POST_FILE \
--controller remote 127.0.0.1
}
# cleaning after mininet
clean_mn() {
wait_ryu
rm -f $MN_PRE_FILE $MN_POST_FILE
}
# check packet and chache-hit
check() {
PACKET=`tshark -r $DUMP_FILE -R "$PCAP_FILTER" 2>/dev/null`
if [ ! "$PACKET" ]; then
RESULT=NG
REASON="(unmatched packet. please check $DUMP_FILE)"
elif [ "$CACHE_HIT" ] && [ `ovs_cache_hit $CACHE_HIT` -eq 0 ]; then
RESULT=NG
REASON="(ovs cache hit miss.)"
else
RESULT=OK; REASON=
fi
echo
echo "TEST ${TEST_NAME} : $RESULT $REASON"
}
# stoping ryu-manager
wait_ryu() {
kill -2 $PID_RYU
wait $PID_RYU
}
# test-main
test_mn() {
DUMP_FILE=$DUMP_DIR/$DUMP_FILE
touch $DUMP_FILE
sudo chmod o+w $DUMP_FILE
[ "$CACHE_HIT" ] && CACHE_HIT=`ovs_cache_hit 0`
mn_pre
mn_post
run_ryu; [ $? -ne 0 ] && return 1
run_mn; [ $? -ne 0 ] && return 1
check
return 0
}
err() {
echo Error: $*
ERRSTAT=1
}
mnfile_check() {
test=`basename $1 $TEST_SUFFIX`
file=`readlink -f $1`
TEST_DIR=`dirname $file`
ERRSTAT=0
ERRTAG="mnfile_check() :"
# test-file check
if [ ! -r $file ]; then
err $ERRTAG "cannot open the file: $file"
return $ERRSTAT
fi
. $file || err $ERRTAG "failed to include $file"
# parameter check
[ "$RYU_APP" ] || err $ERRTAG: "RYU_APP is not defined"
[ "$PCAP_FILE" -o "$PCAP_MZ" ] || err $ERRTAG: "PCAP_FILE or PCAP_MZ is not defined"
[ "$PCAP_FILTER" ] || err $ERRTAG "PCAP_FILTER is not defined"
[ "$TEST_NAME" ] || TEST_NAME=$test
[ "$DUMP_FILE" ] || DUMP_FILE=$test.dump
[ "$RYU_LOG" ] || RYU_LOG=ryu-manager.$test.log
[ $ERRSTAT -ne 0 ] && return $ERRSTAT
# pcap check (pcap-file or mz-option)
if [ "$PCAP_FILE" ]; then
PCAP_FILE=$TEST_DIR/$PCAP_FILE
[ -r $PCAP_FILE ] || err $ERRTAG "PCAP_FILE[$PCAP_FILE] cannot read"
PCAP_COM="h1 tcpreplay -l 3 -i $POST_IF $PCAP_FILE"
elif [ "$PCAP_MZ" ]; then
PCAP_COM="h1 mz $POST_IF $PCAP_MZ"
fi
[ $ERRSTAT -ne 0 ] && return $ERRSTAT
# ryu-app check
[ -r $TEST_DIR/$RYU_APP -o -r $TEST_DIR/${RYU_APP}.py ] && RYU_APP=$TEST_DIR/$RYU_APP
return $ERRSTAT
}
arg_check() {
ARGLIST=
ERRTAG="argcheck() :"
case "$1" in
-h|--help) usage;;
esac
if [ $# -ne 0 ]; then
ARGLIST=$*
else
ARGLIST=`find . -type f -name "*$TEST_SUFFIX"`
fi
for arg in $ARGLIST; do
if [ -d $arg ]; then
file=`find $arg -type f -name "*$TEST_SUFFIX"`
elif [ -f $arg ]; then
file=$arg
else
err $ERRTAG "$arg is not found"
file=
fi
TEST_LIST="$TEST_LIST $file"
done
}
pkg_check() {
no_pkg=
for pkg in $PKG_LIST; do
[ ! `which $pkg` ] && no_pkg="$no_pkg $pkg"
done
for pkg in $no_pkg; do
echo "Error: Package [ $pkg ] is not found. Please install."
done
[ "$no_pkg" ] && exit 1
}
### main
[ -d $DUMP_DIR ] || mkdir -p $DUMP_DIR
pkg_check
arg_check $*
echo "\n---------- test target ----------"
for testfile in $TEST_LIST; do echo $testfile; done
count=0
for testfile in $TEST_LIST; do
echo "\n---------- test [$testfile] start ----------"
set_env
mnfile_check $testfile && test_mn
case $? in
0) msg="finished : $RESULT" ;;
*) msg="skipped with error"; RESULT="skip" ;;
esac
eval RESULT_${count}=\$RESULT
eval REASON_${count}=\$REASON
count=`expr $count + 1`
num=`eval echo \\${num_$RESULT:-0}`
eval num_${RESULT}=`expr $num + 1`
[ "$RESULT" != "OK" ] && RTN=1
clean_mn
echo "\n---------- test [$testfile] $msg ----------"
done
# output summary results
echo "\n---------- test results ----------"
count=0
for testfile in $TEST_LIST; do
eval echo \$testfile : \$RESULT_${count} \$REASON_${count}
count=`expr $count + 1`
done
echo "----------------------------------"
echo "Ran $count tests. Result: ${num_OK:+OK=}$num_OK ${num_NG:+NG=}$num_NG ${num_skip:+skip=}$num_skip"
exit $RTN