54 | | == 1. Create the Software Switch == |
55 | | Now that you are logged in, we need first to initialize OVS: |
56 | | * Start the OVS database: |
57 | | {{{ |
58 | | sudo ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \ |
59 | | --remote=db:Open_vSwitch,manager_options \ |
60 | | --private-key=db:SSL,private_key \ |
61 | | --certificate=db:SSL,certificate \ |
62 | | --bootstrap-ca-cert=db:SSL,ca_cert \ |
63 | | --pidfile --detach |
64 | | }}} |
65 | | * Initialize OVS: |
66 | | {{{ |
67 | | sudo ovs-vsctl --no-wait init |
68 | | }}} |
69 | | {{{ |
70 | | sudo ovs-vswitchd --pidfile --detach |
71 | | }}} |
72 | | Ignore the warnings you are going to see. Now that OVS is running it is time to create our software switch. The software switch will be a bridge, in which we are going to add all the interfaces we want to be part of the switch. |
| 54 | == 1. Configure the Software Switch == |
| 55 | Now that you are logged in, we need first to configure OVS. To save time in the tutorial we have already started OVS and we have added an ethernet bridge that will act as our software switch. Try: |
| 56 | {{{ |
| 57 | sudo ovs-vsctl list-br |
| 58 | }}} |
| 59 | You should see only on bridge `br0`. Now we need to add the interfaces to this bridge that will act as ports of our software switch. |
190 | | == Run a port deflection Controller == |
191 | | In the above example we ran a very simple 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. |
192 | | |
193 | | As a first exercise we are going to take advantage of OpenFlow's ability to rewrite the src or destination port, and we are going to have two servers on the same host listening on different ports and dynamically diverge the packets to a server by rewriting the destination TCP port. In order to do that do the following: |
194 | | 1. Open a second terminal on `host2` |
195 | | 2. On each terminal of `host2` run a netcat server on a different port: |
196 | | {{{ |
197 | | nc -l 5000 |
198 | | }}} |
199 | | {{{ |
200 | | nc -l 6000 |
201 | | }}} |
202 | | 3. On your OVS host: |
203 | | {{{ |
204 | | cd /tmp/pox/ext |
205 | | }}} |
206 | | 4. Open the port_deflection.py file, and edit it to implement a controller that will change the port on the packets and deflect traffic to host2 port 5000 to host2 port 6000. If you want to see the solution, its in file port_deflection_sol.py file. |
207 | | 5. Once you are done coding test your controller: |
208 | | {{{ |
209 | | cd /tmp/pox |
210 | | }}} |
211 | | {{{ |
212 | | pox.py port_deflection |
213 | | }}} |
214 | | 6. Go back to the terminal of `host1` and try to connect to `host2` port 5000 |
215 | | {{{ |
216 | | nc 10.10.1.2 5000 |
217 | | }}} |
218 | | If your controller works correctly you should see your text showing up on the terminal of `host2` port 6000. |
219 | | |
220 | | Congratulations, you wrote an OpenFlow controller! |
221 | | |
222 | | == Run a server deflection Controller == |
223 | | As a second 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. |
224 | | 1. Open a second terminal on `host3` |
225 | | 2. On the terminal of `host3` run a netcat server: |
226 | | {{{ |
227 | | nc -l 5000 |
228 | | }}} |
229 | | 3. On your OVS host open the server_deflection.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. |
| 170 | == Useful Tips for writing your controller == |
| 171 | In order to make this first experience of writing controller easier, we wrote some helpful functions that will abstract some of the particularities of PoX away. |
| 172 | These functions are locates at `/local/pox/ext/utils.py`, so while you write your controller consult this file for details. |
| 173 | |
| 174 | Functions that are implemented include: |
| 175 | * packetIsIP : Test if the packet is IP |
| 176 | * packetIsARP : Test if the packet is ARP |
| 177 | * packetIsRequestARP : Test if this is an ARP Request packet |
| 178 | * packetIsReplyARP : Test if this is an ARP Reply packet |
| 179 | * packetArpDstIp : Test what is the destination IP in an ARP packet |
| 180 | * packetArpSrcIp : Test what is the sources IP in an ARP packet |
| 181 | * packetIsTCP : Test if a packet is TCP |
| 182 | * packetDstIp : Test the destination IP of a packet |
| 183 | * packetSrcIp : Test the source IP of a packet |
| 184 | * packetDstTCPPort : Test the destination TCP port of a packet |
| 185 | * packetSrcTCPPort : Test the source TCP port of a packet |
| 186 | * createOFAction : Create one OpenFlow action |
| 187 | * getFullMatch : get the full match out of a packet |
| 188 | * createFlowMod : create a flow mod |
| 189 | * createArpRequest : Create an Arp Request for a different destination IP |
| 190 | * createArpReply : Create an Arp Reply for a different source IP |
| 191 | |
| 192 | == Run a traffic duplication controller == |
| 193 | In the above example we ran a very simple 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. Our hosts are VMs so we are going |
| 194 | to verify the duplication by doing a `tcpdump` on the port on the ovs switch. |
| 195 | |
| 196 | 1. Open two new terminals to the OVS switch. |
| 197 | |
| 198 | 2. Look at the sliver details page in the portal and see what interfaces are bound to OVS:if1 and OVS:if2, use the MAC address of the interface to figure this out. Run tcpdump on these interfaces; one in each of the new terminals you opened. This will allow you to see all traffic going out the interfaces |
| 199 | {{{ |
| 200 | sudo tcpdump -i <data_interface_name> |
| 201 | }}} |
| 202 | |
| 203 | 2. In the other ovs host go under the `/local/pox/ext` directory: |
| 204 | {{{ |
| 205 | cd ext |
| 206 | }}} |
| 207 | |
| 208 | 2. There you would see two files : |
| 209 | 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. |
| 210 | ii. !DuplicateTraffic.py : this has the actual solution you can just run this if you don't want to bother with writing a controller. |
| 211 | |
| 212 | To run the controller do (while at /local/pox directory) where the <data_interface_name> should be the one that corresponds to OVS:if2 : |
| 213 | {{{ |
| 214 | ./pox.py --verbose myDuplicateTraffic \ |
| 215 | --duplicate_port=<data_interface_name> |
| 216 | }}} |
| 217 | |
| 218 | To test it go to the terminal of host1 and try to ping host2: |
| 219 | {{{ |
| 220 | ping 10.10.1.2 |
| 221 | }}} |
| 222 | |
| 223 | |
| 224 | If your controller is working you the packets registering in both terminals that you run tcpdump. |
| 225 | |
| 226 | == Run a port forward Controller == |
| 227 | 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. |
| 228 | |
| 229 | Under the `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`. |
| 230 | |
| 231 | To run the controller do (while at /local/pox directory) |
| 232 | {{{ |
| 233 | ./pox.py --verbose myPortForwarding |
| 234 | }}} |
| 235 | |
| 236 | To test your controller we are going to use netcat. Go to the two terminals of host2. In one terminal run: |
| 237 | {{{ |
| 238 | nc -l 5000 |
| 239 | }}} |
| 240 | |
| 241 | and in the other terminal run |
| 242 | {{{ |
| 243 | nc -l 6000 |
| 244 | }}} |
| 245 | |
| 246 | Now first start the simple layer 2 forwarding controller: |
| 247 | {{{ |
| 248 | ovs:/local/pox% ./pox.py --verbose forwarding.l2_learning |
| 249 | }}} |
| 250 | |
| 251 | Go to the terminal of host1 and connect to host2 at port 5000: |
| 252 | {{{ |
| 253 | nc 10.10.1.2 5000 |
| 254 | }}} |
| 255 | |
| 256 | Type something and you should see it at the the terminal of host2 at port 5000. |
| 257 | |
| 258 | Start your controller and do the same, now your text should appear on the other terminal of host2. |
| 259 | |
| 260 | == Run a server proxy Controller == |
| 261 | 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. |
| 262 | |
| 263 | Under the `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 a configuration file at `ext/proxy.config`. |
| 264 | |
| 265 | 1. On the terminal of `host3` run a netcat server: |
| 266 | {{{ |
| 267 | nc -l 7000 |
| 268 | }}} |
| 269 | 2. On your OVS host open the server_deflection.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. |