Hi

I add --observe-hosts option to ryu-manager

Here is new patch

Signed-off-by: Takeshi <[email protected]>
---
 ryu/topology/api.py      |  7 +++++
 ryu/topology/event.py    | 23 ++++++++++++++++
 ryu/topology/switches.py | 71
++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/ryu/topology/api.py b/ryu/topology/api.py
index 7485a8e..aa8a09f 100644
--- a/ryu/topology/api.py
+++ b/ryu/topology/api.py
@@ -34,5 +34,12 @@ def get_link(app, dpid=None):
 def get_all_link(app):
     return get_link(app)

+def get_host(app, dpid=None):
+    rep = app.send_request(event.EventHostRequest(dpid))
+    return rep.hosts
+
+def get_all_hosts(app):
+    return get_host(app)
+

 app_manager.require_app('ryu.topology.switches', api_style=True)
diff --git a/ryu/topology/event.py b/ryu/topology/event.py
index bd87ab0..17fcf94 100644
--- a/ryu/topology/event.py
+++ b/ryu/topology/event.py
@@ -126,3 +126,26 @@ class EventLinkReply(event.EventReplyBase):
     def __str__(self):
         return 'EventLinkReply<dst=%s, dpid=%s, links=%s>' % \
             (self.dst, self.dpid, len(self.links))
