So this is our second post about a learning Switch and as promised, it covers OpenFlow 1.3. Before we go into the details, this is what you should already know about SDN and OpenFlow:
- General SDN Paradigm, otherwise go and read this
- A common understanding about what OpenFlow is in contrast to SDN
- What a simple learning switch is
What we are discussing in this post is the simple switch implementation that comes out of the LINC – OpenFlow software switch project as well as some basic principals from the latest OpenFlow Protocol (OFP) specification made by the Open Networking Foundation (ONF). One of the most important things you should know about OFP 1.3.x is the so called “table pipe-lining”. In previous versions of OFP there was a FlowTable in an OpenFlow enabled switch and that table stored the logic of how traffic flows through the network. Furthermore, a SDN-Controller jumps into the game when a packet that arrives at the switch doesn’t match any of the entries in the FlowTable. If this happens, we call it a “table-miss” and the switch sends the packet to the SDN-Controller. Now consider the following: In OpenFlow 1.3.x you not only have one FlowTable in an OpenFlow enabled switch, but there are as many FlowTables as the switch supports and the process how this multiple FlowTables are handled by OpenFlow is called the “table pipe-lining”. The inital behaviour isn’t that much different. If the packet arrives at the switch, the packet is always compared to the FlowTableEntries in the first the – table-0.
If this table-0 contains a FlowTableEntry that matches against the packet, the instruction set of this packet will be updated, but not executed. There are different instructions defined in the OFP specification that can be applied but only two of them a switch must support:
- Write Action
- GOTO-next-table
When a packet matches a FlowTableEntry and this entry contains a write-action instruction but no goto instruction, the process of the table pipe-lining stops and the action from the write-action instruction is executed. That is usually an output-action. But if the entry also contains a goto instruction, the action-set of the packet will be updated. After this, the packet goes to the table specified by the goto instruction and the process starts again until there is no more goto instruction or the packet arrives at the last table-n. When one of this two events occurs, the complete action-set is executed. This process is visualized in the picture below.
Moreover, there can be some metadata added to the packet from table to table but that is material for a next post. The next thing we have to look at is the “table-miss” behavior in OFP1.3. In previous versions, when there was no matching FlowTableEntry for a packet, the packet was automatically sent to the SDN-Controller. In OFP1.3 the packet is dropped, yes right, you gonna loose it forever. What you have to do by yourself is to install a FlowTableEntry with an “empty-match” and a priority of “0”. Usually, this FlowTableEntry contains a write-action instruction with a output-action that points to the SDN-Controller. But of course, a more complex “table-miss” behavior is possible. That’s all you have to know for the learning OpenFlow 1.3 switch. For this we gonna use the code from the LINC switch as mentioned in the beginning of this post. You can find the code of the L2-switch here in the LINC-switch repository on GitHub. The code is written in python and can be used along with the RYU SDN-Controller.
The general structure of the L2 Switch application is as follows:
- The application can react to two OpenFlow events: OFPSwitchFeatures which is raised every time a new switch comes up and OFPPacketIn which is raised every time a packet hits a “table-miss” FlowEntry
- Four methods to send OFP messages, install_table_miss, install_src_entry, install_dst_entry and flood
- Some helper-methods for cleaner code
Every time a new switch appears, the OFPSwitchFeatures event is raised. The application installs in this method a table-miss FlowEntry in table-0 and table-1. The table-miss FlowEntry is as discussed before, a FlowTableEntry with an empty match and a priority of 0 – that is by the way the lowest existing priority. Now consider the following situtation: two hosts, host-1 and host-2, are connected to one switch and they want to start to communicate to each other. host-1 sends a ping to host-2:
- The packet arrives at the switch -> there is no matching FlowTableEntry for host-1 in table-0 thus, the table-miss entry will match and send the packet to the controller (OFPPacketIn)
- The controller checks if the packet is coming from table-0.
- If the packet is coming from table-0, the controller installs two FlowTableEntries. Keep in mind, that this packet contains two important information’s: The in_port and the MAC-address from host-1. The two Entries that will be installed are doing the following:
- Entry one is installed in table-0 and matches every packet that has the in-port and the Source-MAC-address from host-1. The only action is a GOTO-action to table-1.
- Entry two is installed in table-1 and matches every packet that has the Destination-MAC-address from host-1. The action for this entry is an output-action on the Port where host-1 is connected to.
- Since the controller doesn’t know the recipient host-2, the controller performs a flood of the packet
- host-2 receives the ping from host-1 and sends a response as answer of the ping.
- The packet arrives at the switch -> still, there is no matching FlowTableEntry for host-2 in table-0 thus, the the table-miss entry will match and send the packet to the controller (OFPPacketIn)
- The controller checks if the packet is coming from table-0. The controller performs the exact same steps as before but with the in-port and the MAC-address from host-2
- Entry one is installed in table-0 and matches every packet that has the in-port and the Source-MAC-address from host-2. The only action is a GOTO-action to table-1.
- Entry two is installed in table-1 and matches every packet that has the Destination-MAC-address from host-2. The action for this entry is an output-action on the Port where host-2 is connected to.
- Since the controller don’t know the recipient host-2, the controller performs a flood of the packet
- The controller checks if the packet is coming from table-0. The controller performs the exact same steps as before but with the in-port and the MAC-address from host-2
- If host-1 now sends a second packet to host-2, the FlowTableEntry in table-0 will match
- The FlowTableEntry that matches is the one who says: If the in-port and the Source-MAC-address is the one from host-1, GOTO table-1
- In table-1 is a FlowTableEntry that says: If the packet has the Destination-MAC-address of host-2, send it out on the port where host-2 is connected to
Discussion
In the simple learning switch from the previous blog post we had to store the MAC-address associated with the in-ports in a python-dict in the controller. This is not necessary anymore because this information is now stored in table-0 of the device itself. Furthermore there is a possibility to make a more complex processing of the packets. Table-0 can be seen as the table of the known hosts and table-1 contains the actual forwarding logic. If you want now to add some more changes to a packet like QoS settings, you can forward the packet first to a table that updates the instruction-set of the packet with QoS related actions. If this is done, add a GOTO-action to the table that applies the forwarding logic. The table pipe-lining gives the network-programmers a very powerful processing without asking every time the SDN-controller what kind of actions needs to be applied to it.
Whats next?
As usual, there are lot more things you should look at about OFP1.3. For instance the how the metadata information works that can be passed between the tables or which FlowTableEntry is applied if multiple Entries match in one table. The best thing at the moment is: Go and read the OFP specification and check out SDN applications build for OFP1.3 and learn by example. The SDN-controller and also SDN-applications the ICCLab can recommend is the RYU controller.
Thanks for the post. Very clear explanation. If possible, talk about QoS and Meter table of openflow 1.3 in a next post. Thanks.