| 282 | |
| 283 | |
| 284 | {{{ |
| 285 | OpenFlow on RPi |
| 286 | Li Lin, Regina Hain |
| 287 | |
| 288 | The goal of this work is to run an OpenFlow controller on a raspberry pi. |
| 289 | To do so, we used Open vSwitch to configure the virtual switches on the |
| 290 | pi server and Ryu to run the controller and to inject custom flows. |
| 291 | |
| 292 | There are three major pieces of this project: |
| 293 | 1. Use OVS to setup a useful and interesting network |
| 294 | 2. Run a custom script with the Ryu controller to install flows and route packets |
| 295 | 3. Demoing the system with a streaming webcam application |
| 296 | |
| 297 | ==Part I: Using OVS to set up a useful and interesting network== |
| 298 | |
| 299 | =Topology= |
| 300 | _______________________________________________________________________ |
| 301 | |Pi Server | |
| 302 | | ____________ _______________ _______________ | |
| 303 | | | BR1 | | BR2 | | BR3 | | |
| 304 | | | 10.10.1.1 | PP* | 10.10.2.1 | PP* | 10.10.3.1 | | |
| 305 | | | 2|-------|2 3|-------|2 | | |
| 306 | | |_____1______| |______1________| |______1________| | |
| 307 | | _____|______ ______|________ ______|________ | |
| 308 | | |eth1 | |eth2 | |eth3 | | |
| 309 | | |10.10.1.x | |10.10.2.x | |10.10.3.x | | |
| 310 | | |____________| |_______________| |_______________| | |
| 311 | | | | | | |
| 312 | | | | | | |
| 313 | |________|_____________________|_______________________|________________| |
| 314 | | | | |
| 315 | _____|______ ______|________ ______|________ |
| 316 | | Pi1 | | Pi2 | | Pi3 | |
| 317 | | 10.10.1.2 | | 10.10.2.2 | | 10.10.3.2 | |
| 318 | |____________| |_______________| |_______________| |
| 319 | |
| 320 | |
| 321 | *: PP means patch port |
| 322 | |
| 323 | =Description= |
| 324 | This setup consists of 4 pi's- one acting as a server 3 as the clients. |
| 325 | There are 3 accompanying interfaces on the server- eth1, eth2, eth3, each |
| 326 | their own subnet. Additionally, each is connected to a separate OVS bridge. |
| 327 | The OVS bridges forward packets to all other bridges via patch ports. |
| 328 | |
| 329 | =Setup on server= |
| 330 | To configure this network, run configure_pt1 |
| 331 | |
| 332 | =Setup on client= |
| 333 | To configure the ip address of client pi's, add the following |
| 334 | lines to /etc/dhcpcd.conf depending on its ip address and router values |
| 335 | |
| 336 | # In pi1 /etc/dhcpcd.conf |
| 337 | interface eth0 |
| 338 | static ip_address=10.10.1.2/24 |
| 339 | static router=10.10.1.1 |
| 340 | |
| 341 | # In pi2 /etc/dhcpcd.conf |
| 342 | interface eth0 |
| 343 | static ip_address=10.10.2.2/24 |
| 344 | static router=10.10.2.1 |
| 345 | |
| 346 | |
| 347 | # In pi3 /etc/dhcpcd.conf |
| 348 | interface eth0 |
| 349 | static ip_address=10.10.3.2/24 |
| 350 | static router=10.10.3.1 |
| 351 | |
| 352 | =Test= |
| 353 | To test, run ping from one client Pi to another client Pi. Connectivity |
| 354 | should be present, via the OVS bridge and patch port topology, between |
| 355 | all three client Pi's. |
| 356 | |
| 357 | =Teardown= |
| 358 | To teardown this network, run teardown_pt1 |
| 359 | |
| 360 | |
| 361 | ==Part II: Using Ryu to install flows and route packets over our OVS network== |
| 362 | |
| 363 | =Topology= |
| 364 | _______________________________________________________________________ |
| 365 | |Pi Server | |
| 366 | | ____________________________________________________________ | |
| 367 | | | BR1 | | |
| 368 | | | 10.10.1.10 | | |
| 369 | | | | | |
| 370 | | |_____1_____________________3_______________________2________| | |
| 371 | | _____|______ ______|________ ______|________ | |
| 372 | | |eth1 | |eth2 | |eth3 | | |
| 373 | | |10.10.1.1 | |10.10.1.3 | |10.10.1.2 | | |
| 374 | | |____________| |_______________| |_______________| | |
| 375 | | | | | | |
| 376 | | | | | | |
| 377 | |________|_____________________|_______________________|________________| |
| 378 | | | | |
| 379 | _____|______ ______|________ ______|________ |
| 380 | | Pi1 | | Pi2 | | Pi3 | |
| 381 | | 10.10.1.4 | | 10.10.1.5 | | 10.10.1.6 | |
| 382 | |____________| |_______________| |_______________| |
| 383 | |
| 384 | Note that this topology is different from that in part I. This is because |
| 385 | having 3 bridges added too much unneeded complexity when crafting custom |
| 386 | flows. This time we used 1 bridge to connect all three interfaces and |
| 387 | connecting them up through separate ports. |
| 388 | |
| 389 | =RYU Script Description= |
| 390 | |
| 391 | This script creates a custom flow that matches on any packet coming in |
| 392 | on port 1 (source 10.10.1.4) and out on port 3 (destination 10.10.1.5). |
| 393 | It forwards that packet as usual, but also |
| 394 | creates a duplicate packet, modifies its destination (to the address |
| 395 | of pi3) and sends to port 2 (pi 3). The result is that pi3 gets a copy |
| 396 | of every packet that is sent from pi1 to pi2. |
| 397 | |
| 398 | Note that to turn on the special flow, *insert_special_flow* must be set to |
| 399 | True in ryu_13_custom.py |
| 400 | |
| 401 | To see that the custom flow is installed correctly (note that installation |
| 402 | will occur only on the first instance of a packet with source 10.10.1.4 |
| 403 | and destination 10.10.1.5 captured by our controller), on the server type |
| 404 | $ sudo ovs-ofctl dump-flows br1 |
| 405 | |
| 406 | |
| 407 | =Setup= |
| 408 | To configure this network, run configure_pt2 |
| 409 | Note that step 5, connecting the controller to the bridge, takes the |
| 410 | ip address of the server's eth0 interface. This can change based on |
| 411 | network and pi. To find the correct ip address to use, in a terminal type |
| 412 | $ ifconfig -a |
| 413 | |
| 414 | =Run= |
| 415 | To run the ryu controller with our custom script type: |
| 416 | $ ryu-manager ./path/to/ryu_13_custom.py |
| 417 | To ensure controller connectivity type: |
| 418 | $ sudo ovs-vsctl show |
| 419 | and you should see something like this (if connected): |
| 420 | Bridge "br1" |
| 421 | Controller "tcp:128.89.68.110:6633" |
| 422 | is_connected: true |
| 423 | |
| 424 | =Testing= |
| 425 | |
| 426 | Ping test |
| 427 | On 10.10.1.4 (pi1) type |
| 428 | $ ping 10.10.1.5 |
| 429 | You will see that 2 different hosts will reply to the pings- both |
| 430 | pi2 (10.10.1.5) and pi3 (10.10.1.6). |
| 431 | |
| 432 | Netcat test |
| 433 | On 10.10.1.5 (pi2) type |
| 434 | $ nc -l 1234 |
| 435 | On 10.10.1.6 (pi3) type |
| 436 | $ nc -l 1234 |
| 437 | On 10.10.1.4 (pi1) type |
| 438 | $ echo "HELLO WORLD" | nc 10.10.1.5 1234 -u |
| 439 | |
| 440 | You should see that HELLO WORLD should be printed on both pi2 and pi3. |
| 441 | This only works in udp mode (-u) and the reason is left as an |
| 442 | exercise for the reader. |
| 443 | |
| 444 | =Teardown= |
| 445 | To teardown this network, run teardown_pt2 |
| 446 | |
| 447 | |
| 448 | ==Part III: Demoing via a streaming webcam application== |
| 449 | |
| 450 | In this demo, pi1 (10.10.1.4) will send raw video bytes captured from |
| 451 | its webcam to pi2 (10.10.1.5) via the netcat application. Pi2 will capture |
| 452 | the udp packets by using netcat to listen on a specified port and save |
| 453 | the data to a pipe file. Pi2 will then run mplayer on the file to output the |
| 454 | video to screen. Pi3 will perform the same exact functions as Pi2, and |
| 455 | since the controller sends a duplicate copy of every udp packet to Pi3, |
| 456 | it can receive and render the webcam video also. |
| 457 | |
| 458 | On Pi1: |
| 459 | 1. Compile the C file used to read data from the webcam |
| 460 | $ gcc capturevideo.c -o capturevideo |
| 461 | 2. Execute and pipe the output to 10.10.1.5 via netcat |
| 462 | $ ./capturevideo -c 1000 -o | nc 10.10.1.5 5000 |
| 463 | *. Instructions and code taken from: https://www.raspberrypi.org/forums/viewtopic.php?t=98778&p=685576 |
| 464 | |
| 465 | On Pi2: |
| 466 | 1. If not installed already, install mplayer |
| 467 | $ sudo apt-get install mplayer |
| 468 | 2. Create a pipe file |
| 469 | $ mkfifo video.fifo |
| 470 | 3. Call netcat and listen to specified port |
| 471 | $ nc.traditional -lu -p 5000 > video.fifo |
| 472 | 4. Use mplayer to open video |
| 473 | $ mplayer video.fifo -demuxer rawvideo -rawvideo w=640:h=480:format=yuy2 |
| 474 | |
| 475 | On Pi3: |
| 476 | 1. If not installed already, install mplayer |
| 477 | $ sudo apt-get install mplayer |
| 478 | 2. Create a pipe file |
| 479 | $ mkfifo video.fifo |
| 480 | 3. Call tcpdump to listen to specified port |
| 481 | $ sudo tcpdump -i eth0 udp port 5000 -w video.fifo |
| 482 | Note: Netcat will not accept packets because it requires a connection, |
| 483 | even when solely listening for udp packets, when the datagram size is over |
| 484 | 1500 bytes. |
| 485 | 4. Use mplayer to open video |
| 486 | $ mplayer video.fifo -demuxer rawvideo -rawvideo w=640:h=480:format=yuy2 |
| 487 | }}} |
| 488 | |