Hello

Attached files are my patch.

Thanks .

2015-06-14 21:47 GMT+08:00 FUJITA Tomonori <[email protected]>:

> On Thu, 11 Jun 2015 15:19:53 +0800
> Yi Tseng <[email protected]> wrote:
>
> > Please ignore previous patch, because I forgot to check coding style with
> > pep8, here is the new patch
> >
> > Signed-off-by: Takeshi <[email protected]>
> > ---
> >  ryu/topology/api.py      |  9 +++++++
> >  ryu/topology/event.py    | 23 ++++++++++++++++
> >  ryu/topology/switches.py | 69
> > ++++++++++++++++++++++++++++++++++++++++++++++--
> >  3 files changed, 99 insertions(+), 2 deletions(-)
>
> Thanks but I got the following error:
>
> FUJITA-no-MacBook-Pro:ryu fujita$ patch -p1 < 1
> patching file ryu/topology/api.py
> patching file ryu/topology/event.py
> patching file ryu/topology/switches.py
> patch: **** malformed patch at line 246: ofproto_v1_0.OFP_VERSION:
>



-- 
Yi Tseng (a.k.a Takeshi)
Taiwan National Chiao Tung University
Department of Computer Science
W2CNLab
From c8be39932ea9873b08531fb6b5f625495043cb4e Mon Sep 17 00:00:00 2001
From: Takeshi <[email protected]>
Date: Mon, 15 Jun 2015 01:06:04 +0800
Subject: [PATCH 1/2] Implement host discovery in ryu.topology

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

diff --git a/ryu/topology/api.py b/ryu/topology/api.py
index 7485a8e..0a61c1b 100644
--- a/ryu/topology/api.py
+++ b/ryu/topology/api.py
@@ -35,4 +35,13 @@ 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..ea9d8ce 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..3f69f7c 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'),
@@ -158,6 +160,33 @@ class Link(object):
         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
     # OFPPort is defined in ryu.ofproto.ofproto_v1_X_parser
@@ -451,9 +480,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 +713,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 +721,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 +912,18 @@ 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)

From 8afb7198bc686d376bc32c3a90fec330f9c8751d Mon Sep 17 00:00:00 2001
From: Takeshi <[email protected]>
Date: Mon, 15 Jun 2015 01:06:28 +0800
Subject: [PATCH 2/2] Implement "get host" and "list host" RESTful api

Signed-off-by: Takeshi <[email protected]>
---
 ryu/app/rest_topology.py | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/ryu/app/rest_topology.py b/ryu/app/rest_topology.py
index 5eed243..77cfc37 100644
--- a/ryu/app/rest_topology.py
+++ b/ryu/app/rest_topology.py
@@ -19,7 +19,7 @@ from webob import Response
 from ryu.app.wsgi import ControllerBase, WSGIApplication, route
 from ryu.base import app_manager
 from ryu.lib import dpid as dpid_lib
-from ryu.topology.api import get_switch, get_link
+from ryu.topology.api import get_switch, get_link, get_host
 
 # REST API for switch configuration
 #
@@ -76,6 +76,16 @@ class TopologyController(ControllerBase):
     def get_links(self, req, **kwargs):
         return self._links(req, **kwargs)
 
+    @route('topology', '/v1.0/topology/hosts',
+           methods=['GET'])
+    def list_hosts(self, req, **kwargs):
+        return self._hosts(req, **kwargs)
+
+    @route('topology', '/v1.0/topology/hosts/{dpid}',
+           methods=['GET'], requirements={'dpid': dpid_lib.DPID_PATTERN})
+    def get_hosts(self, req, **kwargs):
+        return self._hosts(req, **kwargs)
+
     def _switches(self, req, **kwargs):
         dpid = None
         if 'dpid' in kwargs:
@@ -91,3 +101,11 @@ class TopologyController(ControllerBase):
         links = get_link(self.topology_api_app, dpid)
         body = json.dumps([link.to_dict() for link in links])
         return Response(content_type='application/json', body=body)
+
+    def _hosts(self, req, **kwargs):
+        dpid = None
+        if 'dpid' in kwargs:
+            dpid = dpid_lib.str_to_dpid(kwargs['dpid'])
+        hosts = get_host(self.topology_api_app, dpid)
+        body = json.dumps([host.to_dict() for host in hosts])
+        return Response(content_type='application/json', body=body)
-- 
2.3.2 (Apple Git-55)

------------------------------------------------------------------------------
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to