Changes between Initial Version and Version 1 of GENIExperimenter/Tutorials/OpenFlowRyu/Execute


Ignore:
Timestamp:
02/25/17 18:47:30 (7 years ago)
Author:
Nabeel Akhtar
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • GENIExperimenter/Tutorials/OpenFlowRyu/Execute

    v1 v1  
     1= [http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu Intro to OpenFlow using OVS] =
     2{{{
     3#!html
     4
     5<div style="text-align:center; width:495px; margin-left:auto; margin-right:auto;">
     6<img id="Image-Maps_5201305222028436" src="http://groups.geni.net/geni/attachment/wiki/GENIExperimenter/Tutorials/Graphics/Execute.jpg?format=raw" usemap="#Image-Maps_5201305222028436" border="0" width="495" height="138" alt="" />
     7<map id="_Image-Maps_5201305222028436" name="Image-Maps_5201305222028436">
     8<area shape="rect" coords="18,18,135,110" href="http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu/DesignSetup" alt="" title=""    />
     9<area shape="rect" coords="180,18,297,111" href="http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu/Execute" alt="" title=""    />
     10<area shape="rect" coords="344,17,460,110" href="http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu/Finish" alt="" title=""    />
     11<area shape="rect" coords="493,136,495,138" href="http://www.image-maps.com/index.php?aff=mapped_users_5201305222028436" alt="Image Map" title="Image Map" />
     12</map>
     13<!-- Image map text links - End - -->
     14
     15</div>
     16}}}
     17[[PageOutline]]
     18
     19== Step 2.  Configure and Initialize ==
     20
     21OVS is installed and initialized on the host that is meant to act as a software switch.  This experiment requires two things to be configured: ''(1) configure your software switch with the interfaces as ports'' and '' (2) point the switch to an !OpenFlow controller''.  Item ''(1)'' is already done for you, you just need to define the controller for item ''(2)''.  In order to configure our switch, we first need to login to the host that will be used as an !OpenFlow switch.
     22
     23To get ready for the tutorial you will need to have the following windows open:
     24  * one window with ssh into the controller
     25  * two windows with ssh into OVS
     26  * one windows with ssh into host1
     27  * two window with ssh into host2
     28  * one window with ssh into host3
     29
     30Depending 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 take a look in [wiki:HowTo/LoginToNodes this page.]
     31
     32=== 2a. Software Switch Configuration ===
     33The Software switch configuration has already been applied to the OVS VM. To see the configured bridge name:
     34{{{
     35$ sudo ovs-vsctl list-br
     36br-switch
     37}}}
     38You should see only on bridge `br-switch`. To see the port configured for this bridge:
     39{{{
     40$ sudo ovs-vsctl list-ports br-switch
     41eth1
     42eth2
     43eth3
     44}}}
     45
     46
     47This sections captures how those interfaces were added to the bridge predefined in the OVS image:
     48
     49{{{
     50#!html
     51<table border="0">
     52      <tr >
     53       <td width = "500">
     54         <ol>
     55           <li>List all the interfaces of the node
     56            <ul> <li> <code>ifconfig</code> </ul><br/>
     57            Write down the interface names that correspond to the connections to your hosts. The correspondence is:
     58            <ul>
     59                <li> Interface with IP 10.10.1.11 to host1  - eth1</li>
     60                <li> Interface with IP 10.10.1.12 to host2 - eth2</li>
     61                <li> Interface with IP 10.10.1.13 to host3 - eth3</li>
     62           </ul></li>
     63           </li> <br/>
     64           <li> Note eth0 is your control interface, if you bring that interface down you won't be able to login to your host!. For all interfaces other than <code>eth0</code> and <code> l0</code>, remove the IP from the interfaces (your interface names may vary): <br/>
     65                              <ul><li> <code> sudo ifconfig eth1 0 </code> </li></ul>
     66                              <ul><li> <code> sudo ifconfig eth2 0 </code> </li></ul>
     67                              <ul><li> <code> sudo ifconfig eth3 0 </code> </li></ul>
     68             <li> Add all the data interfaces to your switch (bridge):Be careful <b> not to add interface eth0</b>. This is your control interface. You should see three interfaces that start with VLAN, these are your data interfaces. (Use the same interfaces as you used in the previous step.)
     69                <ul><li> <code> sudo  ovs-vsctl add-port br-switch eth1 </code> </li></ul>
     70                <ul><li> <code> sudo  ovs-vsctl add-port br-switch eth2 </code> </li></ul>
     71                <ul><li> <code> sudo  ovs-vsctl add-port br-switch eth3 </code> </li></ul>
     72             </li>
     73          </ol>
     74       </td>
     75        <td>
     76        <img border="0" src="http://groups.geni.net/geni/attachment/wiki/GENIExperimenter/Tutorials/OpenflowOVS/Graphics/ovs-interfaces.jpg?format=raw" alt="Login information for a VM"  height="250" title="Login information for a VM" /> </a>
     77       </td>
     78    </tr>
     79 </table>
     80}}}
     81The above bridge instructions were used to create the OVS image, you need not execute the above! If you want to see the list of ports associated with the bridge:
     82{{{
     83$ sudo ovs-vsctl list-ports br-switch
     84}}}
     85
     86=== 2b. Point your switch to a controller ===
     87
     88Find the control interface IP of your controller, use /sbin/ifconfig and note down the IP of `eth0`.
     89
     90An !OpenFlow switch will not forward any packet, unless instructed by a controller. Basically the forwarding table is empty, until an external controller inserts forwarding rules. The !OpenFlow controller communicates with the switch over the control network and it can be anywhere in the Internet as long as it is reachable by the OVS host. '''(The following sentence is not true anymore)'''For the purpose of this tutorial and in order to minimize the resources we have reserved we are going to run !OpenFlow controller at the same host as the OVS switch. This is '''merely''' for convenience reasons, the controller could have been anywhere on the Internet.
     91
     92In order to point our software !OpenFlow switch to the controller issue the following command on the OVS host:
     93{{{
     94$sudo ovs-vsctl set-controller br-switch tcp:<controller_ip>:6633
     95}}}
     96
     97==== `standalone` vs `secure` mode ====
     98
     99The !OpenFlow controller is responsible for setting up all flows on the switch, which means that when the controller is not running there should be no packet switching at all. Depending on the setup of your network, such a behavior might not be desired. It might be best that when the controller is down, the switch should default back in being a learning layer 2 switch. In other circumstances however this might be undesirable. In OVS this is a tunable parameter, called `fail-safe-mode` which can be set to the following parameters:
     100  * `standalone` [default]: in which case OVS will take responsibility for forwarding the packets if the controller fails
     101  * `secure`: in which case only the controller is responsible for forwarding packets, and if the controller is down all packets are going to be dropped.
     102
     103In OVS when the parameter is not set it falls back to the `standalone` mode. For the purpose of this tutorial we will set the `fail-safe-mode` to `secure`, since we want to be the ones controlling the forwarding. Run:
     104{{{
     105$ sudo ovs-vsctl set-fail-mode br-switch secure
     106}}}
     107You can verify your OVS settings by issuing the following:
     108
     109{{{
     110$ sudo ovs-vsctl show
     111}}}
     112
     113== Step 3. Execute Experiment ==
     114
     115Now that our switch is up and running we are ready to start working on our controller. For this tutorial we are going to use the [http://osrg.github.io/ryu/ Ryu controller]. The software is already installed in the controller host for running Ryu and can also be found [http://www.research.rutgers.edu/~zhewang/of/ryu-gpo.tar.gz here].
     116
     117=== 3a. Login to your hosts ===
     118
     119To start our experiment we need to ssh 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 take a look in [wiki:HowTo/LoginToNodes this page.] Once you have logged in follow the rest of the instructions.
     120
     121=== 3b. Use a Learning Switch Controller ===
     122
     123In this example we going to run a very simple learning switch controller to forward traffic between host1 and host2.
     124 
     125  1. First we are going to start a ping from  `host1` to `host2`, which should timeout, since there is no controller running.
     126  {{{
     127  ping host2
     128  }}}
     129
     130  2. We have installed the Ryu controller under `/tmp/ryu` on the controller host. We put a set of example modules that you can use out of the box. One of the modules is a learning switch.  Let's start the learning switch controller which is already available:
     131  {{{
     132  cd /tmp/ryu
     133  ./bin/ryu-manager ryu/ext/simple_switch.py
     134  }}}
     135
     136 3. Now go to terminal of `host1` and ping `host2`:
     137  {{{
     138  [experimenter@host1 ~]$ ping host2
     139  PING host2-lan1 (10.10.1.2) 56(84) bytes of data.
     140  From host1-lan0 (10.10.1.1) icmp_seq=2 Destination Host Unreachable
     141  From host1-lan0 (10.10.1.1) icmp_seq=3 Destination Host Unreachable
     142  From host1-lan0 (10.10.1.1) icmp_seq=4 Destination Host Unreachable
     143  64 bytes from host2-lan1 (10.10.1.2): icmp_req=5 ttl=64 time=23.9 ms
     144  64 bytes from host2-lan1 (10.10.1.2): icmp_req=6 ttl=64 time=0.717 ms
     145  64 bytes from host2-lan1 (10.10.1.2): icmp_req=7 ttl=64 time=0.654 ms
     146  64 bytes from host2-lan1 (10.10.1.2): icmp_req=8 ttl=64 time=0.723 ms
     147  64 bytes from host2-lan1 (10.10.1.2): icmp_req=9 ttl=64 time=0.596 ms
     148  }}}
     149
     150  Now the ping should work.
     151
     152  4. Go back to your OVS host and take a look at the print outs. You should see that your controller installed flows based on the mac addresses of your packets.
     153
     154  5. To see the flow table entries on your OVS switch:
     155  {{{
     156  sudo ovs-ofctl dump-flows br-switch
     157  }}}
     158  You should see at least two table entries: One for messages from host1 to host2 and one for messages from host2 to host1.  You may also see flow entries for arp packets.
     159
     160  6. To see messages go between your switch and your controller (listening on port 6633 of your localhost), run tcpdump on the `eth0` interface of your controller node: '''(This one I saw too many other packets)'''
     161  {{{
     162  sudo tcpdump -i eth0
     163  }}}
     164  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).
     165
     166  7. Kill your Ryu controller by pressing `Ctrl-C`.
     167
     168  8. Notice what happens to your ping on host1.
     169
     170  9. Check the flow table entries on your switch:
     171   {{{
     172  sudo ovs-ofctl dump-flows br-switch
     173  }}}
     174  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.
     175
     176
     177==== Soft vs Hard Timeouts ====
     178
     179All rules on the switch have two different timeouts:
     180
     181  * '''Soft Timeout''': This determines for how long the flow will remain at the forwarding table of the switch, if there no packets received that match the specific flow. As long as packets from that flow are received the flow remains on the flow table.
     182  * '''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.
     183
     184Can you tell now why there were packets flowing even after you killed your controller?
     185
     186=== Useful Tips for writing your controller ===
     187
     188In order to make this first experience of writing controller easier, we wrote some helpful functions that will abstract some of the particularities of Ryu away.
     189These functions are located in `/tmp/ryu/ryu/ext/utils.py`, so while you write your controller consult this file for details.
     190
     191Functions that are implemented include:
     192  * packetIsIP : Test if the packet is IP
     193  * packetIsARP : Test if the packet is ARP
     194  * packetIsRequestARP : Test if this is an ARP Request packet
     195  * packetIsReplyARP : Test if this is an ARP Reply packet
     196  * packetArpDstIp : Test what is the destination IP in an ARP packet
     197  * packetArpSrcIp : Test what is the sources IP in an ARP packet
     198  * packetIsTCP : Test if a packet is TCP
     199  * packetDstIp : Test the destination IP of a packet
     200  * packetSrcIp : Test the source IP of a packet
     201  * packetDstTCPPort : Test the destination TCP port of a packet
     202  * packetSrcTCPPort : Test the source TCP port of a packet
     203  * createOFAction : Create one OpenFlow action
     204  * getFullMatch : get the full match out of a packet
     205  * createFlowMod : create a flow mod
     206  * createArpRequest : Create an Arp Request for  a different destination IP
     207  * createArpReply : Create an Arp Reply for  a different source IP
     208
     209=== 3c. Debugging your Controller ===
     210While you are developing your controller, some useful debugging tools are:
     211
     212==== i. Print messages ====
     213Run your controller in verbose mode (add --verbose) and add print messages at various places to see what your controller is seeing.
     214
     215==== ii. Check the status in the switch ====
     216If you are using an OVS switch, you can dump information from your switch.  For example, to dump the flows:
     217{{{
     218sudo ovs-ofctl dump-flows br-switch
     219}}}
     220Two other useful commands show you the status of your switch:
     221{{{
     222sudo ovs-vsctl show
     223sudo ovs-ofctl show br-switch
     224}}}
     225
     226==== iii. Use Wireshark to see the OpenFlow messages ====
     227Many 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. If you are using OVS then you can use wireshark on both ends of the connection, in hardware switches you have to rely only on the controller view.
     228
     229The 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].
     230
     231Here we have a simple case of how to use the OpenFlow dissector for wireshark.
     232
     233If 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.
     234{{{
     235ssh -Y <username>@<controller>
     236}}}
     237
     238We will need to capture a packet trace to feed into wireshark to analyze it. So once you are logged in run:
     239{{{
     240sudo tcpdump -s 0 -w out.pcap tcp port 6633
     241}}}
     242
     243The above command will run tcpdump capturing the full packets (`-s 0`), saving the capture to and out.pcap file (`-w out.pcap`) and only capturing packets with src/dst tcp port 6633 that is where our controller is running (`tcp port 6633`).
     244
     245Run wireshark by typing:
     246{{{
     247wireshark &
     248}}}
     249Use the file menu to load the pcap file. Right-click on one of the files and choose "Decode as ...." and choose the OFP protocol. Once you do that you will see the OpenFlow message types in wireshark. If you have more than openflow packets in your pcap you can type `of` in the filter box on the top and only show OpenFlow messages.
     250
     251=== 3d. Run a traffic duplication controller ===
     252
     253In the above example we ran a very simple learning switch controller. 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 a `tcpdump`  on a port on the OVS switch.
     254
     255  1. Use the interfaces that are connected to `host2` and  `host3`. If you haven't note them down you can use the manifest and the MAC address of the interfaces (ovs:if1 and ovs:if2) to figure this out.  Run tcpdump on these interfaces; one in each of the other two terminals you opened. This will allow you to see all traffic going out the interfaces.
     256  {{{
     257  sudo tcpdump -i <data_interface_name>
     258  }}}
     259
     260  2. In the contorller host directory `/tmp/ryu/ryu/ext` you would see three files:
     261
     262       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.
     263       ii. !DuplicateTraffic.py : this has the actual solution you can just run this if you don't want to bother with writing a controller.
     264       iii. duplicate.config : in this file, you specify which port you want to duplicate traffic to. To figure out which port maps to which interface, use "sudo ovs-ofctl show br-switch".
     265
     266  3. Run your newly written controller :
     267  {{{
     268  cd /tmp/ryu
     269  ./bin/ryu-manager ryu/ext/myDuplicateTraffic.py
     270  }}}
     271   
     272  4. To test it go to the terminal of host1 and try to ping host2:
     273  {{{
     274  ping 10.10.1.2
     275  }}}
     276  If your controller is working, your packets will register in both terminals running tcpdump.
     277
     278  5. Stop the Ryu controller using `Ctrl-C`.
     279
     280=== 3d. Run a port forward Controller ===
     281
     282Now 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.
     283
     284  1. Under the `/tmp/ryu/ryu/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 `port_forward.config`. Use myPortForwarding.py to write your own port forwarding controller.
     285
     286  2. To test your controller we are going to use netcat. Go to the two terminals of host2. In one terminal run:
     287  {{{
     288  nc -l 5000
     289  }}}
     290
     291  and in the other terminal run
     292  {{{
     293  nc -l 6000
     294  }}}
     295
     296  3. Now, start the simple layer 2 forwarding controller. We are doing this to see what happens with a simple controller.
     297   {{{
     298  cd /tmp/ryu
     299  ./bin/ryu-manager ryu/ext/simple_switch.py
     300  }}}
     301
     302  4. Go to the terminal of host1 and connect to host2 at port 5000:
     303  {{{
     304  nc 10.10.1.2 5000
     305  }}}
     306   
     307  5. Type something and you should see it at the the terminal of host2 at port 5000.
     308
     309  6. Now, stop the simple layer 2 forwarding controller by `Ctrl-C`:
     310
     311  7. And start your port forwarding controller:
     312  {{{
     313  ./bin/ryu-manager ryu/ext/myPortForwarding.py
     314  }}}
     315
     316  8. Repeat the netcat scenario described above. Now, your text should appear on the other terminal of host2 which is listening to port 6000.
     317
     318
     319  9. Stop your port forwarding controller.
     320
     321=== 3e. Run a Server Proxy Controller ===
     322
     323As our last exercise, instead of diverging the traffic to a different server running on the same host, we will diverge the traffic to a server running on a different host and on a different port.
     324
     325  1. Under the `/tmp/ryu/ryu/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.
     326
     327  2. On the terminal of `host3` run a netcat server:
     328  {{{
     329  nc -l 7000
     330  }}}
     331
     332  3. On your controller host open the /tmp/ryu/ryu/ext/myProxy.py file, and edit it to implement a controller that will diverge traffic destined for `host2` to `host3`. Before you start implementing think about what are the side effects of diverging traffic to a different host.
     333     * Is it enough to just change the IP address?
     334     * Is it enough to just modify the TCP packets?
     335
     336   If you want to see the solution, it's available in file /tmp/ryu/ryu/ext/Proxy.py file. 
     337 
     338  4. To test your proxy controller run:
     339  {{{
     340  cd /tmp/ryu
     341  ./bin/ryu-manager ryu/ext/myProxy.py
     342  }}}
     343
     344  5. Go back to the terminal of `host1` and try to connect netcat to `host2` port 5000
     345  {{{
     346  nc 10.10.1.2 5000
     347  }}}
     348
     349  6. If your controller works correctly, you should see your text showing up on the terminal of `host3`.
     350
     351== 4. Moving to a Hardware Switch ==
     352To try your controller with a GENI Hardware !OpenFlow switch:
     353       * Delete resources in your slice with the compute resources.  '''Do not''' delete resources in your slice with the controller.
     354       * Follow the instructions at [wiki:GENIExperimenter/Tutorials/OpenFlowOVS/Appendix] '''(I didn't change this part. There are a few wording changes needed.)'''
     355
     356If you do not want to do the Hardware !OpenFlow portion of the tutorial, proceed to [http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu/Finish]
     357----
     358
     359= [http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu Introduction] =
     360= [http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu/Finish Next:  Finish] =