==== Part 1 Preparation before script can be written ====
=== Step 1 Create multiple read-only UML instances ===
To start multiple instances in read-only mode is simple. Just remove the // w // option will be enough.
sudo linux.uml rootfstype=hostfs rootflags=/home/vic/uml/ r umlid=umla eth0=daemon,,unix,/home/vicuml/switch/sw1.ctl
sudo linux.uml rootfstype=hostfs rootflags=/home/vic/uml/ r umlid=umlb eth0=daemon,,unix,/home/vicuml/switch/sw1.ctl
The only issue is that the whole file system of the instance became read-only.
=== Step 2 Create ramfs on the UML instances ===
In order to let the read-only UML instances run nicely and can keep the logs we need later for investigate the behavior of the protocols, we can create a ramfs to contain these files.
In the // /etc/fstab //, we will define the /var as ramfs and give it a 25MB limit
none /var ramfs defaults,size=25M 0 0
Next is to mount it in // /etc/init.d/rcS // and make the folders
mount none /var -t hostfs -o /home/vic/umlvar
mkdir /var/lock /var/run /var/log /var/tmp
=== Step 3 Create virtual console for X use in UML instance ===
By add the next line into // /etc/inittab // we have a new terminal connection and can use // ssh // to connect to the UML instances.
::respawn:/bin/getty -L ttyS0 38400 vt100
=== Step 4 Use screen command to start multiple UML instances ===
Screen is a kind of "task manager" it can be used to start multiple command and monitor them. I can resume to any of the command former started by the screen.
## This command will show all the currently monitored program of current user.
## It it notable that if you start with sudo screen, it will show the process of root user instead of current user.
screen -ls
## This will let the linux.uml, eventually any command run in background
screen -dmS $hostname linux.uml rootfstype=hostfs
==== Part 2 Write script ====
=== Step 1 script on host ===
#!/bin/sh
n=$1
echo "going to create $n networks"
screen -dmS sw1 uml_switch -unix /home/vic/uml/switch/sw1.ctl
for i in `seq 1 $n`
do
screen -d -m -S uml$i linux.uml rootfstype=hostfs rootflags=/home/vic/uml/ r umlid=uml$i hostname=uml$i eth0=daemon,,unix,/home/vic/uml/switc/sw1.ctl ip_eth0="10.0.0.$i" mask_eth0="255.255.255.0" bc_eth0="10.1.0.0"
done
The host code will need a int parameter. It indicates the amount of instances we are going to startup. The the switch will be brought on first. Then the machines will be brought on afterwards and being assigned the IP addresses.
=== Step 2 script on UML instances ===
I add the script into /etc/init.d/rcS
#!/bin/sh
mount -a
mkdir /var/lock /var/run /var/log /var/tmp
hostname $hostname
ifconfig lo up
if [ -z $role ]
then
role="host"
fi
case $role in
router)
echo "router";;
sniffer)
echo "sniffer"
ip link set eth0 up
tcpdump -i eth0 -U -s 0 -w /var/log/$hostname-`date +%H%M`.dmp &
echo "INFO: sniffer $hostname activated"
;;
bridge)
echo "bridge";;
host)
echo "host: $hostname"
if [ ! -z $ip_eth0 ] && [ ! -z $mask_eth0 ] && [ ! -z $bc_eth0 ]
then
ifconfig eth0 $ip_eth0 netmask $mask_eth0 broadcast $bc_eth0 up
fi
if [ ! -z $ip_eth1 ] && [ ! -z $mask_eth1 ] && [ ! -z $bc_eth1 ]
then
ifconfig eth1 up
ifconfig eth1 $ip_eth1 netmask $mask_eth1 broadcast $bc_eth1
fi
if [ ! -z $ip_eth2 ] && [ ! -z $mask_eth2 ] && [ ! -z $bc_eth2 ]
then
ifconfig eth2 up
ifconfig eth2 $ip_eth2 netmask $mask_eth2 broadcast $bc_eth2
then
ifconfig eth2 up
ifconfig eth2 $ip_eth2 netmask $mask_eth2 broadcast $bc_eth2
fi
if [ ! -z $ip_eth3 ] && [ ! -z $mask_eth3 ] && [ ! -z $bc_eth3 ]
then
ifconfig eth3 up
ifconfig eth3 $ip_eth3 netmask $mask_eth3 broadcast $bc_eth3
fi
;;
esac
=== Step 3 Re-create the simple network ===
Now I can re-create the simple network in the first assiginment by simply running the next command
vic@vicubuntu:~$ sudo ./network1 2
going to create 2 networks
And I can view the currently started tasks by using screen
vic@vicubuntu:~$ sudo screen -ls
There are screens on:
11197.uml2 (02/07/2011 02:39:29 PM) (Detached)
11195.uml1 (02/07/2011 02:39:29 PM) (Detached)
2 Sockets in /var/run/screen/S-root.
I can resume to them by
sudo screen -r uml2
The reason why sudo is there is that, in order to give the UML instances enough privilege to connect to the switch daemon which was started with root privilege, we have to start the UML instances with also root privilege. Hence the UML instances stay in the root space of screen. So, everything is working. Next step is to improve the code.
=== Extra step Improve the scripts ===
Now we need for each network a different host script which is in a sense not very "automated". The plan is to make a script which will read configuration files and create networks according to the contents of it.
The revised host script
#!/bin/sh
#netstart [start|stop|stopall] [sniffer|router|switch|hub|host|bridge] [name]
#[ip/cidr] [switchname|gw's ip/cidr]
action=$1
role=$2
hostname=$3
home="/home/vic/uml"
switchhome="/home/vic/umlswitch"
case ${action} in
start)
case ${role} in
sniffer)
sw=$4
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw.ctl
echo "sniffer: $hostname conneted to switch: $sw"
;;
router)
sw1=$4
ip1=$5
mask1=$6
br1=$7
pro=$8
ver=$9
if [ -z "$10" ]; then
echo "screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 pro=$pro ver=$ver role=$role"
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 pro=$pro ver=$ver role=$role
else
sw2=$8
ip2=$9
mask2=$10
br2=$11
pro=$12
ver=$13
if [ -z "$14" ]; then
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ rw umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 eth1=daemon,,unix,$switchhome/$sw2.ctl ip_eth1=$ip2 mask_eth1=$mask2 bc_eth1=$br2 pro=$pro ver=$ver role=$role
else
sw3=$12
ip3=$13
mask3=$14
br3=$15
pro=$16
ver=$17
if [ -z "$18" ]; then
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 eth1=daemon,,unix,$switchhome/$sw2.ctl ip_eth1=$ip2 mask_eth1=$mask2 bc_eth1=$br2 eth2=daemon,,unix,$switchhome/$sw3.ctl ip_eth2=$ip3 mask_eth2=$mask3 bc_eth2=$br3 pro=$pro ver=$ver role=$role
else
sw4=$16
ip4=$17
mask4=$18
br4=$19
pro=$20
ver=$21
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 eth1=daemon,,unix,$switchhome/$sw2.ctl ip_eth1=$ip2 mask_eth1=$mask2 bc_eth1=$br2 eth2=daemon,,unix,$switchhome/$sw3.ctl ip_eth2=$ip3 mask_eth2=$mask3 bc_eth2=$br3 eth3=daemon,,unix,$switchhome/$sw4.ctl ip_eth3=$ip4 mask_eth3=$mask4 bc_eth3=$br4 pro=$pro ver=$ver role=$role
fi
fi
fi
#echo $pro
#echo $ver
if [ $pro = "rip" ] && [ $ver = "1" ]; then
cp -P ~/uml/etc/quagga/ripd1.conf ~/uml/etc/quagga/ripd.conf
#chown quagga:quagga ~/uml/etc/quagga/ripd.conf
#chmod 640 ~/uml/etc/quagga/ripd.conf
fi
if [ $pro = "rip" ] && [ $ver = "2" ]; then
cp ~/uml/etc/quagga/ripd2.conf ~/uml/etc/quagga/ripd.conf
#chown -R quagga:quagga /etc/quagga/ripd.conf
#chmod 640 /etc/quagga/ripd.conf
fi
echo "router $hostname started"
;;
switch)
screen -d -m -S $hostname uml_switch -unix $switchhome/$hostname.ctl &
echo "$switchhome/$hostname.ctl"
echo "switch $hostname started"
;;
hub)
screen -d -m -S $hostname uml_switch -hub -unix $switchhome/$hostname.ctl &
echo "hub $hostname started"
;;
host)
sw1=$4
ip1=$5
mask1=$6
br1=$7
gw=$8
if [ -z "$9" ]; then
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 gw=$gw
else
sw2=$8
ip2=$9
mask2=$10
br2=$11
gw=$12
if [ -z "$13" ]; then
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 eth1=daemon,,unix,$switchhome/$sw2.ctl ip_eth1=$ip2 mask_eth1=$mask2 bc_eth1=$br2 gw=$gw
else
sw3=$12
ip3=$13
mask3=$14
br3=$15
gw=$16
if [ -z "$17" ]; then
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 eth1=daemon,,unix,$switchhome/$sw2.ctl ip_eth1=$ip2 mask_eth1=$mask2 bc_eth1=$br2 eth2=daemon,,unix,$switchhome/$sw3.ctl ip_eth2=$ip3 mask_eth2=$mask3 bc_eth2=$br3 gw=$gw
else
sw4=$16
ip4=$17
mask4=$18
br4=$19
gw=$20
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname eth0=daemon,,unix,$switchhome/$sw1.ctl ip_eth0=$ip1 mask_eth0=$mask1 bc_eth0=$br1 eth1=daemon,,unix,$switchhome/$sw2.ctl ip_eth1=$ip2 mask_eth1=$mask2 bc_eth1=$br2 eth2=daemon,,unix,$switchhome/$sw3.ctl ip_eth2=$ip3 mask_eth2=$mask3 bc_eth2=$br3 eth3=daemon,,unix,$switchhome/$sw4.ctl ip_eth3=$ip4 mask_eth3=$mask4 bc_eth3=$br4 gw=$gw
fi
fi
fi
echo "host $hostname started"
;;
bridge)
macbr=$4
macif1=$5
sw1=$6
#hostname=$macbr
if [ -z "$7" ];
then
#echo "screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname role=$role hostname=$hostname eth0=daemon,,unix,$home/switch/$sw1.ctl macbr=$macbr macif1=$macif1 sw1=$sw1"
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw1.ctl macbr=$macbr macif1=$macif1 sw1=$sw1
else
macif2=$7
sw2=$8
if [ -z "$9" ];
then
#echo "screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$home/switch/$sw1 eth1=daemon,,unix,$home/switch/$sw2 macbr=$macbr macif1=$macif1 sw1=$sw1 macif2=$macif2 sw2=$sw2"
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw1.ctl eth1=daemon,,unix,$switchhome/$sw2.ctl macbr=$macbr macif1=$macif1 sw1=$sw1 macif2=$macif2 sw2=$sw2
else
macif3=$9
sw3=$10
#echo "screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw1.ctl eth1=daemon,,unix,$switchhome/$sw2.ctl eth2=daemon,,unix,$switchhome/$sw3.ctl macbr=$macbr macif1=$macif1 sw1=$sw1 macif2=$macif2 sw2=$sw2 macif3=$macif3 sw3=$sw3"
screen -d -m -S $hostname linux.uml rootfstype=hostfs rootflags=$home/ r umlid=$hostname hostname=$hostname role=$role eth0=daemon,,unix,$switchhome/$sw1.ctl eth1=daemon,,unix,$switchhome/$sw2.ctl eth2=daemon,,unix,$switchhome/$sw3.ctl macbr=$macbr macif1=$macif1 sw1=$sw1 macif2=$macif2 sw2=$sw2 macif3=$macif3 sw3=$sw3
fi
fi
echo "bridge $hostname started"
;;
esac
;;
stop)
echo "stopping all the UML instances"
;;
stopall)
echo "stopping all the instances and switches"
killall linux.uml
killall uml_switch
echo "everything killed"
;;
*)
echo "command usage is "
echo "netstart [start|stop|stopall] [sniffer|router|switch|hub|host|bridge] [name]"
;;
esac
Now the host script will accept parameters and run accordingly to the parameter it was given. and start stop function are also added.
the revised rcS script
#!/bin/sh
mount -a
mkdir -p /var/run /var/lock /var/log /var/tmp /var/run/quagga
chmod 777 /var/* /var/run/quagga
mount none /logfile -t hostfs -o /home/vic/umlvar
hostname $hostname
ifconfig lo up
if [ -z $role ]
then
role="host"
fi
case $role in
router)
echo "router $hostname"
if [ ! -z $ip_eth0 ] && [ ! -z $mask_eth0 ] && [ ! -z $bc_eth0 ];
then
ifconfig eth0 $ip_eth0 netmask $mask_eth0 broadcast $bc_eth0 up
fi
if [ ! -z $ip_eth1 ] && [ ! -z $mask_eth1 ] && [ ! -z $bc_eth1 ];
then
ifconfig eth1 $ip_eth1 netmask $mask_eth1 broadcast $bc_eth1 up
fi
if [ ! -z $ip_eth2 ] && [ ! -z $mask_eth2 ] && [ ! -z $bc_eth2 ];
then
ifconfig eth2 $ip_eth2 netmask $mask_eth2 broadcast $bc_eth2 up
fi
if [ ! -z $ip_eth3 ] && [ ! -z $mask_eth3 ] && [ ! -z $bc_eth3 ];
then
ifconfig eth3 $ip_eth3 netmask $mask_eth3 broadcast $bc_eth3 up
fi
echo "1" > /proc/sys/net/ipv4/ip_forward
/etc/init.d/quagga start
echo "INFO: $pro $ver started"
;;
sniffer)
echo "sniffer"
#ip link set eth0 up
ifconfig eth0 -arp up
tcpdump -i eth0 -U -s 0 -w /logfile/$hostname-`date +%H%M`.dmp &
echo "INFO: sniffer $hostname activated"
;;
bridge)
echo "bridge: $hostname"
mount -t hostfs none /lib/modules/ -o /usr/lib/uml/modules
modprobe llc
modprobe stp
modprobe bridge
#add br and interfaces
/bin/brctl addbr $hostname
ifconfig $hostname hw ether $macbr
if [ ! -z $macif1 ];
then
ifconfig eth0 hw ether $macif1 up
/bin/brctl addif $hostname eth0
fi
if [ ! -z $macif2 ];
then
ifconfig eth1 hw ether $macif2 up
/bin/brctl addif $hostname eth1
fi
if [ ! -z $macif3 ];
then
ifconfig eth2 hw ether $macif3 up
/bin/brctl addif $hostname eth2
fi
/bin/brctl stp $hostname on
ifconfig $hostname up
echo "INFO: bridge $hostname activated"
;;
host)
echo "host: $hostname"
if [ ! -z $ip_eth0 ] && [ ! -z $mask_eth0 ] && [ ! -z $bc_eth0 ];
then
ifconfig eth0 $ip_eth0 netmask $mask_eth0 broadcast $bc_eth0 up
fi
if [ ! -z $ip_eth1 ] && [ ! -z $mask_eth1 ] && [ ! -z $bc_eth1 ];
then
ifconfig eth1 $ip_eth1 netmask $mask_eth1 broadcast $bc_eth1 up
fi
if [ ! -z $ip_eth2 ] && [ ! -z $mask_eth2 ] && [ ! -z $bc_eth2 ];
then
ifconfig eth2 $ip_eth2 netmask $mask_eth2 broadcast $bc_eth2 up
fi
if [ ! -z $ip_eth3 ] && [ ! -z $mask_eth3 ] && [ ! -z $bc_eth3 ];
then
ifconfig eth3 $ip_eth3 netmask $mask_eth3 broadcast $bc_eth3 up
fi
if [ ! -z $gw ];
then
ip route add default via $gw
fi
echo "INFO: host $hostname activated"
;;
esac
configuration file
#usage: ./netstart [start|stop|stopall|*] [role] [hostname] [switch] [(ip & netmask & broadcast) | br_mac & (port_mac & switch)] [gateway]
#start a hub and give it a name (ie. sw1)
./netstart start hub sw1
#start sniffers and give hostname (sniffer1) and then the process file name (sw1)
./netstart start sniffer sniffer1 sw1
#start a host, give host name, switch to connect to, interface to that switch, then optionally a gateway
./netstart start host host1 sw1 192.168.0.1 255.255.255.0 192.168.0.255 192.168.0.100
#start bridges, give hostname, bridge ID, port ID and switch to which the port is connected
./netstart start bridge br1 aa:bb:cc:dd:01:aa aa:bb:cc:dd:01:01 sw1 aa:bb:cc:dd:01:02 sw2
#start a router, give hostname, switch and to which the interface is connected, then routing protocol. optionally protocol version number
./netstart start router routera swa 20.0.0.1 255.0.0.0 20.255.255.255 coreab 10.0.0.1 255.0.0.0 10.255.255.255 coreac 192.168.1.17 255.255.255.240 192.168.1.31 rip 1