From 9f4080595bebaccaac643286aaaae881fe0a7aa1 Mon Sep 17 00:00:00 2001 From: suresh Date: Fri, 16 Mar 2018 17:40:27 +0530 Subject: [PATCH] openflow readme added --- openflow_overview.md | 149 +++++++++++++++++++++ ryu-exercises/ex8_rest_api_integreation.py | 0 ryu-exercises/ex9_project1.py | 0 ryu_part1.md | 89 ++++++++++++ ryu_part10.md | 0 ryu_part2.md | 53 ++++++++ ryu_part3.md | 0 ryu_part4.md | 0 ryu_part5.md | 0 ryu_part6.md | 0 ryu_part7.md | 0 ryu_part8.md | 0 ryu_part9.md | 0 wireshark_traces/Openflow13_GoodMsg.pcapng | Bin 0 -> 62876 bytes 14 files changed, 291 insertions(+) create mode 100644 openflow_overview.md create mode 100644 ryu-exercises/ex8_rest_api_integreation.py create mode 100644 ryu-exercises/ex9_project1.py create mode 100644 ryu_part1.md create mode 100644 ryu_part10.md create mode 100644 ryu_part2.md create mode 100644 ryu_part3.md create mode 100644 ryu_part4.md create mode 100644 ryu_part5.md create mode 100644 ryu_part6.md create mode 100644 ryu_part7.md create mode 100644 ryu_part8.md create mode 100644 ryu_part9.md create mode 100644 wireshark_traces/Openflow13_GoodMsg.pcapng diff --git a/openflow_overview.md b/openflow_overview.md new file mode 100644 index 0000000..d26b345 --- /dev/null +++ b/openflow_overview.md @@ -0,0 +1,149 @@ +# How Traditional L2 Switch Works (Technical details) : + + +1. Traditional Switch have built in Control Plane + Data Plane. +2. Mac Table( a.k.a Forwarding table) is Empty when the switch starts. +3. Control Plane updates the Mac Table with the MAC and the PORT Number. This information is extracted from incoming Packet. +4. Control Plane keeps on building/updating the Mac Table. +5. When the packet arrives, Switch Data plane looks the Mac table, if the destination MAC matches in the Mac table, it forwards the packet to the respective Port. + + +# How SDN Switch(Openflow Switch) Works: + + +1. RYU L3 Application + +``` +ryu-manager ryu.app.simple_switch_13 +``` + + +2. Run the Linear Mininet Topology, + +``` +sudo mn --controller=remote,ip=127.0.0.1 --mac -i 10.1.1.0/24 --switch=ovsk,protocols=OpenFlow13 --topo=linear,4 +``` + + +3. Start Wireshark Capture + + +## overview + +1. Switch is configured with SDN Controller IP and Openflow protocol version. +2. Switch will establish the communication with SDN Controller. +3. Initialy the Switch flow table will be empty, When the Packet arrives Switch will send the packets to the Controller. +4. Controller build the Switch Logic with the packets. +5. Controller adds the Flow table to the switch. +6. Now, Switch data path is built with flows. So when the Packet arrive it will look the Flow table and forward the packet to respective port. + + + +# Openflow Messages in Detail: + + +## 1.Hello Message: + + a. Switch sends Openflow Hello Message(includes version number) to the Controller (port number 6653) + + b. Controller responds with the Hello Message if version is supported. + + Failure Case(Version MisMatch): + + If different Openflow Version is user between the Controller and Switch, Hello Message will fail. + + You will see similar error msg in the controller. + + Error: + unsupported version 0x1. If possible, set the switch to use one of the versions [3] + + +## 2.Features Request/Reply Message: + + 1.Controller will send the Feature Request Message to the Switch and asking for the Switch supported features. + + 2. Switch will reply with + datapath ID, buffers, tables size, + stats reporting : flow stats, port stats, table stats etc. + + +## 3.Port Desc/Status Message: + + 1. Controller will ask for the port description/ status message. + + 2. Switch will send the Port details of each port. + + +## 4. Packet In/Packet Out Message: + + 1. If Switch want to send a data packet to the Controller, it uses the PACKET IN message + + 2.Controller process the Packet in message, and decides what to do(which port to forward/ or drop etc) with this packet. + + 3. Controller respond with Packet Out Message with actions (FLOOD etc.) + + + +## 5. Flow Modification(add,delete) Message: + + 1. To add, remove, modify the flow in the switch, controller using this message. + 2. Controller Sends the Flow Modification message to the switch with this important params. + a. Command, + b. Match + c. Instruction, action. + + + At the time of switch starts(initial negotiatian), Controller adds TABLE MISS entry in to the switch. + + + ### Table Miss Entry: + + The flow entry that wildcards all fields (all fields omitted) and has priority equal to 0 is called the table-miss flow entry + + RYU installs the table miss entry to forward the packets to the controller port(action = output:Controller port). + + +## 6. Echo Request/Reply Message: + + To identify the liveliness of the Controller, Switch will send periodic health Check message to the Controller and expects the response. (default: 5sec interval) + + A. Switch sends Echo Request to the Controller. + + B. Controller responds back with Echo Reply. + + +## Statistics Message: + + 1. flow(individual,aggregate),table,port,queue stats message will send by the controller. + + 2. Switch will respond with the relavent statistics. + + This is used for monitoring the switches (with variour counter packets/sec, errors, etc) + + + +# Important Openvswitch Commands + +sudo ovs-vsctl show +sudo ovs-ofctl -O show +sudo ovs-ofctl -O OpenFlow13 show s1 +sudo ovs-ofctl -O Openflow13 dump-flows s1 + + + +# Take aways: + +1) Controller must use same Openflow version which switch uses. + +2) Our Controller Application(our RYU project/exercise) should process Packet IN (Message), to build the Switching/Routing logic. + +3) Our Controller Application(our RYU project/exercise) should use Flow Modifcation message to add/modify/delete the flows in the switch. + +4) Our Controller Application(our RYU project/exercise) should use Flow Stats, Port Stats request message to get the statistics(Packets Sent/Received , etc) of the flows, Ports . + + + +# References + +https://www.opennetworking.org/software-defined-standards/specifications/ +https://osrg.github.io/ryu/resources.html diff --git a/ryu-exercises/ex8_rest_api_integreation.py b/ryu-exercises/ex8_rest_api_integreation.py new file mode 100644 index 0000000..e69de29 diff --git a/ryu-exercises/ex9_project1.py b/ryu-exercises/ex9_project1.py new file mode 100644 index 0000000..e69de29 diff --git a/ryu_part1.md b/ryu_part1.md new file mode 100644 index 0000000..3d8aaba --- /dev/null +++ b/ryu_part1.md @@ -0,0 +1,89 @@ +RYU Basic Commands: +========================= + + +## 1. How to start the ryu controller + + +``` +ryu-manager + +``` + + +RYU Manager starts the application. +Check the running process details. + +ps -ef | grep ryu-manager + +RYU Manager listens on openflow ports(6653,6633) are in listening state. + +Check the port statistics + +netstat -ap | grep + + + + + + +## 2. How to stop the ryu controller + +``` +CTRL + C (Kill the Process) + +( or ) +pkill -9 ryu-manager + +``` + + + +## 3. RYU Controller command line options + + +``` +ryu-manager --help + +``` + +``` +ryu-manager --verbose + +``` + + +## 4. How to run the Application + +Example Application is installed in ryu/app folder. + +Specify the filename as ryu.app. + +Example: + + +``` +ryu-manager --verbose ryu.app.simple_switch_13 + +``` + +Download the file and run it. + + +``` +ryu-manager --verbose simple_switch_13.py + +``` + + + +# References + +https://en.wikipedia.org/wiki/OpenFlow + +http://ryu.readthedocs.io/en/latest/ + +https://osrg.github.io/ryu/resources.html + +https://github.com/osrg/ryu/tree/master/ryu + diff --git a/ryu_part10.md b/ryu_part10.md new file mode 100644 index 0000000..e69de29 diff --git a/ryu_part2.md b/ryu_part2.md new file mode 100644 index 0000000..5b54ffa --- /dev/null +++ b/ryu_part2.md @@ -0,0 +1,53 @@ +RYU Part2: +========= + +In this part , we are going to start writing the sample RYU applications step by step. + +I will be explaining the openflow protocol and openvswitch commands whereever required. + + + +Base Rule for beginners: +Please copy the example application file and modify as per your needs. + +In this ryu exercises, i am going to use Openflow 1.3 Version, and use simple_switch_13.py as example program to start with. + + +I copied the simple_switch_13.py file in ryu-projects folder. + + + +# RYU Programming Structure Overview : + + + + + + +# How to Implement Openflow L2 Switch in RYU : + + + + + + + + + + + +# Execute the Openflow L2 Switch : + + + + + +# References + +https://en.wikipedia.org/wiki/OpenFlow + +http://ryu.readthedocs.io/en/latest/ + +https://osrg.github.io/ryu/resources.html + +https://github.com/osrg/ryu/tree/master/ryu diff --git a/ryu_part3.md b/ryu_part3.md new file mode 100644 index 0000000..e69de29 diff --git a/ryu_part4.md b/ryu_part4.md new file mode 100644 index 0000000..e69de29 diff --git a/ryu_part5.md b/ryu_part5.md new file mode 100644 index 0000000..e69de29 diff --git a/ryu_part6.md b/ryu_part6.md new file mode 100644 index 0000000..e69de29 diff --git a/ryu_part7.md b/ryu_part7.md new file mode 100644 index 0000000..e69de29 diff --git a/ryu_part8.md b/ryu_part8.md new file mode 100644 index 0000000..e69de29 diff --git a/ryu_part9.md b/ryu_part9.md new file mode 100644 index 0000000..e69de29 diff --git a/wireshark_traces/Openflow13_GoodMsg.pcapng b/wireshark_traces/Openflow13_GoodMsg.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..f08a4cf8290876d260fc71241a7957fbaff74938 GIT binary patch literal 62876 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 literal 0 HcmV?d00001