wiki:GENIExperimenter/Tutorials/OpenFlowOVS-Floodlight/Execute

Version 7 (modified by pjayanth@bbn.com, 7 years ago) (diff)

--

Intro to OpenFlow Tutorial

Image Map

Step 4. Execute Experiment

Now that the switch is up and running we are ready to start working on the controller. For this tutorial we are going to use the Floodlight Controller. We installed the software for running Floodlight in the controller host in Configure the Floodlight Controller section.

4a. Login to your hosts

To start our experiment we need to ssh into all of our hosts.

Depending on which tool and OS you are using there is a slightly different process for logging in. If you don't know how to SSH to your reserved hosts learn how to login. Once you have logged in follow the rest of the instructions.

4b. Use a Learning Switch Controller

In this example we are going to run a very simple learning switch controller to forward traffic between host1 and host2.

  1. First start a ping from host1 to host2, which should timeout, since there is no controller running.
ping host2 -c 10
  1. Start the Floodlight Controller by running the following commands:
cd floodlight
java -jar target/floodlight.jar

The output should look like this:

  1. In the terminal of host1, ping host2:
    [pjayant@host1:~$ ping 10.0.0.2
    PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
    64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=327 ms
    64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=23.2 ms
    64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=2.08 ms
    64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=1.71 ms
    64 bytes from 10.0.0.2: icmp_seq=5 ttl=64 time=1.77 ms
    64 bytes from 10.0.0.2: icmp_seq=6 ttl=64 time=1.74 ms
    64 bytes from 10.0.0.2: icmp_seq=7 ttl=64 time=1.69 ms
    64 bytes from 10.0.0.2: icmp_seq=8 ttl=64 time=1.55 ms
    64 bytes from 10.0.0.2: icmp_seq=9 ttl=64 time=1.60 ms
    64 bytes from 10.0.0.2: icmp_seq=10 ttl=64 time=1.67 ms
    64 bytes from 10.0.0.2: icmp_seq=11 ttl=64 time=1.73 ms
    64 bytes from 10.0.0.2: icmp_seq=12 ttl=64 time=1.50 ms
    64 bytes from 10.0.0.2: icmp_seq=13 ttl=64 time=1.82 ms
    64 bytes from 10.0.0.2: icmp_seq=14 ttl=64 time=1.69 ms
    ^C
    --- 10.0.0.2 ping statistics ---
    14 packets transmitted, 14 received, 0% packet loss, time 13019ms
    rtt min/avg/max/mdev = 1.501/26.489/327.007/83.532 ms}}}
    
      Now the ping should work. You can see that the time for the first ICMP packet is longer than the rest of the ICMP packets. This is because the Open vSwitch consults the controller the first time a packet-in event occurs. The controller then inserts the flow in the Open vSwitch and the switch consults this flow for further packet-in events.
    
      4. Go to your Open vSwitch host and take a look at the flows. You should see that your controller installed flows based on the mac addresses of your packets. Enter the following command:
    
    {{{
    pjayant@switch:~$ sudo ovs-ofctl dump-flows br0
    NXST_FLOW reply (xid=0x4):
     cookie=0x20000005000000, duration=4.782s, table=0, n_packets=4, n_bytes=392, idle_timeout=5, idle_age=0, priority=1,ip,in_port=2,dl_src=02:55:0d:1e:32:8d,dl_dst=02:bd:52:92:0e:86,nw_src=10.0.0.2,nw_dst=10.0.0.1 actions=output:1
     cookie=0x20000004000000, duration=4.790s, table=0, n_packets=4, n_bytes=392, idle_timeout=5, idle_age=0, priority=1,ip,in_port=1,dl_src=02:bd:52:92:0e:86,dl_dst=02:55:0d:1e:32:8d,nw_src=10.0.0.1,nw_dst=10.0.0.2 actions=output:2
     cookie=0x0, duration=1275.644s, table=0, n_packets=6, n_bytes=512, idle_age=4, priority=0 actions=CONTROLLER:65535
    
    }}}
    
    === 4c. Look around your OVS switch  ===
    
      1. If you are using OVS, to see the flow table entries on your OVS switch:
    {{{
    sudo ovs-ofctl dump-flows br0
    }}}
        You should see at least two table entries: One for ICMP Echo (icmp_type=8) messages from host1 to host2 and one for ICMP Echo Reply (icmp_type=0) messages from host2 to host1.  You may also see flow entries for arp packets.
    
      2. To see messages go between your switch and your controller, open a new ssh window to your controller node and run tcpdump on the `eth0` interface and on the tcp port that your controller is listening on usually 6633.  (You can also run `tcpdump` on the `OVS` control interface if you desire.)
    {{{
    sudo tcpdump -i eth0 tcp port 6633
    }}}
      You will see (1) periodic keepalive messages being exchanged by the switch and the controller, (2) messages from the switch to the controller (e.g. when there is a table miss) and an ICMP Echo message in, and (3) messages from the controller to the switch (e.g. to install new flow entries).
    
      3. Kill your POX controller by pressing `Ctrl-C`:
    {{{
    DEBUG:forwarding.l2_learning:installing flow for 02:c7:e8:a7:40:65.1 -> 02:f1:ae:bb:e3:a8.2
    INFO:core:Going down...
    INFO:openflow.of_01:[3a-51-a1-ab-c3-43 1] disconnected
    INFO:core:Down.
    }}}
    
      4. Notice what happens to your ping on host1.
    
      5. If you are using OVS, check the flow table entries on your switch:
    {{{
    sudo ovs-ofctl dump-flows br0
    }}}
      Since you set your switch to "secure" mode, i.e. don't forward packets if the controller fails, you will not see flow table entries.  If you see flow table entries, try again after 10 seconds to give the entries time to expire.
    
    
    ==== Soft vs Hard Timeouts ====
    
    All rules on the switch have two different timeouts:
    
      * '''Soft Timeout''': This determines for how long the flow will remain in the forwarding table of the switch if there are no packets received that match the specific flow. As long as packets from that flow are received the flow remains on the flow table. 
      * '''Hard Timeout''': This determines the total time that a flow will remain at the forwarding table, independent of whether packets that match the flow are received; i.e. the flow will be removed after the hard timeout expires. 
    
    Can you tell now why there were packets flowing even after you killed your controller?
    
    === 4d. Download the pox apps ===
    To help you get started with your controller writing, we will provide: 
      * skeleton files for the controllers where you only need to complete some missing functionality
      * the solution: fully implemented controllers
      * a utility library that makes some of the pox messages easier to write
    
    '''In the controller terminal execute''':
    {{{
      cd /tmp/pox/ext
      wget http://www.gpolab.bbn.com/experiment-support/NFVApps/pox-intro-ctrlapps.tar.gz
      tar xvfz pox-intro-ctrlapps.tar.gz
    }}}
    ==== Useful Tips for writing your controller ====
    
    In order to make this first experience of writing a controller easier, we wrote some helpful functions that will abstract some of the particularities of POX away. 
    These functions are located in `/tmp/pox/ext/utils.py`, so while you write your controller consult this file for details. 
    
    Functions that are implemented include:
      * packetIsIP : Test if the packet is IP
      * packetIsARP : Test if the packet is ARP
      * packetIsRequestARP : Test if this is an ARP Request packet
      * packetIsReplyARP : Test if this is an ARP Reply packet
      * packetArpDstIp : Test what is the destination IP in an ARP packet
      * packetArpSrcIp : Test what is the sources IP in an ARP packet
      * packetIsTCP : Test if a packet is TCP
      * packetDstIp : Test the destination IP of a packet
      * packetSrcIp : Test the source IP of a packet
      * packetDstTCPPort : Test the destination TCP port of a packet
      * packetSrcTCPPort : Test the source TCP port of a packet
      * createOFAction : Create one OpenFlow action
      * getFullMatch : get the full match out of a packet
      * createFlowMod : create a flow mod
      * createArpRequest : Create an Arp Request for  a different destination IP
      * createArpReply : Create an Arp Reply for  a different source IP
    
    === 4e. Debugging your Controller ===
    While you are developing your controller, some useful debugging tools are:
    
    ==== i. Print messages ====
    Run your controller in verbose mode (add --verbose) and add print messages at various places to see what your controller is seeing. 
    
    ==== ii. Check the status in the switch ====
    If you are using an OVS switch, you can dump information from your switch.  For example, to dump the flows:
    {{{
    sudo ovs-ofctl dump-flows br0
    }}}
    Two other useful commands show you the status of your switch:
    {{{
    sudo ovs-vsctl show 
    sudo ovs-ofctl show br0
    }}}
    
    ==== iii. Use Wireshark to see the OpenFlow messages ====
    Many times it is useful to see the OpenFlow messages being exchanged between your controller and the switch. This will tell you whether the messages that are created by your controller are correct and will allow you to see the details of any errors you might be seeing from the switch. You can use wireshark on both ends of the connection, in hardware switches you have to rely only on the controller view. 
    
    The controller host and OVS has wireshark installed, including the openflow dissector. For more information on wireshark you can take a look at the [http://wiki.wireshark.org/ wireshark wiki]. 
    
    Here we have a simple case of how to use the OpenFlow dissector for wireshark.
    
    If you are on a Linux friendly machine (this includes MACs) open a terminal and ssh to your controller machine using the -Y command line argument, i.e.
    {{{
    ssh -Y <username>@<controller>
    }}}
    
    Assuming that the public IP address on the controller is eth0, run wireshark by typing: 
    {{{
    sudo wireshark -i eth0&
    }}}
    
    When the wireshark window pops up, you might still have to choose eth0 for a live capture.  And you will want to use a filter to cut down on the chatter in the wireshark window.   One such filter might be just seeing what shows up on port 6633. To do that type ''tcp.port eq 6633'' in the filter window, assuming that 6633 is the port that the controller is
    listening on.   And once you have lines, you can choose one of the lines and choose "Decode as ...." and choose the ''OFP protocol''. 
    
    === 4f. Run a traffic duplication controller ===
    
    In the above example we ran a very simple learning switch controller. [[BR]]
    [[Image(GENIExperimenter/Tutorials/Graphics:4NotesIcon_512x512.png, 5%, nolink)]]
    The power of !OpenFlow comes from the fact that you can decide to forward the packet anyway you want based on the supported !OpenFlow actions. A very simple but powerful modification you can do, is to duplicate all the traffic of the switch out a specific port. This is very useful for application and network analysis. You can imagine that at the port where you duplicate traffic you connect a device that does analysis. For this tutorial we  are going to verify the duplication by doing `tcpdump`  on two ports on the OVS switch. 
    
      1. '''Use the interfaces that are connected to `host2` and  `host3`. '''
        * Software Switch (OVS): If you have not noted them down you can use the manifest and the MAC address of the interfaces (ovs:if1 and ovs:if2) to figure this out. But you should have noted down the interfaces in Section 2 when you were configuring the software switch. Run tcpdump on these interfaces; one in each of the two ovs terminals you opened. This will allow you to see all traffic going out the interfaces.
        [[BR]]
       
      To see that duplication is happening, on the ovs host, run:  
    {{{
    sudo tcpdump -i <data_interface_name>  [data_interface to host2]
    sudo tcpdump -i <data_interface_name>  [data_interface to host3]
    }}}
    
      You should see traffic from host1 to host2 showing up in the tcpdump window for host3.  As a comparison, you will notice that no traffic shows up in that window when the controller is running the learning switch.
      2. '''In the controller host directory `/tmp/pox/ext` you should see two files:'''
    
           i. '''myDuplicateTraffic.py''' : This is the file that has instructions about how to complete the missing information. Go ahead and try to implement your first controller. 
           ii. '''!DuplicateTraffic.py''' : This has the actual solution. You can just run this if you don't want to bother with writing a controller. 
    
      3. Run your newly written controller on the <data_interface_name> that corresponds to ''OVS:if2'' (which is connected to `host3`):  
    {{{
    cd /tmp/pox
    ./pox.py --verbose DuplicateTraffic --duplicate_port=?
    }}}
    
      For example, if ''OVS:if2'' corresponds to "eth1", enter
    
      {{{
      ./pox.py --verbose myDuplicateTraffic --duplicate_port=eth1
      }}}
       
      4. To test it go to the terminal of host1 and try to ping host2:
    {{{
    ping 10.10.1.2
    }}}
      If your controller is working, your packets will register in both terminals running tcpdump. 
    
      5. Stop the POX controller:
    {{{
    DEBUG:DuplicateTraffic:Got a packet : [02:f1:ae:bb:e3:a8>02:c7:e8:a7:40:65 IP]
    DEBUG:SimpleL2Learning:installing flow for 02:f1:ae:bb:e3:a8.2 -> 02:c7:e8:a7:40:65.[1, 2]
    
    INFO:core:Going down...
    INFO:openflow.of_01:[3a-51-a1-ab-c3-43 1] disconnected
    INFO:core:Down.
    }}}
    
    === 4g. Run a port forward Controller ===
    
    Now let's do a slightly more complicated controller. OpenFlow gives you the power to overwrite fields of your packets at the switch, for example the TCP source or destination port and do port forwarding. You can have clients trying to contact a server at port 5000, and the OpenFlow switch can redirect your traffic to a service listening on port 6000. 
    
      1. Under the `/tmp/pox/ext` directory there are two files: '''!PortForwarding.py''' and '''myPortForwarding.py''' that are similar like the previous exercise. Both of these controller are configured by a configuration file at `ext/port_forward.config`. Use myPortForwarding.py to write your own port forwarding controller.
    
      2. To test your controller we are going to use netcat. Go to the two terminals of host2. In one terminal run:
    {{{
    nc -l 5000
    }}}
    
      and in the other terminal run
    {{{
    nc -l 6000
    }}}
    
      3. Now, start the simple layer 2 forwarding controller. We are doing this to see what happens with a simple controller.
    {{{
    cd /tmp/pox
    ./pox.py --verbose forwarding.l2_learning
    }}}
    
      4. Go to the terminal of host1 and connect to host2 at port 5000:
    {{{
    nc 10.10.1.2 5000
    }}}
       
      5. Type something and you should see it at the the terminal of host2 at port 5000. 
    
      6. Now, stop the simple layer 2 forwarding controller:
    {{{
    DEBUG:forwarding.l2_learning:installing flow for 02:d4:15:ed:07:4e.3 -> 02:ff:be:1d:19:ea.2
    
    INFO:core:Going down...
    INFO:openflow.of_01:[36-63-8b-d7-16-4b 1] disconnected
    INFO:core:Down.
    }}}
    
      7. And start your port forwarding controller (if you have written your controller then use myPortForwarding in the following command):
    {{{
    ./pox.py --verbose PortForwarding
    }}}
    
      8. Repeat the netcat scenario described above. Now, your text should appear on the other terminal of host2 which is listening to port 6000. 
    
    
      9. Stop your port forwarding controller:
    {{{
    DEBUG:myPortForwarding:Got a packet : [02:aa:a3:e8:6c:db>33:33:ff:e8:6c:db IPV6]
    
    INFO:core:Going down...
    INFO:openflow.of_01:[36-63-8b-d7-16-4b 1] disconnected
    INFO:core:Down.
    }}}
    
    === 4h. Run a Server Proxy Controller ===
    
    As our last exercise, instead of diverting the traffic to a different server running on the same host, we will divert the traffic to a server running on a different host and on a different port. 
    
      1. Under the `/tmp/pox/ext/` directory there are two files: '''Proxy.py''' and '''myProxy.py''' that are similar like the previous exercise. Both of these controllers are configured by the configuration file `proxy.config`. Use myProxy.py to write your own proxy controller.
    
      2. On the terminal of `host3` run a netcat server:
    {{{
    nc -l 7000
    }}}
    
      3. On your controller host, open the /tmp/pox/ext/myProxy.py file, and edit it to implement a controller that will divert traffic destined for `host2` to `host3`. Before you start implementing think about what are the side effects of diverting traffic to a different host. 
         * Is it enough to just change the IP address? 
         * Is it enough to just modify the TCP packets? 
    
       If you want to see the solution, it's available in file /tmp/pox/ext/Proxy.py file.  
      
      4. To test your proxy controller run  (if you have written your controller then use myProxy in the following command):: 
    {{{
    cd /tmp/pox
    ./pox.py --verbose Proxy
    }}}
    
    
      5. Go back to the terminal of `host1` and try to connect netcat to `host2` port 5000
    {{{
    nc 10.10.1.2 5000
    }}}
    
      6. If your controller works correctly, you should see your text showing up on the terminal of `host3`.
    
    === 4i. Delete your bridge ===
    Before moving to the next step make sure you delete the bridge you have created, especially if you are using the same reservation for a different exercise:
    {{{
      sudo ovs-vsctl del-br br0
    }}}
    
    {{{
    #!comment
    == 4. Moving to a Hardware Switch ==
    To try your controller with a GENI Hardware !OpenFlow switch:
           * Delete the sliver with your experiment topology.  '''Do not''' delete your controller. 
           * Follow the instructions at [wiki:GENIExperimenter/Tutorials/OpenFlowOVS/HW/DesignSetup OpenFlow Design and Setup for Hardware Switch]
    
    If you do not want to do the Hardware !OpenFlow portion of the tutorial, proceed to [wiki:GENIExperimenter/Tutorials/OpenFlowOVS/Finish Finish]
    }}}
    ----
    
    = [wiki:GENIExperimenter/Tutorials/OpenFlowOVS-Floodlight/DesignSetup Prev: Design and Setup for OVS] =
    
    {{{
    #!comment
    = [wiki:GENIExperimenter/Tutorials/OpenFlowOVS/NATExecute Next: Make your switch to act as a NAT server] = 
    = [wiki:GENIExperimenter/Tutorials/OpenFlowOVS/FirewallExecute Next: Make your switch to act as a Firewall] =
    }}}
    = [wiki:GENIExperimenter/Tutorials/OpenFlowOVS-Floodlight/Finish Next:  Finish] =
    

Attachments (2)

Download all attachments as: .zip