So, Openflow doesn’t do shortest path forwarding? How can a network architecture NOT do shortest path forwarding? SDN is BS.

Yes, Openflow doesn’t do shortest path forwarding by itself, in fact, it doesn’t do anything by itself. Openflow is a tool that allows you to programmatically control your network devices.

However, it gives you the power to do it. In this post I’ll guide you through the development of a shortest-path forwarding network application using the RYU Controller and Openflow. Hopefully I’ll post a few thoughts on different forwarding schemes and Openflow.

For this tutorial, I’m assuming you are familiar with Openflow, Mininet and RYU. If you are not, go ahead and check this other posts. I’m using RYU, which is an OpenFlow Controller written in python with support to OpenFlow 1.3. To know more about it visit their website

To install RYU you can easily do pip install ryu and BOOM! If it doesn’t work you can try using the Mininet installation script with the -y option.

The network application will be organized in three blocks:

  • topology discovery
  • network view construction
  • forwarding

For the topology discovery we’ll use a RYU module/library called topology. For network view construction we’ll use an awesome python graph library called networkX. For forwarding we’ll use OpenFlow.

Topology discovery

First, let’s see how the topology discovery works on RYU. Go ahead and copy the simple_switch.py application, to a new file called sp.py. We’ll start from that. Now, import the topology module adding this:

from ryu.topology import event, switches
from ryu.topology.api import get_switch, get_link

Also add the following function at the end of the code.

@set_ev_cls(event.EventSwitchEnter)

The event EventSwitchEnter will trigger the activation of get_topology_data(). Next we call get_switch() to get the list of objects Switch, and get_link() to get the list of objects Link. This objects are defined in the topology.switches file. Then, we build a list with all the switches ([switches]) and next a list with all the links [(srcNode, dstNode, port)]. Notice that we also get the port from the source node that arrives at the destination node, as that information will be necessary later during the forwarding step.

Let’s go ahead and add a “print links” and “print switches” to get_topology_data() and see what happens. Start ryu, then start mininet. ATTENTION: make sure you run ryu-manager sp.py --observe-links. You should see something like this:

[1, 2, 3, 4]
[(2, 3, {'port': 3}), (3, 2, {'port': 2}), (3, 4, {'port': 3}), (2, 1, {'port': 2}), (4, 3, {'port': 2}), (1, 2, {'port': 2})]

If you forget to add the –observe-links option you will see something like this:

[1, 2, 3, 4]
[]

Now that topology discover is working we can move ahead and build a central view of the network.

Network view

To build the network view we will need the networkx library. To install it do: sudo pip install networkx They can do SEVERAL cool graph operations for you, you should check their documentation. First we’ll instantiated a Graph to represent the network adding this to the init function of our application:

self.net=nx.DiGraph()

Next we’ll update the graph every time we get topology data:

self.net.add_nodes_from(switches)
self.net.add_edges_from(links)

And BOOM! Now we have real-time info from our topology in the self.net. Also don’t forget to import networkx as nx.

Shortest path forwarding

The last step is the actual forwarding. This is the pseudo code for it.

If source MAC is unknown then learn it
If destination MAC is unknown then flood it.
If destination MAC is known then:
get shortest path
get next hop in path
get output port for next hop

The actual code is:

if src not in self.net: #Learn it
    self.net.add_node(src) # Add a node to the graph
    self.net.add_edge(src,dpid) # Add a link from the node to it's edge switch
    self.net.add_edge(dpid,src,{'port':msg.in_port})  # Add link from switch to node and make sure you are identifying the output port.
if dst in self.net:
    path=nx.shortest_path(self.net,src,dst) # get shortest path  
    next=path[path.index(dpid)+1] #get next hop
    out_port=self.net[dpid][next]['port'] get output port
else:
    out_port = ofproto.OFPP_FLOOD

The code is self explanatory, feel free to contact me if you have any doubts.

The full code for this application can be download from the following github repo: https://github.com/castroflavio/ryu.

To run the topology feature from RYU, make sure you run the controller as ryu-manager –observe-links shortestpath.py