Tutorial 5 - SDN & VLANs

Submission process:

  • Submission deadline is January 22, 14:00 CET (before the lecture) .
  • Commit and push your solution as separate notebook files per subtask via git as ./tutorial/tutorial5/tutorial5_1.ipynb. Please take care of the correct subfolder/filename since submission is denied otherwise.
  • During the first lecture after the deadline we will discuss a sample solution in class.
  • Afterwards, you have time until January 27, 16:00 CET (before the lecture) to submit a corrected version of your submission:
    1. Rework your solution according to our discussion in class.
    2. Commit and push the corrected version as a separate file per subtask via git as ./tutorial/tutorial5/tutorial5_1.ipynb. Please take care of the correct filename since submission is denied otherwise.

Remarks:

  • Grading is done based on both versions of your submission.
  • If the first submission is missing or contains major flaws a deduction of up to 50% of the achieved points will be applied
  • A sample solution is provided after January 27, 16:00 CET eventually.
  • Do NOT duplicate cells or change the type of cells, otherwise you might receive zero points for your submission
  • Please use acn@net.in.tum.de for questions regarding lecture, tutorial, and project of ACN.

This cell is used to verify the structure of the submission

DO NOT DELETE OR CHANGE THIS CELL, otherwise the task will be graded with 0 points

Problem 1- OpenFlow [2.95 credits]

For the following exercise we use the network emulator mininet. The emulated network consists of two hosts called 'h1' and 'h2'. Both hosts are connected via the switch 's1'. For the switching solution we use the software switch Open vSwitch. We use the tool ovs-ofctl (see documentation), which is a CLI controller controlling OpenFlow devices manually.

