Skip to content

Topology Discovery with Ryu

How can be openflow used to do topology discovery? Why would you want to do that?

You might be interest in doing topology discovery on your topology for multiple reasons such as applying custom forwarding strategies from a centralized global view of the network. You may want something simple like running spanning tree or you may want to run shortest path forwarding. OpenFlow gives you the power to do that or even harder things.

SDN controllers can capitalize on the centralized view of the network and perform all kinds of operations such as pre-computing and installing backup paths.*

In this tutorial I’ll briefly describe the topology discovery module of the RYU controller and guide you through the development of a very naive application to print the information of the network.

The dependencies for this tutorial are:

  • Mininet 2.1 (If you haven’t installed it yet, follow this link or get the original installation instructions from this link)
  • Ryu (If you haven’t installed it yet, follow this link)
  • OpenVSwitch 2.0 (If you haven’t installed it yet, follow this link)

Copy the application from RYU to a new file called We’ll start from that:

cd ryu/ryu/app/  

Now, import the topology module adding this two lines:

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.

    def get_topology_data(self, ev):
    switch_list = get_switch(self.topology_api_app, None)
    switches=[ for switch in switch_list]
    links_list = get_link(self.topology_api_app, None)
    links=[(link.src.dpid,link.dst.dpid,{'port':link.src.port_no}) for link in links_list]

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.

Let’s test it:
Start ryu, then start mininet. ATTENTION: make sure you run ryu-manager --observe-links. The –observe-links option will turn on the topology RYU app. 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 do lot’s of cool stuff with it, such as build a central view of the network using a library and then run shortest path forwarding, for example.

