0%

Use Open vSwitch as OpenFlow Switch

This is the second experiment in the course Software-Defined Network at NCTU. The requirement is to use virtual machine to build a simple topology with an OpenFlow switch emulated by Open vSwitch.

The topology is an Open vSwitch connected with a Ryu controller and two hosts. The following picture is the network settings.

Install VirtualBox and Vagrant

I use VirtualBox to deploy the topology.

1
2
$ wget https://download.virtualbox.org/virtualbox/5.2.8/virtualbox-5.2_5.2.8-121009~Ubuntu~xenial_amd64.deb
$ dpkg -i virtualbox-5.2_5.2.8-121009~Ubuntu~xenial_amd64.deb

Since my computer is dual boot, I encountered the following error messege when installing it.

1
vboxdrv.sh: failed: modprobe vboxdrv failed. Please use 'dmesg' to find out why.

Here is the solution for your reference.

Vagrant is a command line tool to manage virtual machines. In this experiment I use Vagrant to set up my VirtualBox environments.

Reference official guide to install Vagrant from source.

Or you can simply install it by using apt-get.

Use Vagrant to Build VMs

See the official tutorial.

Some Setup on VMs

There are some system and network setups in Vagrantfile.

To acces the Ryu controller web UI from host, we need to set up port forwarding. Ryu web UI is open at port 8080, which is set up in next section.

1
ryu.vm.network "forwarding_port", guest: 8080, host: 8080

Adjust the memory size to 1024 MB.

1
2
3
ryu.vm.provider :virtualbox do |vb|
vb.memory = 1024
end

This adjustment is also done in Open vSwitch VM.

In Open vSwitch VM, set promiscuous mode to Allow All at two adapters connecting to hosts. This allow the traffic between hosts and the switch.

1
2
3
4
ovs.vm.rpovider :virtualbox do |vb|
vb.customize ["modifyvm", :id, "--nicpromisc3", "allow-all"]
vb.customize ["modifyvm", :id, "--nicpromisc4", "allow-all"]
end

The number after --nicpromisc is the network interface card ID. The default NIC’s ID is set to 1, and every NIC you add has the ID incremented by 1.

Set up VMs’ Environment

Set up Open vSwitch. You can reference the installation guide.

OvS Setupview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
# ovs setup

# dependencies
sudo apt-get install git autoconf automake libtool -y

# get Open vSwitch project
git clone -b v2.5.4 https://github.com/openvswitch/ovs.git

# build Open vSwitch
cd ovs
./boot.sh
./configure
make && sudo make install

# load kernel module
sudo /sbin/modprobe openvswitch

# initialize the configuration database
sudo mkdir -p /usr/local/etc/openvswitch
sudo ovsdb-tool create /usr/local/etc/openvswitch/conf.db \
vswitchd/vswitch.ovsschema

Run up Open vSwitch daemon and config it to be an OpenFlow switch.

OvS Configview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
# ovs config

# run up the daemon
sudo ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \
--remote=db:Open_vSwitch,Open_vSwitch,manager_options \
--private-key=db:Open_vSwitch,SSL,private_key \
--certificate=db:Open_vSwitch,SSL,certificate \
--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
--pidfile --detach

# initialize the database using ovs-vsctl
# This is only necessary the first time after creating the database
sudo ovs-vsctl --no-wait init

# start the daemon
sudo ovs-vswitchd --pidfile --detach

# set Open vSwitch to be an Openflow switch
sudo ovs-vsctl add-br br0

sudo ovs-vsctl add-port br0 eth2
sudo ovs-vsctl add-port br0 eth3

sudo ovs-vsctl set-controller br0 tcp:192.168.33.33:6633

Set up Ryu controller.

Ryu Setupview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
# ryu setup

# dependencies
sudo apt-get install git python-pip -y
sudo apt-get install gcc python-dev libffi-dev \
libssl-dev libxml2-dev libxslt1-dev zlib1g-dev -y

# get Ryu controller and install
git clone https://github.com/osrg/ryu.git
cd ryu
sudo pip install .
sudo pip install --upgrade .

Run Ryu web UI.

1
2
3
$ ryu-manager --observe-links \
ryu/app/gui_topology/gui_topology.py \
ryu/app/simple_switch_websocket_13.py

or

1
2
3
$ PYTHONPATH=. ./bin/ryu --observe-links \
ryu/app/gui_topology/gui_topology.py \
ryu/app/simple_switch_websocket_13.py

Now you can see the Ryu web UI at port 8080.

Vagrantfile

Following is the Vagrantfile to set up the environment.

Vagrant fileview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
$ryu_webui_script = <<SCRIPT
ryu-manager --observe-links \
/home/vagrant/ryu/ryu/app/gui_topology/gui_topology.py \
/home/vagrant/ryu/ryu/app/simple_switch_websocket_13.py
SCRIPT

$add_route_h2_script = <<SCRIPT
sudo route add -net 192.168.2.0 netmask 255.255.255.0 dev eth1
SCRIPT

$add_route_h1_script = <<SCRIPT
sudo route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
SCRIPT

Vagrant.configure("2") do |config|
config.vm.define "ryu" do |ryu|
ryu.vm.box = "ubuntu/trusty64"
# add forwarding port to access Ryu web UI from host
ryu.vm.network "forwarded_port", guest: 8080, host: 8080
ryu.vm.network "private_network", ip: "192.168.33.33", virtualbox__intnet: "LANs1"
ryu.vm.provider :virtualbox do |vb|
# adjust system memory to 1024 MB
vb.memory = 1024
end
ryu.vm.provision "ryusetup", type: "shell", path: "ryu_setup.sh"
ryu.vm.provision "ryuwebui", type: "shell", inline: $ryu_webui_script
end

config.vm.define "ovs" do |ovs|
ovs.vm.box = "ubuntu/trusty64"
ovs.vm.network "private_network", ip: "192.168.33.34", virtualbox__intnet: "LANs1"
ovs.vm.network "private_network", ip: "192.168.1.12", virtualbox__intnet: "LANs2"
ovs.vm.network "private_network", ip: "192.168.2.23", virtualbox__intnet: "LANs3"
ovs.vm.provider :virtualbox do |vb|
# adjust system memory to 1024 MB
vb.memory = 1024
# set promiscuous mode to allow all at two adapters connecting to hosts
vb.customize ["modifyvm", :id, "--nicpromisc3", "allow-all"]
vb.customize ["modifyvm", :id, "--nicpromisc4", "allow-all"]
end
ovs.vm.provision "ovssetup", type: "shell", path: "ovs_setup.sh"
ovs.vm.provision "ovsconfig", type: "shell", path: "ovs_config.sh"
end

config.vm.define "host1" do |host1|
host1.vm.box = "ubuntu/trusty64"
host1.vm.network "private_network", ip: "192.168.1.11", virtualbox__intnet: "LANs2"
host1.vm.provision "addrouteh2", type: "shell", inline: $add_route_h2_script
end

config.vm.define "host2" do |host2|
host2.vm.box = "ubuntu/trusty64"
host2.vm.network "private_network", ip: "192.168.2.22", virtualbox__intnet: "LANs3"
host2.vm.provision "addrouteh1", type: "shell", inline: $add_route_h1_script
end
end

If you set up and configure correctly, you could ping the host from the other host.

Issues

Shutdown the OvS daemon correctly.

1
$ sudo /usr/local/share/openvswitch/scripts/ovs-ctl stop