Changes between Version 4 and Version 5 of GENIExperimenter/Tutorials/OpenFlowRyu/Execute


Ignore:
Timestamp:
02/25/17 20:58:03 (7 years ago)
Author:
Nabeel Akhtar
Comment:

--

Legend:

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

    v4 v5  
    1 = [http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu Intro to OpenFlow using OVS] =
     1= [wiki:GENIExperimenter/Tutorials/OpenFlowRyu Intro to OpenFlow Tutorial with Ryu Controller] =
    22{{{
    33#!html
     
    1616}}}
    1717[[PageOutline]]
    18 
    19 == Step 2.  Configure and Initialize ==
    20 
    21 OVS 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.
     18== Step 3. Execute Experiment ==
     19
     20Now 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 [http://osrg.github.io/ryu/ Ryu controller]. The software is already installed in the controller host for running Ryu controller.
     21
     22=== 3a. Login to your hosts ===
     23
     24To start our experiment we need to ssh all of our hosts.
    2225
    2326To get ready for the tutorial you will need to have the following windows open:
    2427  * 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  * four windows with ssh into OVS
     29  * one window with ssh into host1
     30  * two windows with ssh into host2
    2831  * one window with ssh into host3
    2932
    30 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.]
    31 
    32 === 2a. Software Switch Configuration ===
    33 The Software switch configuration has already been applied to the OVS VM. To see the configured bridge name:
    34 {{{
    35 $ sudo ovs-vsctl list-br
    36 br-switch
    37 }}}
    38 You should see only on bridge `br-switch`. To see the port configured for this bridge:
    39 {{{
    40 $ sudo ovs-vsctl list-ports br-switch
    41 eth1
    42 eth2
    43 eth3
    44 }}}
    45 
    46 
    47 This 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 }}}
    81 The 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 
    88 Find the control interface IP of your controller, use /sbin/ifconfig and note down the IP of `eth0`.
    89 
    90 An !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 
    92 In 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 
    99 The !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 
    103 In 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 }}}
    107 You can verify your OVS settings by issuing the following:
    108 
    109 {{{
    110 $ sudo ovs-vsctl show
    111 }}}
    112 
    113 == Step 3. Execute Experiment ==
    114 
    115 Now 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 
    119 To 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.
     33Depending 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 [wiki:HowTo/LoginToNodes how to login.] Once you have logged in follow the rest of the instructions.
    12034
    12135=== 3b. Use a Learning Switch Controller ===
    12236
    123 In this example we going to run a very simple learning switch controller to forward traffic between host1 and host2.
     37In this example we are going to run a very simple learning switch controller to forward traffic between `host1` and `host2`.
    12438 
    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   }}}
     39  1. First start a ping from  `host1` to `host2`, which should timeout, since there is no controller running.
     40
     41{{{
     42ping host2 -c 10
     43}}}
     44
     45  2. We have installed the Ryu controller under `/tmp/ryu` on the controller host. Ryu comes with a set of example modules that you can use out of the box. One of the modules is a learning switch.  Start the learning switch controller which is already available by running the following two commands:
     46 
     47{{{
     48cd /tmp/ryu
     49./bin/ryu-manager ryu/ext/simple_switch.py
     50}}}
     51
     52The output should look like this:
     53{{{
     54loading app ryu/ext/simple_switch.py
     55loading app ryu.controller.ofp_handler
     56instantiating app ryu.controller.ofp_handler of OFPHandler
     57instantiating app ryu/ext/simple_switch.py of SimpleSwitch
     58}}}
     59
     60 3. In the terminal of `host1`, ping `host2`:
     61{{{
     62[experimenter@host1 ~]$ ping host2
     63PING host2-lan1 (10.10.1.2) 56(84) bytes of data.
     64From host1-lan0 (10.10.1.1) icmp_seq=2 Destination Host Unreachable
     65From host1-lan0 (10.10.1.1) icmp_seq=3 Destination Host Unreachable
     66From host1-lan0 (10.10.1.1) icmp_seq=4 Destination Host Unreachable
     6764 bytes from host2-lan1 (10.10.1.2): icmp_req=5 ttl=64 time=23.9 ms
     6864 bytes from host2-lan1 (10.10.1.2): icmp_req=6 ttl=64 time=0.717 ms
     6964 bytes from host2-lan1 (10.10.1.2): icmp_req=7 ttl=64 time=0.654 ms
     7064 bytes from host2-lan1 (10.10.1.2): icmp_req=8 ttl=64 time=0.723 ms
     7164 bytes from host2-lan1 (10.10.1.2): icmp_req=9 ttl=64 time=0.596 ms
     72}}}
    14973
    15074  Now the ping should work.
    15175
    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:
    161   {{{
    162   sudo tcpdump -i eth0 tcp port 6633
    163   }}}
     764. Go to your controller 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.
     77
     78=== 3b. Look around your OVS switch  ===
     79
     80  1. If you are using OVS, to see the flow table entries on your OVS switch:
     81{{{
     82sudo ovs-ofctl dump-flows br0
     83}}}
     84    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.
     85
     86  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.)
     87{{{
     88sudo tcpdump -i eth0 tcp port 6633
     89}}}
    16490  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).
    16591
    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   }}}
     92  3. Kill your Ryu controller by pressing `Ctrl-C`:
     93
     94  4. Notice what happens to your ping on host1.
     95
     96  5. If you are using OVS, check the flow table entries on your switch:
     97{{{
     98sudo ovs-ofctl dump-flows br0
     99}}}
    174100  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.
    175101
     
    179105All rules on the switch have two different timeouts:
    180106
    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.
     107  * '''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.
    182108  * '''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.
    183109
    184110Can you tell now why there were packets flowing even after you killed your controller?
    185111
    186 === Useful Tips for writing your controller ===
    187 
    188 In 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.
     112=== 3d. Useful Tips for writing your controller ===
     113
     114In order to make this first experience of writing a controller easier, we wrote some helpful functions that will abstract some of the particularities of Ryu away.
    189115These functions are located in `/tmp/ryu/ryu/ext/utils.py`, so while you write your controller consult this file for details.
    190116
     
    207133  * createArpReply : Create an Arp Reply for  a different source IP
    208134
    209 === 3c. Debugging your Controller ===
     135=== 3e. Debugging your Controller ===
    210136While you are developing your controller, some useful debugging tools are:
    211137
     
    216142If you are using an OVS switch, you can dump information from your switch.  For example, to dump the flows:
    217143{{{
    218 sudo ovs-ofctl dump-flows br-switch
     144sudo ovs-ofctl dump-flows br0
    219145}}}
    220146Two other useful commands show you the status of your switch:
    221147{{{
    222148sudo ovs-vsctl show
    223 sudo ovs-ofctl show br-switch
     149sudo ovs-ofctl show br0
    224150}}}
    225151
    226152==== iii. Use Wireshark to see the OpenFlow messages ====
    227 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. 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.
     153Many 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.
    228154
    229155The 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].
     
    236162}}}
    237163
    238 We will need to capture a packet trace to feed into wireshark to analyze it. So once you are logged in run:
    239 {{{
    240 sudo tcpdump -s 0 -w out.pcap tcp port 6633
    241 }}}
    242 
    243 The 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 
    245 Run wireshark by typing:
    246 {{{
    247 wireshark &
    248 }}}
    249 Use 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 
    253 In 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   }}}
     164Assuming that the public IP address on the controller is eth0, run wireshark by typing:
     165{{{
     166sudo wireshark -i eth0&
     167}}}
     168
     169When 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
     170listening on.   And once you have lines, you can choose one of the lines and choose "Decode as ...." and choose the ''OFP protocol''.
     171
     172=== 3f. Run a traffic duplication controller ===
     173
     174In the above example we ran a very simple learning switch controller. [[BR]]
     175[[Image(GENIExperimenter/Tutorials/Graphics:4NotesIcon_512x512.png, 5%, nolink)]]
     176The 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.
     177
     178  1. '''Use the interfaces that are connected to `host2` and  `host3`. '''
     179    * 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.
     180    [[BR]]
     181   
     182  To see that duplication is happening, on the ovs host, run: 
     183{{{
     184sudo tcpdump -i <data_interface_name>  [data_interface to host2]
     185sudo tcpdump -i <data_interface_name>  [data_interface to host3]
     186}}}
     187
     188  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.
     189  2. '''In the controller host directory `/tmp/ryu/ryu/ext` you should see two files:'''
     190
     191       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.
     192       ii. '''!DuplicateTraffic.py''' : This has the actual solution. You can just run this if you don't want to bother with writing a controller.
     193       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".
     194
     195  3. Run your newly written controller on the <data_interface_name> that corresponds to ''OVS:if2'' (which is connected to `host3`): 
     196{{{
     197cd /tmp/ryu
     198./bin/ryu-manager ryu/ext/myDuplicateTraffic.py
     199}}}
    271200   
    272201  4. To test it go to the terminal of host1 and try to ping host2:
    273   {{{
    274   ping 10.10.1.2
    275   }}}
     202{{{
     203ping 10.10.1.2
     204}}}
    276205  If your controller is working, your packets will register in both terminals running tcpdump.
    277206
    278   5. Stop the Ryu controller using `Ctrl-C`.
    279 
    280 === 3d. Run a port forward Controller ===
     207  5. Stop the Ryu controller using `Ctrl-C`:
     208
     209=== 3g. Run a port forward Controller ===
    281210
    282211Now 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.
    283212
    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.
     213  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 `ext/port_forward.config`. Use myPortForwarding.py to write your own port forwarding controller.
    285214
    286215  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   }}}
     216{{{
     217nc -l 5000
     218}}}
    290219
    291220  and in the other terminal run
    292   {{{
    293   nc -l 6000
    294   }}}
     221{{{
     222nc -l 6000
     223}}}
    295224
    296225  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   }}}
     226{{{
     227cd /tmp/ryu
     228./bin/ryu-manager ryu/ext/simple_switch.py
     229}}}
    301230
    302231  4. Go to the terminal of host1 and connect to host2 at port 5000:
    303   {{{
    304   nc 10.10.1.2 5000
    305   }}}
     232{{{
     233nc 10.10.1.2 5000
     234}}}
    306235   
    307236  5. Type something and you should see it at the the terminal of host2 at port 5000.
    308237
    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   }}}
     238  6. Now, stop the simple layer 2 forwarding controller by `Ctrl-C`.
     239
     240  7. And start your port forwarding controller (if you have written your controller then use myPortForwarding in the following command):
     241{{{
     242./bin/ryu-manager ryu/ext/PortForwarding.py
     243}}}
    315244
    316245  8. Repeat the netcat scenario described above. Now, your text should appear on the other terminal of host2 which is listening to port 6000.
    317246
    318247
    319   9. Stop your port forwarding controller.
    320 
    321 === 3e. Run a Server Proxy Controller ===
    322 
    323 As 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.
     248  9. Stop your port forwarding controller using `Ctrl-C`.
     249
     250=== 3h. Run a Server Proxy Controller ===
     251
     252As 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.
     253
     254  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.
    326255
    327256  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.
     257{{{
     258nc -l 7000
     259}}}
     260
     261  3. On your controller host, open the /tmp/ryu/ryu/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.
    333262     * Is it enough to just change the IP address?
    334263     * Is it enough to just modify the TCP packets?
     
    336265   If you want to see the solution, it's available in file /tmp/ryu/ryu/ext/Proxy.py file. 
    337266 
    338   4. To test your proxy controller run:
    339   {{{
    340   cd /tmp/ryu
    341   ./bin/ryu-manager ryu/ext/myProxy.py
    342   }}}
     267  4. To test your proxy controller run  (if you have written your controller then use myProxy in the following command)::
     268{{{
     269cd /tmp/ryu
     270./bin/ryu-manager ryu/ext/myProxy.py
     271}}}
    343272
    344273  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   }}}
     274{{{
     275nc 10.10.1.2 5000
     276}}}
    348277
    349278  6. If your controller works correctly, you should see your text showing up on the terminal of `host3`.
    350279
    351 == 4. Moving to a Hardware Switch ==
    352 To 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 
    356 If 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 Finish]
     280=== 3i. Delete your bridge ===
     281Before 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:
     282{{{
     283  sudo ovs-vsctl del-br br0
     284}}}
     285
    357286----
    358287
    359 = [http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu Introduction] =
    360 = [http://groups.geni.net/geni/wiki/GENIExperimenter/Tutorials/OpenFlowRyu/Finish Next:  Finish] =
     288= [wiki:GENIExperimenter/Tutorials/OpenFlowRyu/DesignSetup Prev: Design and Setup for OVS] =
     289= [wiki:GENIExperimenter/Tutorials/OpenFlowRyu/Finish Next:  Finish] =