Hello up there,
I was studying netconf2011 slides and saw there is an LNST effort to
automatically test net, bonding, vlan, etc..., so I'd like to say thanks
and also I think I have something to share on the topic:
When I was working on bonding some time ago, it turned out that with the
help of TAP devices, virtual VDE switches and route-based send-to-self,
it is possible to create virtual nets on non-virtualized host and then
see/test how e.g. bonding works over such network.
Attached is a sample script which creates two virtual ethernet segments,
and bonds them together.
Hope it will be somewhat useful idea/sample and thanks,
Kirill
---- 8< ----
#!/bin/bash -e
# Handy program to prepare environment for testing etherdup:
#
# - setup tap interfaces and switches and plug cables between them;
# - setup bonding interfaces above taps;
# - setup routing so that send-to-self works;
# - for convenience, screen sessions with switch/cables control (yes, you can
# break and restore cables) and tcpdump's are started;
# - everything is cleaned up on exit.
#
#
# tap0 --- switch0 --- tap1
# / 1.10 1.11 \
# bond0 -- -- bond1
# 4.10 \ / 4.11
# tap2 --- switch1 --- tap3
# 2.10 2.11
# die <msg>...
die() {
echo 1>&2 $@
exit 1
}
verbose=
# trace <msg>
trace() {
test -z "$verbose" || echo $@
}
# lower priority of kernel local table from 0 to 500
# (so that we can install our own rules before it)
ip rule del pref 0 lookup local 2>/dev/null || :
ip rule del pref 500 lookup local 2>/dev/null || :
ip rule add pref 500 lookup local
# ifcfg_tap <tap-name>
ifcfg_tap() {
tap=$1
trace ifcfg_tap $tap
# reset interface
ip link del $tap 2>/dev/null || :
# create interface
vde_tunctl -t $tap
}
# xifup <ifname> <ip>
xifup() {
xif=$1
ip=$2
trace xifup $xif $ip
# assign IP address
ip addr add $ip/24 dev $xif
# put if up
ip link set $xif up
}
# if_get_ipaddr <iface>
if_get_ipaddr() {
iface=$1
ip=$(ip -4 addr show $iface | tail -1 | awk '{print $2}')
ip=${ip%/*} # 192.168.1.10/24 -> 192.168.1.10
echo $ip
}
# if_get_n <iface>
# tap<n> -- n
# bond<n> -- 10+n
if_get_n() {
ifx=$1
case $ifx in
tap*)
n=${ifx#tap}
;;
bond*)
n=${ifx#bond}
n=$((10+$n))
;;
*)
die "unsupported iface $ifx"
;;
esac
echo $n
}
# rt_setup_loop <if1> <if2>
# setup routing loop between two interfaces
#
http://marc.info/?l=linux-netdev&m=129500124207256&w=2
rt_setup_loop() {
if1=$1
if2=$2
trace rt_setup_loop $if1 $if2
n1=`if_get_n $if1`
n2=`if_get_n $if2`
ip1=`if_get_ipaddr $if1`
ip2=`if_get_ipaddr $if2`
# on rx side handle packets by local table, so we can receive them
echo 1 >/proc/sys/net/ipv4/conf/$if1/accept_local
echo 1 >/proc/sys/net/ipv4/conf/$if2/accept_local
ip rule del pref $((0+$n1)) 2>/dev/null || :
ip rule del pref $((0+$n2)) 2>/dev/null || :
ip rule add pref $((0+$n1)) iif $if1 lookup local
ip rule add pref $((0+$n2)) iif $if2 lookup local
# tx
ip rule del pref $((100+$n1)) 2>/dev/null || :
ip rule del pref $((100+$n2)) 2>/dev/null || :
ip rule add pref $((100+$n1)) to $ip1 lookup $((100+$n1)) # if1 <- if2
ip rule add pref $((100+$n2)) to $ip2 lookup $((100+$n2)) # if2 <- if1
ip route flush table $((100+$n1))
ip route flush table $((100+$n2))
ip route add default dev $if2 table $((100+$n1))
ip route add default dev $if1 table $((100+$n2))
}
# ifcfg_bond <bond-name> <slave1> <slave2>
ifcfg_bond() {
bond=$1
slave1=$2
slave2=$3
trace ifcfg_bond $bond $slave1 $slave2
# FIXME bonding wants slave to be initially down, why?
ip link set $slave1 down
ip link set $slave2 down
echo -$bond >/sys/class/net/bonding_masters 2>/dev/null || :
echo +$bond >/sys/class/net/bonding_masters
echo broadcast >/sys/class/net/$bond/bonding/mode
echo +$slave1 >/sys/class/net/$bond/bonding/slaves
echo +$slave2 >/sys/class/net/$bond/bonding/slaves
}
ifcfg_tap tap0 && xifup tap0 192.168.1.10
ifcfg_tap tap1 && xifup tap1 192.168.1.11
ifcfg_tap tap2 && xifup tap2 192.168.2.10
ifcfg_tap tap3 && xifup tap3 192.168.2.11
rt_setup_loop tap0 tap1
rt_setup_loop tap2 tap3
ifcfg_bond bond0 tap0 tap2 && xifup bond0 192.168.4.10
ifcfg_bond bond1 tap1 tap3 && xifup bond1 192.168.4.11
rt_setup_loop bond0 bond1
# kill unnneeded routes from 'table main' set by `ip addr add`
for ifx in tap0 tap1 tap2 tap3 bond0 bond1 ; do
ip route del `ip route list table main | grep $ifx`
done
# ensure (visually) we've set up it ok
echo
echo " >>> rules:"
ip rule
echo
echo " >>> tap/bond routing table:"
routel | grep '\<\(tap\|bond\).\>'
#ip route show table all | grep '\<\(tap\|bond\).\>'
# tx path
echo
echo " >>> checking routing for tx path:"
ip route get 192.168.1.10 connected
ip route get 192.168.1.11 connected
echo
ip route get 192.168.2.10 connected
ip route get 192.168.2.11 connected
echo
ip route get 192.168.4.10 connected
ip route get 192.168.4.11 connected
# rx path
echo
echo " >>> checking routing for rx path:"
ip route get from 192.168.1.10 to 192.168.1.11 iif tap1
ip route get from 192.168.1.11 to 192.168.1.10 iif tap0
echo
ip route get from 192.168.2.10 to 192.168.2.11 iif tap3
ip route get from 192.168.2.11 to 192.168.2.10 iif tap2
echo
ip route get from 192.168.4.10 to 192.168.4.11 iif bond1
ip route get from 192.168.4.11 to 192.168.4.10 iif bond0
echo
echo " >>> ready to start switches, connect wires, etc ..."
read
S() {
screen -S switches -X $@
}
screen -d -m -S switches -t S0 vde_switch -s switch0
S zombie qr
S verbose on
sleep 0.2
S screen -t 'S0-tap0' vde_plug2tap -s switch0 tap0
S screen -t 'S0-tap1' vde_plug2tap -s switch0 tap1
S screen -t 'S1' vde_switch -s switch1
sleep 0.2
S screen -t 'S1-tap2' vde_plug2tap -s switch1 tap2
S screen -t 'S1-tap3' vde_plug2tap -s switch1 tap3
S() {
screen -S dumps -X $@
sleep 0.01 # :( or else it can miss some commands
}
screen -d -m -S dumps -t tap0 tcpdump -i tap0 -n -t -e
S zombie qr
S verbose on
S screen -t tap1 tcpdump -i tap1 -n -t -e
S screen -t tap2 tcpdump -i tap2 -n -t -e
S screen -t tap3 tcpdump -i tap3 -n -t -e
S screen -t bond0 tcpdump -i bond0 -n -t -e
S screen -t bond1 tcpdump -i bond1 -n -t -e
XTERM="xterm -fn
-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1"
$XTERM -T "tap/bond dumps" -e screen -r dumps &
$XTERM -T "tap/bond switches" -e screen -r switches &
# wait for xterm with `screen -r dumps` started
sleep 1
# layout dumps as follows
# tap0 tap1
# tap2 tap3
# bond0 bond1
S select -
S split
S focus down
S split
S focus up
S split -v
S select tap0
S focus down
S select tap1
S focus down
S split -v
S select tap2
S focus down
S select tap3
S focus down
S split -v
S select bond0
S focus down
S select bond1
wait
# cleanup
echo " >>> cleanup..."
for ifx in bond0 bond1 tap0 tap1 tap2 tap3 ; do
# kill 'to <if-ip>' rule
ip rule del to `if_get_ipaddr $ifx`
# kill 'iif <if>' rule
ip rule del iif $ifx
# kills interfaces and routes
ip link del $ifx
done
echo done