+
+
+
+class EventHostRequest(event.EventRequestBase):
+    # If dpid is None, reply all list
+    def __init__(self, dpid=None):
+        super(EventHostRequest, self).__init__()
+        self.dst = 'switches'
+        self.dpid = dpid
+
+    def __str__(self):
+        return 'EventHostRequest<dpid=%s>' % \
+            (self.dpid)
+
+class EventHostReply(event.EventReplyBase):
+    def __init__(self, dst, dpid, hosts):
+        super(EventHostReply, self).__init__(dst)
+        self.dpid = dpid
+        self.hosts = hosts
+
+    def __str__(self):
+        return 'EventLinkReply<dpid=%s, hosts=%s>' % \
+            (self.dpid, self.hosts)
diff --git a/ryu/topology/switches.py b/ryu/topology/switches.py
index 63335f2..1212c6c 100644
--- a/ryu/topology/switches.py
+++ b/ryu/topology/switches.py
@@ -46,6 +46,8 @@ CONF = cfg.CONF
 CONF.register_cli_opts([
     cfg.BoolOpt('observe-links', default=False,
                 help='observe link discovery events.'),
+    cfg.BoolOpt('observe-hosts', default=False,
+                help='observe host discovery events.'),
     cfg.BoolOpt('install-lldp-flow', default=True,
                 help='link discovery: explicitly install flow entry '
                      'to send lldp packet to controller'),
@@ -157,6 +159,34 @@ class Link(object):
     def __str__(self):
         return 'Link: %s to %s' % (self.src, self.dst)

+class Host(object):
+    # This is data class passed by EventHostXXXX
+    def __init__(self, dpid, port, mac):
+        super(Host, self).__init__()
+        self.dpid = dpid
+        self.port = port
+        self.mac = mac
+
+    def to_dict(self):
+        d = {
+            'dpid': self.dpid,
+            'port': self.port,
+            'mac': self.mac
+            }
+        return d
+
+    def __eq__(self, other):
+        return self.mac == other.mac
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __hash__(self):
+        return hash(self.mac)
+
+    def __str__(self):
+        return 'Host<Mac address=%s>' % (self.mac, )
+

 class PortState(dict):
     # dict: int port_no -> OFPPort port
@@ -451,9 +481,12 @@ class Switches(app_manager.RyuApp):
         self.port_state = {}          # datapath_id => ports
         self.ports = PortDataState()  # Port class -> PortData class
         self.links = LinkState()      # Link class -> timestamp
+        self.hosts = {}
         self.is_active = True

         self.link_discovery = self.CONF.observe_links
+        self.host_discovery = self.CONF.observe_hosts
+
         if self.link_discovery:
             self.install_flow = self.CONF.install_lldp_flow
             self.explicit_drop = self.CONF.explicit_drop
@@ -681,7 +714,7 @@ class Switches(app_manager.RyuApp):

     @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
     def packet_in_handler(self, ev):
-        if not self.link_discovery:
+        if not self.link_discovery and not self.host_discovery:
             return

         msg = ev.msg
@@ -689,7 +722,25 @@ class Switches(app_manager.RyuApp):
             src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
         except LLDPPacket.LLDPUnknownFormat as e:
             # This handler can receive all the packtes which can be
-            # not-LLDP packet. Ignore it silently
+            # not-LLDP packet.
+            # Check if it's new host
+            if self.host_discovery:
+                dpid = msg.datapath.id
+                port = -1
+
+                if msg.datapath.ofproto.OFP_VERSION ==
ofproto_v1_0.OFP_VERSION:
+                    port = msg.in_port
+                elif msg.datapath.ofproto.OFP_VERSION >=
ofproto_v1_2.OFP_VERSION:
+                    port = msg.match['in_port']
+
+                pkt = packet.Packet(msg.data)
+                eth = pkt.get_protocols(ethernet.ethernet)[0]
+                mac = eth.src
+
+                if mac not in self.hosts and port != -1:
+                    LOG.debug('Found host(mac=%s) from dpid=%d, port=%d',
mac, dpid, port)
+                    self.hosts[mac] = Host(dpid, port, mac)
+
             return

         dst_dpid = msg.datapath.id
@@ -862,3 +913,19 @@ class Switches(app_manager.RyuApp):
             links = [link for link in self.links if link.src.dpid == dpid]
         rep = event.EventLinkReply(req.src, dpid, links)
         self.reply_to_request(req, rep)
+
+    @set_ev_cls(event.EventHostRequest)
+    def host_request_handler(self, req):
+        # LOG.debug(req)
+        dpid = req.dpid
+        hosts = []
+
+        if dpid is None:
+            hosts = [host for host in self.hosts.itervalues()]
+
+        else:
+            hosts = [host for host in self.hosts.itervalues() if host.dpid
== dpid]
+
+        rep = event.EventHostReply(req.src, dpid, hosts)
+        self.reply_to_request(req, rep)
+
-- 
2.3.2 (Apple Git-55)




2015-06-11 13:29 GMT+08:00 Yi Tseng <[email protected]>:

> Hi
>
> Sorry that I forgot to remove comment (# this type is used for key value
> of LinkState) in class Host (I copied class Link and modify it)
>
> Should I send a new patch ?
>
>
>
> 2015-06-11 13:08 GMT+08:00 Yi Tseng <[email protected]>:
>
>> Hi
>>
>> I didn't concern that host can be configured to send lldp packets.
>>
>> If a host can be configured to send lldp packet, there will be two
>> situations:
>>
>> 1. Host always send lldp packets : ryu can't discover that host.
>>
>> 2. Host not always send lldp packet, sometimes it send normal packet :
>> ryu can discover it.
>>
>> I think maybe I can add "--observe-hosts" option to ryu manager and send
>> a new patch?
>>
>>
>>
>>
>> 2015-06-11 12:33 GMT+08:00 IWAMOTO Toshihiro <[email protected]>:
>>
>>> At Thu, 11 Jun 2015 02:30:40 +0800,
>>> Yi Tseng wrote:
>>> >
>>> > Signed-off-by: Takeshi <[email protected]>
>>> > ---
>>> >  ryu/topology/api.py      |  7 +++++
>>> >  ryu/topology/event.py    | 23 +++++++++++++++++
>>> >  ryu/topology/switches.py | 66
>>> > +++++++++++++++++++++++++++++++++++++++++++++++-
>>> >  3 files changed, 95 insertions(+), 1 deletion(-)
>>>
>>> > diff --git a/ryu/topology/switches.py b/ryu/topology/switches.py
>>> > index 63335f2..ab7f9f6 100644
>>> > --- a/ryu/topology/switches.py
>>> > +++ b/ryu/topology/switches.py
>>> > @@ -157,6 +157,35 @@ class Link(object):
>>> >      def __str__(self):
>>> >          return 'Link: %s to %s' % (self.src, self.dst)
>>> >
>>> > +class Host(object):
>>> > +    # This is data class passed by EventHostXXXX
>>> > +    def __init__(self, dpid, port, mac):
>>> > +        super(Host, self).__init__()
>>> > +        self.dpid = dpid
>>> > +        self.port = port
>>> > +        self.mac = mac
>>> > +
>>> > +    def to_dict(self):
>>> > +        d = {
>>> > +            'dpid': self.dpid,
>>> > +            'port': self.port,
>>> > +            'mac': self.mac
>>> > +            }
>>> > +        return d
>>> > +
>>> > +    # this type is used for key value of LinkState
>>>
>>> Really? And why are you ignoring dpid and port in comparison
>>> operators?
>>>
>>> > +    def __eq__(self, other):
>>> > +        return self.mac == other.mac
>>> > +
>>> > +    def __ne__(self, other):
>>> > +        return not self.__eq__(other)
>>> > +
>>> > +    def __hash__(self):
>>> > +        return hash(self.mac)
>>> > +
>>> > +    def __str__(self):
>>> > +        return 'Host<Mac address=%s>' % (self.mac, )
>>> > +
>>> >
>>> >  class PortState(dict):
>>> >      # dict: int port_no -> OFPPort port
>>> > @@ -451,6 +480,7 @@ class Switches(app_manager.RyuApp):
>>> >          self.port_state = {}          # datapath_id => ports
>>> >          self.ports = PortDataState()  # Port class -> PortData class
>>> >          self.links = LinkState()      # Link class -> timestamp
>>> > +        self.hosts = {}
>>> >          self.is_active = True
>>> >
>>> >          self.link_discovery = self.CONF.observe_links
>>> > @@ -689,7 +719,25 @@ class Switches(app_manager.RyuApp):
>>> >              src_dpid, src_port_no = LLDPPacket.lldp_parse(msg.data)
>>> >          except LLDPPacket.LLDPUnknownFormat as e:
>>> >              # This handler can receive all the packtes which can be
>>> > -            # not-LLDP packet. Ignore it silently
>>> > +            # not-LLDP packet.
>>> > +            # Check if it's new host
>>> > +
>>> > +            dpid = msg.datapath.id
>>> > +            port = -1
>>> > +
>>> > +            if msg.datapath.ofproto.OFP_VERSION ==
>>> > ofproto_v1_0.OFP_VERSION:
>>> > +                port = msg.in_port
>>> > +            elif msg.datapath.ofproto.OFP_VERSION >=
>>> > ofproto_v1_2.OFP_VERSION:
>>> > +                port = msg.match['in_port']
>>> > +
>>> > +            pkt = packet.Packet(msg.data)
>>> > +            eth = pkt.get_protocols(ethernet.ethernet)[0]
>>> > +            mac = eth.src
>>> > +
>>> > +            if mac not in self.hosts and port != -1:
>>> > +                LOG.debug('Found host(mac=%s) from dpid=%d, port=%d',
>>> mac,
>>> > dpid, port)
>>> > +                self.hosts[mac] = Host(dpid, port, mac)
>>> > +
>>> >              return
>>> >
>>> >          dst_dpid = msg.datapath.id
>>>
>>> --
>>> IWAMOTO Toshihiro
>>>
>>
>>
>>
>> --
>> Yi Tseng (a.k.a Takeshi)
>> Taiwan National Chiao Tung University
>> Department of Computer Science
>> W2CNLab
>>
>
>
>
> --
> Yi Tseng (a.k.a Takeshi)
> Taiwan National Chiao Tung University
> Department of Computer Science
> W2CNLab
>



-- 
Yi Tseng (a.k.a Takeshi)
Taiwan National Chiao Tung University
Department of Computer Science
W2CNLab
------------------------------------------------------------------------------
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to