Hi,

Thanks for sharing your app.

    @set_ev_cls(event.EventSwitchEnter)
    def get_topology_data(self, ev):
        global switches
switch_list = get_switch(self.topology_api_app, None) switches=[switch.dp.id for switch in switch_list]
        self.datapath_list=[switch.dp for switch in switch_list]
        #print "self.datapath_list=", self.datapath_list
        print "switches=", switches

        links_list = get_link(self.topology_api_app, None)
        print links_list

You tried to get all links in "EventSwitchEnter" handler, right?
At this time, I guess Ryu topology service does NOT yet discover links between
the connected switches. Links on a switch will be discovered after Ryu found
that switch.

Just my opinion, "get_link()" API is suitable for user triggered API calls,
implementing REST API or RPC API for example. On the other hand,
"EventLinkAdd" is suitable for this case because this event notifies Ryu apps
when links are discovered.

For example, the following updates a list of all links every time when link
found or lost.

    @set_ev_cls([topology_event.EventLinkAdd, topology_event.EventLinkDelete])
    def _event_link_handler(self, ev):
        links = get_link(self.topology_api_app, None)
        self.logger.info(links)
        my_links = [
            (link.src.dpid, link.dst.dpid, link.src.port_no, link.dst.port_no)
            for link in links
        ]
        for s1, s2, port1, port2 in my_links:
            adjacency[s1][s2] = port1
            adjacency[s2][s1] = port2
            self.logger.info(s1, s2, port1, port2)

Thanks,
Iwase


On 2018年03月06日 01:46, Myra Sh wrote:

I wrote the following simple code to see how RYU works. Based on the code, I can see the list of switches. However, the links between switches (wireless) are empty.





from ryu.base import app_manager
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.packet import ether_types
from ryu.topology import event
from ryu.topology.api import get_all_switch, get_all_link, get_switch, get_link
from ryu.lib import dpid as dpid_lib
from ryu.controller import dpset
from ryu.lib.packet import packet
from ryu.lib.packet import ethernet
from ryu.lib.packet import arp
from ryu.lib.packet import ipv4
from ryu.lib.packet import icmp
import copy
from ryu.topology.api import get_switch, get_link
from ryu.app.wsgi import ControllerBase
from ryu.topology import event, switches
from collections import defaultdict

#switches
switches = []
#mymac[srcmac]->(switch, port)
mymac={}
#adjacency map [sw1][sw2]->port from sw1 to sw2
adjacency=defaultdict(lambda:defaultdict(lambda:None))

class SimpleSwitch13(app_manager.RyuApp):
     OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

     def __init__(self, *args, **kwargs):
         super(SimpleSwitch13, self).__init__(*args, **kwargs)
         self.mac_to_port = {}
         self.topology_api_app = self
         self.datapath_list=[]


     @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
     def switch_features_handler(self, ev):
self.logger.info <http://self.logger.info>("RYU received 
EventOFPSwitchFeatures")
         #ev.msg: the instance of openflow message class corresponding to the 
event
         datapath = ev.msg.datapath #the instance of datapath
         ofproto = datapath.ofproto
         parser = datapath.ofproto_parser
         match = parser.OFPMatch() #match all packets
         #OFPActionOutput:out_port to the controller
         actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                           ofproto.OFPCML_NO_BUFFER)]


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

         mod = parser.OFPFlowMod(datapath=datapath, priority=0,
                                 match=match, instructions=inst)
         datapath.send_msg(mod)

     #    self.add_flow(datapath, 0, match, actions)
        #table-miss flow entry has the lowest (0)priority and this entry matches all packets


     @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
        # get the received port number
         in_port = msg.match['in_port']
     #    print in_port

         pkt = packet.Packet(msg.data)
         eth = pkt.get_protocols(ethernet.ethernet)[0]

         if eth.ethertype == ether_types.ETH_TYPE_LLDP:
             # ignore lldp packet
             return
         dst = eth.dst
         src = eth.src
     #    print eth.ethertype
         dpid = datapath.id <http://datapath.id>
         self.mac_to_port.setdefault(dpid, {})
      #   print self.mac_to_port
