Bernhard's Homepage

GNS3 - SDN Lab with Faucet controller and OpenvSwitch

GNS3 - SDN Lab with Faucet controller and OpenvSwitch

Faucet is a very compact SDN controller, which is easy to install and setup. That makes it a good choice for a SDN beginners lab. For the network devices I'm using OpenvSwitch, a multi-layer virtual switch.

But be warned: Faucet and OpenvSwitch are based on Linux. You need to be comfortable working in the Linux environment and editing files with vi.

Installation

Faucet

Faucet provides official builds on Docker Hub, which makes it very easy to install it.

To install it into GNS3 open the preferences, select the Docker / Docker Containers section and click on "New". The "New Docker VM template" wizard will start and it asks a couple of questions:

  • Server type: Run this Docker VM on the GNS3 VM
  • Docker image: Select "New Image" and enter "faucet/faucet" as the image name.
  • Name: Give the VM a name, e.g. faucet
  • Adapters: Stick with the default value of 1
  • Start command: Set it to sh -c 'cd; faucet & sleep 10; ash -i -l'
  • Console type: Stick with the default telnet
  • Environment: Leave it empty, then finish the wizard.

Now edit the newly added faucet appliance and in the Advanced tab set the additional persistent directories to "/root".

The template should now look like this (in edit mode):

General settings Advanced

OpenvSwitch

In principle you can use the openvswitch-management appliance. But the software is quite old (from 2016) and the OpenFlow port numbers do not correspond to the interface numbers, which makes its use in Faucet very cumbersome.

I've created an updated OpenvSwitch Docker appliance, that can be installed like this:

Open the preferences, select the Docker / Docker Containers section and click on "New". The "New Docker VM template" wizard will start and it asks a couple of questions:

  • Server type: Run this Docker VM on the GNS3 VM
  • Docker image: Select "New Image" and enter "ehlers/openvswitch" as the image name.
  • Name: Give the VM a name, e.g. ovs
  • Adapters: Give the switch a reasonable number of interfaces, e.g. 16
  • Start command: Leave it empty
  • Console type: Stick with the default telnet
  • Environment: Leave it empty, then finish the wizard.

If you like, you can edit the template and set a different symbol, for example the multilayer_switch symbol.

First project

Now we create our first project with the Faucet controller and just one OpenvSwitch switch. Basically I'm following Faucet's Installing faucet for the first time tutorial. But with GNS3 it gets a bit easier.

First we create a GNS3 project like this:

SDN Base Project

Don't power on the devices!!! This will be done later.

The first time a docker VM is added, the image gets downloaded. As Faucet and OpenvSwitch are quite small (53MB and 9MB), this shouldn't take very long.

I'm using ipterm devices to simulate hosts, but feel free to use any device you like, for example VPCS.

ovs-1 Configuration

It's best to configure the management IP address before it's powered on. If you have already started the OpenvSwitch, stop it before continuing.

In the GNS3 device configuration (right-click, "Edit config") configure the management IP address on eth0.

Here the eth0 section when using IP 172.20.1.1/24:

# Static config for eth0
auto eth0
iface eth0 inet static
	address 172.20.1.1
	netmask 255.255.255.0
#	gateway 172.20.1.254
#	up echo nameserver 172.20.1.254 > /etc/resolv.conf

Now startup ovs-1 and open its console.

On its first start the OpenvSwitch image creates an initial configuration. All interfaces without IP addresses (eth1 - eth15) are added to bridge br0. You can view it with ovs-ofctl show br0.

Now we need to configure the connection to the SDN controller. We need to set the datapath-id for br0. It must consist of exactly 16 hex digits, otherwise it won't work. And, of course, we need to set the IP address of the controller.

The management port eth0 should not be a member of any bridge, ovs-vsctl del-port eth0 takes care of that.

ovs-1:~# ovs-vsctl set bridge br0 other-config:datapath-id=0000000000000001 \
                -- set bridge br0 fail_mode=secure \
                -- set-controller br0 tcp:172.20.1.100:6653 \
                -- set controller br0 connection-mode=out-of-band \
                -- --if-exists del-port eth0

Without a connection to the controller the forwarding table of the switch, the OpenFlow flow table, is empty. That can be verified by ovs-ofctl dump-flows br0. The host devices (ipterm-1 and ipterm-2) won't be able to reach each other.

faucet-1 Configuration

Now we need to configure the IP address of the SDN controller. In the GNS3 device configuration (right-click, "Edit config") configure the IP address of eth0. Faucet needs a (dummy) nameserver, otherwise it won't start.

Here the eth0 section when using IP 172.20.1.100/24:

# Static config for eth0
auto eth0
iface eth0 inet static
	address 172.20.1.100
	netmask 255.255.255.0
#	gateway 172.20.1.254
	up echo nameserver 0.0.0.0 > /etc/resolv.conf

Now startup faucet-1 and open its console. You will see the startup messages of the Faucet controller. Some seconds later a Linux shell is started.

Our main tasks within Faucet will be editing its configuration, signal the server process to reload the configuration and check the log files.

Reloading the configuration is done with pkill -HUP ryu-manager. That's hard to remember (at least for me), so I created an alias. Edit .profile and add the following:

freload() {
	pkill -HUP ryu-manager
}

Afterwards update your shell with . .profile and now you can use freload to reload Faucet's configuration.

Finally we need to create the configuration. As shown in https://docs.faucet.nz/en/latest/tutorials/first_time.html#configure-faucet, edit /etc/faucet/faucet.yaml to look like this:

