1 | """Statistics application.""" |
||
2 | from pyof.v0x01.controller2switch.stats_request import StatsType |
||
3 | |||
4 | from kytos.core import KytosNApp, log |
||
5 | from kytos.core.helpers import listen_to |
||
6 | from napps.kytos.of_stats import settings |
||
7 | from napps.kytos.of_stats.stats import FlowStats, PortStats |
||
8 | |||
9 | |||
10 | class Main(KytosNApp): |
||
11 | """Main class for statistics application.""" |
||
12 | |||
13 | def setup(self): |
||
14 | """Initialize all statistics and set their loop interval.""" |
||
15 | self.execute_as_loop(settings.STATS_INTERVAL) |
||
16 | |||
17 | # Initialize statistics |
||
18 | msg_out = self.controller.buffers.msg_out |
||
19 | app_buffer = self.controller.buffers.app |
||
20 | self._stats = {StatsType.OFPST_PORT.value: PortStats(msg_out, |
||
21 | app_buffer), |
||
22 | StatsType.OFPST_FLOW.value: FlowStats(msg_out, |
||
23 | app_buffer)} |
||
24 | |||
25 | def execute(self): |
||
26 | """Query all switches sequentially and then sleep before repeating.""" |
||
27 | switches = list(self.controller.switches.values()) |
||
28 | for switch in switches: |
||
29 | if switch.is_connected(): |
||
30 | self._update_stats(switch) |
||
31 | |||
32 | def shutdown(self): |
||
33 | """End of the application.""" |
||
34 | log.debug('Shutting down...') |
||
35 | |||
36 | def _update_stats(self, switch): |
||
37 | for stats in self._stats.values(): |
||
38 | if switch.connection is not None: |
||
39 | stats.request(switch.connection) |
||
40 | |||
41 | @listen_to('kytos/of_core.v0x01.messages.in.ofpt_stats_reply') |
||
42 | def listen_v0x01(self, event): |
||
43 | """Detect the message body type.""" |
||
44 | stats_reply = event.content['message'] |
||
45 | stats_type = stats_reply.body_type |
||
46 | self._listen(event, stats_type) |
||
47 | |||
48 | @listen_to('kytos/of_core.v0x04.messages.in.ofpt_multipart_reply') |
||
49 | def listen_v0x04(self, event): |
||
50 | """Detect the message body type.""" |
||
51 | multipart_reply = event.content['message'] |
||
52 | stats_type = multipart_reply.multipart_type |
||
53 | self._listen(event, stats_type) |
||
54 | |||
55 | def _listen(self, event, stats_type): |
||
56 | """Listen to all stats reply we deal with. |
||
57 | |||
58 | Note: v0x01 ``body_type`` and v0x04 ``multipart_type`` have the same |
||
59 | values. Besides, both ``msg.body`` have the fields/attributes we use. |
||
60 | Thus, we can treat them the same way and reuse the code. |
||
61 | """ |
||
62 | msg = event.content['message'] |
||
63 | if stats_type.value in self._stats: |
||
64 | stats = self._stats[stats_type.value] |
||
65 | stats_list = msg.body |
||
66 | stats.listen(event.source.switch, stats_list) |
||
67 | else: |
||
68 | log.debug('No listener for %s = %s in %s.', stats_type.name, |
||
69 | stats_type.value, list(self._stats.keys())) |
||
70 |