1 # Copyright (C) 2016 Nippon Telegraph and Telephone Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 from operator import attrgetter
18 from ryu.app import simple_switch_13
19 from ryu.controller import ofp_event
20 from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER
21 from ryu.controller.handler import set_ev_cls
22 from ryu.lib import hub
25 class SimpleMonitor13(simple_switch_13.SimpleSwitch13):
27 def __init__(self, *args, **kwargs):
28 super(SimpleMonitor13, self).__init__(*args, **kwargs)
30 self.monitor_thread = hub.spawn(self._monitor)
32 @set_ev_cls(ofp_event.EventOFPStateChange,
33 [MAIN_DISPATCHER, DEAD_DISPATCHER])
34 def _state_change_handler(self, ev):
35 datapath = ev.datapath
36 if ev.state == MAIN_DISPATCHER:
37 if datapath.id not in self.datapaths:
38 self.logger.debug('register datapath: %016x', datapath.id)
39 self.datapaths[datapath.id] = datapath
40 elif ev.state == DEAD_DISPATCHER:
41 if datapath.id in self.datapaths:
42 self.logger.debug('unregister datapath: %016x', datapath.id)
43 del self.datapaths[datapath.id]
47 for dp in self.datapaths.values():
48 self._request_stats(dp)
51 def _request_stats(self, datapath):
52 self.logger.debug('send stats request: %016x', datapath.id)
53 ofproto = datapath.ofproto
54 parser = datapath.ofproto_parser
56 req = parser.OFPFlowStatsRequest(datapath)
57 datapath.send_msg(req)
59 req = parser.OFPPortStatsRequest(datapath, 0, ofproto.OFPP_ANY)
60 datapath.send_msg(req)
62 @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER)
63 def _flow_stats_reply_handler(self, ev):
66 self.logger.info('datapath '
68 'out-port packets bytes')
69 self.logger.info('---------------- '
70 '-------- ----------------- '
71 '-------- -------- --------')
72 for stat in sorted([flow for flow in body if flow.priority == 1],
73 key=lambda flow: (flow.match['in_port'],
74 flow.match['eth_dst'])):
75 self.logger.info('%016x %8x %17s %8x %8d %8d',
77 stat.match['in_port'], stat.match['eth_dst'],
78 stat.instructions[0].actions[0].port,
79 stat.packet_count, stat.byte_count)
81 @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER)
82 def _port_stats_reply_handler(self, ev):
85 self.logger.info('datapath port '
86 'rx-pkts rx-bytes rx-error '
87 'tx-pkts tx-bytes tx-error')
88 self.logger.info('---------------- -------- '
89 '-------- -------- -------- '
90 '-------- -------- --------')
91 for stat in sorted(body, key=attrgetter('port_no')):
92 self.logger.info('%016x %8x %8d %8d %8d %8d %8d %8d',
93 ev.msg.datapath.id, stat.port_no,
94 stat.rx_packets, stat.rx_bytes, stat.rx_errors,
95 stat.tx_packets, stat.tx_bytes, stat.tx_errors)