Published inRYUSDN


  1. abhi abhi

    i have done exactly the same thing, but it is showing
    AttributeError: ‘SimpleSwitch’ object has no attribute ‘topology_api_app’

      • abhi abhi

        yes it is working, thanks.

      • abhi abhi

        hey form your code i got an idea, what i am doing is storing the information of new links created in a text file but i don,t know how to proceed further, can you help me, this is the code.

        def dictify network(self, src, dst):
        for line in fi:
        return nx.shortest_path(G,”dpid=”+str(src),”dpid=”+str(dst))

  2. Anonymous Anonymous

    yes, all given above

  3. Nicolai Nicolai

    Sorry, i have an error object has no attribute ‘topology_api_app’ , how to fix it? previous answer has not helped

  4. Nicolai Nicolai

    Why the value of links empty?

  5. Aiman Aiman

    Thanks a lot, I need to simulate precomouting and installing backup paths , Any help with this would be very very appreciated. thanks again

  6. Ben Ben

    I have the same problem as Nicolai.. The link list is always empty. I have tried many differennt things, but could not get it running correctly.

    What I tried was:

    1) starting the app with different position of –observe-links
    2) using the Zodiac FX and Raspberry PIs to set up a topology
    3) using the OpenVswitch for simulated switch and topology
    4) adding the described lines from above to the code and using the example provided by the author above (

    All this results in a given datapathID for the switch and an empty links list.. You can find my problems described with more details here:

    Any help is very appreciated!


  7. Hi Ben and Nicolai. I’m troubleshooting this application again. I find that for whatever reason, now the application works better when starting ryu after starting mininet.

    • samuel samuel

      Yes, I also found this problem. It seems that only when ryu is started after starting the mininet, then the link data can be collected. I wonder what causes this problem?

  8. Ben Ben


    Thanks for checking again! In my current setup (topology discrovery of a ring topology with 4 zodiac fx openflow switches) the above code works fine and I usually start Ryu after

    What would have really saved much time in my troubleshouting: Mention in your tutorial, that a link is only a connection between switches and NOT a connection between a host and a switch. I was trying to get link info from Ryu with a topology that unfortunately had no links in it.. (I guess it is a networking beginner fault.)

    PS: Is there a way to get the information from a link, that detemines which port on a switch is connected to which (other) switch. So if there is a link between switch A and switch B, I want to know which port on switch A is connected switch B. This is very important for routing and there has to be a way, but I dont see it at the moment.


    • There’s definitely a way.

      Otherwise I wouldn’t be able to do routing. Take a look at my shortest path code/post. I don’t remember now how is it. But I’ll get back to you.

      Can I ask you something. Is the zodiac FX hardware assisted OF forwarding? Or is all of it in software?

      Flavio Castro

  9. The Zodiac FX is a hardware device but all OpenFlow processing is done in software.

  10. Anonymous Anonymous

    Hi Flavio Castro,

    I also debugged your code for shortestpath (because I am interested in your routing strategy).

    Seems that line 115 (next=path[path.index(dpid)+1]) does not work properly, because the bounds of the path list are not checked before.
    I tried this:

    # …

    path_length = nx.shortest_path_length(,src,dst)

    if path_length != 0:

    # …

    and sent ARP, IGMP and UDP packets, which did not work, as the out_port is never be written, because the calculated path is either 00:00:00:00:00:00 (path_length = 0), or the dst was not known. Maybe an end-to-end connection for example with TCP would work.

    I dont understand this line (which I think is the critical part of the routing, as it extracts the port info for the link):[dpid][next][‘port’]

    Also, this line only works for OpenFlow 1.0. I need it for OpenFlow 1.3. Do you know how the equivalent could look like?


  11. Thanks for your comments.

    I have not tested this for OF 1.3.

    Regarding line 115, what is the topology you are trying to run when that fails? Is that for OF 1.3 or 1.0?

    the net data structure is a dictionary organized in the following way.
    { switch1: {
    neighbor1: {
    ‘port’: port }

    You can obtain all the links for given switch by reading its neighbors, the port represents the output port that connects the switch to the neighbor.

    What does it mean to have a path length 0 for you?

    If a destination is unknown, then we will flood the packet.

  12. Ben Ben


    thanks for your answer!

    I tried your OpenFlow 1.0 app with OpenFlow 1.3 switches. This is the resulting error:

    Error in the datapath 000070b3d56cd425 from (‘’, 49197)
    hub: uncaught exception: Traceback (most recent call last):
    File “/usr/local/lib/python2.7/dist-packages/ryu/lib/”, line 54, in _launch
    return func(*args, **kwargs)
    File “/usr/local/lib/python2.7/dist-packages/ryu/controller/”, line 447, in datapath_connection_factory
    File “/usr/local/lib/python2.7/dist-packages/ryu/controller/”, line 365, in serve
    File “/usr/local/lib/python2.7/dist-packages/ryu/controller/”, line 129, in deactivate
    File “/usr/local/lib/python2.7/dist-packages/ryu/controller/”, line 269, in _recv_loop
    File “/usr/local/lib/python2.7/dist-packages/ryu/controller/”, line 205, in switch_features_handler
    datapath.ports = msg.ports
    AttributeError: ‘OFPSwitchFeatures’ object has no attribute ‘ports’

    Thank you for clarifying. So you are kind of mixing the “learning switch”
    approach (learn src; if dst known forward to port otherwise flood) with the
    topology information you receive from Ryu’s topology API and you use the topo API
    only for calculating the shortest path. Am I right?

    Your approach will not work for me (I think), as I am interested in directly
    forwarding UDP traffic (unidirectional, multicast), so I will never be able to
    “learn” the path to my dst, as the dst will never be the src for another packet
    (it could be, but this is not sure).. I had a look at the LLDP packets that are
    automatically sent by the ryu topology api, when starting a controller with the
    –observe-links option and it seems, that this packets clearly provide the port
    info for a link.. I’m wondering why this info is not available through the Ryu
    topology API. Do I really have to parse the LLDP packets manually? 🙁 (Ryu also
    parses them for the link info)

    I think path length 0 means that src == dst = true. if this is the case, your
    path is empty, so this line (115)


    is likely to fail, or is python preventing this? (Im pretty new to python..)

    PS: To make things worse, my topology is a ring topology of 4 3-port switches
    (zodiac fx with 2 links and 1 host (raspberry pi) respectively) 😉

    Best regards,

  13. Ben Ben

    PSPS: When I change the version of your app to OF1.3 (by changing OFP_VERSIONS = [ofproto_v1_0.OFP_VERSION] to OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]) the error looks like this:

    ProjectController: Exception occurred during handler processing. Backtrace from offending handler [_packet_in_handler] servicing event [EventOFPPacketIn] follows.
    Traceback (most recent call last):
    File “/usr/local/lib/python2.7/dist-packages/ryu/base/”, line 290, in _event_loop
    File “/home/ben/masterthesis/ryu_code/”, line 76, in _packet_in_handler,src,{‘port’:msg.in_port})
    AttributeError: ‘OFPPacketIn’ object has no attribute ‘in_port’

    The error in the last post was with OF1.0 (app)

  14. Okay.

    My first suggestion is not to develop the application using the zodiacFX. If you develop the app using software switches you end up isolating hardware bugs.

    After the application works, then you move to the hardware.

    Would you elaborate better on your use case? If you are not learning, then you need to pre-configure the network. In other words, you have to tell the SDN controller where each network is connected.

  15. Hi,

    I’m currently doing my masterthesis with the topic “Evaluation of SDN Methods for Distributed Industrial Automation Systems”. I am especially interested in UDP multicast traffic, which is directly routed with the topology information (ring network) without flooding or learning. Therefore I use IGMP (for host discovery and multicast group membership management) and LLDP (for link discovery). No other traffic will be forwarded in my small experimental setup, which contains 4 openflow enabled switches and 4 hosts. My topology is static, but it is dynamically discovered and the controller can also handle topology changes.

    I started to parse the LLDP manually, because Ryu’s topology information on links is not sufficient for my use case, as it does not contain explicit port information.


  16. I wouldn’t parse LLDP manually.

    I can get the port information just fine. I’d recommend spend more time experimenting with RYU and figure out how to get the OF information.

  17. Ben Ben

    Thanks for the advice!

    I had a look at the topology discovery API again. I thought the link passed by an ‘EventLinkxxx’ event contains src and dst of type ryu.topology.switches.Switch, but it actually does not contain Switches, but ports (ryu.topology.switches.Port), that are connected by the link. I think I was a little confused 😉


  18. Anonymous Anonymous

    I am also facing the same issue:
    AttributeError: ‘SimpleSwitch’ object has no attribute ‘topology_api_app’

    How to resolve this issue?

  19. Anonymous Anonymous

    I got this error: AttributeError: ‘SimpleSwitch’ object has no attribute ‘topology_api_app’

    I believe in the init you need to add
    self.topology_api_app = self

  20. Edison de Queiroz Albuquerque Edison de Queiroz Albuquerque

    iside __init__ I wrote “self.topology_api_app = self”. this belongs to but is missing in “ After I did it, the program ran, but it is still missing the links.
    I’ll work on that. If I find the answer I’ll share.

  21. Edison de Queiroz Albuquerque Edison de Queiroz Albuquerque

    the first test I made was with mininet and a single switch.
    the I use a network of 3 switches, tree topology, and the links appeared.
    I was expecting to see links from switch to host, but the links are only from switch to switch.
    Hope this helps somebody.

  22. Khubaib Khubaib

    It doesn’t work for OpenFlow1.5

    You get data on the switches, but not the links. Anyone know how to do it (I had to make some changes to ryu/topology/ to incorporate v1.5, perhaps more are required?)

  23. sh sh

    Can I use the topology discovery in Ryu for wireless networks? How?

  24. HusaynS HusaynS

    How can I use topology discover module to identify legacy routers as well in my network. Im working on Hybrid SDN where I have to route traffic between two SDN switches connected to a router.

  25. I believe the topology discover uses LLDP, thus it should be able to identify other routers as well.

  26. Madiha Mateen Madiha Mateen

    I am using RYU controller for my link recovery use case. Ryu have Topology discovery module . My topology is fat tree. Topology discovery module is initiating but not getting the topology and its links. Ping between hosts is not successful. Any help on this would be appreciated.
    Thank You

Leave a Reply

Your email address will not be published. Required fields are marked *