Running Open vSwitch in Network Namespace

Update: Look at the followup post on how I figured out getting scenario 3 to work for in-band controller.

———-

If you’ve seen some of my previous posts, you will know that I have been battling with getting in-band control working.  My first attempt was actually a failure trying to use Open vSwitch because it appeared that the packets going between two switches traversed the global routing space and didn’t actually traverse the ‘link’ that was between them.  My second attempt, which it appears I didn’t post about, but you can find a message in the MiniNet Discuss mailing list,  was a bit more promising because each switch was running in a Linux network namespace.  In Mininet, switching in network namespaces are only supported by the UserSwitch and not Open vSwitch.  This worked better, but I really wanted to get Open vSwitch working in a network namespace.

I looked in many old forum and mailing list posts looking for how to run OVS in a network namespace.  I eventually found a post saying that you will probably have to run an OVSDB and OVS in each namespace.  So, I thought I’d give it a try.  So the following is what I have been able to get working so far.  There are three stages to this attempt.

  1. OVS in each network namespace running in standalone mode (standard L2 learning switch not under SDN control).
  2. OVS in each network namespace running in secure mode with a local SDN controller for each switch
  3. OVS in each network namespace running in secure mode with a remote in-band SDN controller

What I’ll show below is #1 and #2.  I haven’t been able to get #3 working quite yet, but this is progress.  First, the following is the MiniNet script I use for the testing.  The topology is a simple h1-s1-s2-h2 linear topology.  But to do my test, s1 and s2 are created as hosts instead of switches, which will automatically create the network namespaces and a shell to run OVS in.

#!/usr/bin/python

from mininet.net import Mininet
from mininet.cli import CLI
from mininet.log import setLogLevel, info

def ovsns():

    "Create an empty network and add nodes to it."

    net = Mininet( topo=None,
                   build=False)

    h1 = net.addHost( 'h1', ip='10.0.0.1' )
    s1 = net.addHost( 's1', ip='0.0.0.0' )
    s2 = net.addHost( 's2', ip='0.0.0.0' )
    h2 = net.addHost( 'h2', ip='10.0.0.2' )

    net.addLink( h1, s1 )
    net.addLink( s1, s2 )
    net.addLink( h2, s2 )

    net.start()
    CLI( net )
    net.stop()

if __name__ == '__main__':
    setLogLevel( 'info' )
    ovsns()

The next part is to figure out the commands to run OVS. So I made up the following few scripts to make it a bit easier.

  • Script to start OVSDB
  • Script to start OVS daemon
  • Script to create the bridge in standalone mode and attach the ports.
  • Script to create the bridge in secure mode and attach the ports.

I had to make sure each OVS instance was using its own communications channel and its own DB file, logs, etc.

This first script(startOvsDb) will create the unique OVSDB instance.

#!/bin/bash

echo Starting OVSDB for $1
mkdir -p /tmp/mininet-$1

if [ -e /tmp/mininet-$1/conf.db ]; then
   echo DB already exists
else
   echo Createing OVSDB
   ovsdb-tool create /tmp/mininet-$1/conf.db /usr/share/openvswitch/vswitch.ovsschema
fi

ovsdb-server /tmp/mininet-$1/conf.db \
-vconsole:emer \
-vsyslog:err \
-vfile:info \
--remote=punix:/tmp/mininet-$1/db.sock \
--private-key=db:Open_vSwitch,SSL,private_key \
--certificate=db:Open_vSwitch,SSL,certificate \
--bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
--no-chdir \
--log-file=/tmp/mininet-$1/ovsdb-server.log \
--pidfile=/tmp/mininet-$1/ovsdb-server.pid \
--detach \
--monitor

ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock --no-wait init

The next script(startOvs) will start the OVS daemon.

#!/bin/bash

echo Starting OVS for $1
ovs-vswitchd unix:/tmp/mininet-$1/db.sock \
-vconsole:emer \
-vsyslog:err \
-vfile:info \
--mlockall \
--no-chdir \
--log-file=/tmp/mininet-$1/ovs-vswitchd.log \
--pidfile=/tmp/mininet-$1/ovs-vswitchd.pid \
--detach \
--monitor

