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. |
| 33 | 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 [wiki:HowTo/LoginToNodes how to login.] Once you have logged in follow the rest of the instructions. |
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 | {{{ |
| 42 | ping 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 | {{{ |
| 48 | cd /tmp/ryu |
| 49 | ./bin/ryu-manager ryu/ext/simple_switch.py |
| 50 | }}} |
| 51 | |
| 52 | The output should look like this: |
| 53 | {{{ |
| 54 | loading app ryu/ext/simple_switch.py |
| 55 | loading app ryu.controller.ofp_handler |
| 56 | instantiating app ryu.controller.ofp_handler of OFPHandler |
| 57 | instantiating 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 |
| 63 | PING host2-lan1 (10.10.1.2) 56(84) bytes of data. |
| 64 | From host1-lan0 (10.10.1.1) icmp_seq=2 Destination Host Unreachable |
| 65 | From host1-lan0 (10.10.1.1) icmp_seq=3 Destination Host Unreachable |
| 66 | From host1-lan0 (10.10.1.1) icmp_seq=4 Destination Host Unreachable |
| 67 | 64 bytes from host2-lan1 (10.10.1.2): icmp_req=5 ttl=64 time=23.9 ms |
| 68 | 64 bytes from host2-lan1 (10.10.1.2): icmp_req=6 ttl=64 time=0.717 ms |
| 69 | 64 bytes from host2-lan1 (10.10.1.2): icmp_req=7 ttl=64 time=0.654 ms |
| 70 | 64 bytes from host2-lan1 (10.10.1.2): icmp_req=8 ttl=64 time=0.723 ms |
| 71 | 64 bytes from host2-lan1 (10.10.1.2): icmp_req=9 ttl=64 time=0.596 ms |
| 72 | }}} |
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 | | }}} |
| 76 | 4. 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 | {{{ |
| 82 | sudo 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 | {{{ |
| 88 | sudo tcpdump -i eth0 tcp port 6633 |
| 89 | }}} |
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 | | }}} |
| 164 | Assuming that the public IP address on the controller is eth0, run wireshark by typing: |
| 165 | {{{ |
| 166 | sudo wireshark -i eth0& |
| 167 | }}} |
| 168 | |
| 169 | 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 |
| 170 | listening 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 | |
| 174 | In the above example we ran a very simple learning switch controller. [[BR]] |
| 175 | [[Image(GENIExperimenter/Tutorials/Graphics:4NotesIcon_512x512.png, 5%, nolink)]] |
| 176 | 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. |
| 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 | {{{ |
| 184 | sudo tcpdump -i <data_interface_name> [data_interface to host2] |
| 185 | sudo 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 | {{{ |
| 197 | cd /tmp/ryu |
| 198 | ./bin/ryu-manager ryu/ext/myDuplicateTraffic.py |
| 199 | }}} |
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 | |
| 252 | 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. |
| 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. |