vlans:
    office:
        vid: 100

dps:
    ovs-1:
        dp_id: 0x1
        hardware: "Open vSwitch"
        interfaces:
            1:
                name: "eth1"
                native_vlan: office
            2:
                name: "eth2"
                native_vlan: office

Very important: Tabs are forbidden in the YAML language, please use only spaces for indentation.

Caution: Faucet uses the OpenFlow port number in the configuration. In my OpenvSwitch appliance the OpenFlow port number matches the interface number. But that's not the case with the openvswitch-management appliance. If you use that appliance, you need to use ovs-ofctl show br0 to find out the OpenFlow port number for each interface you want to use.

Use freload to reload the configuration. Afterwards check the log file /var/log/faucet/faucet.log for errors.

In the switch ovs-1 the flow table should be populated by the controller, use ovs-ofctl dump-flows br0 to verify it. If it's still empty, check the log file /var/log/openvswitch/ovs-vswitchd.log.

Host Devices

Finally the host devices (ipterm-1 and ipterm-2) need to be started and configured.

If everything is configured correctly, they can now ping each other.

Larger Project

The first project was used as an introduction to the SDN world. But lets create a larger switch topology.

SDN Project

The three switches are interconnected in a redundant way, that needs some attention to avoid a loop.

With traditional switches we would use spanning tree to handle the loop. If the switches in Faucet are managed as independent entities, they also need STP enabled. But that defeats the idea of SDN, the switches should be dump devices, the intelligence should be in the controller.

Faucet has a distributed switching (a.k.a stacking) mode. Stacking allows decisions such as switching and routing to be made in the context of the whole network. That way loops will be avoided and switch and port/cable failures can be automatically recovered.

OpenvSwitch configuration

Caution: In the initial configuration an OpenvSwitch operates like a traditional switch without STP. So please don't start all switches at once, you would experience a loop with all the unpleasant consequences. Start one of them, configure the controller connection, then start the next one. After all switches got their configuration, you no longer need these precautions. You can turn them on all at once.

The configuration of the switches doesn't differ from the configuration in the first project.

First you need to configure the eth0 IP addresses of the switches in GNS3 (right click, "Edit config").

Then start one switch and configure the datapath-id and controller IP address. Just be aware that the datapath-id must be unique within the network. When done, continue with the next switch.

Here the OpenvSwitch configurations:

ovs-1:~# ovs-vsctl set bridge br0 other-config:datapath-id=0000000000000001 \
                -- set bridge br0 fail_mode=secure \
                -- set-controller br0 tcp:172.20.1.100:6653 \
                -- set controller br0 connection-mode=out-of-band \
                -- --if-exists del-port eth0
ovs-2:~# ovs-vsctl set bridge br0 other-config:datapath-id=0000000000000002 \
                -- set bridge br0 fail_mode=secure \
                -- set-controller br0 tcp:172.20.1.100:6653 \
                -- set controller br0 connection-mode=out-of-band \
                -- --if-exists del-port eth0
ovs-3:~# ovs-vsctl set bridge br0 other-config:datapath-id=0000000000000003 \
                -- set bridge br0 fail_mode=secure \
                -- set-controller br0 tcp:172.20.1.100:6653 \
                -- set controller br0 connection-mode=out-of-band \
                -- --if-exists del-port eth0

Faucet configuration

Faucet's Stacking tutorial tells us how to configure stacking:

To connect the switches we can use the Faucet switch stacking feature. First, we need to define a root switch for our stack by setting a stack priority value for br0, the datapath with the lowest priority will be root. Second, we need to add stack interfaces connecting each datapath, we do this by defining the stack parameter on an interface. When defining a stack interface we say which datapath (dp) and port the other end of the cable is connected to.

vlans:
    office:
        vid: 100

dps:
    ovs-1:
        dp_id: 0x1
        hardware: "Open vSwitch"
        stack:
            priority: 1
        interfaces:
            1:
                name: "eth1"
                native_vlan: office
            2:
                name: "eth2"
                native_vlan: office
            14:
                name: "eth14"
                description: "Link ovs-1 eth14 - ovs-3 eth15"
                stack:
                    dp: ovs-3
                    port: 15
            15:
                name: "eth15"
                description: "Link ovs-1 eth15 - ovs-2 eth15"
                stack:
                    dp: ovs-2
                    port: 15

    ovs-2:
        dp_id: 0x2
        hardware: "Open vSwitch"
        interfaces:
            1:
                name: "eth1"
                native_vlan: office
            2:
                name: "eth2"
                native_vlan: office
            14:
                name: "eth14"
                description: "Link ovs-2 eth14 - ovs-3 eth14"
                stack:
                    dp: ovs-3
                    port: 14
            15:
                name: "eth15"
                description: "Link ovs-2 eth15 - ovs-1 eth15"
                stack:
                    dp: ovs-1
                    port: 15

    ovs-3:
        dp_id: 0x3
        hardware: "Open vSwitch"
        interfaces:
            1:
                name: "eth1"
                native_vlan: office
            2:
                name: "eth2"
                native_vlan: office
            14:
                name: "eth14"
                description: "Link ovs-3 eth14 - ovs-2 eth14"
                stack:
                    dp: ovs-2
                    port: 14
            15:
                name: "eth15"
                description: "Link ovs-3 eth15 - ovs-1 eth14"
                stack:
                    dp: ovs-1
                    port: 14

As shown in the first project use freload to signal Faucet to reload and activate this configuration.

Now all host devices (ipterm-1, ipterm-2 and ipterm-3) should be able to reach each other.