This script(createBr) creates the bridge in standalone mode and adds the ports.

#!/bin/bash

echo Configure OVS for $1
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock add-br $1
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock add-port $1 $1-eth0
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock add-port $1 $1-eth1
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock set-fail-mode $1 standalone
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock show

This script(createBrSdn) creates the bridge in secure mode and adds the ports.

#!/bin/bash

echo Configure OVS for $1
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock add-br $1
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock add-port $1 $1-eth0
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock add-port $1 $1-eth1
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock set-fail-mode $1 secure
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock set-controller $1 tcp:127.0.0.1:6633
ovs-vsctl --db=unix:/tmp/mininet-$1/db.sock show

To test the standalone mode, I run the MiniNet script at the top of the post to create the network and the start an xterm to both switches (s1 and s2).  In each xterm I run the three scripts to start OVS up.  Open vSwitch in standalone mode is just running OVS as a regular L2 learning switch that is not under an SDN controller.

In the xterm for S1:

startOvsDb s1
startOvs s1
createBr s1

In the xterm for S2:

startOvsDb s2
startOvs s2
createBr s2

Then, from an xterm to the host h1, I run a ping to h2 and all worked great.  I’m feeling good at this point. One note here, I haven’t done the script to cleanup. I seems that quiting MiniNet does not kill off OVS in each namespace.  So I eventually will need to write a script that will do the following in each network namespace.

  • Delete the bridge
  • Stop OVS daemon
  • Stop OVSDB

So with it all cleaned up, I do the same test but having each switch running a controller in its network namespace.   This will prove that SDN control and that each controller is listening an the same port but  in different network namespace.

In the xterm for S1:

startOvsDb s1
startOvs s1
createBrSdn s1
controller -v ptcp:6633

In the xterm for S2:

startOvsDb s2
startOvs s2
createBrSdn s2
controller -v ptcp:6633

Now, each switch is listening to its own controller.  I run the ping test again and all is good.

So to be anticlimactic, this is where it ends for now.  I haven’t been able to get scenario #3 working yet where all of the switches are talking to the same SDN controller that is running on a remote host and not locally on each switch.  I did get this working using the UserSwitch, so I must have missed a step or OVS is doing something to get in the way.  Hopefully I’ll figure it out.  Hopefully, this post will give some people some ideas.

This post ‘Running Open vSwitch in Network Namespace’ first appeared on https://gregorygee.wordpress.com/.

 

MiniEdit 2.1.0.8

This release got more focus on adding different node types.  From a MiniNet perspective, all these can by done using the MiniNet Python API.  But from the MiniEdit GUI perspective, I thought I’d create them as different icons you can see on the canvas for better visualization.

New node types:

  • Switch now includes additional options to be:
    • UserSwitch
    • UserSwitch inNamespace
  • Legacy Switch.  This is Open vSwitch running in standalone mode as a non-SDN L2 learning switch.
  • Legacy Router.  This under the hood is the same as a Host but with IPv4 forwarding turned on. Since is extends Host, you have the ability to XTerm into it and setup any additional static routes you want or run a dynamic routing protocol in it.

Other improvements and fixes:

  • Fixed bug in setting DPID on Switch.
  • New icons for some of the nodes. The OpenFlow switch uses the OpenFlow icon.
  • Only use TCLink and CPULimitedHost classes when actually needed.

Download MiniEdit 2.1.0.8 here.

MiniEdit2108

 

 

Using Linux GRE tunnels to connect two Mininet networks

I’ve had a few posts about how to use Open vSwitch’s built in GRE tunnel support to connect two Mininet networks. As many that have tried to use my scripts, I’ve also found it a pain to get going. Sometimes it works, sometimes it doesn’t. Then I saw a post in the Mininet mailing list from Felix Wallaschek about how he uses Linux GRE tunnels to connect separate Mininet networks in a program he setup called Maxinet. I decided to take a look at how his application did it and try using that same method.