self.logger.info <http://self.logger.info>("packet in %s %s %s %s", dpid, src, dst, in_port)


         # learn a mac address to avoid FLOOD next time.
         self.mac_to_port[dpid][src] = in_port
      #   print self.mac_to_port

        #if the destination mac address is already learned, decide
        #which port to output the packet, otherwise FLOOD

         if dst in self.mac_to_port[dpid]:
             out_port = self.mac_to_port[dpid][dst]
         else:
             out_port = ofproto.OFPP_FLOOD

         actions = [parser.OFPActionOutput(out_port)]


     @set_ev_cls(event.EventSwitchEnter)
     def get_topology_data(self, ev):
         global switches
         switch_list = get_switch(self.topology_api_app, None)
         switches=[switch.dp.id <http://switch.dp.id> for switch in switch_list]
         self.datapath_list=[switch.dp for switch in switch_list]
         #print "self.datapath_list=", self.datapath_list
         print "switches=", switches

links_list = get_link(self.topology_api_app, None)
         print links_list
mylinks=[(link.src.dpid,link.dst.dpid,link.src.port_no,link.dst.port_no) for link in links_list]
         for s1,s2,port1,port2 in mylinks:
           adjacency[s1][s2]=port1
           adjacency[s2][s1]=port2
           print s1,s2,port1,port2


On Sun, Mar 4, 2018 at 9:40 PM, Iwase Yusuke <iwase.yusu...@gmail.com <mailto:iwase.yusu...@gmail.com>> wrote:

    Hi,

    When (or in which handler) do you call "get_link()" API?
    Early point of starting up? For example, in your app's "__init__()" or
    "switch_features_handler()", topology service could not yet discover links.
    To discover all links, it will take some seconds and you need to wait for 
it.

    For another approach, how about using "EventLinkAdd" or "EventLinkDelete" to
    catch new links?
    
https://github.com/osrg/ryu/blob/8a48b62c90745e8112bb3f7277e8ac46dabb3e4e/ryu/topology/event.py#L104-L111
    
<https://github.com/osrg/ryu/blob/8a48b62c90745e8112bb3f7277e8ac46dabb3e4e/ryu/topology/event.py#L104-L111>

    Thanks,
    Iwase


    On 2018年03月05日 10:24, Myra Sh wrote:

        Thank you for your reply.

        I added the same code. However, I only can see the list of switches and
        the list of links is empty (Links between switches are wireless.)

        I used the following lines to see links.

                  links_list = get_link(self.topology_api_app, None)
                  print links_list

        Do you have any suggestion to fix the problem?

        Thank you

        On Thu, Mar 1, 2018 at 9:06 PM, Iwase Yusuke <iwase.yusu...@gmail.com
        <mailto:iwase.yusu...@gmail.com> <mailto:iwase.yusu...@gmail.com
        <mailto:iwase.yusu...@gmail.com>>> wrote:

             Hi,

             You can enables the LLDP topology discovery feature, provided by
        "ryu.topology"
             module, to discover switches (and hosts) on your topology.
        https://github.com/osrg/ryu/blob/master/ryu/topology/api.py
        <https://github.com/osrg/ryu/blob/master/ryu/topology/api.py>
             <https://github.com/osrg/ryu/blob/master/ryu/topology/api.py
        <https://github.com/osrg/ryu/blob/master/ryu/topology/api.py>>
        https://github.com/osrg/ryu/blob/master/ryu/topology/event.py
        <https://github.com/osrg/ryu/blob/master/ryu/topology/event.py>
             <https://github.com/osrg/ryu/blob/master/ryu/topology/event.py
        <https://github.com/osrg/ryu/blob/master/ryu/topology/event.py>>

             =================
             ...(snip)...
             from ryu.topology import api as topology_api
             from ryu.topology import event as topology_event


             class MyApp(app_manager.RyuApp):

                  def my_handler(self, ...):
                      ...(snip)...
                      switches = topology_api.get_all_switch(self)
                      ...(snip)...

                  @set_ev_cls(topology_event.EventSwitchEnter)
                  def _switch_enter_handler(self, ev):
        self.logger.info <http://self.logger.info>
        <http://self.logger.info>("switch connected: %s", ev.switch)

                      ...(snip)...
             =================

             Please note to enable Ryu's topology discovery service, please 
specify
             "--observe-links" option to "ryu-manager".

             $ ryu-manager --help
                ...(snip)...
                --observe-links       observe link discovery events.
                ...(snip)...


             Thanks,
             Iwase


             On 2018年03月02日 05:13, Myra Sh wrote:


                 Hello,

                 I am new to Ryu controller. I have a wireless network with two
                 openvswitch(running on wireless nodes) both of them connected
        to Ryu.

                 Could you guide me how to enable topology discovery for this
                 wireless network in Ryu?

                 Using other SDN controllers, after connecting Openvswitches to 
the
                 controller, LLDP messages are exchanged between nodes in the
        network. Do
                 I need to activate LLDP messages manually in Ryu?

                 Thank you


------------------------------------------------------------------------------
                 Check out the vibrant tech community on one of the world's most
                 engaging tech sites, Slashdot.org! http://sdm.link/slashdot



                 _______________________________________________
                 Ryu-devel mailing list
        Ryu-devel@lists.sourceforge.net <mailto:Ryu-devel@lists.sourceforge.net>
        <mailto:Ryu-devel@lists.sourceforge.net
        <mailto:Ryu-devel@lists.sourceforge.net>>
        https://lists.sourceforge.net/lists/listinfo/ryu-devel
        <https://lists.sourceforge.net/lists/listinfo/ryu-devel>
                 <https://lists.sourceforge.net/lists/listinfo/ryu-devel
        <https://lists.sourceforge.net/lists/listinfo/ryu-devel>>




        
------------------------------------------------------------------------------
        Check out the vibrant tech community on one of the world's most
        engaging tech sites, Slashdot.org! http://sdm.link/slashdot



        _______________________________________________
        Ryu-devel mailing list
        Ryu-devel@lists.sourceforge.net <mailto:Ryu-devel@lists.sourceforge.net>
        https://lists.sourceforge.net/lists/listinfo/ryu-devel
        <https://lists.sourceforge.net/lists/listinfo/ryu-devel>




------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot



_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
Ryu-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to