Introduction

This tutorial demonstrate how you can setup a simple SDN network, using the Faucet controller and Open vSwitch

The goal of the tutorial is to demonstrate Open vSwitch and Faucet in an end-to-end way, that is, to show how it works from the Faucet controller configuration at the top, through the OpenFlow flow table, to the datapath processing. Along the way

Environment

  • Ubuntu 20.04

Setting Up OVS

This section explain how to setup Open vSwitch for the purpose of using it with Faucet controller

To install Open vSwitch run following command

sudo apt install -y openvswitch-switch

Setting up Faucet

This section explains how to install Faucet inside a docker container

sudo mkdir -p /opt/faucet/{logs,config,scripts,images}
sudo touch /opt/faucet/config/faucet.yaml

sudo docker run -d \
    --name faucet \
    --restart=always \
    -v /opt/faucet/config/:/etc/faucet/ \
    -v /opt/faucet/logs/:/var/log/faucet/ \
    -p 6653:6653 \
    -p 9302:9302 \
    faucet/faucet

Overview

Now that Open vSwitch and Faucet are ready, here’s an overview of what we’re going to do for the remainder of the tutorial:

  • Switching: Set up an L2 network with Faucet.
  • Routing: Route between multiple L3 networks with Faucet.
  • ACLs: Add and modify access control rules.

At each step, we will take a look at how the features in question work from Faucet at the top to the data plane layer at the bottom. From the highest to lowest level, these layers and the software components that connect them are:

image

Faucet.

As the top level in the system, this is the authoritative source of the network configuration.

Faucet connects to a variety of monitoring and performance tools, but we won’t use them in this tutorial. Our main insights into the system will be through faucet.yaml for configuration and faucet.log to observe state, such as MAC learning and ARP resolution, and to tell when we’ve screwed up configuration syntax or semantics.

The OpenFlow subsystem in Open vSwitch.

OpenFlow is the protocol, standardized by the Open Networking Foundation, that controllers like Faucet use to control how Open vSwitch and other switches treat packets in the network.

We will use ovs-ofctl, a utility that comes with Open vSwitch, to observe and occasionally modify Open vSwitch’s OpenFlow behavior. We will also use ovs-appctl, a utility for communicating with ovs-vswitchd and other Open vSwitch daemons, to ask “what-if?” type questions.

Setup a switch

Layer-2 (L2) switching is the basis of modern networking. It’s also very simple and a good place to start, so let’s set up a switch with some VLANs in Faucet and see how it works at each layer. Begin by putting the following into faucet/config/faucet.yaml:

dps:
    switch0:
        dp_id: 0x1
        timeout: 7201
        arp_neighbor_timeout: 3600
        stack:
            priority: 1
        interfaces:
            1:
                native_vlan: office
            2:
                native_vlan: office
            3:
                native_vlan: office
            4:
                native_vlan: guest
            5:
                native_vlan: guest
vlans:
    office:
        vid: 100
        description: "Office network 100 Vlan"
        faucet_mac: "0e:00:00:00:00:01"
        faucet_vips: ['10.0.100.254/24'] 
    guest:
        vid: 200
        description: "Guest network"
        faucet_mac: "0e:00:00:00:00:02"
        faucet_vips: ['10.0.200.254/24']

routers:
    router-datacenter-networks:
        vlans: [office, guest]  
        

This configuration file defines a single switch (“datapath” or “dp”) named switch0. The switch has five ports, numbered 1 through 5. Ports 1, 2, and 3 are in VLAN 100, and ports 4 and 5 are in VLAN 200. Faucet can identify the switch from its datapath ID, which is defined to be 0x1.

Now restart Faucet so that the configuration takes effect, e.g.:

$ sudo docker restart faucet

Assuming that the configuration update is successful, you should now see a new line at the end of /opt/faucet/logs/faucet.log:

faucet INFO     Add new datapath DPID 1 (0x1)
faucet.valve INFO     DPID 1 (0x1) switch0 IPv4 routing is active on VLAN office vid:100 untagged: Port 1,Port 2,Port 3 with VIPs ['10.0.100.254/24']
faucet.valve INFO     DPID 1 (0x1) switch0 IPv4 routing is active on VLAN guest vid:200 untagged: Port 4,Port 5 with VIPs ['10.0.200.254/24']

Faucet is now waiting for a switch with datapath ID 0x1 to connect to it over OpenFlow, so our next step is to create a switch with OVS and make it connect to Faucet. Let’s create a switch (“bridge”) named switch0, set its datapath ID to 0x1 and tell it to connect to the Faucet controller

To do that, switch to the terminal and issue following command

sudo ovs-vsctl add-br switch0 \
         -- set bridge switch0 other-config:datapath-id=0000000000000001 \
         -- set-controller switch0 tcp:127.0.0.1:6653 \
         -- set controller switch0 connection-mode=out-of-band

We are now ready to launch some VMS with and connect ports into the switch

Setting up KVM instances

This section describes how to use Open vSwitch with the Kernel-based Virtual Machine (KVM).

You will need to modify or create custom versions of the qemu-ifup and qemu-ifdown scripts. In this guide, we’ll create custom versions that make use of example Open vSwitch bridges that we’ll describe in this guide.

Create the following two files and store them in known locations. For example:

$ cat << 'EOF' > /opt/faucet/scripts/ovs-ifup
#!/bin/bash

netdev=$1
switch="switch${netdev:2:1}"
ip link set $netdev up
ovs-vsctl add-port ${switch} $netdev -- set Interface $netdev ofport=${netdev: -1}
EOF
$ cat << 'EOF' > /opt/faucet/scripts/ovs-ifdown
#!/bin/bash