Below is an example of the commands to run on one of the systems running Mininet. You would need to setup this tunnel before you can bind it into your switch in Mininet using the Intf(name, node) method like the example in mininet/examples/hwintf.py.

sudo ip link add s1-gre1 type gretap remote 192.168.56.103 local 192.168.56.102 ttl 64
sudo ip link set dev s1-gre1 up

A few notes. I am using Ubuntu 12.04. The version of Open vSwitch that comes with this version of Ubuntu does not play nicely with the Linux GRE tunnels. But when I upgraded to Open vSwitch 2.0, everything worked much better. So below are the scripts that I had in my previous post, but changed to setup and use Linux GRE tunnels.

Script for VM1(192.168.56.102):

#!/usr/bin/python

from mininet.net import Mininet
from mininet.node import Controller, RemoteController, Node
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from mininet.link import Link, Intf

def emptyNet():

    NODE1_IP='192.168.56.102'
    NODE2_IP='192.168.56.103'
    CONTROLLER_IP='192.168.56.103'

    net = Mininet( topo=None,
                   build=False)

    net.addController( 'c0',
                      controller=RemoteController,
                      ip=CONTROLLER_IP,
                      port=6633)

    h1 = net.addHost( 'h1', ip='10.0.0.1' )
    h2 = net.addHost( 'h2', ip='10.0.0.2' )
    s1 = net.addSwitch( 's1' )
    net.addLink( h1, s1 )
    net.addLink( h2, s1 )

    # Delete old tunnel if still exists
    s1.cmd('ip tun del s1-gre1')
    # Create GRE tunnel
    s1.cmd('ip li ad s1-gre1 type gretap local '+NODE1_IP+' remote '+NODE2_IP+' ttl 64')
    s1.cmd('ip li se dev s1-gre1 up')
    Intf( 's1-gre1', node=s1 )

    net.start()
    CLI( net )
    net.stop()

if __name__ == '__main__':
    setLogLevel( 'info' )
    emptyNet()

Script for VM2(192.168.56.103):

#!/usr/bin/python

from mininet.net import Mininet
from mininet.node import Controller, RemoteController
from mininet.cli import CLI
from mininet.log import setLogLevel, info
from mininet.link import Link, Intf

def emptyNet():

    NODE1_IP='192.168.56.102'
    NODE2_IP='192.168.56.103'
    CONTROLLER_IP='192.168.56.103'

    net = Mininet( topo=None,
                   build=False)

    net.addController( 'c0',
                      controller=RemoteController,
                      ip=CONTROLLER_IP,
                      port=6633)

    h3 = net.addHost( 'h3', ip='10.0.0.3' )
    h4 = net.addHost( 'h4', ip='10.0.0.4' )
    s2 = net.addSwitch( 's2' )
    net.addLink( h3, s2 )
    net.addLink( h4, s2 )

    # Delete old tunnel if still exists
    s2.cmd('ip tun del s2-gre1')
    # Create GRE tunnel
    s2.cmd('ip li ad s2-gre1 type gretap local '+NODE2_IP+' remote '+NODE1_IP+' ttl 64')
    s2.cmd('ip li se dev s2-gre1 up')
    Intf( 's2-gre1', node=s2 )

    net.start()
    CLI( net )
    net.stop()

if __name__ == '__main__':
    setLogLevel( 'info' )
    emptyNet()

I just run the above script on the appropriate VM and then test it. Below shows me having h1 on the VM1 Mininet ping h3 on the VM2 Mininet.

mininet> h1 ping -c 1 10.0.0.3
PING 10.0.0.3 (10.0.0.3) 56(84) bytes of data.
64 bytes from 10.0.0.3: icmp_req=1 ttl=64 time=7.97 ms

--- 10.0.0.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 7.972/7.972/7.972/0.000 ms

One other thing to note, the above is a point to point network. If you are going to have more than two Mininet networks, you will also need to add the ‘key’ parameter to tunnel creation command.

Thanks again Felix for showing us how to use Linux GRE tunnels with Mininet.

This post ‘Using Linux GRE tunnels to connect two Mininet networks’ first appeared on https://gregorygee.wordpress.com/.