CPqD/OpenFlow 1.3 Software Switch (2014-10)

The OpenFlow 1.3 software switch is built upon the Stanford OpenFlow 1.0 reference switch and Ericsson's Traffic Lab OpenFlow 1.1 switch and is intended for fast experimentation purposes.

The following components are available in the release:

Getting Started

Before building

The switch makes use of the NetBee library to parse packets, so we need to install it first.

  1. Install the following packages:
    sudo apt-get install cmake libpcap-dev libxerces-c-dev libpcre3-dev flex bison pkg-config autoconf libtool libboost-dev
  2. Download the most recent Netbee version, and unpack the source code from:http://www.nbee.org/download/nbeesrc-jan-10-2013.php
    cd ~/Downloads
    unzip nbeesrc-*
    
  3. Unfortunately, we need to downgrade bison in order to get NetBee to compile correctly.
    bison --version
    wget -nc http://mirror.cs.nchu.edu.tw/debian/pool/main/b/bison/bison_2.5.dfsg-2.1_amd64.deb
    wget -nc http://mirror.cs.nchu.edu.tw/debian/pool/main/b/bison/libbison-dev_2.5.dfsg-2.1_amd64.deb
    sudo dpkg -i bison_2.5.dfsg-2.1_amd64.deb libbison-dev_2.5.dfsg-2.1_amd64.deb
    
  4. Create the build system
    cd nbeesrc-*/src
    cmake .
    
  5. Compile
    make
    echo $?
    0
    
  6. Add the shared libraries built in /nbeesrc/bin/ to your /usr/local/lib directory
    sudo cp ../bin/libn*.so /usr/local/lib
  7. Run ldconfig
    sudo ldconfig
  8. Put the contens of folder nbeesrc/include in the /usr/include
    sudo cp -R ../include/* /usr/local/include/
    cd ../..
    

Building

  1. Get source
    git clone https://github.com/CPqD/ofsoftswitch13.git
  2. Run the following commands in the of13softswitch directory to build and install everything:
    cd ofsoftswitch13
    ./boot.sh
    ./configure
    make
    echo $?
    0
    sudo make install
    dpctl --version
    dpctl 1.3.0 compiled Apr  1 2015 14:29:07
    

Running

  1. Usage
    ofdatapath --help
    ofdatapath: userspace OpenFlow datapath
    usage: ofdatapath [OPTIONS] LISTEN...
    where LISTEN is a passive OpenFlow connection method on which
    to listen for incoming connections from the secure channel.
    
    Passive OpenFlow connection methods:
      ptcp:[PORT]             listen to TCP PORT (default: 6633)
      punix:FILE              listen on Unix domain socket FILE
    
    Configuration options:
      -i, --interfaces=NETDEV[,NETDEV]...
                              add specified initial switch ports
      -L, --local-port=NETDEV set network device for local port
      --no-local-port         disable local port
      -d, --datapath-id=ID    Use ID as the OpenFlow switch ID
                              (ID must consist of 12 hex digits)
      -m, --multiconn         enable multiple connections to the
                              same controller.
      --no-slicing            disable slicing
    
    Other options:
      -D, --detach            run in background as daemon
      -P, --pidfile[=FILE]    create pidfile (default: /usr/local/var/run/ofdatapath.pid)
      -f, --force             with -P, start even if already running
      -v, --verbose=MODULE[:FACILITY[:LEVEL]]  set logging levels
      -v, --verbose           set maximum verbosity level
      -h, --help              display this help message
      -V, --version           display version information
    
    
  2. Start the datapath
    sudo ofdatapath -D --pidfile=/usr/local/var/run/s1.pid ptcp:6633
    cat /usr/local/var/run/s1.pid
    8522
    
  3. Turn off the datapath
    sudo kill -2 `cat /usr/local/var/run/s1.pid`
  4. Start the secure channel, which will connect the datapath to the controller:
    ofprotocol tcp:<switch-host>:<switch-port> tcp:<ctrl-host>:<ctrl-port>
    ofprotocol --help
    ofprotocol: secure channel, a relay for OpenFlow messages.
    usage: ofprotocol [OPTIONS] DATAPATH [CONTROLLER]
    DATAPATH is an active connection method to a local datapath.
    CONTROLLER is an active OpenFlow connection method; if it is
    omitted, then secchan performs controller discovery.
    
    Active OpenFlow connection methods:
      tcp:HOST[:PORT]         PORT (default: 6633) on remote TCP HOST
      unix:FILE               Unix domain socket named FILE
      fd:N                    File descriptor N
    Passive OpenFlow connection methods:
      ptcp:[PORT]             listen to TCP PORT (default: 6633)
      punix:FILE              listen on Unix domain socket FILE
    
    Controller discovery options:
      --accept-vconn=REGEX    accept matching discovered controllers
      --no-resolv-conf        do not update /etc/resolv.conf
    
    Networking options:
      --inactivity-probe=SECS time between inactivity probes
      --max-idle=SECS         max idle for flows set up by secchan
      --max-backoff=SECS      max time between controller connection
                              attempts (default: 15 seconds)
      -l, --listen=METHOD     allow management connections on METHOD
                              (a passive OpenFlow connection method)
      -m, --monitor=METHOD    copy traffic to/from kernel to METHOD
                              (a passive OpenFlow connection method)
      --out-of-band           controller connection is out-of-band
      --stp                   enable 802.1D Spanning Tree Protocol
      --no-stp                disable 802.1D Spanning Tree Protocol
    
    Rate-limiting of "packet-in" messages to the controller:
      --rate-limit[=PACKETS]  max rate, in packets/s (default: 1000)
      --burst-limit=BURST     limit on packet credit for idle time
    
    Daemon options:
      -D, --detach            run in background as daemon
      -P, --pidfile[=FILE]    create pidfile (default: /usr/local/var/run/ofprotocol.pid)
      -f, --force             with -P, start even if already running
    
    Logging options:
      -v, --verbose=MODULE[:FACILITY[:LEVEL]]  set logging levels
      -v, --verbose           set maximum verbosity level
      --log-file[=FILE]       enable logging to specified FILE
                              (default: /usr/local/var/log/openflow/ofprotocol.log)
    
    Other options:
      -h, --help              display this help message
      -V, --version           display version information
      --check-leaks=FILE      log malloc and free calls to FILE
    
    

Dpctl Documentation

Dpctl is a management utility that enable some control over the OpenFlow switch. With this tool it's possible to add flows to the flow table, query for switch features and status, and change other configurations.

  1. A dpctl command has the following syntax
    dpctl [OPTIONS] SWITCH COMMAND [ARG...]
    dpctl --help
    dpctl: OpenFlow switch management utility
    usage: dpctl [OPTIONS] SWITCH COMMAND [ARG...]
      SWITCH ping [N] [B]                    latency of B-byte echos N times
      SWITCH monitor                         monitors packets from the switch
    
      SWITCH features                        show basic information
      SWITCH get-config                      get switch configuration
      SWITCH port-desc                       print port description and status
      SWITCH meter-config [METER]            get meter configuration
      SWITCH stats-desc                      print switch description
      SWITCH stats-flow [ARG [MATCH]]        print flow stats
      SWITCH stats-aggr [ARG [MATCH]]        print flow aggregate stats
      SWITCH stats-table                     print table stats
      SWITCH stats-port [PORT]               print port statistics
      SWITCH stats-queue [PORT [QUEUE]]      print queue statistics
      SWITCH stats-group [GROUP]             print group statistics
      SWITCH stats-meter [METER]             print meter statistics
      SWITCH stats-group-desc [GROUP]        print group desc statistics
    
      SWITCH set-config ARG                  set switch configuration
      SWITCH flow-mod ARG [MATCH [INST...]]  send flow_mod message
      SWITCH group-mod ARG [BUCARG ACT...]   send group_mod message
      SWITCH meter-mod ARG [BANDARG ...]     send meter_mod message
      SWITCH port-mod ARG                    send port_mod message
      SWITCH table-mod ARG                   send table_mod message
      SWITCH queue-get-config PORT           send queue_get_config message
    
    OpenFlow extensions
      SWITCH set-desc DESC                   sets the DP description
      SWITCH queue-mod PORT QUEUE BW         adds/modifies queue
      SWITCH queue-del PORT QUEUE            deletes queue
    
    
    Active OpenFlow connection methods:
      tcp:HOST[:PORT]         PORT (default: 6633) on remote TCP HOST
      unix:FILE               Unix domain socket named FILE
      fd:N                    File descriptor N
    
    Logging options:
      -v, --verbose=MODULE[:FACILITY[:LEVEL]]  set logging levels
      -v, --verbose           set maximum verbosity level
      --log-file[=FILE]       enable logging to specified FILE
                              (default: /usr/local/var/log/openflow/dpctl.log)
    
    Other options:
      --strict                    use strict match for flow commands
      -t, --timeout=SECS          give up after SECS seconds
      -h, --help                  display this help message
      -V, --version               display version information
    
    
  2. Example
    dpctl tcp:127.0.0.1 features
    
    SENDING:
    feat_req
    
    
    RECEIVED:
    feat_repl{dpid="0x0000f2a580810a1e", buffs="256", tabs="64", aux_id="0", caps="0x4f"]}
    
    
    

Lab 1 - mininet

Mininet

  1. Download and Install
    sudo mkdir /src3/mininet; sudo chown jssu:jssu /src3/mininet
    cd /src3/mininet
    git clone git://github.com/mininet/mininet
    mininet/util/install.sh -n3fxw
    mn --version
    2.2.1d2
    
  2. Starting the topology
    sudo mn --topo single,2 --mac --switch user --controller remote

Using dpctl

  1. Show all flows present in table 0.
    sudo dpctl unix:/tmp/s1 stats-flow table=0
    
    SENDING:
    stat_req{type="flow", flags="0x0", table="0", oport="any", ogrp="any", cookie=0x0", mask=0x0", match=oxm{all match}}
    
    
    RECEIVED:
    stat_repl{type="flow", flags="0x0", stats=[]}
      
    
    
  2. Ping between the topology hosts
    sudo dpctl unix:/tmp/s1 flow-mod table=0,cmd=add in_port=1 apply:output=2
    sudo dpctl unix:/tmp/s1 flow-mod table=0,cmd=add in_port=2 apply:output=1
    sudo dpctl unix:/tmp/s1 stats-flow table=0
    
    SENDING:
    stat_req{type="flow", flags="0x0", table="0", oport="any", ogrp="any", cookie=0x0", mask=0x0", match=oxm{all match}}
    
    
    RECEIVED:
    stat_repl{type="flow", flags="0x0", stats=[
    {table="0", match="oxm{in_port="1"}", dur_s="7", dur_ns="727000", prio="32768", idle_to="0", hard_to="0", cookie="0x0", pkt_cnt="0", byte_cnt="0", insts=[apply{acts=[out{port="2"}]}]},
    {table="0", match="oxm{in_port="2"}", dur_s="2", dur_ns="937000", prio="32768", idle_to="0", hard_to="0", cookie="0x0", pkt_cnt="0", byte_cnt="0", insts=[apply{acts=[out{port="1"}]}]}]}
      
    
    h1 ping h2
    

Lab 2

  1. Starting the topology

    Let's start a simple topology with KVM by using Tap device

    Host1: 192.168.180.200, host2: 192.168.180.201

    topo1
  2. Initial a datapath
    sudo ofdatapath -D --pidfile=/usr/local/var/run/s1.pid -i eth0,tap0,tap1 punix:/usr/local/var/run/s1.sock
    Apr 13 19:06:01|00001|dp_ports|ERR|tap0 device has assigned IPv6 address fe80::5824:18ff:fec1:bb3a
    RTNETLINK answers: No such file or directory
    Apr 13 19:06:01|00002|dp_ports|ERR|tap1 device has assigned IPv6 address fe80::9011:2fff:fe9a:3e03
    RTNETLINK answers: No such file or directory
    
  3. Using dpctl

    Command, port-desc, sends a message requesting the ports description, with the current configurations.

    sudo dpctl unix:/usr/local/var/run/s1.sock port-desc
    
    SENDING:
    stat_req{type="port-desc", flags="0x0"}
    
    
    RECEIVED:
    stat_repl{type="port-desc", flags="0x0"
    {no="1", hw_addr="50:e5:49:42:f5:40", name="eth0", config="0x0", state="0x4", curr="0x2020", adv="0xe83f", supp="0x283f", peer="0x0", curr_spd="1048576kbps", max_spd="1048576kbps"},
    {no="2", hw_addr="de:24:01:f4:ad:d3", name="tap0", config="0x0", state="0x4", curr="0x802", adv="0x0", supp="0x0", peer="0x0", curr_spd="10240kbps", max_spd="0kbps"},
    {no="3", hw_addr="be:7c:7d:e2:74:1b", name="tap1", config="0x0", state="0x4", curr="0x802", adv="0x0", supp="0x0", peer="0x0", curr_spd="10240kbps", max_spd="0kbps"},
    {no="local", hw_addr="12:1f:88:b8:94:4d", name="tap:", config="0x0", state="0x4", curr="0x802", adv="0x0", supp="0x0", peer="0x0", curr_spd="10240kbps", max_spd="0kbps"}}}
    
    

    Show all flows present in table 0.

    sudo dpctl unix:/usr/local/var/run/s1.sock stats-flow table=0
    
    SENDING:
    stat_req{type="flow", flags="0x0", table="0", oport="any", ogrp="any", cookie=0x0", mask=0x0", match=oxm{all match}}
    
    
    RECEIVED:
    stat_repl{type="flow", flags="0x0", stats=[]}
    
    
    

    Ping between the topology hosts

    sudo dpctl unix:/usr/local/var/run/s1.sock flow-mod table=0,cmd=add in_port=2 apply:output=3
    sudo dpctl unix:/usr/local/var/run/s1.sock flow-mod table=0,cmd=add in_port=3 apply:output=2
    sudo dpctl unix:/usr/local/var/run/s1.sock stats-flow table=0
    
    SENDING:
    stat_req{type="flow", flags="0x0", table="0", oport="any", ogrp="any", cookie=0x0", mask=0x0", match=oxm{all match}}
    
    
    RECEIVED:
    stat_repl{type="flow", flags="0x0", stats=[
    {table="0", match="oxm{in_port="2"}", dur_s="108", dur_ns="61000", prio="32768", idle_to="0", hard_to="0", cookie="0x0", pkt_cnt="29", byte_cnt="2282", insts=[apply{acts=[out{port="3"}]}]},
    {table="0", match="oxm{in_port="3"}", dur_s="100", dur_ns="505000", prio="32768", idle_to="0", hard_to="0", cookie="0x0", pkt_cnt="21", byte_cnt="1946", insts=[apply{acts=[out{port="2"}]}]}]}
    
    
    ping 192.168.180.254
    

    Forward packets to gateway

    sudo dpctl unix:/usr/local/var/run/s1.sock flow-mod table=0,cmd=add in_port=1 apply:output=2
    sudo dpctl unix:/usr/local/var/run/s1.sock flow-mod table=0,cmd=add in_port=2 apply:output=1
    sudo route add default gw 192.168.180.254
    ping 8.8.8.8
    

KVM net-tap scripts

VM startup script

cat start-CPqD0-AsDaemon
#! /bin/bash

MEM=512M
MACaddr='52:54:00:b8:9c:58'

# Don't Edit, File automatically generated by Config-Kvm-vhoston script
if [ $EUID -ne 0 ]
   then sudo echo "Super User passwd, please:"
        if [ $? -ne 0 ]
          then  echo "Sorry, need su privilege!"
                exit 1
        fi
fi

sudo chmod 666 /dev/net/tun
sudo tunctl -u jssu -t tap0
#sudo ifconfig tap0 192.168.180.3 netmask 255.255.255.255 up
#sudo sysctl net.ipv4.conf.tap0.proxy_arp=1
#sudo route add -host 192.168.180.200 dev tap0
/src3/KVM/bin/vhostOn.sh
mkdir /src3/KVM/network-CPqD0

echo "Starting VM: CPqD0..., mem=${MEM}"

screen -S CPqD0 -d -m qemu-system-x86_64 -name CPqD0 -localtime -curses \
       -m ${MEM} -enable-kvm \
       -monitor unix:/src3/KVM/network-CPqD0/MonSock,server,nowait \
       -netdev tap,id=hostnet0,ifname=tap0,vhost=on \
       -net nic,vlan=0,netdev=hostnet0,macaddr=${MACaddr},model=virtio \
       -drive index=0,media=disk,if=virtio,file=/src3/KVM/img/CPqD0.ovl

VM stop and restore lan script

cat stop-CPqD0-restore-lan
#! /bin/bash

# Don't Edit, File automatically generated by Config-Kvm-vhoston script

if [ $EUID -ne 0 ]
   then sudo echo "Super User passwd, please:"
        if [ $? -ne 0 ]
          then  echo "Sorry, need su privilege!"
                exit 1
        fi
fi

if [ -S /src3/KVM/network-CPqD0/MonSock ]; then
    echo "system_powerdown" | socat - unix-connect:/src3/KVM/network-CPqD0/MonSock
    echo "Please wait 5 seconds."
    sleep 5
else
    echo "Socket has been removed! Shutdown by ssh or resotre Lan only."
fi

ping -c 3 192.168.180.200
if [ $? -eq 0 ]; then
    echo "CPqD0 still alive, shut it down.  Enter passwd twice!"
    ssh -t jssu@192.168.180.200 'sudo init 0'
else
    rm -rf /src3/KVM/network-CPqD0
fi

echo "Restore lan..."
if [ -d /proc/sys/net/ipv4/conf/tap0 ]; then
    sudo /sbin/ifconfig tap0 down
    sudo tunctl -d tap0
fi

References