blob: 25befe2c3775b39371aed0c94482f3daacecf147 [file] [log] [blame]
Girish Gowdrae09a6202021-01-12 18:10:59 -08001/*
2 * Copyright 2021-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000017//Package pmmgr provides the utilities to manage onu metrics
18package pmmgr
Girish Gowdrae09a6202021-01-12 18:10:59 -080019
20import (
21 "context"
Girish Gowdra0e533642021-03-02 22:02:51 -080022 "encoding/json"
Girish Gowdrae09a6202021-01-12 18:10:59 -080023 "fmt"
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +000024 "math"
25 "sync"
26 "time"
27
Girish Gowdrae0140f02021-02-02 16:55:09 -080028 "github.com/looplab/fsm"
mpagenko836a1fd2021-11-01 16:12:42 +000029 "github.com/opencord/omci-lib-go/v2"
30 me "github.com/opencord/omci-lib-go/v2/generated"
khenaidoo7d3c5582021-08-11 18:09:44 -040031 "github.com/opencord/voltha-lib-go/v7/pkg/db"
32 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000034 cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
khenaidoo7d3c5582021-08-11 18:09:44 -040035 "github.com/opencord/voltha-protos/v5/go/extension"
36 "github.com/opencord/voltha-protos/v5/go/voltha"
Girish Gowdrae09a6202021-01-12 18:10:59 -080037)
38
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000039// events of L2 PM FSM
Girish Gowdrae0140f02021-02-02 16:55:09 -080040const (
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000041 L2PmEventInit = "L2PmEventInit"
42 L2PmEventTick = "L2PmEventTick"
43 L2PmEventSuccess = "L2PmEventSuccess"
44 L2PmEventFailure = "L2PmEventFailure"
45 L2PmEventAddMe = "L2PmEventAddMe"
46 L2PmEventDeleteMe = "L2PmEventDeleteMe"
47 L2PmEventStop = "L2PmEventStop"
Girish Gowdrae0140f02021-02-02 16:55:09 -080048)
49
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000050// states of L2 PM FSM
51const (
52 L2PmStNull = "L2PmStNull"
53 L2PmStStarting = "L2PmStStarting"
54 L2PmStSyncTime = "L2PmStSyncTime"
55 L2PmStIdle = "L2PmStIdle"
56 L2PmStCreatePmMe = "L2PmStCreatePm"
57 L2PmStDeletePmMe = "L2PmStDeletePmMe"
58 L2PmStCollectData = "L2PmStCollectData"
59)
60
61// CL2PmFsmIdleState - TODO: add comment
62const CL2PmFsmIdleState = L2PmStIdle
Girish Gowdrae0140f02021-02-02 16:55:09 -080063
Girish Gowdra5a7c4922021-01-22 18:33:41 -080064// general constants used for overall Metric Collection management
65const (
66 DefaultMetricCollectionFrequency = 15 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
67 GroupMetricEnabled = true // This is READONLY and cannot be changed from VOLTHA NBI
68 DefaultFrequencyOverrideEnabled = true // This is READONLY and cannot be changed from VOLTHA NBI
69 FrequencyGranularity = 5 // The frequency (in seconds) has to be multiple of 5. This setting cannot changed later.
Girish Gowdraabcceb12022-04-13 23:35:22 -070070 MaxTimeForPmFsmShutDown = 120 // in seconds
Girish Gowdra5a7c4922021-01-22 18:33:41 -080071)
72
Himani Chawla43f95ff2021-06-03 00:24:12 +053073// constants for ethernet frame extended pm collection
74const (
75 ExtendedPmCreateAttempts = 3
76 UnsupportedCounterValue32bit uint64 = 4294967294
77 UnsupportedCounterValue64bit uint64 = 18446744073709551614
Himani Chawla43f95ff2021-06-03 00:24:12 +053078)
79
Girish Gowdra5a7c4922021-01-22 18:33:41 -080080// OpticalPowerGroupMetrics are supported optical pm names
81var OpticalPowerGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrae20a4f62021-03-09 16:06:23 -080082 "ani_g_instance_id": voltha.PmConfig_CONTEXT,
83 "transmit_power_dBm": voltha.PmConfig_GAUGE,
84 "receive_power_dBm": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -080085}
86
87// OpticalPowerGroupMetrics specific constants
88const (
Girish Gowdrae0140f02021-02-02 16:55:09 -080089 OpticalPowerGroupMetricName = "PON_Optical"
Girish Gowdra5a7c4922021-01-22 18:33:41 -080090 OpticalPowerGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
91 OpticalPowerMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
92)
93
94// UniStatusGroupMetrics are supported UNI status names
95var UniStatusGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrad3436802021-06-28 13:15:40 -070096 "uni_port_no": voltha.PmConfig_CONTEXT,
97 "me_class_id": voltha.PmConfig_CONTEXT,
98 "entity_id": voltha.PmConfig_CONTEXT,
99 "configuration_ind": voltha.PmConfig_GAUGE,
100 "oper_status": voltha.PmConfig_GAUGE,
101 "uni_admin_state": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800102}
103
104// UniStatusGroupMetrics specific constants
105const (
Girish Gowdrae0140f02021-02-02 16:55:09 -0800106 UniStatusGroupMetricName = "UNI_Status"
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800107 UniStatusGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
108 UniStatusMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
109)
110
Girish Gowdrae0140f02021-02-02 16:55:09 -0800111// *** Classical L2 PM Counters begin ***
112
113// EthernetBridgeHistory are supported ethernet bridge history counters fetched from
114// Ethernet Frame Performance Monitoring History Data Downstream and Ethernet Frame Performance Monitoring History Data Upstream MEs.
115var EthernetBridgeHistory = map[string]voltha.PmConfig_PmType{
116 "class_id": voltha.PmConfig_CONTEXT,
117 "entity_id": voltha.PmConfig_CONTEXT,
118 "interval_end_time": voltha.PmConfig_CONTEXT,
119 "parent_class_id": voltha.PmConfig_CONTEXT,
120 "parent_entity_id": voltha.PmConfig_CONTEXT,
121 "upstream": voltha.PmConfig_CONTEXT,
122
123 "drop_events": voltha.PmConfig_COUNTER,
124 "octets": voltha.PmConfig_COUNTER,
125 "packets": voltha.PmConfig_COUNTER,
126 "broadcast_packets": voltha.PmConfig_COUNTER,
127 "multicast_packets": voltha.PmConfig_COUNTER,
128 "crc_errored_packets": voltha.PmConfig_COUNTER,
129 "undersize_packets": voltha.PmConfig_COUNTER,
130 "oversize_packets": voltha.PmConfig_COUNTER,
131 "64_octets": voltha.PmConfig_COUNTER,
132 "65_to_127_octets": voltha.PmConfig_COUNTER,
133 "128_to_255_octets": voltha.PmConfig_COUNTER,
134 "256_to_511_octets": voltha.PmConfig_COUNTER,
135 "512_to_1023_octets": voltha.PmConfig_COUNTER,
136 "1024_to_1518_octets": voltha.PmConfig_COUNTER,
137}
138
139// EthernetUniHistory are supported ethernet uni history counters fetched from
140// Ethernet Performance Monitoring History Data ME.
141var EthernetUniHistory = map[string]voltha.PmConfig_PmType{
142 "class_id": voltha.PmConfig_CONTEXT,
143 "entity_id": voltha.PmConfig_CONTEXT,
144 "interval_end_time": voltha.PmConfig_CONTEXT,
145
146 "fcs_errors": voltha.PmConfig_COUNTER,
147 "excessive_collision_counter": voltha.PmConfig_COUNTER,
148 "late_collision_counter": voltha.PmConfig_COUNTER,
149 "frames_too_long": voltha.PmConfig_COUNTER,
150 "buffer_overflows_on_rx": voltha.PmConfig_COUNTER,
151 "buffer_overflows_on_tx": voltha.PmConfig_COUNTER,
152 "single_collision_frame_counter": voltha.PmConfig_COUNTER,
153 "multiple_collisions_frame_counter": voltha.PmConfig_COUNTER,
154 "sqe_counter": voltha.PmConfig_COUNTER,
155 "deferred_tx_counter": voltha.PmConfig_COUNTER,
156 "internal_mac_tx_error_counter": voltha.PmConfig_COUNTER,
157 "carrier_sense_error_counter": voltha.PmConfig_COUNTER,
158 "alignment_error_counter": voltha.PmConfig_COUNTER,
159 "internal_mac_rx_error_counter": voltha.PmConfig_COUNTER,
160}
161
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800162// FecHistory is supported FEC Performance Monitoring History Data related metrics
163var FecHistory = map[string]voltha.PmConfig_PmType{
164 "class_id": voltha.PmConfig_CONTEXT,
165 "entity_id": voltha.PmConfig_CONTEXT,
166 "interval_end_time": voltha.PmConfig_CONTEXT,
167
168 "corrected_bytes": voltha.PmConfig_COUNTER,
169 "corrected_code_words": voltha.PmConfig_COUNTER,
170 "uncorrectable_code_words": voltha.PmConfig_COUNTER,
171 "total_code_words": voltha.PmConfig_COUNTER,
172 "fec_seconds": voltha.PmConfig_COUNTER,
173}
174
175// GemPortHistory is supported GEM Port Network Ctp Performance Monitoring History Data
176// related metrics
177var GemPortHistory = map[string]voltha.PmConfig_PmType{
178 "class_id": voltha.PmConfig_CONTEXT,
179 "entity_id": voltha.PmConfig_CONTEXT,
180 "interval_end_time": voltha.PmConfig_CONTEXT,
181
182 "transmitted_gem_frames": voltha.PmConfig_COUNTER,
183 "received_gem_frames": voltha.PmConfig_COUNTER,
184 "received_payload_bytes": voltha.PmConfig_COUNTER,
185 "transmitted_payload_bytes": voltha.PmConfig_COUNTER,
186 "encryption_key_errors": voltha.PmConfig_COUNTER,
187}
188
Himani Chawla43f95ff2021-06-03 00:24:12 +0530189var maskToEthernetFrameExtendedPM32Bit = map[uint16][]string{
190 0x3F00: {"drop_events", "octets", "frames", "broadcast_frames", "multicast_frames", "crc_errored_frames"},
191 0x00FC: {"undersize_frames", "oversize_frames", "64_octets", "65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
192 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
193}
194
195var maskToEthernetFrameExtendedPM64Bit = map[uint16][]string{
196 0x3800: {"drop_events", "octets", "frames"},
197 0x0700: {"broadcast_frames", "multicast_frames", "crc_errored_frames"},
198 0x00E0: {"undersize_frames", "oversize_frames", "64_octets"},
199 0x001C: {"65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
200 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
201}
202
Girish Gowdrae0140f02021-02-02 16:55:09 -0800203// Constants specific for L2 PM collection
204const (
205 L2PmCollectionInterval = 15 * 60 // Unit in seconds. Do not change this as this fixed by OMCI specification for L2 PM counters
206 SyncTimeRetryInterval = 15 // Unit seconds
207 L2PmCreateAttempts = 3
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800208 L2PmDeleteAttempts = 3
Girish Gowdrae0140f02021-02-02 16:55:09 -0800209 L2PmCollectAttempts = 3
Girish Gowdra453750f2021-02-16 16:36:46 -0800210 // Per Table 11.2.9-1 – OMCI baseline message limitations in G.988 spec, the max GET Response
211 // payload size is 25. We define 24 (one less) to allow for dynamic insertion of IntervalEndTime
212 // attribute (1 byte) in L2 PM GET Requests.
Himani Chawla43f95ff2021-06-03 00:24:12 +0530213 MaxL2PMGetPayLoadSize = 24
214 MaxEthernetFrameExtPmPayloadSize = 25
Girish Gowdrae0140f02021-02-02 16:55:09 -0800215)
216
217// EthernetUniHistoryName specific constants
218const (
219 EthernetBridgeHistoryName = "Ethernet_Bridge_Port_History"
220 EthernetBridgeHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
221 EthernetBridgeHistoryFrequency = L2PmCollectionInterval
222)
223
224// EthernetBridgeHistory specific constants
225const (
226 EthernetUniHistoryName = "Ethernet_UNI_History"
227 EthernetUniHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
228 EthernetUniHistoryFrequency = L2PmCollectionInterval
229)
230
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800231// FecHistory specific constants
232const (
233 FecHistoryName = "FEC_History"
234 FecHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
235 FecHistoryFrequency = L2PmCollectionInterval
236)
237
238// GemPortHistory specific constants
239const (
240 GemPortHistoryName = "GEM_Port_History"
241 GemPortHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
242 GemPortHistoryFrequency = L2PmCollectionInterval
243)
244
Holger Hildebrandt60652202021-11-02 11:09:36 +0000245// CPmKvStorePrefixBase - kv store base path of ONU specific PM data
246const CPmKvStorePrefixBase = cmn.CBasePathOnuKVStore + "/pm-data" // <some-base-path>/openonu/pm-data
247
Girish Gowdra0e533642021-03-02 22:02:51 -0800248// KV Store related constants
249const (
Holger Hildebrandt60652202021-11-02 11:09:36 +0000250 cPmKvStorePrefix = CPmKvStorePrefixBase + "/%s" // <some-base-path>/openonu/pm-data/<onu-device-id>
Himani Chawla43f95ff2021-06-03 00:24:12 +0530251 cPmAdd = "add"
252 cPmAdded = "added"
253 cPmRemove = "remove"
254 cPmRemoved = "removed"
255 cExtPmKvStorePrefix = "%s/omci_me" //<some-base-path>/omci_me/<onu_vendor>/<onu_equipment_id>/<onu_sw_version>
Girish Gowdra0e533642021-03-02 22:02:51 -0800256)
257
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800258// Defines the type for generic metric population function
259type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
260
Girish Gowdrae0140f02021-02-02 16:55:09 -0800261// *** Classical L2 PM Counters end ***
262
Girish Gowdra0e533642021-03-02 22:02:51 -0800263type pmMEData struct {
264 InstancesActive []uint16 `json:"instances_active"` // list of active ME instance IDs for the group
265 InstancesToDelete []uint16 `json:"instances_to_delete"` // list of ME instance IDs marked for deletion for the group
266 InstancesToAdd []uint16 `json:"instances_to_add"` // list of ME instance IDs marked for addition for the group
267}
268
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800269type groupMetric struct {
270 groupName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000271 Enabled bool
272 Frequency uint32 // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800273 metricMap map[string]voltha.PmConfig_PmType
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000274 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
275 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdrae0140f02021-02-02 16:55:09 -0800276 collectAttempts uint32 // number of attempts to collect L2 PM data
Girish Gowdra0e533642021-03-02 22:02:51 -0800277 pmMEData *pmMEData
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800278}
279
280type standaloneMetric struct {
281 metricName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000282 Enabled bool
283 Frequency uint32 // valid only if FrequencyOverride is enabled.
284 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800285}
286
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000287// OnuMetricsManager - TODO: add comment
288type OnuMetricsManager struct {
289 deviceID string
290 pDeviceHandler cmn.IdeviceHandler
291 pOnuDeviceEntry cmn.IonuDeviceEntry
292 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800293
Himani Chawlaee10b542021-09-20 16:46:40 +0530294 opticalMetricsChan chan me.AttributeValueMap
295 uniStatusMetricsChan chan me.AttributeValueMap
296 l2PmChan chan me.AttributeValueMap
297 extendedPmMeChan chan me.AttributeValueMap
298 syncTimeResponseChan chan bool // true is success, false is fail
299 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
300 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -0800301
302 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
303 l2PmToDelete []string // list of L2 PMs to delete
304 l2PmToAdd []string // list of L2 PM to add
Girish Gowdrae09a6202021-01-12 18:10:59 -0800305
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000306 GroupMetricMap map[string]*groupMetric
307 StandaloneMetricMap map[string]*standaloneMetric
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800308
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000309 StopProcessingOmciResponses chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700310 omciProcessingActive bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800311
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000312 StopTicks chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700313 tickGenerationActive bool
Girish Gowdrae0140f02021-02-02 16:55:09 -0800314
Girish Gowdraabcceb12022-04-13 23:35:22 -0700315 deviceDeletionInProgress bool
316 GarbageCollectionComplete chan bool
317
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000318 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800319
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000320 OnuMetricsManagerLock sync.RWMutex
Girish Gowdra0e533642021-03-02 22:02:51 -0800321
322 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530323
324 supportedEthernetFrameExtendedPMClass me.ClassID
Himani Chawlac77d5372021-07-12 15:42:26 +0530325 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
326 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530327 extPmKvStore *db.Backend
328 onuEthernetFrameExtendedPmLock sync.RWMutex
329 isDeviceReadyToCollectExtendedPmStats bool
Himani Chawlaee10b542021-09-20 16:46:40 +0530330 isEthernetFrameExtendedPmOperationOngoing bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800331}
332
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000333// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800334// The metrics manager module is responsible for configuration and management of individual and group metrics.
335// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
336// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
337// the collection interval configurable.
338// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
339// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000340func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800341
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000342 var metricsManager OnuMetricsManager
343 metricsManager.deviceID = dh.GetDeviceID()
344 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800345 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000346 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800347
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000348 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800349 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
350 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800351 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530352 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800353
354 metricsManager.syncTimeResponseChan = make(chan bool)
355 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530356 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800357
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000358 metricsManager.StopProcessingOmciResponses = make(chan bool)
359 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800360
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000361 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
362 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800363
Himani Chawlac77d5372021-07-12 15:42:26 +0530364 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
365 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530366
Girish Gowdraabcceb12022-04-13 23:35:22 -0700367 // make this a buffered channel so that the sender is not blocked for any reason if there is no listener
368 metricsManager.GarbageCollectionComplete = make(chan bool, 1)
369
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000370 if dh.GetPmConfigs() == nil { // dh.GetPmConfigs() is NOT nil if adapter comes back from a restart. We should NOT go back to defaults in this case
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800371 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800372 }
373
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800374 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800375
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800376 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800377 return nil
378 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800379
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800380 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000381 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800382
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000383 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
384 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800385 if metricsManager.pmKvStore == nil {
386 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000387 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800388 return nil
389 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700390 // restore data from KV store
391 if err := metricsManager.restorePmData(ctx); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000392 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700393 // we continue given that it does not effect the actual services for the ONU,
394 // but there may be some negative effect on PM collection (there may be some mismatch in
395 // the actual PM config and what is present on the device).
396 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800397
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000398 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
399 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530400 if metricsManager.extPmKvStore == nil {
401 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000402 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530403 return nil
404 }
405
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000406 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800407 return &metricsManager
408}
409
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000410// InitializeMetricCollectionTime - TODO: add comment
411func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
412 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
413 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
414 mm.OnuMetricsManagerLock.Lock()
415 defer mm.OnuMetricsManagerLock.Unlock()
416 for _, v := range mm.GroupMetricMap {
417 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
418 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800419 }
420 }
421
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000422 for _, v := range mm.StandaloneMetricMap {
423 if v.Enabled {
424 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800425 }
426 }
427 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000428 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
429 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800430 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000431 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800432}
433
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000434// UpdateDefaultFrequency - TODO: add comment
435func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800436 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800437 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800438 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
439 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
440 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000441 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
442 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
443 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
444 logger.Debugw(ctx, "frequency-updated--new-frequency", log.Fields{"device-id": mm.deviceID, "frequency": mm.pDeviceHandler.GetPmConfigs().DefaultFreq})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800445 return nil
446}
447
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000448// UpdateGroupFreq - TODO: add comment
449func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800450 var newGroupFreq uint32
451 found := false
452 groupSliceIdx := 0
453 var group *voltha.PmGroupConfig
454 for groupSliceIdx, group = range pmConfigs.Groups {
455 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800456 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
457 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
458 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
459 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800460 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800461 newGroupFreq = group.GroupFreq
462 found = true
463 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800464 }
465 }
466 // if not found update group freq and next collection interval for the group
467 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000468 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800469 return fmt.Errorf("group-name-not-found-%v", aGroupName)
470 }
471
472 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000473 mm.OnuMetricsManagerLock.Lock()
474 defer mm.OnuMetricsManagerLock.Unlock()
475 for k, v := range mm.GroupMetricMap {
476 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
477 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800478 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000479 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800480 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000481 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800482 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000483 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800484 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800485 }
486 }
487 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000488 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800489 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
490 }
491 return nil
492}
493
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000494// UpdateMetricFreq - TODO: add comment
495func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800496 var newMetricFreq uint32
497 found := false
498 metricSliceIdx := 0
499 var metric *voltha.PmConfig
500 for metricSliceIdx, metric = range pmConfigs.Metrics {
501 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800502 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
503 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
504 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
505 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800506 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800507 newMetricFreq = metric.SampleFreq
508 found = true
509 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800510 }
511 }
512 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000513 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800514 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
515 }
516
517 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000518 mm.OnuMetricsManagerLock.Lock()
519 defer mm.OnuMetricsManagerLock.Unlock()
520 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800521 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000522 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800523 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000524 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800525 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000526 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800527 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000528 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800529 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800530 }
531 }
532 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000533 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800534 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
535 }
536 return nil
537}
538
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000539// UpdateGroupSupport - TODO: add comment
540func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800541 groupSliceIdx := 0
542 var group *voltha.PmGroupConfig
543
544 for groupSliceIdx, group = range pmConfigs.Groups {
545 if group.GroupName == aGroupName {
546 break
547 }
548 }
549 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000550 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800551 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
552 }
553
554 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000555 mm.OnuMetricsManagerLock.Lock()
556 defer mm.OnuMetricsManagerLock.Unlock()
557 for k, v := range mm.GroupMetricMap {
558 if k == aGroupName && v.Enabled != group.Enabled {
559 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
560 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800561 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000562 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800563 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800564 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800565 // If the group support flag toggles too soon, we need to delete the group name from l2PmToDelete slice
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800566 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
567
568 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
569 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
570 // take further action
571 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800572 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800573 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000574 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
575 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800576 }
577 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000578 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800579 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800580 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800581 // If the group support flag toggles too soon, we need to delete the group name from l2PmToAdd slice
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800582 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
583
584 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
585 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
586 // take further action
587 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800588 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800589 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800590 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800591 }
592 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000593 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800594 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000595 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800596 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000597 logger.Infow(ctx, "group metric support updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800598 }
599 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800600 }
601 }
602
603 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000604 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800605 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
606 }
607 return nil
608}
609
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000610// UpdateMetricSupport - TODO: add comment
611func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800612 metricSliceIdx := 0
613 var metric *voltha.PmConfig
614
615 for metricSliceIdx, metric = range pmConfigs.Metrics {
616 if metric.Name == aMetricName {
617 break
618 }
619 }
620
621 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000622 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800623 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
624 }
625
626 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000627 mm.OnuMetricsManagerLock.Lock()
628 defer mm.OnuMetricsManagerLock.Unlock()
629 for k, v := range mm.StandaloneMetricMap {
630 if k == aMetricName && v.Enabled != metric.Enabled {
631 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
632 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800633 // If the standalone metric is now enabled and frequency override is enabled, set the next metric collection time
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000634 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
635 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800636 }
637 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000638 logger.Infow(ctx, "standalone metric support updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName, "enabled": metric.Enabled})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800639 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800640 }
641 }
642 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000643 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800644 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
645 }
646 return nil
647}
648
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000649// CollectAllGroupAndStandaloneMetrics - TODO: add comment
650func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
651 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800652 go mm.collectAllGroupMetrics(ctx)
653 } else {
654 go mm.collectAllStandaloneMetrics(ctx)
655 }
656}
657
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000658func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800659 go func() {
660 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300661 metricInfo, err := mm.collectOpticalMetrics(ctx)
662 if err != nil {
663 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000664 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300665 return
666 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800667 if metricInfo != nil {
668 mm.publishMetrics(ctx, metricInfo)
669 }
670 }()
671
672 go func() {
673 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300674 metricInfo, err := mm.collectUniStatusMetrics(ctx)
675 if err != nil {
676 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000677 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300678 return
679 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800680 if metricInfo != nil {
681 mm.publishMetrics(ctx, metricInfo)
682 }
683 }()
684
685 // Add more here
686}
687
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000688func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800689 // None exists as of now, add when available here
690}
691
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000692// CollectGroupMetric - TODO: add comment
693func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800694 switch groupName {
695 case OpticalPowerGroupMetricName:
696 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300697 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800698 mm.publishMetrics(ctx, mi)
699 }
700 }()
701 case UniStatusGroupMetricName:
702 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300703 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800704 mm.publishMetrics(ctx, mi)
705 }
706 }()
707 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000708 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800709 }
710}
711
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000712// CollectStandaloneMetric - TODO: add comment
713func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800714 switch metricName {
715 // None exist as of now, add when available
716 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000717 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800718 }
719}
720
721// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000722func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
723 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800724
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000725 mm.OnuMetricsManagerLock.RLock()
726 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
727 mm.OnuMetricsManagerLock.RUnlock()
728 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300729 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800730 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000731 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800732
Girish Gowdrae09a6202021-01-12 18:10:59 -0800733 var metricInfoSlice []*voltha.MetricInformation
734 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000735 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
736 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
737 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800738
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800739 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800740 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800741 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800742 Ts: float64(raisedTs),
743 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000744 DeviceId: mm.deviceID,
745 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
746 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800747 }
748
Girish Gowdrae09a6202021-01-12 18:10:59 -0800749 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000750 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800751loop:
752 for _, anigInstID := range anigInstKeys {
753 var meAttributes me.AttributeValueMap
754 opticalMetrics := make(map[string]float32)
755 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000756 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000757 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300758 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000759 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
760 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300761 return nil, err
762 }
763
764 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800765 select {
766 case meAttributes = <-mm.opticalMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000767 logger.Debugw(ctx, "received optical metrics", log.Fields{"device-id": mm.deviceID})
768 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
769 logger.Errorw(ctx, "timeout waiting for omci-get response for optical metrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800770 // The metrics will be empty in this case
771 break loop
772 }
773 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800774 for k := range OpticalPowerGroupMetrics {
775 switch k {
776 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000777 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800778 opticalMetrics[k] = float32(val.(uint16))
779 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800780 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000781 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000782 opticalMetrics[k] = float32(math.Round((float64(cmn.TwosComplementToSignedInt16(val.(uint16)))/500.0)*10) / 10) // convert to dBm rounded of to single decimal place
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800783 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800784 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000785 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000786 opticalMetrics[k] = float32(math.Round((float64(cmn.TwosComplementToSignedInt16(val.(uint16)))/500.0)*10) / 10) // convert to dBm rounded of to single decimal place
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800787 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800788 default:
789 // do nothing
790 }
791 }
792 }
793 // create slice of metrics given that there could be more than one ANI-G instance and
794 // optical metrics are collected per ANI-G instance
795 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
796 metricInfoSlice = append(metricInfoSlice, &metricInfo)
797 }
798
ozgecanetsiab36ed572021-04-01 10:38:48 +0300799 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800800}
801
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800802// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800803// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000804func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
805 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
806 mm.OnuMetricsManagerLock.RLock()
807 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
808 mm.OnuMetricsManagerLock.RUnlock()
809 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300810 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800811 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000812 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800813
Girish Gowdrae09a6202021-01-12 18:10:59 -0800814 var metricInfoSlice []*voltha.MetricInformation
815 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000816 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
817 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
818 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800819
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800820 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800821 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700822 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800823 Ts: float64(raisedTs),
824 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000825 DeviceId: mm.deviceID,
826 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
827 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800828 }
829
Girish Gowdrae09a6202021-01-12 18:10:59 -0800830 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000831 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800832loop1:
833 for _, unigInstID := range unigInstKeys {
834 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
835 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
836 unigMetrics := make(map[string]float32)
837 var meAttributes me.AttributeValueMap
838 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000839 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000840 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300841 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000842 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
843 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300844 return nil, err
845 }
846 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800847 // Wait for metrics or timeout
848 select {
849 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000850 logger.Debugw(ctx, "received uni-g metrics", log.Fields{"device-id": mm.deviceID})
851 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
852 logger.Errorw(ctx, "timeout waiting for omci-get response for uni status", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800853 // The metrics could be empty in this case
854 break loop1
855 }
856 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800857 for k := range UniStatusGroupMetrics {
858 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800859 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000860 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800861 unigMetrics[k] = float32(val.(byte))
862 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800863 default:
864 // do nothing
865 }
866 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000867 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800868 entityID := val.(uint16)
869 unigMetrics["entity_id"] = float32(entityID)
870 // TODO: Rlock needed for reading uniEntityMap? May not be needed given uniEntityMap is populated setup at initial ONU bring up
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000871 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
872 if uni.EntityID == entityID {
873 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700874 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800875 }
876 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800877 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700878 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800879
Girish Gowdrae09a6202021-01-12 18:10:59 -0800880 // create slice of metrics given that there could be more than one UNI-G instance
881 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
882 metricInfoSlice = append(metricInfoSlice, &metricInfo)
883 }
884 }
885
886 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000887 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800888loop2:
889 for _, pptpInstID := range pptpInstKeys {
890 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
891 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
892 var meAttributes me.AttributeValueMap
893 pptpMetrics := make(map[string]float32)
894
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000895 requestedAttributes := me.AttributeValueMap{
896 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
897 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
898 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
899 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
900 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300901 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000902 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
903 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300904 return nil, err
905 }
906 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800907 // Wait for metrics or timeout
908 select {
909 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000910 logger.Debugw(ctx, "received pptp metrics", log.Fields{"device-id": mm.deviceID})
911 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
912 logger.Errorw(ctx, "timeout waiting for omci-get response for uni status", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800913 // The metrics could be empty in this case
914 break loop2
915 }
916
917 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800918 for k := range UniStatusGroupMetrics {
919 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700920 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000921 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800922 pptpMetrics[k] = float32(val.(byte))
923 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800924 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000925 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800926 pptpMetrics[k] = float32(val.(byte))
927 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800928 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000929 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800930 pptpMetrics[k] = float32(val.(byte))
931 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800932 default:
933 // do nothing
934 }
935 }
936 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000937 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800938 entityID := val.(uint16)
939 pptpMetrics["entity_id"] = float32(entityID)
940 // TODO: Rlock needed for reading uniEntityMap? May not be needed given uniEntityMap is populated setup at initial ONU bring up
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000941 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
942 if uni.EntityID == entityID {
943 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700944 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800945 }
946 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800947 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700948 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800949
Girish Gowdrae09a6202021-01-12 18:10:59 -0800950 // create slice of metrics given that there could be more than one PPTP instance and
951 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
952 metricInfoSlice = append(metricInfoSlice, &metricInfo)
953 }
954
955 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000956 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800957loop3:
958 for _, veipInstID := range veipInstKeys {
959 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
960 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
961 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800962 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800963
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000964 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0, me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000965 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300966 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000967 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
968 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300969 return nil, err
970 }
971 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800972 // Wait for metrics or timeout
973 select {
974 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000975 logger.Debugw(ctx, "received veip metrics", log.Fields{"device-id": mm.deviceID})
976 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
977 logger.Errorw(ctx, "timeout waiting for omci-get response for uni status", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800978 // The metrics could be empty in this case
979 break loop3
980 }
981
982 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800983 for k := range UniStatusGroupMetrics {
984 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800985 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000986 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800987 veipMetrics[k] = float32(val.(byte))
988 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800989 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000990 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800991 veipMetrics[k] = float32(val.(byte))
992 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800993 default:
994 // do nothing
995 }
996 }
997 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800998
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000999 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001000 entityID := val.(uint16)
1001 veipMetrics["entity_id"] = float32(entityID)
1002 // TODO: Rlock needed for reading uniEntityMap? May not be needed given uniEntityMap is populated setup at initial ONU bring up
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001003 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1004 if uni.EntityID == entityID {
1005 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001006 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001007 }
1008 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001009 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001010 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001011
Girish Gowdrae09a6202021-01-12 18:10:59 -08001012 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001013 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001014 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1015 }
1016
ozgecanetsiab36ed572021-04-01 10:38:48 +03001017 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001018}
1019
1020// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001021func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001022 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001023 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001024 ke.SliceData = metricInfo
1025 ke.Type = voltha.KpiEventType_slice
1026 ke.Ts = float64(ts)
1027
Himani Chawlaf9768882021-12-01 00:18:58 +05301028 if err := mm.pDeviceHandler.GetEventProxy().SendKpiEvent(ctx, "STATS_PUBLISH_EVENT", &ke, voltha.EventCategory_EQUIPMENT, voltha.EventSubCategory_ONU, ts); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001029 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001030 }
1031}
1032
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001033// ProcessOmciMessages - TODO: add comment
1034func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context) {
1035 logger.Infow(ctx, "Start routine to process OMCI-GET messages for device-id", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001036 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001037 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001038 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001039 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001040 // is stopped - as a result of ONU going down.
1041 mm.flushMetricCollectionChannels(ctx)
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001042 mm.updateOmciProcessingStatus(true)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001043 for {
1044 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001045 case <-mm.StopProcessingOmciResponses: // stop this routine
1046 logger.Infow(ctx, "Stop routine to process OMCI-GET messages for device-id", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001047 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001048 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001049 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001050 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001051 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001052 continue
1053 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001054 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001055
1056 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001057 case cmn.OMCI:
1058 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001059 mm.handleOmciMessage(ctx, msg)
1060 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001061 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001062 }
1063 }
1064 }
1065}
1066
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001067func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1068 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001069 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1070 switch msg.OmciMsg.MessageType {
1071 case omci.GetResponseType:
1072 //TODO: error handling
1073 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001074 case omci.SynchronizeTimeResponseType:
1075 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1076 case omci.CreateResponseType:
1077 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1078 case omci.DeleteResponseType:
1079 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301080 case omci.GetCurrentDataResponseType:
1081 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301082 case omci.SetResponseType:
1083 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001084 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001085 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001086
1087 }
1088}
1089
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001090func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001091 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1092 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001093 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1094 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001095 }
1096 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1097 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001098 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1099 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001100 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001101 logger.Debugw(ctx, "OMCI GetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001102 if msgObj.Result == me.Success {
1103 meAttributes := msgObj.Attributes
1104 switch msgObj.EntityClass {
1105 case me.AniGClassID:
1106 mm.opticalMetricsChan <- meAttributes
1107 return nil
1108 case me.UniGClassID:
1109 mm.uniStatusMetricsChan <- meAttributes
1110 return nil
1111 case me.PhysicalPathTerminationPointEthernetUniClassID:
1112 mm.uniStatusMetricsChan <- meAttributes
1113 return nil
1114 case me.VirtualEthernetInterfacePointClassID:
1115 mm.uniStatusMetricsChan <- meAttributes
1116 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001117 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1118 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001119 me.EthernetPerformanceMonitoringHistoryDataClassID,
1120 me.FecPerformanceMonitoringHistoryDataClassID,
1121 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001122 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301123 return nil
1124 case me.EthernetFrameExtendedPmClassID,
1125 me.EthernetFrameExtendedPm64BitClassID:
1126 mm.extendedPmMeChan <- meAttributes
1127 return nil
1128 default:
1129 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001130 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301131 }
1132 } else {
1133 meAttributes := msgObj.Attributes
1134 switch msgObj.EntityClass {
1135 case me.EthernetFrameExtendedPmClassID,
1136 me.EthernetFrameExtendedPm64BitClassID:
1137 // not all counters may be supported in which case we have seen some ONUs throwing
1138 // AttributeFailure error code, while correctly populating other counters it supports
1139 mm.extendedPmMeChan <- meAttributes
1140 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001141 default:
1142 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001143 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001144 }
1145 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001146 return fmt.Errorf("unhandled-omci-get-response-message")
1147}
1148
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001149func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301150 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1151 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001152 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1153 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301154 }
1155 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1156 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001157 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1158 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301159 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001160 logger.Debugw(ctx, "OMCI GetCurrentDataResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301161 if msgObj.Result == me.Success {
1162 meAttributes := msgObj.Attributes
1163 switch msgObj.EntityClass {
1164 case me.EthernetFrameExtendedPmClassID,
1165 me.EthernetFrameExtendedPm64BitClassID:
1166 mm.extendedPmMeChan <- meAttributes
1167 return nil
1168 default:
1169 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001170 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301171 }
1172 } else {
1173 meAttributes := msgObj.Attributes
1174 switch msgObj.EntityClass {
1175 case me.EthernetFrameExtendedPmClassID,
1176 me.EthernetFrameExtendedPm64BitClassID:
1177 // not all counters may be supported in which case we have seen some ONUs throwing
1178 // AttributeFailure error code, while correctly populating other counters it supports
1179 mm.extendedPmMeChan <- meAttributes
1180 return nil
1181 default:
1182 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001183 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301184 }
1185 }
1186 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1187}
1188
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001189func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001190 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1191 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001192 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1193 return fmt.Errorf("omci Msg layer could not be detected for synchronize time response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001194 }
1195 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1196 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001197 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1198 return fmt.Errorf("omci Msg layer could not be assigned for synchronize time response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001199 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001200 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001201 if msgObj.Result == me.Success {
1202 switch msgObj.EntityClass {
1203 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001204 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001205 mm.syncTimeResponseChan <- true
1206 return nil
1207 default:
1208 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001209 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001210 }
1211 }
1212 mm.syncTimeResponseChan <- false
1213 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1214 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001215}
1216
Himani Chawlaee10b542021-09-20 16:46:40 +05301217func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1218 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1219 if msgLayer == nil {
1220 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1221 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1222 }
1223 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1224 if !msgOk {
1225 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1226 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1227 }
1228 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1229 switch msgObj.EntityClass {
1230 case me.EthernetFrameExtendedPmClassID,
1231 me.EthernetFrameExtendedPm64BitClassID:
1232 mm.extendedPMMeResponseChan <- msgObj.Result
1233 return nil
1234 default:
1235 logger.Errorw(ctx, "unhandled omci set response message",
1236 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1237 }
1238 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1239}
1240
Girish Gowdrae09a6202021-01-12 18:10:59 -08001241// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001242func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001243 // flush commMetricsChan
1244 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001245 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001246 logger.Debug(ctx, "flushed common metrics channel")
1247 default:
1248 }
1249
1250 // flush opticalMetricsChan
1251 select {
1252 case <-mm.opticalMetricsChan:
1253 logger.Debug(ctx, "flushed optical metrics channel")
1254 default:
1255 }
1256
1257 // flush uniStatusMetricsChan
1258 select {
1259 case <-mm.uniStatusMetricsChan:
1260 logger.Debug(ctx, "flushed uni status metrics channel")
1261 default:
1262 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001263
1264 // flush syncTimeResponseChan
1265 select {
1266 case <-mm.syncTimeResponseChan:
1267 logger.Debug(ctx, "flushed sync time response channel")
1268 default:
1269 }
1270
1271 // flush l2PmChan
1272 select {
1273 case <-mm.l2PmChan:
1274 logger.Debug(ctx, "flushed L2 PM collection channel")
1275 default:
1276 }
1277
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001278 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001279 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001280 case <-mm.StopTicks:
1281 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001282 default:
1283 }
1284
1285}
1286
1287// ** L2 PM FSM Handlers start **
1288
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001289func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001290 if mm.GetdeviceDeletionInProgress() {
1291 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1292 return
1293 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001294
Girish Gowdrae0140f02021-02-02 16:55:09 -08001295 // Loop through all the group metrics
1296 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1297 // list of active L2 PM list then mark it for creation
1298 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1299 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001300 mm.OnuMetricsManagerLock.Lock()
1301 for n, g := range mm.GroupMetricMap {
1302 if g.IsL2PMCounter { // it is a l2 pm counter
1303 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001304 found := false
1305 inner1:
1306 for _, v := range mm.activeL2Pms {
1307 if v == n {
1308 found = true // metric already present in active l2 pm list
1309 break inner1
1310 }
1311 }
1312 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001313 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001314 }
1315 } else { // metric not enabled.
1316 found := false
1317 inner2:
1318 for _, v := range mm.activeL2Pms {
1319 if v == n {
1320 found = true // metric is found in active l2 pm list
1321 break inner2
1322 }
1323 }
1324 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001325 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001326 }
1327 }
1328 }
1329 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001330 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001331 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001332 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001333 go func() {
1334 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001335 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1336 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001337 }
1338 }()
1339}
1340
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001341func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001342 if mm.GetdeviceDeletionInProgress() {
1343 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1344 return
1345 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001346 // Sync time with the ONU to establish 15min boundary for PM collection.
1347 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001348 // device could be deleted while waiting on sync time response
1349 if mm.GetdeviceDeletionInProgress() {
1350 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1351 return
1352 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001353 go func() {
1354 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1355 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001356 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1357 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001358 }
1359 }()
1360 }
1361 // Initiate a tick generation routine every L2PmCollectionInterval
1362 go mm.generateTicks(ctx)
1363
1364 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001365 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1366 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001367 }
1368 }()
1369}
1370
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001371func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001372 // We need to reset the local data so that the L2 PM MEs are re-provisioned once the ONU is back up based on the latest PM CONFIG
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001373 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001374 mm.activeL2Pms = nil
1375 mm.l2PmToAdd = nil
1376 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001377 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001378 // If the FSM was stopped, then clear PM data from KV store
1379 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001380 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001381 _ = mm.clearPmGroupData(ctx) // ignore error
1382 }
1383
Girish Gowdraabcceb12022-04-13 23:35:22 -07001384 if mm.GetdeviceDeletionInProgress() {
1385 mm.pDeviceHandler = nil
1386 mm.pOnuDeviceEntry = nil
1387 mm.GarbageCollectionComplete <- true
1388 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001389}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001390func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1391 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001392 if mm.GetdeviceDeletionInProgress() {
1393 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1394 return
1395 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001396
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001397 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001398 numOfPmToDelete := len(mm.l2PmToDelete)
1399 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001400 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001401
1402 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001403 logger.Debugw(ctx, "state idle - pms to delete", log.Fields{"device-id": mm.deviceID, "pms-to-delete": numOfPmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001404 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001405 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1406 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001407 }
1408 }()
1409 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001410 logger.Debugw(ctx, "state idle - pms to add", log.Fields{"device-id": mm.deviceID, "pms-to-add": numOfPmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001411 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001412 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1413 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001414 }
1415 }()
1416 }
1417}
1418
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001419func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1420 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001421 if mm.GetdeviceDeletionInProgress() {
1422 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1423 return
1424 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001425 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001426 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001427 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1428 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001429 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001430
1431 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001432 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001433
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001434 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1435 mm.OnuMetricsManagerLock.RLock()
1436 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1437 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1438 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001439
Girish Gowdrae0140f02021-02-02 16:55:09 -08001440 switch n {
1441 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001442 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001443 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001444 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1445 metricInfoSlice = append(metricInfoSlice, metricInfo)
1446 }
1447 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1448 metricInfoSlice = append(metricInfoSlice, metricInfo)
1449 }
1450 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001451 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001452 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001453 for _, entityID := range copyOfEntityIDs {
1454 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1455 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001456 }
1457 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001458
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001459 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001460 for _, entityID := range copyOfEntityIDs {
1461 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001462 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001463 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001464 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001465 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001466 for _, entityID := range copyOfEntityIDs {
1467 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001468 metricInfoSlice = append(metricInfoSlice, metricInfo)
1469 }
1470 }
1471
Girish Gowdrae0140f02021-02-02 16:55:09 -08001472 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001473 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001474 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001475 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001476 }
1477 // Does not matter we send success or failure here.
1478 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1479 // we have not exceed max attempts to collect the PM data)
1480 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001481 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1482 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001483 }
1484 }()
1485}
1486
Girish Gowdra0e533642021-03-02 22:02:51 -08001487// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001488func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001489 if mm.GetdeviceDeletionInProgress() {
1490 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1491 return nil
1492 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001493 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001494 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001495 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1496 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001497 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001498
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001499 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001500 for _, n := range copyOfL2PmToAdd {
1501 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001502 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1503 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001504 switch n {
1505 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001506 // Create ME twice, one for each direction. Boolean true is used to indicate upstream and false for downstream.
Himani Chawlac77d5372021-07-12 15:42:26 +05301507 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001508 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001509 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001510 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001511 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1512 inner1:
1513 // retry L2PmCreateAttempts times to create the instance of PM
1514 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001515 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1516 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001517 if err != nil {
1518 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001519 log.Fields{"device-id": mm.deviceID})
1520 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001521 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001522 go func(p_pmFsm *cmn.AdapterFsm) {
1523 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001524 }(pPMFsm)
1525 }
1526 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001527 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001528 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001529 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1530 atLeastOneSuccess = true
1531 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1532 break inner1
1533 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001534 if mm.GetdeviceDeletionInProgress() {
1535 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1536 return nil
1537 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001538 }
1539 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1540 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001541 }
1542 }
1543 }
1544 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001545 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1546 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001547 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001548 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001549 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1550 inner2:
1551 // retry L2PmCreateAttempts times to create the instance of PM
1552 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001553 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1554 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001555 if err != nil {
1556 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001557 log.Fields{"device-id": mm.deviceID})
1558 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001559 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001560 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001561 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001562 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1563 atLeastOneSuccess = true
1564 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1565 break inner2
1566 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001567 if mm.GetdeviceDeletionInProgress() {
1568 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1569 return nil
1570 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001571 }
1572 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1573 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001574 }
1575 }
1576 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001577 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001578 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001579 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001580 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1581 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001582 if err != nil {
1583 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001584 log.Fields{"device-id": mm.deviceID})
1585 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001586 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001587 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001588 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001589 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1590 inner3:
1591 // retry L2PmCreateAttempts times to create the instance of PM
1592 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1593 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1594 atLeastOneSuccess = true
1595 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1596 break inner3
1597 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001598 if mm.GetdeviceDeletionInProgress() {
1599 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1600 return nil
1601 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001602 }
1603 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1604 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001605 }
1606 }
1607 case GemPortHistoryName:
1608
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001609 mm.OnuMetricsManagerLock.RLock()
1610 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1611 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1612 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001613
1614 if len(copyOfGemPortInstIDsToAdd) == 0 {
1615 // If there are no gemport history MEs to be created, just skip further processing
1616 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1617 // Normally there are no GemPortHistory MEs to create at start up. They come in only after provisioning service on the ONU.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001618 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001619 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001620 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001621 continue
1622 }
1623
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001624 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001625 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1626 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001627 if err != nil {
1628 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001629 log.Fields{"device-id": mm.deviceID})
1630 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001631 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001632 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001633 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001634 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1635 inner4:
1636 // retry L2PmCreateAttempts times to create the instance of PM
1637 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1638 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1639 atLeastOneSuccess = true
1640 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1641 break inner4
1642 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001643 if mm.GetdeviceDeletionInProgress() {
1644 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1645 return nil
1646 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001647 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001648 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1649 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1650 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001651 }
1652
Girish Gowdrae0140f02021-02-02 16:55:09 -08001653 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001654 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001655 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001656 // On success of at least one instance of the PM for a given ME, update the local list maintained for active PMs and PMs to add
1657 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001658 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001659 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001660 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1661 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001662 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001663 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1664 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001665 logger.Debugw(ctx, "success-resp", log.Fields{"pm-name": n, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001666 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001667 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001668 // If we are here then no instance of the PM of the given ME were created successfully, so locally disable the PM
Girish Gowdrae0140f02021-02-02 16:55:09 -08001669 // and also remove it from l2PmToAdd slice so that we do not try to create the PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001670 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001671 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001672 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001673 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001674
Girish Gowdrae0140f02021-02-02 16:55:09 -08001675 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001676 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001677 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001678 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001679 }
1680 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001681 mm.OnuMetricsManagerLock.RLock()
1682 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1683 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001684 // Does not matter we send success or failure here.
1685 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1686 // we have not exceed max attempts to create the PM ME)
1687 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001688 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1689 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001690 }
1691 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001692 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001693}
1694
Girish Gowdra0e533642021-03-02 22:02:51 -08001695// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001696func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001697 if mm.GetdeviceDeletionInProgress() {
1698 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1699 return nil
1700 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001701 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001702 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001703 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1704 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001705 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001706
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001707 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001708 for _, n := range copyOfL2PmToDelete {
1709 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001710 cnt := 0
1711 atLeastOneDeleteFailure := false
1712
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001713 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1714 mm.OnuMetricsManagerLock.RLock()
1715 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1716 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1717 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001718
1719 if len(copyOfEntityIDs) == 0 {
1720 // if there are no enityIDs to remove for the PM ME just clear the PM name entry from cache and continue
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001721 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001722 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1723 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1724 logger.Debugw(ctx, "success-resp", log.Fields{"pm-name": n, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001725 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001726 continue
1727 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001728 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001729 switch n {
1730 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001731 // Create ME twice, one for each direction. Boolean true is used to indicate upstream and false for downstream.
Himani Chawlac77d5372021-07-12 15:42:26 +05301732 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001733 for _, entityID := range copyOfEntityIDs {
1734 inner1:
1735 // retry L2PmDeleteAttempts times to delete the instance of PM
1736 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001737 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1738 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001739 if err != nil {
1740 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001741 log.Fields{"device-id": mm.deviceID})
1742 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001743 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001744 go func(p_pmFsm *cmn.AdapterFsm) {
1745 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001746 }(pPMFsm)
1747 }
1748 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001749 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001750 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001751 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1752 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001753 if mm.GetdeviceDeletionInProgress() {
1754 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1755 return nil
1756 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001757 atLeastOneDeleteFailure = true
1758 } else {
1759 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1760 break inner1
1761 }
1762 }
1763 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1764 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001765 }
1766 }
1767 }
1768 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001769 for _, entityID := range copyOfEntityIDs {
1770 inner2:
1771 // retry L2PmDeleteAttempts times to delete the instance of PM
1772 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001773 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1774 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001775 if err != nil {
1776 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001777 log.Fields{"device-id": mm.deviceID})
1778 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001779 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001780 go func(p_pmFsm *cmn.AdapterFsm) {
1781 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001782 }(pmFsm)
1783 return err
1784 }
1785 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001786 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001787 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001788 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001789 if mm.GetdeviceDeletionInProgress() {
1790 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1791 return nil
1792 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001793 atLeastOneDeleteFailure = true
1794 } else {
1795 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001796 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001797 }
1798 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001799 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1800 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1801 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001802 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001803 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001804 for _, entityID := range copyOfEntityIDs {
1805 inner3:
1806 // retry L2PmDeleteAttempts times to delete the instance of PM
1807 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001808 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1809 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001810 if err != nil {
1811 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001812 log.Fields{"device-id": mm.deviceID})
1813 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001814 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001815 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001816 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001817 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001818 if mm.GetdeviceDeletionInProgress() {
1819 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1820 return nil
1821 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001822 atLeastOneDeleteFailure = true
1823 } else {
1824 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1825 break inner3
1826 }
1827 }
1828 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1829 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001830 }
1831 }
1832 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001833 for _, entityID := range copyOfEntityIDs {
1834 inner4:
1835 // retry L2PmDeleteAttempts times to delete the instance of PM
1836 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001837 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1838 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001839 if err != nil {
1840 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001841 log.Fields{"device-id": mm.deviceID})
1842 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001843 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001844 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001845 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001846 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001847 if mm.GetdeviceDeletionInProgress() {
1848 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1849 return nil
1850 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001851 atLeastOneDeleteFailure = true
1852 } else {
1853 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1854 break inner4
1855 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001856 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001857 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1858 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1859 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001860 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001861 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001862 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001863 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001864 // If we could not completely clean up the PM ME then just give up.
1865 if atLeastOneDeleteFailure {
1866 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001867 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001868 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001869 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001870 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1871 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1872 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001873 mm.GroupMetricMap[n].Enabled = false
1874 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001875 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001876 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001877 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001878 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1879 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001880 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001881 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1882 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001883 logger.Debugw(ctx, "success-resp", log.Fields{"pm-name": n, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001884 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001885 }
1886 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001887 mm.OnuMetricsManagerLock.RLock()
1888 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1889 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001890 // Does not matter we send success or failure here.
1891 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1892 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001893 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1894 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001895 }
1896 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001897 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001898}
1899
1900// ** L2 PM FSM Handlers end **
1901
1902// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001903func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001904 if mm.GetdeviceDeletionInProgress() {
1905 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1906 return nil
1907 }
1908
1909 if !mm.GetOmciProcessingStatus() {
1910 logger.Errorw(ctx, "not sending sync time, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
1911 return fmt.Errorf("omci-resp-processor-not-running")
1912 }
1913
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001914 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1915 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001916 return err
1917 }
1918
1919 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001920 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1921 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1922 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001923 case syncTimeRes := <-mm.syncTimeResponseChan:
1924 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001925 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001926 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001927 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001928 return nil
1929 }
1930}
1931
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001932func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001933 var mEnt *me.ManagedEntity
1934 var omciErr me.OmciErrors
1935 var classID me.ClassID
1936 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001937 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001938 meParam := me.ParamData{EntityID: entityID}
1939 if upstream {
1940 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001941 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001942 return nil
1943 }
1944 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1945 } else {
1946 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001947 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001948 return nil
1949 }
1950 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
1951 }
1952
Girish Gowdrae0140f02021-02-02 16:55:09 -08001953 intervalEndTime := -1
1954 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001955 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
1956 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001957 }
1958
1959 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
1960 ethPMHistData["class_id"] = float32(classID)
1961 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
1962 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
1963 ethPMHistData["parent_entity_id"] = float32(entityID)
1964 if upstream {
1965 ethPMHistData["upstream"] = float32(1)
1966 } else {
1967 ethPMHistData["upstream"] = float32(0)
1968 }
1969
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001970 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001971
Girish Gowdrae0140f02021-02-02 16:55:09 -08001972 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001973 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001974 return &metricInfo
1975}
1976
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001977func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001978 var mEnt *me.ManagedEntity
1979 var omciErr me.OmciErrors
1980 var classID me.ClassID
1981 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001982 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001983 meParam := me.ParamData{EntityID: entityID}
1984 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001985 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001986 return nil
1987 }
1988 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
1989
Girish Gowdrae0140f02021-02-02 16:55:09 -08001990 intervalEndTime := -1
1991 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001992 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
1993 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001994 }
1995
1996 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
1997 ethUniHistData["class_id"] = float32(classID)
1998 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
1999
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002000 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002001
Girish Gowdrae0140f02021-02-02 16:55:09 -08002002 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002003 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002004 return &metricInfo
2005}
2006
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002007func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002008 var mEnt *me.ManagedEntity
2009 var omciErr me.OmciErrors
2010 var classID me.ClassID
2011 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002012 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002013 meParam := me.ParamData{EntityID: entityID}
2014 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002015 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002016 return nil
2017 }
2018 classID = me.FecPerformanceMonitoringHistoryDataClassID
2019
2020 intervalEndTime := -1
2021 fecHistData := make(map[string]float32)
2022 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
2023 return nil
2024 }
2025
2026 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2027 fecHistData["class_id"] = float32(classID)
2028 fecHistData["interval_end_time"] = float32(intervalEndTime)
2029
2030 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2031
2032 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002033 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002034 return &metricInfo
2035}
2036
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002037func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002038 var mEnt *me.ManagedEntity
2039 var omciErr me.OmciErrors
2040 var classID me.ClassID
2041 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002042 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002043 meParam := me.ParamData{EntityID: entityID}
2044 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002045 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002046 return nil
2047 }
2048 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2049
2050 intervalEndTime := -1
2051 gemHistData := make(map[string]float32)
2052 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
2053 return nil
2054 }
2055
2056 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2057 gemHistData["class_id"] = float32(classID)
2058 gemHistData["interval_end_time"] = float32(intervalEndTime)
2059
2060 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2061
2062 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002063 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002064 return &metricInfo
2065}
2066
Girish Gowdrae0140f02021-02-02 16:55:09 -08002067// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002068func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002069 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002070 upstream := false
2071 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2072 upstream = true
2073 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002074 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002075 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002076 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002077 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002078 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2079 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002080 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002081 go func(p_pmFsm *cmn.AdapterFsm) {
2082 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002083 }(pmFsm)
2084 return err
2085 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002086 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002087 }
2088 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002089 select {
2090 case meAttributes = <-mm.l2PmChan:
2091 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002092 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2093 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002094 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002095 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002096 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002097 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002098 }
2099 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002100 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002101 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002102 }
2103 }
2104 for k := range EthernetBridgeHistory {
2105 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2106 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2107 if _, ok := ethPMHistData[k]; !ok {
2108 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002109 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002110 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002111 ethPMHistData[k] = float32(val.(uint16))
2112 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002113 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002114 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002115 ethPMHistData[k] = float32(val.(uint32))
2116 }
2117 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002118 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002119 ethPMHistData[k] = float32(val.(uint32))
2120 }
2121 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002122 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002123 ethPMHistData[k] = float32(val.(uint32))
2124 }
2125 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002126 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002127 ethPMHistData[k] = float32(val.(uint32))
2128 }
2129 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002130 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002131 ethPMHistData[k] = float32(val.(uint32))
2132 }
2133 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002134 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002135 ethPMHistData[k] = float32(val.(uint32))
2136 }
2137 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002138 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002139 ethPMHistData[k] = float32(val.(uint32))
2140 }
2141 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002142 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002143 ethPMHistData[k] = float32(val.(uint32))
2144 }
2145 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002146 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002147 ethPMHistData[k] = float32(val.(uint32))
2148 }
2149 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002150 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002151 ethPMHistData[k] = float32(val.(uint32))
2152 }
2153 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002154 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002155 ethPMHistData[k] = float32(val.(uint32))
2156 }
2157 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002158 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002159 ethPMHistData[k] = float32(val.(uint32))
2160 }
2161 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002162 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002163 ethPMHistData[k] = float32(val.(uint32))
2164 }
2165 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002166 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002167 ethPMHistData[k] = float32(val.(uint32))
2168 }
2169 default:
2170 // do nothing
2171 }
2172 }
2173 }
2174 return nil
2175}
2176
2177// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002178func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002179 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002180 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
ozgecanetsiab36ed572021-04-01 10:38:48 +03002181 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2182 requestedAttributes["IntervalEndTime"] = 0
2183 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002184 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002185 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002186 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2187 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2188 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002189 }
2190 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002191 select {
2192 case meAttributes = <-mm.l2PmChan:
2193 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002194 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2195 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002196 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002197 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002198 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002199 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002200 }
2201 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002202 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002203 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002204 }
2205 }
2206 for k := range EthernetUniHistory {
2207 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2208 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2209 if _, ok := ethPMUniHistData[k]; !ok {
2210 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002211 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002212 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002213 ethPMUniHistData[k] = float32(val.(uint16))
2214 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002215 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002216 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002217 ethPMUniHistData[k] = float32(val.(uint32))
2218 }
2219 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002220 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002221 ethPMUniHistData[k] = float32(val.(uint32))
2222 }
2223 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002224 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002225 ethPMUniHistData[k] = float32(val.(uint32))
2226 }
2227 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002228 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002229 ethPMUniHistData[k] = float32(val.(uint32))
2230 }
2231 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002232 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002233 ethPMUniHistData[k] = float32(val.(uint32))
2234 }
2235 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002236 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002237 ethPMUniHistData[k] = float32(val.(uint32))
2238 }
2239 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002240 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002241 ethPMUniHistData[k] = float32(val.(uint32))
2242 }
2243 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002244 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002245 ethPMUniHistData[k] = float32(val.(uint32))
2246 }
2247 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002248 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002249 ethPMUniHistData[k] = float32(val.(uint32))
2250 }
2251 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002252 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002253 ethPMUniHistData[k] = float32(val.(uint32))
2254 }
2255 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002256 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002257 ethPMUniHistData[k] = float32(val.(uint32))
2258 }
2259 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002260 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002261 ethPMUniHistData[k] = float32(val.(uint32))
2262 }
2263 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002264 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002265 ethPMUniHistData[k] = float32(val.(uint32))
2266 }
2267 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002268 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002269 ethPMUniHistData[k] = float32(val.(uint32))
2270 }
2271 default:
2272 // do nothing
2273 }
2274 }
2275 }
2276 return nil
2277}
2278
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002279// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002280func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002281 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002282 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002283 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2284 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002285 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002286 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002287 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002288 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2289 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2290 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002291 }
2292 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002293 select {
2294 case meAttributes = <-mm.l2PmChan:
2295 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002296 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2297 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002298 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002299 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002300 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002301 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002302 }
2303 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2304 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002305 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002306 }
2307 }
2308 for k := range FecHistory {
2309 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2310 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2311 if _, ok := fecHistData[k]; !ok {
2312 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002313 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002314 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002315 fecHistData[k] = float32(val.(uint16))
2316 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002317 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002318 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002319 fecHistData[k] = float32(val.(uint32))
2320 }
2321 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002322 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002323 fecHistData[k] = float32(val.(uint32))
2324 }
2325 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002326 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002327 fecHistData[k] = float32(val.(uint32))
2328 }
2329 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002330 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002331 fecHistData[k] = float32(val.(uint32))
2332 }
2333 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002334 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002335 fecHistData[k] = float32(val.(uint16))
2336 }
2337 default:
2338 // do nothing
2339 }
2340 }
2341 }
2342 return nil
2343}
2344
2345// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002346func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002347 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002348 // Insert "IntervalEndTime" is part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002349 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2350 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002351 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002352 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002353 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002354 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2355 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2356 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002357 }
2358 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002359 select {
2360 case meAttributes = <-mm.l2PmChan:
2361 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002362 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2363 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002364 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002365 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002366 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002367 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002368 }
2369 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2370 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002371 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002372 }
2373 }
2374 for k := range GemPortHistory {
2375 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2376 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2377 if _, ok := gemPortHistData[k]; !ok {
2378 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002379 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002380 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002381 gemPortHistData[k] = float32(val.(uint16))
2382 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002383 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002384 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002385 gemPortHistData[k] = float32(val.(uint32))
2386 }
2387 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002388 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002389 gemPortHistData[k] = float32(val.(uint32))
2390 }
2391 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002392 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002393 gemPortHistData[k] = float32(val.(uint64))
2394 }
2395 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002396 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002397 gemPortHistData[k] = float32(val.(uint64))
2398 }
2399 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002400 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002401 gemPortHistData[k] = float32(val.(uint32))
2402 }
2403 default:
2404 // do nothing
2405 }
2406 }
2407 }
2408 return nil
2409}
2410
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002411func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002412 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2413 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002414 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2415 return fmt.Errorf("omci Msg layer could not be detected for create response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002416 }
2417 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2418 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002419 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2420 return fmt.Errorf("omci Msg layer could not be assigned for delete response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002421 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002422 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002423 switch msgObj.EntityClass {
2424 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2425 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002426 me.EthernetPerformanceMonitoringHistoryDataClassID,
2427 me.FecPerformanceMonitoringHistoryDataClassID,
2428 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002429 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2430 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2431 mm.l2PmCreateOrDeleteResponseChan <- true
2432 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002433 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002434 mm.l2PmCreateOrDeleteResponseChan <- false
2435 }
2436 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302437 case me.EthernetFrameExtendedPmClassID,
2438 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302439 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302440 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002441 default:
2442 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002443 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002444 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002445 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002446}
2447
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002448func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002449 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2450 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002451 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2452 return fmt.Errorf("omci Msg layer could not be detected for create response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002453 }
2454 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2455 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002456 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2457 return fmt.Errorf("omci Msg layer could not be assigned for delete response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002458 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002459 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002460 switch msgObj.EntityClass {
2461 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2462 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002463 me.EthernetPerformanceMonitoringHistoryDataClassID,
2464 me.FecPerformanceMonitoringHistoryDataClassID,
2465 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002466 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2467 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2468 mm.l2PmCreateOrDeleteResponseChan <- true
2469 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002470 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002471 mm.l2PmCreateOrDeleteResponseChan <- false
2472 }
2473 return nil
2474 default:
2475 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002476 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002477 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002478 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002479}
2480
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002481func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002482 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002483 for {
2484 select {
2485 case <-time.After(L2PmCollectionInterval * time.Second):
2486 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002487 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2488 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002489 }
2490 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002491 case <-mm.StopTicks:
2492 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002493 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002494 return
2495 }
2496 }
2497}
2498
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002499func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002500 // Publish metrics if it is valid
2501 if metricInfoSlice != nil {
2502 mm.publishMetrics(ctx, metricInfoSlice)
2503 } else {
2504 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2505 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002506 mm.OnuMetricsManagerLock.Lock()
2507 mm.GroupMetricMap[metricName].collectAttempts++
2508 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002509 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2510 }
2511 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002512 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2513 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002514 }
2515}
2516
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002517func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002518 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2519 var grpFunc groupMetricPopulateFunc
2520 switch classID {
2521 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2522 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2523 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2524 grpFunc = mm.populateEthernetUniHistoryMetrics
2525 case me.FecPerformanceMonitoringHistoryDataClassID:
2526 grpFunc = mm.populateFecHistoryMetrics
2527 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2528 grpFunc = mm.populateGemPortMetrics
2529 default:
2530 return fmt.Errorf("unknown-classid-%v", classID)
2531 }
2532
2533 size := 0
2534 requestedAttributes := make(me.AttributeValueMap)
2535 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002536 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2537 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2538 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2539 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2540 continue
2541 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002542 if (v.Size + size) <= MaxL2PMGetPayLoadSize {
2543 requestedAttributes[v.Name] = v.DefValue
2544 size = v.Size + size
2545 } else { // We exceeded the allow omci get size
2546 // Let's collect the attributes via get now and collect remaining in the next iteration
2547 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2548 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002549 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002550 return err
2551 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002552 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002553 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2554 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002555 }
2556 }
2557 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002558 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2559 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002560 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002561 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002562 }
2563 return nil
2564}
2565
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002566func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002567 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002568 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2569 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2570 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002571
2572 raisedTs := time.Now().Unix()
2573 mmd := voltha.MetricMetaData{
2574 Title: title,
2575 Ts: float64(raisedTs),
2576 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002577 DeviceId: mm.deviceID,
2578 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2579 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002580 }
2581
2582 // create slice of metrics given that there could be more than one VEIP instance
2583 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2584 return metricInfo
2585}
2586
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002587func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002588 valid := false
2589 if *intervalEndTime == -1 { // first time
2590 // Update the interval end time
2591 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2592 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2593 valid = true
2594 }
2595 } else {
2596 var currIntervalEndTime int
2597 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2598 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2599 }
2600 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2601 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002602 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002603 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2604 } else {
2605 valid = true
2606 }
2607 }
2608 return valid
2609}
2610
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002611func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002612 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002613 if !mm.GetOmciProcessingStatus() {
2614 logger.Errorw(ctx, "not waiting for omci resp, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
2615 return false
2616 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002617 select {
2618 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002619 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002620 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002621 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002622 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002623 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002624 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002625 }
2626 return false
2627}
2628
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002629func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002630 var pmConfigSlice []*voltha.PmConfig
2631 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002632 pmConfigSlice = append(pmConfigSlice,
2633 &voltha.PmConfig{
2634 Name: k,
2635 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002636 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002637 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002638 }
2639 groupMetric := voltha.PmGroupConfig{
2640 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002641 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002642 GroupFreq: grpFreq,
2643 Metrics: pmConfigSlice,
2644 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002645 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002646
2647}
2648
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002649func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2650 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2651 if mm.PAdaptFsm == nil {
2652 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2653 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002654 return fmt.Errorf("nil-adapter-fsm")
2655 }
2656 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002657 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2658 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002659 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002660 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2661 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2662 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2663 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2664 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2665 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2666 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2667 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2668 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002669 },
2670 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002671 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2672 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2673 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2674 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2675 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2676 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2677 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2678 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002679 },
2680 )
2681 return nil
2682}
2683
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002684func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2685 mm.pDeviceHandler.InitPmConfigs()
2686 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2687 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2688 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2689 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002690
2691 // Populate group metrics.
2692 // Lets populate irrespective of GroupMetricEnabled is true or not.
2693 // The group metrics collection will decided on this flag later
2694
2695 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2696 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2697
2698 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2699 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2700
2701 // classical l2 pm counter start
2702
2703 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2704 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2705
2706 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2707 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2708
2709 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2710 FecHistoryEnabled, FecHistoryFrequency)
2711
2712 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2713 GemPortHistoryEnabled, GemPortHistoryFrequency)
2714
2715 // classical l2 pm counter end
2716
2717 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2718}
2719
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002720func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002721 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002722 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2723 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002724 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002725 Enabled: g.Enabled,
2726 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002727 }
2728 switch g.GroupName {
2729 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002730 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002731 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002732 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002733 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002734 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2735 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002736 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002737 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2738 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002739 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002740 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2741 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002742 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002743 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2744 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002745 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002746 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002747 }
2748 }
2749
2750 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002751 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2752 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002753 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002754 Enabled: m.Enabled,
2755 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002756 }
2757 switch m.Name {
2758 // None exist as of now. Add when available.
2759 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002760 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002761 }
2762 }
2763}
2764
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002765// AddGemPortForPerfMonitoring - TODO: add comment
2766func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2767 mm.OnuMetricsManagerLock.Lock()
2768 defer mm.OnuMetricsManagerLock.Unlock()
2769 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002770 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002771 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002772 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002773 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002774
2775 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2776 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2777 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2778 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2779 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002780
2781 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002782 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2783 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002784 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002785 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002786 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002787 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002788 }
2789 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002790}
2791
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002792// RemoveGemPortForPerfMonitoring - TODO: add comment
2793func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2794 mm.OnuMetricsManagerLock.Lock()
2795 defer mm.OnuMetricsManagerLock.Unlock()
2796 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2797 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002798 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002799 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002800
2801 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2802 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2803 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2804 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2805 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002806
2807 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002808 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2809 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002810 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002811 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002812 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002813 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002814 }
2815 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002816}
2817
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002818func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2819 if mm.pDeviceHandler.GetOnuTP() != nil {
2820 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002821 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002822 for _, v := range gemPortInstIDs {
2823 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002824 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002825 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002826 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002827 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002828 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002829 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002830 }
2831}
2832
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002833func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2834 if mm.pDeviceHandler.GetOnuTP() != nil {
2835 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002836 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002837 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002838 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002839 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002840 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002841 }
2842 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002843 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002844 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002845}
2846
2847// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002848func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2849 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002850 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002851 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2852 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002853 }
2854 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002855 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002856 group.pmMEData = &pmMEData{}
2857 Value, err := mm.pmKvStore.Get(ctx, groupName)
2858 if err == nil {
2859 if Value != nil {
2860 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002861 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002862 tmpBytes, _ := kvstore.ToByte(Value.Value)
2863
2864 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002865 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2866 errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-PM-data-%s-for-group-%s", mm.deviceID, groupName)))
Girish Gowdra0e533642021-03-02 22:02:51 -08002867 continue
2868 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002869 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002870 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002871 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002872 continue
2873 }
2874 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002875 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2876 errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s-for-group-%s", mm.deviceID, groupName)))
Girish Gowdra0e533642021-03-02 22:02:51 -08002877 continue
2878 }
2879 }
2880 if len(errorsList) > 0 {
2881 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2882 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002883 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002884 return nil
2885}
2886
2887// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2888// the data must be available in cache.
2889// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002890func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2891 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002892 return grp.pmMEData, nil
2893 }
2894 // Data not in cache, try to fetch from kv store.
2895 data := &pmMEData{}
2896 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002897 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2898 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002899 }
2900 Value, err := mm.pmKvStore.Get(ctx, groupName)
2901 if err == nil {
2902 if Value != nil {
2903 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002904 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002905 tmpBytes, _ := kvstore.ToByte(Value.Value)
2906
2907 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002908 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002909 return data, err
2910 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002911 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002912 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002913 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002914 return data, err
2915 }
2916 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002917 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002918 return data, err
2919 }
2920
2921 return data, nil
2922}
2923
2924// updatePmData update pmMEData to store. It is write through cache, i.e., write to cache first and then update store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002925func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2926 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2927 mm.OnuMetricsManagerLock.Lock()
2928 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002929
2930 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002931 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2932 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002933 }
2934
2935 pmMEData, err := mm.getPmData(ctx, groupName)
2936 if err != nil || pmMEData == nil {
2937 // error already logged in called function.
2938 return err
2939 }
2940 switch pmAction {
2941 case cPmAdd:
2942 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
2943 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2944 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2945 case cPmAdded:
2946 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
2947 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2948 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2949 case cPmRemove:
2950 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
2951 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2952 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2953 case cPmRemoved:
2954 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2955 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2956 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2957 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002958 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
2959 return fmt.Errorf(fmt.Sprintf("unknown-pm-action-deviceid-%s-groupName-%s-pmaction-%s", mm.deviceID, groupName, pmAction))
Girish Gowdra0e533642021-03-02 22:02:51 -08002960 }
2961 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002962 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08002963
2964 Value, err := json.Marshal(*pmMEData)
2965 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002966 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
2967 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002968 return err
2969 }
2970 // Update back to kv store
2971 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002972 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
2973 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002974 return err
2975 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002976 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
2977 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08002978
2979 return nil
2980}
2981
2982// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002983func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
2984 mm.OnuMetricsManagerLock.Lock()
2985 defer mm.OnuMetricsManagerLock.Unlock()
2986 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002987 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002988 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2989 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002990 }
2991
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002992 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002993 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002994 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002995 // do not abort this procedure. continue to delete next group.
2996 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002997 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08002998 }
2999 }
3000
3001 return nil
3002}
3003
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003004// ClearAllPmData clears all PM data associated with the device from KV store
3005func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3006 mm.OnuMetricsManagerLock.Lock()
3007 defer mm.OnuMetricsManagerLock.Unlock()
3008 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003009 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003010 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3011 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003012 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003013 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003014 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003015 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003016 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003017 value = err
3018 // do not abort this procedure - continue to delete next group.
3019 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003020 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003021 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003022 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003023 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003024 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003025 }
3026 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003027}
3028
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003029func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3030 mm.OnuMetricsManagerLock.Lock()
3031 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003032 mm.omciProcessingActive = status
3033}
3034
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003035// updateTickGenerationStatus - TODO: add comment
3036func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3037 mm.OnuMetricsManagerLock.Lock()
3038 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003039 mm.tickGenerationActive = status
3040}
3041
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003042// GetOmciProcessingStatus - TODO: add comment
3043func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3044 mm.OnuMetricsManagerLock.RLock()
3045 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003046 return mm.omciProcessingActive
3047}
3048
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003049// GetTickGenerationStatus - TODO: add comment
3050func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3051 mm.OnuMetricsManagerLock.RLock()
3052 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003053 return mm.tickGenerationActive
3054}
3055
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003056func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003057 for _, ele := range slice {
3058 if ele == n {
3059 return slice
3060 }
3061 }
3062 return append(slice, n)
3063}
3064
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003065func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003066 for i, ele := range slice {
3067 if ele == n {
3068 return append(slice[:i], slice[i+1:]...)
3069 }
3070 }
3071 return slice
3072}
3073
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003074func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003075 for _, ele := range slice {
3076 if ele == n {
3077 return slice
3078 }
3079 }
3080 return append(slice, n)
3081}
3082
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003083func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003084 for i, ele := range slice {
3085 if ele == n {
3086 return append(slice[:i], slice[i+1:]...)
3087 }
3088 }
3089 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003090}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303091
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003092func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303093 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3094 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003095 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3096 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3097 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303098 Value, err := mm.extPmKvStore.Get(ctx, key)
3099 if err == nil {
3100 if Value != nil {
3101 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003102 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303103 tmpBytes, _ := kvstore.ToByte(Value.Value)
3104
3105 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003106 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303107 return false, err
3108 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003109 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303110 // We have found the data from db, no need to get through omci get message.
3111 mm.supportedEthernetFrameExtendedPMClass = data
3112 return true, nil
3113 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003114 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303115 return false, nil
3116 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003117 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303118 return false, err
3119}
3120
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003121func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303122 logger.Debugw(ctx, "wait-for-ethernet-frame-create-or-delete-response-or-timeout", log.Fields{"create": create, "instID": instID, "meClassID": meClassID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07003123 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3124 logger.Errorw(ctx, "not waiting for omci resp, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
3125 return false, fmt.Errorf("omci-processor-shutdown")
3126 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303127 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303128 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303129 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003130 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303131 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3132 if resp == me.Success || resp == me.InstanceExists {
3133 return true, nil
3134 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3135 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3136 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3137 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003138 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "resp": resp, "class-id": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303139 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3140 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003141 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303142 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003143 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303144 }
3145 return false, fmt.Errorf("timeout-while-waiting-for-response")
3146}
3147
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003148func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303149 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303150 // Create ME twice, one for each direction. Boolean true is used to indicate upstream and false for downstream.
Himani Chawlac77d5372021-07-12 15:42:26 +05303151 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003152 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303153 var entityID uint16
3154 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003155 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303156 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003157 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303158 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303159 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303160 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303161 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303162
3163 inner1:
3164 // retry ExtendedPmCreateAttempts times to create the instance of PM
3165 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003166 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3167 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3168 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303169 if err != nil {
3170 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003171 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303172 return false, err
3173 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303174 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3175 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303176 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303177 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303178 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303179 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303180 }
3181 break inner1
3182 } else if err != nil {
3183 if !supported {
3184 // Need to return immediately
3185 return false, err
3186 }
3187 //In case of failure, go for a retry
3188 }
3189 }
3190 if cnt == ExtendedPmCreateAttempts {
3191 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3192 return true, fmt.Errorf("unable-to-create-me")
3193 }
3194 }
3195 }
3196 return true, nil
3197}
3198
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003199func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3200 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3201 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3202 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303203 // check if we get the supported type me for ethernet frame extended pm class id
3204 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3205 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3206 }
3207 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3208 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003209 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303210 }
3211 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003212 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303213 }
3214}
3215
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003216func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303217 mm.onuEthernetFrameExtendedPmLock.Lock()
3218 mm.isDeviceReadyToCollectExtendedPmStats = true
3219 mm.onuEthernetFrameExtendedPmLock.Unlock()
3220}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003221
Himani Chawlaee10b542021-09-20 16:46:40 +05303222// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003223func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303224 //get the type of extended frame pm me supported by onu first
3225 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3226 if err != nil {
3227 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3228 return
3229 }
3230 if exist {
3231 // we have the me type, go ahead with the me type supported.
3232 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003233 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303234 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3235 return
3236 }
3237 mm.setAllExtPmMeCreatedFlag()
3238 return
3239 }
3240 // First try with 64 bit me
3241 // we have the me type, go ahead with the me type supported.
3242 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3243 if err != nil && !supported64Bit {
3244 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003245 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303246 "supported": supported64Bit})
3247 // Then Try with 32 bit type
3248 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003249 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303250 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3251 } else if supported32Bit {
3252 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3253 mm.putExtPmMeKvStore(ctx)
3254 mm.setAllExtPmMeCreatedFlag()
3255 }
3256 } else if err == nil && supported64Bit {
3257 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3258 mm.putExtPmMeKvStore(ctx)
3259 mm.setAllExtPmMeCreatedFlag()
3260 }
3261}
3262
Himani Chawlaee10b542021-09-20 16:46:40 +05303263func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3264 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3265 uniPortEntityID := entityID
3266 if upstream {
3267 uniPortEntityID = entityID - 0x100
3268 }
3269 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3270 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3271 mm.pDeviceHandler.GetOmciTimeout(), true,
3272 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3273 if err != nil {
3274 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3275 log.Fields{"device-id": mm.deviceID})
3276 return extension.GetValueResponse_INTERNAL_ERROR, err
3277 }
3278
3279 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3280 return extension.GetValueResponse_REASON_UNDEFINED, nil
3281 }
3282 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3283}
3284
3285func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3286 logger.Debugw(ctx, "wait-for-ethernet-frame-reset-counters-response-or-timeout", log.Fields{"instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07003287 if !mm.GetOmciProcessingStatus() {
3288 logger.Errorw(ctx, "not waiting for omci resp, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
3289 return false
3290 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303291 select {
3292 case resp := <-mm.extendedPMMeResponseChan:
3293 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3294 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3295 if resp == me.Success {
3296 return true
3297 }
3298 return false
3299 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3300 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3301 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3302 }
3303 return false
3304}
3305
3306func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3307 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3308 className := "EthernetFrameExtendedPm64Bit"
3309 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3310 className = "EthernetFrameExtendedPm"
3311 }
3312 // Reset the counters if option is specified
3313 for entityID := range upstreamEntityMap {
3314 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3315 true)
3316 if err != nil {
3317 return errReason, err
3318 }
3319 }
3320
3321 for entityID := range downstreamEntityMap {
3322 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3323 true)
3324 if err != nil {
3325 return errReason, err
3326 }
3327 }
3328 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3329 // device itself.
3330 // Unset the reset bit if option is specified
3331 for entityID := range upstreamEntityMap {
3332 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3333 false)
3334 if err != nil {
3335 return errReason, err
3336 }
3337 }
3338
3339 for entityID := range downstreamEntityMap {
3340 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3341 false)
3342 if err != nil {
3343 return errReason, err
3344 }
3345 }
3346 return extension.GetValueResponse_REASON_UNDEFINED, nil
3347}
3348
3349func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3350 mm.onuEthernetFrameExtendedPmLock.Lock()
3351 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3352 mm.isEthernetFrameExtendedPmOperationOngoing = val
3353}
3354
3355func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3356 mm.onuEthernetFrameExtendedPmLock.Lock()
3357 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3358 return mm.isEthernetFrameExtendedPmOperationOngoing
3359}
3360
3361// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3362func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3363 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3364 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3365 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303366 return &extension.SingleGetValueResponse{
3367 Response: &extension.GetValueResponse{
3368 Status: extension.GetValueResponse_ERROR,
3369 ErrReason: reason,
3370 },
3371 }
3372 }
3373 mm.onuEthernetFrameExtendedPmLock.RLock()
3374 if !mm.isDeviceReadyToCollectExtendedPmStats {
3375 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303376 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303377 }
3378 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303379
3380 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3381 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3382 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3383 }
3384 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3385 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3386
3387 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3388 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3389 if onuInfo.IsUniIndex != nil {
3390 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3391 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3392 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3393 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3394 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3395 break
3396 }
3397 }
3398 if len(downstreamEntityMap) == 0 {
3399 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3400 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3401 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3402 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3403 }
3404 } else {
3405 // make a copy of all downstream and upstream maps in the local ones
3406 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3407 upstreamEntityMap[entityID] = meEnt
3408 }
3409 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3410 downstreamEntityMap[entityID] = meEnt
3411 }
3412 }
3413 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3414 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3415 // Reset the metrics first for all required me's
3416 if onuInfo.Reset_ {
3417 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3418 if err != nil {
3419 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3420 log.Fields{"device-id": mm.deviceID})
3421 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3422 }
3423 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303424 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3425 var pmUpstream extension.OmciEthernetFrameExtendedPm
3426 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303427 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3428 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3429 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3430 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303431 if !onuInfo.Reset_ {
3432 for entityID, meEnt := range upstreamEntityMap {
3433 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3434 var receivedMask uint16
3435 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3436 if receivedMask == 0 {
3437 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303438 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3439 // It might be possible that still some downstream pms are supported and hence we need to continue
3440 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3441 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303442 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303443 // Aggregate the result for upstream
3444 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3445 } else {
3446 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303447 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303448 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303449
Himani Chawlaee10b542021-09-20 16:46:40 +05303450 for entityID, meEnt := range downstreamEntityMap {
3451 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3452 var receivedMask uint16
3453 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303454 if receivedMask == 0 {
3455 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3456 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3457 // Stop collecting downstream counters for other ME's.
3458 break
3459 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303460 // Aggregate the result for downstream
3461 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3462 } else {
3463 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3464 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303465 }
3466 }
3467 singleValResp := extension.SingleGetValueResponse{
3468 Response: &extension.GetValueResponse{
3469 Status: extension.GetValueResponse_OK,
3470 Response: &extension.GetValueResponse_OnuCounters{
3471 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303472 Upstream: &pmUpstream,
3473 Downstream: &pmDownstream,
3474 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303475 },
3476 },
3477 },
3478 }
3479 return &singleValResp
3480}
3481
Himani Chawlaee10b542021-09-20 16:46:40 +05303482func (mm *OnuMetricsManager) collectEthernetFrameExtendedPMData(ctx context.Context, meEnt *me.ManagedEntity, entityID uint16, upstream bool, receivedMask *uint16) (map[string]uint64, extension.GetValueResponse_ErrorReason, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303483 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003484 logger.Debugw(ctx, "collecting-data-for-ethernet-frame-extended-pm", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303485
3486 classID = mm.supportedEthernetFrameExtendedPMClass
3487 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3488 if classID == me.EthernetFrameExtendedPmClassID {
3489 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3490 }
3491 ethPMData := make(map[string]uint64)
3492 var sumReceivedMask uint16
3493 for mask := range attributeMaskList {
3494 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3495 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003496 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303497 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303498 }
3499 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3500 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3501 //populate all counters as failure and return
3502 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3503 break
3504 }
3505 }
3506 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303507 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303508}
3509
3510// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003511func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303512 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3513 var meAttributes me.AttributeValueMap
3514 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003515 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303516 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003517 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303518 return extension.GetValueResponse_INTERNAL_ERROR, err
3519 }
3520 select {
3521 case meAttributes = <-mm.extendedPmMeChan:
3522 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003523 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3524 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303525 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003526 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303527 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3528 }
3529 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3530 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3531 *sumReceivedMask += mask
3532 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3533 } else {
3534 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3535 *sumReceivedMask += mask
3536 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3537 }
3538
3539 return extension.GetValueResponse_REASON_UNDEFINED, nil
3540}
3541
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003542func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303543 sourceMap := maskToEthernetFrameExtendedPM64Bit
3544 errorCounterValue := UnsupportedCounterValue64bit
3545 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3546 sourceMap = maskToEthernetFrameExtendedPM32Bit
3547 errorCounterValue = UnsupportedCounterValue32bit
3548 }
3549 for _, value := range sourceMap {
3550 for _, k := range value {
3551 if _, ok := ethFrameExtPMData[k]; !ok {
3552 ethFrameExtPMData[k] = errorCounterValue
3553 }
3554 }
3555 }
3556}
3557
3558// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003559func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303560 receivedMask := uint16(0)
3561 switch requestedAttributesMask {
3562 case 0x3F00:
3563 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3564 if _, ok := ethFrameExtPMData[k]; !ok {
3565 switch k {
3566 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003567 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303568 ethFrameExtPMData[k] = uint64(val.(uint32))
3569 receivedMask |= 0x2000
3570 } else if !ok {
3571 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3572 }
3573 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003574 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303575 ethFrameExtPMData[k] = uint64(val.(uint32))
3576 receivedMask |= 0x1000
3577 } else if !ok {
3578 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3579 }
3580 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003581 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303582 ethFrameExtPMData[k] = uint64(val.(uint32))
3583 receivedMask |= 0x800
3584 } else if !ok {
3585 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3586 }
3587 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003588 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303589 ethFrameExtPMData[k] = uint64(val.(uint32))
3590 receivedMask |= 0x400
3591 } else if !ok {
3592 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3593 }
3594 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003595 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303596 ethFrameExtPMData[k] = uint64(val.(uint32))
3597 receivedMask |= 0x200
3598 } else if !ok {
3599 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3600 }
3601 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003602 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303603 ethFrameExtPMData[k] = uint64(val.(uint32))
3604 receivedMask |= 0x100
3605 } else if !ok {
3606 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3607 }
3608 default:
3609 //do nothing
3610 }
3611 }
3612 }
3613 case 0x00FC:
3614 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3615 if _, ok := ethFrameExtPMData[k]; !ok {
3616 switch k {
3617 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003618 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303619 ethFrameExtPMData[k] = uint64(val.(uint32))
3620 receivedMask |= 0x80
3621 } else if !ok {
3622 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3623 }
3624 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003625 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303626 ethFrameExtPMData[k] = uint64(val.(uint32))
3627 receivedMask |= 0x40
3628 } else if !ok {
3629 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3630 }
3631 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003632 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303633 ethFrameExtPMData[k] = uint64(val.(uint32))
3634 receivedMask |= 0x20
3635 } else if !ok {
3636 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3637 }
3638 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003639 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303640 ethFrameExtPMData[k] = uint64(val.(uint32))
3641 receivedMask |= 0x10
3642 } else if !ok {
3643 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3644 }
3645 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003646 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303647 ethFrameExtPMData[k] = uint64(val.(uint32))
3648 receivedMask |= 0x8
3649 } else if !ok {
3650 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3651 }
3652 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003653 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303654 ethFrameExtPMData[k] = uint64(val.(uint32))
3655 receivedMask |= 0x4
3656 } else if !ok {
3657 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3658 }
3659 default:
3660 //do nothing
3661 }
3662 }
3663 }
3664 case 0x0003:
3665 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3666 if _, ok := ethFrameExtPMData[k]; !ok {
3667 switch k {
3668 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003669 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303670 ethFrameExtPMData[k] = uint64(val.(uint32))
3671 receivedMask |= 0x2
3672 } else if !ok {
3673 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3674 }
3675 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003676 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303677 ethFrameExtPMData[k] = uint64(val.(uint32))
3678 receivedMask |= 0x1
3679 } else if !ok {
3680 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3681 }
3682 default:
3683 //do nothing
3684 }
3685 }
3686 }
3687 default:
3688 //do nothing
3689 }
3690 return receivedMask
3691}
3692
3693// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003694func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303695 receivedMask := uint16(0)
3696 switch requestedAttributesMask {
3697 case 0x3800:
3698 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3699 if _, ok := ethFrameExtPMData[k]; !ok {
3700 switch k {
3701 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003702 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303703 ethFrameExtPMData[k] = val.(uint64)
3704 receivedMask |= 0x2000
3705 } else if !ok {
3706 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3707 }
3708 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003709 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303710 ethFrameExtPMData[k] = val.(uint64)
3711 receivedMask |= 0x1000
3712 } else if !ok {
3713 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3714 }
3715 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003716 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303717 ethFrameExtPMData[k] = val.(uint64)
3718 receivedMask |= 0x800
3719 } else if !ok {
3720 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3721 }
3722 }
3723 }
3724 }
3725 case 0x0700:
3726 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3727 if _, ok := ethFrameExtPMData[k]; !ok {
3728 switch k {
3729 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003730 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303731 ethFrameExtPMData[k] = val.(uint64)
3732 receivedMask |= 0x400
3733 } else if !ok {
3734 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3735 }
3736 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003737 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303738 ethFrameExtPMData[k] = val.(uint64)
3739 receivedMask |= 0x200
3740 } else if !ok {
3741 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3742 }
3743 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003744 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303745 ethFrameExtPMData[k] = val.(uint64)
3746 receivedMask |= 0x100
3747 } else if !ok {
3748 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3749 }
3750 }
3751 }
3752 }
3753 case 0x00E0:
3754 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3755 if _, ok := ethFrameExtPMData[k]; !ok {
3756 switch k {
3757 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003758 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303759 ethFrameExtPMData[k] = val.(uint64)
3760 receivedMask |= 0x80
3761 } else if !ok {
3762 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3763 }
3764 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003765 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303766 ethFrameExtPMData[k] = val.(uint64)
3767 receivedMask |= 0x40
3768 } else if !ok {
3769 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3770 }
3771 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003772 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303773 ethFrameExtPMData[k] = val.(uint64)
3774 receivedMask |= 0x20
3775 } else if !ok {
3776 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3777 }
3778 }
3779 }
3780 }
3781 case 0x001C:
3782 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3783 if _, ok := ethFrameExtPMData[k]; !ok {
3784 switch k {
3785 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003786 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303787 ethFrameExtPMData[k] = val.(uint64)
3788 receivedMask |= 0x10
3789 } else if !ok {
3790 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3791 }
3792 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003793 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303794 ethFrameExtPMData[k] = val.(uint64)
3795 receivedMask |= 0x8
3796 } else if !ok {
3797 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3798 }
3799 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003800 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303801 ethFrameExtPMData[k] = val.(uint64)
3802 receivedMask |= 0x4
3803 } else if !ok {
3804 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3805 }
3806 default:
3807 //do nothing
3808 }
3809 }
3810 }
3811 case 0x0003:
3812 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3813 if _, ok := ethFrameExtPMData[k]; !ok {
3814 switch k {
3815 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003816 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303817 ethFrameExtPMData[k] = val.(uint64)
3818 receivedMask |= 0x2
3819 } else if !ok {
3820 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3821 }
3822 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003823 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303824 ethFrameExtPMData[k] = val.(uint64)
3825 receivedMask |= 0x1
3826 } else if !ok {
3827 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3828 }
3829 default:
3830 //do nothing
3831 }
3832 }
3833 }
3834 }
3835 return receivedMask
3836}
3837
Himani Chawlaee10b542021-09-20 16:46:40 +05303838func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3839 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303840 errorCounterValue := UnsupportedCounterValue64bit
3841 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3842 errorCounterValue = UnsupportedCounterValue32bit
3843 }
3844 var pmDataOut extension.OmciEthernetFrameExtendedPm
3845 if aggregate {
3846 if pmData.DropEvents != errorCounterValue {
3847 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3848 } else {
3849 pmDataOut.DropEvents = pmData.DropEvents
3850 }
3851 if pmData.Octets != errorCounterValue {
3852 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3853 } else {
3854 pmDataOut.Octets = pmData.Octets
3855 }
3856 if pmData.Frames != errorCounterValue {
3857 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3858 } else {
3859 pmDataOut.Frames = pmData.Frames
3860 }
3861 if pmData.BroadcastFrames != errorCounterValue {
3862 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3863 } else {
3864 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3865 }
3866 if pmData.MulticastFrames != errorCounterValue {
3867 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3868 } else {
3869 pmDataOut.MulticastFrames = pmData.MulticastFrames
3870 }
3871 if pmData.CrcErroredFrames != errorCounterValue {
3872 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3873 } else {
3874 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3875 }
3876 if pmData.UndersizeFrames != errorCounterValue {
3877 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3878 } else {
3879 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3880 }
3881 if pmData.OversizeFrames != errorCounterValue {
3882 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3883 } else {
3884 pmDataOut.OversizeFrames = pmData.OversizeFrames
3885 }
3886 if pmData.Frames_64Octets != errorCounterValue {
3887 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3888 } else {
3889 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3890 }
3891 if pmData.Frames_65To_127Octets != errorCounterValue {
3892 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3893 } else {
3894 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3895 }
3896 if pmData.Frames_128To_255Octets != errorCounterValue {
3897 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3898 } else {
3899 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3900 }
3901 if pmData.Frames_256To_511Octets != errorCounterValue {
3902 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3903 } else {
3904 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3905 }
3906 if pmData.Frames_512To_1023Octets != errorCounterValue {
3907 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3908 } else {
3909 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3910 }
3911 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3912 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3913 } else {
3914 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3915 }
3916 } else {
3917 pmDataOut.DropEvents = pmDataIn["drop_events"]
3918 pmDataOut.Octets = pmDataIn["octets"]
3919 pmDataOut.Frames = pmDataIn["frames"]
3920 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3921 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3922 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3923 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3924 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3925 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3926 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3927 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3928 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3929 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3930 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3931 }
3932 return pmDataOut
3933}
3934
Himani Chawlaee10b542021-09-20 16:46:40 +05303935func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303936 controlBlock := make([]uint16, 8)
3937 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3938 controlBlock[0] = 0
3939 // Next two bytes are for the parent class ID
3940 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3941 // Next two bytes are for the parent me instance id
3942 controlBlock[2] = entityID
3943 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05303944 if reset {
3945 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
3946 } else {
3947 controlBlock[3] = 0
3948 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303949 // Next two bytes are for tca disable
3950 controlBlock[4] = 0x4000 //tca global disable
3951 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
3952 if upstream {
3953 controlBlock[5] = 1 << 0
3954 } else {
3955 controlBlock[5] = (1 << 0) | (1 << 1)
3956 }
3957 // Next two bytes are for tci - does not matter here
3958 controlBlock[6] = 0
3959 // Next two bytes are for reserved bits - does not matter here
3960 controlBlock[7] = 0
3961 return controlBlock
3962}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003963
Girish Gowdraabcceb12022-04-13 23:35:22 -07003964// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
3965func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
3966 mm.OnuMetricsManagerLock.RLock()
3967 defer mm.OnuMetricsManagerLock.RUnlock()
3968 return mm.deviceDeletionInProgress
3969}
3970
3971// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
3972func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
3973 mm.OnuMetricsManagerLock.Lock()
3974 defer mm.OnuMetricsManagerLock.Unlock()
3975 mm.deviceDeletionInProgress = true
3976}
3977
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003978// PrepareForGarbageCollection - remove references to prepare for garbage collection
3979func (mm *OnuMetricsManager) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07003980 logger.Debugw(ctx, "prepare for garbage collection - no action, garbage collection done when PM FSM is stopped", log.Fields{"device-id": aDeviceID})
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003981}