netdev=$1
switch="br${netdev:2:1}"
ip addr flush dev $netdev
ip link set $netdev down
ovs-vsctl del-port ${switch} $netdev
EOF

Make these script executable by issuing:

chmod +x /opt/faucet/scripts/ovs-*

### CirrOS is a minimal Linux distribution that was designed for use as a test image on clouds such as OpenStack Compute.

Download CirrOS

sudo wget -P /opt/faucet/images https://download.cirros-cloud.net/0.5.2/cirros-0.5.2-x86_64-disk.img

Launch Instances

We will launch 4 instances of CirrOS and connect them with switch0

Let’s start by booting up and connecting our first instance, open a new terminal windows/tab and issuing following commands in an interactive way

IFACE=switch0p1
HOST=host1
MAC_ADDR=$(printf '52:54:00:%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))

cp /opt/faucet/images/cirros-0.5.2-x86_64-disk.img /opt/faucet/images/cirros-${HOST}.img

kvm -m 512 \
	-device e1000,netdev=${IFACE},mac=$MAC_ADDR  \
	-drive file=/opt/faucet/images/${HOST}.img,boot=on -nographic \
	-netdev tap,id=${IFACE},ifname=${IFACE},script=/opt/faucet/scripts/ovs-ifup,downscript=/opt/faucet/scripts/ovs-ifdown

Verify if port has been created, check for following lines at the end of logs/faucet.log

DPID 1 (0x1) switch-1 status change: Port 1 up status True reason ADD state 0
DPID 1 (0x1) switch-1 Port 1 (1) up
DPID 1 (0x1) switch-1 Configuring VLAN office vid:100 untagged: Port 1,Port 2,Port 3
DPID 1 (0x1) switch-1 status did not change: Port 1 up status True reason MODIFY state 4
DPID 1 (0x1) switch-1 L2 learned on Port 1 52:54:00:b1:6c:84 (L2 type 0x0800, L2 dst ff:ff:ff:ff:ff:ff, L3 src 0.0.0.0, L3 dst 255.255.255.255) Port 1 VLAN 100 (1 hos

take a look at line at the end of faucet/faucet.log. It says that it learned about our instance’s MAC 52:54:00:b1:6c:84

Take a look at current state of Open vSwitch using ovs-vsctl show command.

ovs-vsctl show 
328b079b-4efb-4b3e-8e49-2d1626fe73fc
    Bridge switch0
        Controller "tcp:127.0.0.1:6653"
            is_connected: true
        Port switch0p1
            Interface switch0p1
        Port switch0
            Interface switch0
                type: internal
    ovs_version: "2.13.3"

You can see a new port switch0p1 created using ovs-ifup script on instance launch, is added into switch0

ovs-ifup and ovs-ifdown take switch0p1 as input argument and create the tap device and add it into port 1 of the switch0 using ovs-vsctl, this naming scheme helps identify data paths and ports at every layer (OVS, Faucet, Host system)

Let’s launch more instances and assign ports in Open vSwitch

host2, port = 2

IFACE=switch0p2
HOST=host2
MAC_ADDR=$(printf '52:54:00:%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))

cp /opt/faucet/images/cirros-0.5.2-x86_64-disk.img /opt/faucet/images/cirros-${HOST}.img

kvm -m 512 \
	-device e1000,netdev=${IFACE},mac=$MAC_ADDR  \
	-drive file=/opt/faucet/images/${HOST}.img,boot=on -nographic \
	-netdev tap,id=${IFACE},ifname=${IFACE},script=/opt/faucet/scripts/ovs-ifup,downscript=/opt/faucet/scripts/ovs-ifdown

host3, port = 3

IFACE=switch0p3
HOST=host3
MAC_ADDR=$(printf '52:54:00:%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))

cp /opt/faucet/images/cirros-0.5.2-x86_64-disk.img /opt/faucet/images/cirros-${HOST}.img

kvm -m 512 \
	-device e1000,netdev=${IFACE},mac=$MAC_ADDR  \
	-drive file=/opt/faucet/images/${HOST}.img,boot=on -nographic \
	-netdev tap,id=${IFACE},ifname=${IFACE},script=/opt/faucet/scripts/ovs-ifup,downscript=/opt/faucet/scripts/ovs-ifdown

host4, port = 4

IFACE=switch0p4
HOST=host4
MAC_ADDR=$(printf '52:54:00:%02x:%02x:%02x' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)))

cp /opt/faucet/images/cirros-0.5.2-x86_64-disk.img /opt/faucet/images/cirros-${HOST}.img

kvm -m 512 \
	-device e1000,netdev=${IFACE},mac=$MAC_ADDR  \
	-drive file=/opt/faucet/images/${HOST}.img,boot=on -nographic \
	-netdev tap,id=${IFACE},ifname=${IFACE},script=/opt/faucet/scripts/ovs-ifup,downscript=/opt/faucet/scripts/ovs-ifdown

Configure Network on all nodes

host1:

sudo ip a a 10.0.100.1/24 dev eth0
sudo ip r a default via 10.0.100.254 dev eth0

host2:

sudo ip a a 10.0.100.2/24 dev eth0
sudo ip r a default via 10.0.100.254 dev eth0

host3:

sudo ip a a 10.0.100.3/24 dev eth0
sudo ip r a default via 10.0.100.254 dev eth0

host4:

sudo ip a a 10.0.200.1/24 dev eth0
sudo ip r a default via 10.0.200.254 dev eth0

Verify by ping-ing nodes from each other, in this scnario all nodes shoule be able to ping all nodes