In [1]:
# in case mininet stops working execute this cell
!mn -c
*** Removing excess controllers/ofprotocols/ofdatapaths/pings/noxes
killall controller ofprotocol ofdatapath ping nox_corelt-nox_core ovs-openflowd ovs-controllerovs-testcontroller udpbwtest mnexec ivs ryu-manager 2> /dev/null
killall -9 controller ofprotocol ofdatapath ping nox_corelt-nox_core ovs-openflowd ovs-controllerovs-testcontroller udpbwtest mnexec ivs ryu-manager 2> /dev/null
pkill -9 -f "sudo mnexec"
*** Removing junk from /tmp
rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log
*** Removing old X11 tunnels
*** Removing excess kernel datapaths
ps ax | egrep -o 'dp[0-9]+' | sed 's/dp/nl:/'
***  Removing OVS datapaths
ovs-vsctl --timeout=1 list-br
ovs-vsctl --timeout=1 list-br
*** Removing all links of the pattern foo-ethX
ip link show | egrep -o '([-_.[:alnum:]]+-eth[[:digit:]]+)'
ip link show
*** Killing stale mininet node processes
pkill -9 -f mininet:
*** Shutting down stale tunnels
pkill -9 -f Tunnel=Ethernet
pkill -9 -f .ssh/mn
rm -f ~/.ssh/mn/*
*** Cleanup complete.

a) [0.25 credits] What is the task of the control plane?

Make the decisions for the forwarding plane.

b) [0.25 credits] What is the task of the data plane?

Forwarding packets.

c) [0.20 credits] What is the forwarding plane?

Another word for data plane.

Execute the following cell to test the mininet setup. The setup works if all hosts are reachable using pingAll().

In [2]:
from mininet.net import Mininet
from mininet.topo import Topo
from mininet.link import TCLink
from mininet.node import OVSSwitch
from mininet.log import setLogLevel, info

class simpleTopo(Topo):
    "Four switches connected to 2 hosts as specified in the task."
    def __init__(self, **opts):
        # initialize topology and default options
        Topo.__init__(self, **opts)
        switch1 = self.addSwitch('s1')
        host1 = self.addHost('h1', ip='10.0.0.1')
        host2 = self.addHost('h2', ip='10.0.0.2')
        self.addLink(host1, switch1, bw=1, delay='1ms')
        self.addLink(host2, switch1, bw=1, delay='1ms')
        
def simpleTest(cmds):
    # create and start network
    topo = simpleTopo()
    net = Mininet(topo, link=TCLink, switch=OVSSwitch)
    net.start()
    
    # preparing switch for this exercise
    s1 = net.get('s1')
    info(s1.cmd('echo switch info:'))
    info(s1.cmd('ovs-vsctl show'))          # output switch info
    info(s1.cmd('ovs-ofctl dump-flows s1')) # print flow info
    info(s1.cmd('ovs-ofctl del-flows s1'))  # remove all default flows
    info(s1.cmd('ovs-ofctl dump-flows s1'))
    
    for cmd in cmds:
        info(s1.cmd(cmd))
        
    # tests reachability of all hosts
    net.pingAll()
    
    # shut down network
    net.stop()
    
if __name__ == '__main__':
    # tell mininet to print useful information
    setLogLevel('info')
    
    # enter user specified OpenFlow rules on the switch 
    cmds = [
         'ovs-ofctl add-flow s1 actions=output:flood' 
    ]
    
    simpleTest(cmds)
*** Creating network
*** Adding controller
*** Adding hosts:
h1 
h2 
*** Adding switches:
s1 
*** Adding links:
(1.00Mbit 1ms delay) 
(1.00Mbit 1ms delay) 
(h1, s1) 
(1.00Mbit 1ms delay) 
(1.00Mbit 1ms delay) 
(h2, s1) 

*** Configuring hosts
h1 
h2 

*** Starting controller
c0 

*** Starting 1 switches
s1 
...
(1.00Mbit 1ms delay) 
(1.00Mbit 1ms delay) 

switch info:
3c6fad27-14fe-45d2-974c-7625df3728ea
    Bridge s1
        Controller "tcp:127.0.0.1:6653"
        fail_mode: secure
        Port s1-eth2
            Interface s1-eth2
        Port s1-eth1
            Interface s1-eth1
        Port s1
            Interface s1
                type: internal
    ovs_version: "3.5.0"
 cookie=0x0, duration=0.035s, table=0, n_packets=0, n_bytes=0, priority=0 actions=CONTROLLER:128
*** Ping: testing ping reachability
h1 -> 
h2 

h2 -> 
h1 

*** Results: 0% dropped (2/2 received)
*** Stopping 1 controllers
c0 

*** Stopping 2 links
.
.

*** Stopping 1 switches
s1 

*** Stopping 2 hosts
h1 
h2 
*** Done

d) [0.5 credits] Execute the code of the network. The output gives the result of the ping (search for "Ping: testing ping reachability" in the output). What does the command "ovs-ofctl add-flow s1 actions=output:flood" do? How does the switch behave when receiving a packet?

Argument Description
add-flow ''
s1 ''
actions=output:flood ''

Adds an OpenFlow rule (add-flow) on the device called (s1) which performs forwards the packet to all available ports except the receiving port (actions=output:flood). This transforms the switch (OpenFlow device) into a hub.

e) [0.25 credits] After installing the rule, which packets can be seen by the controller?

The controller cannot see any further packets.

f) [1.5 credits] Execute the following cell. Explain why the ping is not successful. Enter OpenFlow rules at the given location to fix this problem.

Note: You can ignore the following error: "*** Error: RTNETLINK answers: No such file or directory". This does not influence the behavior of the given program.

Explain why ping was unsuccessful: Hosts h1 and h2 do not know the MAC addresses of each other. Both hosts try to get this information via ARP. However, the ARP requests cannot pass the switch because the OpenFlow rules are only valid for IPv4 (0x0800). To fix this problem rules for ARP forwarding, must be installed.

In [3]:
from mininet.net import Mininet
from mininet.topo import Topo
from mininet.link import TCLink
from mininet.node import OVSSwitch
from mininet.log import setLogLevel, info

class simpleTopo(Topo):
    "Four switches connected to 2 hosts as specified in the task."
    def __init__(self, **opts):
        # initialize topology and default options
        Topo.__init__(self, **opts)
        switch1 = self.addSwitch('s1')
        host1 = self.addHost('h1', ip='10.0.0.1')
        host2 = self.addHost('h2', ip='10.0.0.2')
        self.addLink(host1, switch1, bw=1, delay='1ms')
        self.addLink(host2, switch1, bw=1, delay='1ms')
        
def simpleTest(cmds):
    # create and start network
    topo = simpleTopo()
    net = Mininet(topo, link=TCLink, switch=OVSSwitch)
    net.start()
    
    # preparing switch for this exercise
    s1 = net.get('s1')
    info(s1.cmd('echo switch info:'))
    info(s1.cmd('ovs-vsctl show'))          # output switch info
    info(s1.cmd('ovs-ofctl dump-flows s1')) # print flow info
    info(s1.cmd('ovs-ofctl del-flows s1'))  # remove all default flows
    
    for cmd in cmds:
        info(s1.cmd(cmd))
    
    info(s1.cmd('ovs-ofctl dump-flows s1'))

    
    # tests reachability of all hosts
    net.pingAll()
    
    # remove '#' of next line to see statistics after ping
    #info(s1.cmd('ovs-ofctl dump-flows s1'))
    
    # shut down network
    net.stop()
    
if __name__ == '__main__':
    # tell mininet to print useful information
    setLogLevel('info')
    
    # enter user specified OpenFlow rules on the switch 
    cmds = [
        'ovs-ofctl add-flow s1 dl_type=0x0800,nw_dst=10.0.0.2,actions=output:2',
        'ovs-ofctl add-flow s1 dl_type=0x0800,nw_dst=10.0.0.1,actions=output:1',
        # begin insert code
        # simple solution
        #'ovs-ofctl add-flow s1 dl_type=0x0806,actions=output:flood'
        
        # more sophisticated solution
        
        'ovs-ofctl add-flow s1 in_port:1,dl_type=0x0806,actions=output:2',
        'ovs-ofctl add-flow s1 in_port:2,dl_type=0x0806,actions=output:1'
        # end insert code
    ]
    simpleTest(cmds)
*** Creating network
*** Adding controller
*** Adding hosts:
h1 
h2 
*** Adding switches:
s1 
*** Adding links:
(1.00Mbit 1ms delay) 
(1.00Mbit 1ms delay) 
(h1, s1) 
(1.00Mbit 1ms delay) 
(1.00Mbit 1ms delay) 
(h2, s1) 

*** Configuring hosts
h1 
h2 

*** Starting controller
c0 

*** Starting 1 switches
s1 
...
(1.00Mbit 1ms delay) 
(1.00Mbit 1ms delay) 

switch info:
3c6fad27-14fe-45d2-974c-7625df3728ea
    Bridge s1
        Controller "tcp:127.0.0.1:6653"
        fail_mode: secure
        Port s1
            Interface s1
                type: internal
        Port s1-eth1
            Interface s1-eth1
        Port s1-eth2
            Interface s1-eth2
    ovs_version: "3.5.0"
 cookie=0x0, duration=0.074s, table=0, n_packets=0, n_bytes=0, priority=0 actions=CONTROLLER:128
 cookie=0x0, duration=0.026s, table=0, n_packets=0, n_bytes=0, ip,nw_dst=10.0.0.2 actions=output:"s1-eth2"
 cookie=0x0, duration=0.020s, table=0, n_packets=0, n_bytes=0, ip,nw_dst=10.0.0.1 actions=output:"s1-eth1"
 cookie=0x0, duration=0.014s, table=0, n_packets=0, n_bytes=0, arp,in_port="s1-eth1" actions=output:"s1-eth2"
 cookie=0x0, duration=0.005s, table=0, n_packets=0, n_bytes=0, arp,in_port="s1-eth2" actions=output:"s1-eth1"
*** Ping: testing ping reachability
h1 -> 
h2 

h2 -> 
h1 

*** Results: 0% dropped (2/2 received)
*** Stopping 1 controllers
c0 

*** Stopping 2 links
.
.

*** Stopping 1 switches
s1 

*** Stopping 2 hosts
h1 
h2 
*** Done
In [ ]:
 

Advanced Computer Networking by Prof. Dr.-Ing. Georg Carle

Teaching assistants: Christian Dietze, Sebastian Gallenmüller, Marcel Kempf, Lorenz Lehle, Nikolas Gauder, Patrick Dirks