Shortest Path + OpenFlow13



        Referring to and, I prepare a script that can find a shortest path from sender to receiver even when there is a loop in transmission environment . The openvswitch used in the mininet environment supports OpenFlow version 1.3.


[script— : put this file under ~/ryu/ryu/app]

# Copyright (C) 2011 Nippon Telegraph and Telephone Corporation.


# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at




# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,


# implied.

# See the License for the specific language governing permissions and

# limitations under the License.


from ryu.base import app_manager

from ryu.controller import mac_to_port

from ryu.controller import ofp_event

from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER

from ryu.controller.handler import set_ev_cls

from ryu.ofproto import ofproto_v1_3

from ryu.lib.mac import haddr_to_bin

from ryu.lib.packet import packet

from ryu.lib.packet import ethernet

from ryu.lib.packet import ether_types

from ryu.lib import mac


from ryu.topology.api import get_switch, get_link

from import ControllerBase

from ryu.topology import event, switches

import networkx as nx


class ProjectController(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]


    def __init__(self, *args, **kwargs):

        super(ProjectController, self).__init__(*args, **kwargs)

        self.mac_to_port = {}

        self.topology_api_app = self

        self.nodes = {}

        self.links = {}

        self.no_of_nodes = 0

        self.no_of_links = 0



    # Handy function that lists all attributes in the given object

    def ls(self,obj):

        print("\n".join([x for x in dir(obj) if x[0] != "_"]))


    def add_flow(self, datapath, in_port, dst, actions):

        ofproto = datapath.ofproto

        parser = datapath.ofproto_parser      

        match = datapath.ofproto_parser.OFPMatch(in_port=in_port, eth_dst=dst)

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] 

        mod = datapath.ofproto_parser.OFPFlowMod(

            datapath=datapath, match=match, cookie=0,

            command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0,

            priority=ofproto.OFP_DEFAULT_PRIORITY, instructions=inst)



    @set_ev_cls(ofp_event.EventOFPSwitchFeatures , CONFIG_DISPATCHER)

    def switch_features_handler(self , ev):

         print "switch_features_handler is called"

         datapath = ev.msg.datapath

         ofproto = datapath.ofproto

            parser = datapath.ofproto_parser

        match = parser.OFPMatch()

            actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, ofproto.OFPCML_NO_BUFFER)]

        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS , actions)]

            mod = datapath.ofproto_parser.OFPFlowMod(

        datapath=datapath, match=match, cookie=0,

        command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0, priority=0, instructions=inst)



    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)

    def _packet_in_handler(self, ev):

        msg = ev.msg

        datapath = msg.datapath

        ofproto = datapath.ofproto

        parser = datapath.ofproto_parser

        in_port = msg.match['in_port']


        pkt = packet.Packet(

        eth = pkt.get_protocol(ethernet.ethernet)


        dst = eth.dst

        src = eth.src

        dpid =

        self.mac_to_port.setdefault(dpid, {})

        #print "nodes"


        #print "edges"

        #print"packet in %s %s %s %s", dpid, src, dst, in_port)


        if src not in




        if dst in

            #print (src in

            #print nx.shortest_path(,1,4)

            #print nx.shortest_path(,4,1)

            #print nx.shortest_path(,src,4)






            out_port = ofproto.OFPP_FLOOD


        actions = [datapath.ofproto_parser.OFPActionOutput(out_port)]

        # install a flow to avoid packet_in next time

        if out_port != ofproto.OFPP_FLOOD:

            self.add_flow(datapath, in_port, dst, actions)


        out = datapath.ofproto_parser.OFPPacketOut(

            datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port,





    def get_topology_data(self, ev):

        switch_list = get_switch(self.topology_api_app, None)  

        switches=[ for switch in switch_list]


        print "**********List of switches"

        for switch in switch_list:

          print switch

          #self.nodes[self.no_of_nodes] = switch

          #self.no_of_nodes += 1


        links_list = get_link(self.topology_api_app, None)

        #print links_list

        links=[(link.src.dpid,link.dst.dpid,{'port':link.src.port_no}) for link in links_list]

        #print links

        links=[(link.dst.dpid,link.src.dpid,{'port':link.dst.port_no}) for link in links_list]

        #print links

        print "**********List of links"




1.      Open a terminal to start ryu controller


2.      Open another terminal to generate a tree topology.


3.      After creating the topology, we can see the nodes and links in ryu controller.


4.      h1 can ping h3


Dr. Chih-Heng Ke

Department of Computer Science and Information Engineering, National Quemoy University, Kinmen, Taiwan