blob: 5629e7ccfa760b29145203d08a21a51009798357 [file] [log] [blame]
William Kurkian6f436d02019-02-06 16:25:01 -05001# Copyright 2017-present Open Networking Foundation
2#
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
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
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 implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import arrow
16from voltha.protos.device_pb2 import PmConfig, PmGroupConfig
17from voltha.protos.events_pb2 import KpiEvent2, MetricInformation, MetricMetaData, KpiEventType
18from voltha.extensions.kpi.adapter_pm_metrics import AdapterPmMetrics
19from voltha.extensions.omci.omci_entities import \
20 EthernetFrameUpstreamPerformanceMonitoringHistoryData, \
21 EthernetFrameDownstreamPerformanceMonitoringHistoryData, \
22 EthernetFrameExtendedPerformanceMonitoring, \
23 EthernetFrameExtendedPerformanceMonitoring64Bit, \
24 EthernetPMMonitoringHistoryData, FecPerformanceMonitoringHistoryData, \
25 GemPortNetworkCtpMonitoringHistoryData, XgPonTcPerformanceMonitoringHistoryData, \
26 XgPonDownstreamPerformanceMonitoringHistoryData, \
27 XgPonUpstreamPerformanceMonitoringHistoryData
28
29
30class OnuPmIntervalMetrics(AdapterPmMetrics):
31 """
32 ONU OMCI PM Interval metrics
33
34 These differ from other PM Metrics as they are collected and generated as a
35 result of receipt of OMCI get responses on various PM History MEs. They are
36 also always managed as a group with a fixed frequency of 15 minutes.
37 """
38 ME_ID_INFO = {
39 EthernetFrameUpstreamPerformanceMonitoringHistoryData.class_id: 'Ethernet_Bridge_Port_History',
40 EthernetFrameDownstreamPerformanceMonitoringHistoryData.class_id: 'Ethernet_Bridge_Port_History',
41 EthernetFrameExtendedPerformanceMonitoring.class_id: 'Ethernet_Bridge_Port_History',
42 EthernetFrameExtendedPerformanceMonitoring64Bit.class_id: 'Ethernet_Bridge_Port_History',
43 EthernetPMMonitoringHistoryData.class_id: 'Ethernet_UNI_History',
44 FecPerformanceMonitoringHistoryData.class_id: 'FEC_History',
45 GemPortNetworkCtpMonitoringHistoryData.class_id: 'GEM_Port_History',
46 XgPonTcPerformanceMonitoringHistoryData.class_id: 'xgPON_TC_History',
47 XgPonDownstreamPerformanceMonitoringHistoryData.class_id: 'xgPON_Downstream_History',
48 XgPonUpstreamPerformanceMonitoringHistoryData.class_id: 'xgPON_Upstream_History'
49 }
50 ETHERNET_BRIDGE_HISTORY_ENABLED = True
51 ETHERNET_UNI_HISTORY_ENABLED = True
52 FEC_HISTORY_ENABLED = True
53 GEM_PORT_HISTORY_ENABLED = False
54 TRANS_CONV_HISTORY_ENABLED = False
55 XGPON_DOWNSTREAM_HISTORY = False
56 XGPON_UPSTREAM_HISTORY = False
57
58 def __init__(self, adapter_agent, device_id, logical_device_id, **kwargs):
59 super(OnuPmIntervalMetrics, self).__init__(adapter_agent, device_id, logical_device_id,
60 grouped=True, freq_override=False,
61 **kwargs)
62 ethernet_bridge_history = {
63 ('class_id', PmConfig.CONTEXT),
64 ('entity_id', PmConfig.CONTEXT),
65 ("interval_end_time", PmConfig.CONTEXT),
66 ('parent_class_id', PmConfig.CONTEXT),
67 ('parent_entity_id', PmConfig.CONTEXT),
68 ('upstream', PmConfig.CONTEXT),
69
70 ("drop_events", PmConfig.COUNTER),
71 ("octets", PmConfig.COUNTER),
72 ("packets", PmConfig.COUNTER),
73 ("broadcast_packets", PmConfig.COUNTER),
74 ("multicast_packets", PmConfig.COUNTER),
75 ("crc_errored_packets", PmConfig.COUNTER),
76 ("undersize_packets", PmConfig.COUNTER),
77 ("oversize_packets", PmConfig.COUNTER),
78 ("64_octets", PmConfig.COUNTER),
79 ("65_to_127_octets", PmConfig.COUNTER),
80 ("128_to_255_octets", PmConfig.COUNTER),
81 ("256_to_511_octets", PmConfig.COUNTER),
82 ("512_to_1023_octets", PmConfig.COUNTER),
83 ("1024_to_1518_octets", PmConfig.COUNTER)
84 }
85 self._ethernet_bridge_history_config = {m: PmConfig(name=m, type=t, enabled=True)
86 for (m, t) in ethernet_bridge_history}
87
88 ethernet_uni_history = { # Ethernet History Data (Class ID 24)
89 ('class_id', PmConfig.CONTEXT),
90 ('entity_id', PmConfig.CONTEXT),
91 ("interval_end_time", PmConfig.CONTEXT),
92
93 ("fcs_errors", PmConfig.COUNTER),
94 ("excessive_collision_counter", PmConfig.COUNTER),
95 ("late_collision_counter", PmConfig.COUNTER),
96 ("frames_too_long", PmConfig.COUNTER),
97 ("buffer_overflows_on_rx", PmConfig.COUNTER),
98 ("buffer_overflows_on_tx", PmConfig.COUNTER),
99 ("single_collision_frame_counter", PmConfig.COUNTER),
100 ("multiple_collisions_frame_counter", PmConfig.COUNTER),
101 ("sqe_counter", PmConfig.COUNTER),
102 ("deferred_tx_counter", PmConfig.COUNTER),
103 ("internal_mac_tx_error_counter", PmConfig.COUNTER),
104 ("carrier_sense_error_counter", PmConfig.COUNTER),
105 ("alignment_error_counter", PmConfig.COUNTER),
106 ("internal_mac_rx_error_counter", PmConfig.COUNTER),
107 }
108 self._ethernet_uni_history_config = {m: PmConfig(name=m, type=t, enabled=True)
109 for (m, t) in ethernet_uni_history}
110
111 fec_history = { # FEC History Data (Class ID 312)
112 ('class_id', PmConfig.CONTEXT),
113 ('entity_id', PmConfig.CONTEXT),
114 ("interval_end_time", PmConfig.CONTEXT),
115
116 ("corrected_bytes", PmConfig.COUNTER),
117 ("corrected_code_words", PmConfig.COUNTER),
118 ("uncorrectable_code_words", PmConfig.COUNTER),
119 ("total_code_words", PmConfig.COUNTER),
120 ("fec_seconds", PmConfig.COUNTER),
121 }
122 self._fec_history_config = {m: PmConfig(name=m, type=t, enabled=True)
123 for (m, t) in fec_history}
124
125 gem_port_history = { # GEM Port Network CTP History Data (Class ID 341)
126 ('class_id', PmConfig.CONTEXT),
127 ('entity_id', PmConfig.CONTEXT),
128 ("interval_end_time", PmConfig.CONTEXT),
129
130 ("transmitted_gem_frames", PmConfig.COUNTER),
131 ("received_gem_frames", PmConfig.COUNTER),
132 ("received_payload_bytes", PmConfig.COUNTER),
133 ("transmitted_payload_bytes", PmConfig.COUNTER),
134 ("encryption_key_errors", PmConfig.COUNTER),
135 }
136 self._gem_port_history_config = {m: PmConfig(name=m, type=t, enabled=True)
137 for (m, t) in gem_port_history}
138
139 xgpon_tc_history = { # XgPon TC History Data (Class ID 344)
140 ('class_id', PmConfig.CONTEXT),
141 ('entity_id', PmConfig.CONTEXT),
142 ("interval_end_time", PmConfig.CONTEXT),
143
144 ("psbd_hec_error_count", PmConfig.COUNTER),
145 ("xgtc_hec_error_count", PmConfig.COUNTER),
146 ("unknown_profile_count", PmConfig.COUNTER),
147 ("transmitted_xgem_frames", PmConfig.COUNTER),
148 ("fragment_xgem_frames", PmConfig.COUNTER),
149 ("xgem_hec_lost_words_count", PmConfig.COUNTER),
150 ("xgem_key_errors", PmConfig.COUNTER),
151 ("xgem_hec_error_count", PmConfig.COUNTER),
152 }
153 self._xgpon_tc_history_config = {m: PmConfig(name=m, type=t, enabled=True)
154 for (m, t) in xgpon_tc_history}
155
156 xgpon_downstream_history = { # XgPon Downstream History Data (Class ID 345)
157 ('class_id', PmConfig.CONTEXT),
158 ('entity_id', PmConfig.CONTEXT),
159 ("interval_end_time", PmConfig.CONTEXT),
160
161 ("ploam_mic_error_count", PmConfig.COUNTER),
162 ("downstream_ploam_messages_count", PmConfig.COUNTER),
163 ("profile_messages_received", PmConfig.COUNTER),
164 ("ranging_time_messages_received", PmConfig.COUNTER),
165 ("deactivate_onu_id_messages_received", PmConfig.COUNTER),
166 ("disable_serial_number_messages_received", PmConfig.COUNTER),
167 ("request_registration_messages_received", PmConfig.COUNTER),
168 ("assign_alloc_id_messages_received", PmConfig.COUNTER),
169 ("key_control_messages_received", PmConfig.COUNTER),
170 ("sleep_allow_messages_received", PmConfig.COUNTER),
171 ("baseline_omci_messages_received_count", PmConfig.COUNTER),
172 ("extended_omci_messages_received_count", PmConfig.COUNTER),
173 ("assign_onu_id_messages_received", PmConfig.COUNTER),
174 ("omci_mic_error_count", PmConfig.COUNTER),
175 }
176 self._xgpon_downstream_history_config = {m: PmConfig(name=m, type=t, enabled=True)
177 for (m, t) in xgpon_downstream_history}
178
179 xgpon_upstream_history = { # XgPon Upstream History Data (Class ID 346)
180 ('class_id', PmConfig.CONTEXT),
181 ('entity_id', PmConfig.CONTEXT),
182 ("interval_end_time", PmConfig.CONTEXT),
183
184 ("upstream_ploam_message_count", PmConfig.COUNTER),
185 ("serial_number_onu_message_count", PmConfig.COUNTER),
186 ("registration_message_count", PmConfig.COUNTER),
187 ("key_report_message_count", PmConfig.COUNTER),
188 ("acknowledge_message_count", PmConfig.COUNTER),
189 ("sleep_request_message_count", PmConfig.COUNTER),
190 }
191 self._xgpon_upstream_history_config = {m: PmConfig(name=m, type=t, enabled=True)
192 for (m, t) in xgpon_upstream_history}
193 self._configs = {
194 EthernetFrameUpstreamPerformanceMonitoringHistoryData.class_id: self._ethernet_bridge_history_config,
195 EthernetFrameDownstreamPerformanceMonitoringHistoryData.class_id: self._ethernet_bridge_history_config,
196 EthernetFrameExtendedPerformanceMonitoring.class_id: self._ethernet_bridge_history_config,
197 EthernetFrameExtendedPerformanceMonitoring64Bit.class_id: self._ethernet_bridge_history_config,
198 EthernetPMMonitoringHistoryData.class_id: self._ethernet_uni_history_config,
199 FecPerformanceMonitoringHistoryData.class_id: self._fec_history_config,
200 GemPortNetworkCtpMonitoringHistoryData.class_id: self._gem_port_history_config,
201 XgPonTcPerformanceMonitoringHistoryData.class_id: self._xgpon_tc_history_config,
202 XgPonDownstreamPerformanceMonitoringHistoryData.class_id: self._xgpon_downstream_history_config,
203 XgPonUpstreamPerformanceMonitoringHistoryData.class_id: self._xgpon_upstream_history_config
204 }
205
206 def update(self, pm_config):
207 """
208 Update the PM Configuration.
209
210 For historical PM Intervals, the frequency always zero since the actual collection
211 and publishing is provided by the OpenOMCI library
212
213 :param pm_config:
214 """
215 self.log.debug('update')
216
217 try:
218 if pm_config.grouped:
219 for group in pm_config.groups:
220 group_config = self.pm_group_metrics.get(group.group_name)
221 if group_config is not None and group_config.enabled != group.enabled:
222 group_config.enabled = group.enabled
223 # TODO: For OMCI PM Metrics, tie this into add/remove of the PM Interval ME itself
224 else:
225 msg = 'There are on independent OMCI Interval metrics, only group metrics at this time'
226 raise NotImplemented(msg)
227
228 except Exception as e:
229 self.log.exception('update-failure', e=e)
230 raise
231
232 def make_proto(self, pm_config=None):
233 """
234 From the PM Configurations defined in this class's initializer, create
235 the PMConfigs protobuf message that defines our PM configuration and
236 data.
237
238 All ONU PM Interval metrics are grouped metrics that are generated autonmouslly
239 from the OpenOMCI Performance Intervals state machine.
240
241 :param pm_config (PMConfigs) PM Configuration message to add OpenOMCI config items too
242 :return: (PmConfigs) PM Configuration Protobuf message
243 """
244 assert pm_config is not None
245
246 pm_ethernet_bridge_history = PmGroupConfig(group_name=OnuPmIntervalMetrics.ME_ID_INFO[EthernetFrameUpstreamPerformanceMonitoringHistoryData.class_id],
247 group_freq=0,
248 enabled=OnuPmIntervalMetrics.ETHERNET_BRIDGE_HISTORY_ENABLED)
249 self.pm_group_metrics[pm_ethernet_bridge_history.group_name] = pm_ethernet_bridge_history
250
251 for m in sorted(self._ethernet_bridge_history_config):
252 pm = self._ethernet_bridge_history_config[m]
253 pm_ethernet_bridge_history.metrics.extend([PmConfig(name=pm.name,
254 type=pm.type,
255 enabled=pm.enabled)])
256
257 pm_ethernet_uni_history = PmGroupConfig(group_name=OnuPmIntervalMetrics.ME_ID_INFO[EthernetPMMonitoringHistoryData.class_id],
258 group_freq=0,
259 enabled=OnuPmIntervalMetrics.ETHERNET_UNI_HISTORY_ENABLED)
260 self.pm_group_metrics[pm_ethernet_uni_history.group_name] = pm_ethernet_uni_history
261
262 for m in sorted(self._ethernet_uni_history_config):
263 pm = self._ethernet_uni_history_config[m]
264 pm_ethernet_uni_history.metrics.extend([PmConfig(name=pm.name,
265 type=pm.type,
266 enabled=pm.enabled)])
267
268 pm_fec_history = PmGroupConfig(group_name=OnuPmIntervalMetrics.ME_ID_INFO[FecPerformanceMonitoringHistoryData.class_id],
269 group_freq=0,
270 enabled=OnuPmIntervalMetrics.FEC_HISTORY_ENABLED)
271 self.pm_group_metrics[pm_fec_history.group_name] = pm_fec_history
272
273 for m in sorted(self._fec_history_config):
274 pm = self._fec_history_config[m]
275 pm_fec_history.metrics.extend([PmConfig(name=pm.name,
276 type=pm.type,
277 enabled=pm.enabled)])
278
279 pm_gem_port_history = PmGroupConfig(group_name=OnuPmIntervalMetrics.ME_ID_INFO[GemPortNetworkCtpMonitoringHistoryData.class_id],
280 group_freq=0,
281 enabled=OnuPmIntervalMetrics.GEM_PORT_HISTORY_ENABLED)
282 self.pm_group_metrics[pm_gem_port_history.group_name] = pm_gem_port_history
283
284 for m in sorted(self._gem_port_history_config):
285 pm = self._gem_port_history_config[m]
286 pm_gem_port_history.metrics.extend([PmConfig(name=pm.name,
287 type=pm.type,
288 enabled=pm.enabled)])
289
290 pm_xgpon_tc_history = PmGroupConfig(group_name=OnuPmIntervalMetrics.ME_ID_INFO[XgPonTcPerformanceMonitoringHistoryData.class_id],
291 group_freq=0,
292 enabled=OnuPmIntervalMetrics.TRANS_CONV_HISTORY_ENABLED)
293 self.pm_group_metrics[pm_xgpon_tc_history.group_name] = pm_xgpon_tc_history
294
295 for m in sorted(self._xgpon_tc_history_config):
296 pm = self._xgpon_tc_history_config[m]
297 pm_xgpon_tc_history.metrics.extend([PmConfig(name=pm.name,
298 type=pm.type,
299 enabled=pm.enabled)])
300
301 pm_xgpon_downstream_history = PmGroupConfig(group_name=OnuPmIntervalMetrics.ME_ID_INFO[XgPonDownstreamPerformanceMonitoringHistoryData.class_id],
302 group_freq=0,
303 enabled=OnuPmIntervalMetrics.XGPON_DOWNSTREAM_HISTORY)
304 self.pm_group_metrics[pm_xgpon_downstream_history.group_name] = pm_xgpon_downstream_history
305
306 for m in sorted(self._xgpon_downstream_history_config):
307 pm = self._xgpon_downstream_history_config[m]
308 pm_xgpon_downstream_history.metrics.extend([PmConfig(name=pm.name,
309 type=pm.type,
310 enabled=pm.enabled)])
311
312 pm_xgpon_upstream_history = PmGroupConfig(group_name=OnuPmIntervalMetrics.ME_ID_INFO[XgPonUpstreamPerformanceMonitoringHistoryData.class_id],
313 group_freq=0,
314 enabled=OnuPmIntervalMetrics.XGPON_UPSTREAM_HISTORY)
315 self.pm_group_metrics[pm_xgpon_upstream_history.group_name] = pm_xgpon_upstream_history
316
317 for m in sorted(self._xgpon_upstream_history_config):
318 pm = self._xgpon_upstream_history_config[m]
319 pm_xgpon_upstream_history.metrics.extend([PmConfig(name=pm.name,
320 type=pm.type,
321 enabled=pm.enabled)])
322
323 pm_config.groups.extend([stats for stats in self.pm_group_metrics.itervalues()])
324
325 return pm_config
326
327 def publish_metrics(self, interval_data):
328 """
329 Collect the metrics for this ONU PM Interval
330
331 :param interval_data: (dict) PM interval dictionary with structure of
332 {
333 'class_id': self._class_id,
334 'entity_id': self._entity_id,
335 'me_name': self._entity.__name__, # Mostly for debugging...
336 'interval_utc_time': None,
337 # Counters added here as they are retrieved
338 }
339
340 :return: (dict) Key/Value of metric data
341 """
342 self.log.debug('publish-metrics')
343
344 try:
345 # Locate config
346 now = arrow.utcnow()
347 class_id = interval_data['class_id']
348 config = self._configs.get(class_id)
349 group = self.pm_group_metrics.get(OnuPmIntervalMetrics.ME_ID_INFO.get(class_id, ''))
350
351 if config is not None and group is not None and group.enabled:
352 # Extract only the metrics we need to publish
353 metrics = dict()
354 context = {
355 'interval_start_time': str(now.replace(minute=int(now.minute / 15) * 15,
356 second=0,
357 microsecond=0).timestamp)
358 }
359 for metric, config_item in config.items():
360 if config_item.type == PmConfig.CONTEXT and metric in interval_data:
361 context[metric] = str(interval_data[metric])
362
363 elif (config_item.type in (PmConfig.COUNTER, PmConfig.GAUGE, PmConfig.STATE) and
364 metric in interval_data and
365 config_item.enabled):
366 metrics[metric] = interval_data[metric]
367
368 if len(metrics):
369 metadata = MetricMetaData(title=group.group_name,
370 ts=now.float_timestamp,
371 logical_device_id=self.logical_device_id,
372 serial_no=self.serial_number,
373 device_id=self.device_id,
374 context=context)
375 slice_data = [MetricInformation(metadata=metadata, metrics=metrics)]
376
377 kpi_event = KpiEvent2(type=KpiEventType.slice,
378 ts=now.float_timestamp,
379 slice_data=slice_data)
380 self.adapter_agent.submit_kpis(kpi_event)
381
382 except Exception as e:
383 self.log.exception('failed-to-submit-kpis', e=e)