Do you have any reason prefixing double underscore "__"
instead of single underscore "_"?

thanks

On Fri, Feb 22, 2013 at 07:14:20PM +0900, YAMADA Hideki wrote:
> This is an alternative of dpset, which supports event passing.
> 
> event.py: event class
> switch.py: switch(datapath) discovery app using ofp_event
> dumper.py: test and example app using switch discovery event
> 
> TODO: support link discovery using LLDP.
> 
> Signed-off-by: YAMADA Hideki <[email protected]>
> ---
>  ryu/physicaltopology/dumper.py   |   87 ++++++++++++++++
>  ryu/physicaltopology/event.py    |   85 ++++++++++++++++
>  ryu/physicaltopology/switch.py   |  207 
> ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 379 insertions(+), 0 deletions(-)
>  create mode 100644 ryu/physicaltopology/__init__.py
>  create mode 100644 ryu/physicaltopology/dumper.py
>  create mode 100644 ryu/physicaltopology/event.py
>  create mode 100644 ryu/physicaltopology/switch.py
> 
> diff --git a/ryu/physicaltopology/__init__.py 
> b/ryu/physicaltopology/__init__.py
> new file mode 100644
> index 0000000..e69de29
> diff --git a/ryu/physicaltopology/dumper.py b/ryu/physicaltopology/dumper.py
> new file mode 100644
> index 0000000..ada890a
> --- /dev/null
> +++ b/ryu/physicaltopology/dumper.py
> @@ -0,0 +1,87 @@
> +# Copyright (C) 2013 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
> +#
> +#    http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> +# implied.
> +# See the License for the specific language governing permissions and
> +# limitations under the License.
> +
> +
> +import logging
> +import gevent
> +import gevent.queue
> +
> +from ryu.base import app_manager
> +from ryu.controller import handler
> +
> +from .event import EventSwitchEnter, EventSwitchLeave
> +from .event import EventPortAdd, EventPortDelete, EventPortModify
> +from .event import EventSwitchListRequest, EventSwitchListReply
> +import switch
> +
> +LOG = logging.getLogger(__name__)
> +
> +
> +class DiscoveryEventDumper(app_manager.RyuApp):
> +    ''' This app dumps discovery events
> +    '''
> +
> +    # For testing when multi request threads, there is no race condition
> +    __THREAD_COUNT = 2
> +    __THREAD_SLEEP = 5
> +
> +    def __init__(self):
> +        super(DiscoveryEventDumper, self).__init__()
> +
> +        for i in range(0, self.__THREAD_COUNT):
> +            self.threads.append(gevent.spawn_later(0, self.__request_loop))
> +
> +        self.is_active = True
> +
> +    @handler.set_ev_cls(EventSwitchEnter)
> +    def dp_enter_handler(self, ev):
> +        LOG.debug(ev)
> +
> +    @handler.set_ev_cls(EventSwitchLeave)
> +    def dp_leave_handler(self, ev):
> +        LOG.debug(ev)
> +
> +    @handler.set_ev_cls(EventPortAdd)
> +    def dp_port_add_handler(self, ev):
> +        LOG.debug(ev)
> +
> +    @handler.set_ev_cls(EventPortDelete)
> +    def dp_port_delete_handler(self, ev):
> +        LOG.debug(ev)
> +
> +    @handler.set_ev_cls(EventPortModify)
> +    def dp_port_modify_handler(self, ev):
> +        LOG.debug(ev)
> +
> +    def __get_switches(self, dpid=None):
> +        request = EventSwitchListRequest(dpid)
> +        self.send_request(switch.SwitchDiscovery.__name__, request)
> +
> +        reply = self.recv_reply(request.xid)
> +        assert reply.xid == request.xid
> +
> +        return reply.switches
> +
> +    def __request_loop(self):
> +        while self.is_active:
> +            all_switches = self.__get_switches()
> +            if len(all_switches) > 0:
> +                LOG.debug('request thread(%s) print ALL Switches: ',
> +                          id(gevent.getcurrent()))
> +                for sw in all_switches:
> +                    LOG.debug('  %s', sw)
> +            #sw1 = self.__get_switches(1)
> +            #LOG.debug('SW1: %s', sw1)
> +            gevent.sleep(self.__THREAD_SLEEP)
> diff --git a/ryu/physicaltopology/event.py b/ryu/physicaltopology/event.py
> new file mode 100644
> index 0000000..34fa863
> --- /dev/null
> +++ b/ryu/physicaltopology/event.py
> @@ -0,0 +1,85 @@
> +# Copyright (C) 2013 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
> +#
> +#    http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> +# implied.
> +# See the License for the specific language governing permissions and
> +# limitations under the License.
> +
> +import logging
> +from ryu.controller import event
> +
> +LOG = logging.getLogger(__name__)
> +
> +
> +class EventSwitchBase(event.EventBase):
> +    def __init__(self, switch):
> +        super(EventSwitchBase, self).__init__()
> +        self.switch = switch
> +
> +    def __str__(self):
> +        return '%s<dpid=%s, %s ports>' % \
> +            (self.__class__.__name__,
> +             self.switch.dpid, len(self.switch.ports))
> +
> +
> +class EventSwitchEnter(EventSwitchBase):
> +    def __init__(self, switch):
> +        super(EventSwitchEnter, self).__init__(switch)
> +
> +
> +class EventSwitchLeave(EventSwitchBase):
> +    def __init__(self, switch):
> +        super(EventSwitchLeave, self).__init__(switch)
> +
> +
> +class EventPortBase(event.EventBase):
> +    def __init__(self, port):
> +        super(EventPortBase, self).__init__()
> +        self.port = port
> +
> +    def __str__(self):
> +        return '%s<%s>' % (self.__class__.__name__, self.port)
> +
> +
> +class EventPortAdd(EventPortBase):
> +    def __init__(self, port):
> +        super(EventPortAdd, self).__init__(port)
> +
> +
> +class EventPortDelete(EventPortBase):
> +    def __init__(self, port):
> +        super(EventPortDelete, self).__init__(port)
> +
> +
> +class EventPortModify(EventPortBase):
> +    def __init__(self, port):
> +        super(EventPortModify, self).__init__(port)
> +
> +
> +class EventSwitchListRequest(event.EventRequestBase):
> +    # If dpid is None, reply all list
> +    def __init__(self, dpid=None):
> +        super(EventSwitchListRequest, self).__init__()
> +        self.dpid = dpid
> +
> +    def __str__(self):
> +        return 'EventSwitchListRequest<src=%s, xid=%s, dpid=%s>' % \
> +            (self.src, self.xid, self.dpid)
> +
> +
> +class EventSwitchListReply(event.EventReplyBase):
> +    def __init__(self, switches):
> +        super(EventSwitchListReply, self).__init__()
> +        self.switches = switches
> +
> +    def __str__(self):
> +        return 'EventSwitchListReply<src=%s, xid=%s, %s>' % \
> +            (self.src, self.xid, self.switches)
> diff --git a/ryu/physicaltopology/switch.py b/ryu/physicaltopology/switch.py
> new file mode 100644
> index 0000000..9f99ead
> --- /dev/null
> +++ b/ryu/physicaltopology/switch.py
> @@ -0,0 +1,207 @@
> +# Copyright (C) 2013 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
> +#
> +#    http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> +# implied.
> +# See the License for the specific language governing permissions and
> +# limitations under the License.
> +
> +import logging
> +from ryu.base import app_manager
> +from ryu.controller import ofp_event, handler
> +
> +from .event import EventSwitchEnter, EventSwitchLeave
> +from .event import EventPortAdd, EventPortDelete, EventPortModify
> +from .event import EventSwitchListRequest, EventSwitchListReply
> +LOG = logging.getLogger(__name__)
> +
> +
> +class Port(object):
> +    # This is data class passed by EventPortXXX
> +    def __init__(self, dpid, ofproto, ofpport):
> +        super(Port, self).__init__()
> +
> +        self.dpid = dpid
> +        self.__ofproto = ofproto
> +
> +        self.__config = ofpport.config
> +        self.__state = ofpport.state
> +        self.port_no = ofpport.port_no
> +        self.hw_addr = ofpport.hw_addr
> +        self.name = ofpport.name
> +
> +    def is_reserved(self):
> +        return self.port_no > self.__ofproto.OFPP_MAX
> +
> +    def is_down(self):
> +        return (self.__state & self.__ofproto.OFPPS_LINK_DOWN) > 0 \
> +            or (self.__config & self.__ofproto.OFPPC_PORT_DOWN) > 0
> +
> +    def is_live(self):
> +        # NOTE: OF1.2 has OFPPS_LIVE state
> +        #       return (self.__state & self.__ofproto.OFPPS_LIVE) > 0
> +        return not self.is_down()
> +
> +    # for Switch.del_port()
> +    def __eq__(self, other):
> +        return self.dpid == other.dpid and self.port_no == other.port_no
> +
> +    def __ne__(self, other):
> +        return not self.__eq__(other)
> +
> +    def __hash__(self):
> +        return hash((self.dpid, self.port_no))
> +
> +    def __str__(self):
> +        LIVE_MSG = {False: 'DOWN', True: 'LIVE'}
> +        return 'Port<dpid=%s, port_no=%s, %s>' % \
> +            (self.dpid, self.port_no, LIVE_MSG[self.is_live()])
> +
> +
> +class Switch(object):
> +    # This is data class passed by EventSwitchXXX
> +    def __init__(self, dp):
> +        super(Switch, self).__init__()
> +
> +        self.__ofproto = dp.ofproto
> +        self.dpid = dp.id
> +        self.ports = []
> +
> +    def add_port(self, ofpport):
> +        port = Port(self.dpid, self.__ofproto, ofpport)
> +        if not port.is_reserved():
> +            self.ports.append(port)
> +
> +    def del_port(self, ofpport):
> +        self.ports.remove(Port(ofpport))
> +
> +    def __str__(self):
> +        msg = 'Switch<dpid=%s, ' % self.dpid
> +        for port in self.ports:
> +            msg += str(port) + ' '
> +
> +        msg += '>'
> +        return msg
> +
> +
> +class PortState(dict):
> +    # dict: int port_no -> OFPPort port
> +    # OFPPort is defined in ryu.ofproto.ofproto_v1_X_parser
> +    def __init__(self):
> +        super(PortState, self).__init__()
> +
> +    def add(self, port_no, port):
> +        self[port_no] = port
> +
> +    def remove(self, port_no):
> +        del self[port_no]
> +
> +    def modify(self, port_no, port):
> +        self[port_no] = port
> +
> +
> +class SwitchDiscovery(app_manager.RyuApp):
> +    _EVENTS = [EventSwitchEnter, EventSwitchLeave,
> +               EventPortAdd, EventPortDelete, EventPortModify]
> +
> +    def __init__(self):
> +        super(SwitchDiscovery, self).__init__()
> +
> +        self.dps = {}   # datapath_id => class Datapath
> +        self.port_state = {}  # datapath_id => ports
> +
> +    def __register(self, dp):
> +        assert dp.id is not None
> +        assert dp.id not in self.dps
> +
> +        self.dps[dp.id] = dp
> +        self.port_state[dp.id] = PortState()
> +        for port in dp.ports.values():
> +            self.port_state[dp.id].add(port.port_no, port)
> +
> +    def __unregister(self, dp):
> +        if dp.id in self.dps:
> +            del self.dps[dp.id]
> +            del self.port_state[dp.id]
> +
> +    def __get_switch(self, dp):
> +        switch = Switch(dp)
> +        for ofpport in self.port_state[dp.id].itervalues():
> +            switch.add_port(ofpport)
> +        return switch
> +
> +    @handler.set_ev_cls(ofp_event.EventOFPStateChange,
> +                        [handler.MAIN_DISPATCHER, handler.DEAD_DISPATCHER])
> +    def state_change_handler(self, ev):
> +        dp = ev.datapath
> +        assert dp is not None
> +        LOG.debug(dp)
> +
> +        if ev.state == handler.MAIN_DISPATCHER:
> +            self.__register(dp)
> +            switch = self.__get_switch(dp)
> +            LOG.debug('register %s', switch)
> +            self.send_event_to_observers(EventSwitchEnter(switch))
> +
> +        elif ev.state == handler.DEAD_DISPATCHER:
> +            # dp.id is None when datapath dies before handshake
> +            if dp.id is None:
> +                return
> +            switch = self.__get_switch(dp)
> +            self.__unregister(dp)
> +            LOG.debug('unregister %s', switch)
> +            self.send_event_to_observers(EventSwitchLeave(switch))
> +
> +    @handler.set_ev_cls(ofp_event.EventOFPPortStatus, 
> handler.MAIN_DISPATCHER)
> +    def port_status_handler(self, ev):
> +        msg = ev.msg
> +        reason = msg.reason
> +        dp = msg.datapath
> +        ofpport = msg.desc
> +
> +        if reason == dp.ofproto.OFPPR_ADD:
> +            #LOG.debug('A port was added.' +
> +            #          '(datapath id = %s, port number = %s)',
> +            #          dp.id, ofpport.port_no)
> +            self.port_state[dp.id].add(ofpport.port_no, ofpport)
> +            self.send_event_to_observers(
> +                EventPortAdd(Port(dp.id, dp.ofproto, ofpport)))
> +
> +        elif reason == dp.ofproto.OFPPR_DELETE:
> +            #LOG.debug('A port was deleted.' +
> +            #          '(datapath id = %s, port number = %s)',
> +            #          dp.id, ofpport.port_no)
> +            self.port_state[dp.id].remove(ofpport.port_no)
> +            self.send_event_to_observers(
> +                EventPortDelete(Port(dp.id, dp.ofproto, ofpport)))
> +
> +        else:
> +            assert reason == dp.ofproto.OFPPR_MODIFY
> +            #LOG.debug('A port was modified.' +
> +            #          '(datapath id = %s, port number = %s)',
> +            #          dp.id, ofpport.port_no)
> +            self.port_state[dp.id].modify(ofpport.port_no, ofpport)
> +            self.send_event_to_observers(
> +                EventPortModify(Port(dp.id, dp.ofproto, ofpport)))
> +
> +    @handler.set_ev_cls(EventSwitchListRequest)
> +    def request_handler(self, ev):
> +        #LOG.debug(ev)
> +        dpid = ev.dpid
> +
> +        switches = []
> +        if dpid is None:
> +            # reply all list
> +            for dp in self.dps.itervalues():
> +                switches.append(self.__get_switch(dp))
> +        elif dpid in self.dps:
> +            switches.append(self.__get_switch(self.dps[dpid]))
> +
> +        self.send_reply(ev, EventSwitchListReply(switches))
> -- 
> 1.7.1
> 
> 
> 
> ------------------------------------------------------------------------------
> Everyone hates slow websites. So do we.
> Make your web apps faster with AppDynamics
> Download AppDynamics Lite for free today:
> http://p.sf.net/sfu/appdyn_d2d_feb
> _______________________________________________
> Ryu-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/ryu-devel
> 

-- 
yamahata

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to