blob: 2736b65b03db911c927c0fd7320151d950d23f55 [file] [log] [blame]
Girish Gowdrae09a6202021-01-12 18:10:59 -08001/*
Joey Armstrong89c812c2024-01-12 19:00:20 -05002 * Copyright 2021-2024 Open Networking Foundation (ONF) and the ONF Contributors
Girish Gowdrae09a6202021-01-12 18:10:59 -08003
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
praneeth nalmas808f43a2023-05-14 12:54:34 +053017// Package pmmgr provides the utilities to manage onu metrics
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000018package 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"
Holger Hildebrandtd930cb22022-06-17 09:24:50 +000029 omci "github.com/opencord/omci-lib-go/v2"
mpagenko836a1fd2021-11-01 16:12:42 +000030 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"
balaji.nagarajan3cab2b62025-06-23 15:44:54 +053037 codes "google.golang.org/grpc/codes"
38 "google.golang.org/grpc/status"
Girish Gowdrae09a6202021-01-12 18:10:59 -080039)
40
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000041// events of L2 PM FSM
Girish Gowdrae0140f02021-02-02 16:55:09 -080042const (
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000043 L2PmEventInit = "L2PmEventInit"
44 L2PmEventTick = "L2PmEventTick"
45 L2PmEventSuccess = "L2PmEventSuccess"
46 L2PmEventFailure = "L2PmEventFailure"
47 L2PmEventAddMe = "L2PmEventAddMe"
48 L2PmEventDeleteMe = "L2PmEventDeleteMe"
49 L2PmEventStop = "L2PmEventStop"
Girish Gowdrae0140f02021-02-02 16:55:09 -080050)
51
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000052// states of L2 PM FSM
53const (
54 L2PmStNull = "L2PmStNull"
55 L2PmStStarting = "L2PmStStarting"
56 L2PmStSyncTime = "L2PmStSyncTime"
57 L2PmStIdle = "L2PmStIdle"
58 L2PmStCreatePmMe = "L2PmStCreatePm"
59 L2PmStDeletePmMe = "L2PmStDeletePmMe"
60 L2PmStCollectData = "L2PmStCollectData"
61)
62
63// CL2PmFsmIdleState - TODO: add comment
64const CL2PmFsmIdleState = L2PmStIdle
Girish Gowdrae0140f02021-02-02 16:55:09 -080065
Girish Gowdra5a7c4922021-01-22 18:33:41 -080066// general constants used for overall Metric Collection management
67const (
68 DefaultMetricCollectionFrequency = 15 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
69 GroupMetricEnabled = true // This is READONLY and cannot be changed from VOLTHA NBI
70 DefaultFrequencyOverrideEnabled = true // This is READONLY and cannot be changed from VOLTHA NBI
71 FrequencyGranularity = 5 // The frequency (in seconds) has to be multiple of 5. This setting cannot changed later.
Girish Gowdraabcceb12022-04-13 23:35:22 -070072 MaxTimeForPmFsmShutDown = 120 // in seconds
Girish Gowdra5a7c4922021-01-22 18:33:41 -080073)
74
Himani Chawla43f95ff2021-06-03 00:24:12 +053075// constants for ethernet frame extended pm collection
76const (
77 ExtendedPmCreateAttempts = 3
78 UnsupportedCounterValue32bit uint64 = 4294967294
79 UnsupportedCounterValue64bit uint64 = 18446744073709551614
Himani Chawla43f95ff2021-06-03 00:24:12 +053080)
81
Girish Gowdra5a7c4922021-01-22 18:33:41 -080082// OpticalPowerGroupMetrics are supported optical pm names
83var OpticalPowerGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrae20a4f62021-03-09 16:06:23 -080084 "ani_g_instance_id": voltha.PmConfig_CONTEXT,
85 "transmit_power_dBm": voltha.PmConfig_GAUGE,
86 "receive_power_dBm": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -080087}
88
89// OpticalPowerGroupMetrics specific constants
90const (
Girish Gowdrae0140f02021-02-02 16:55:09 -080091 OpticalPowerGroupMetricName = "PON_Optical"
Girish Gowdra5a7c4922021-01-22 18:33:41 -080092 OpticalPowerGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
93 OpticalPowerMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
94)
95
96// UniStatusGroupMetrics are supported UNI status names
97var UniStatusGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrad3436802021-06-28 13:15:40 -070098 "uni_port_no": voltha.PmConfig_CONTEXT,
99 "me_class_id": voltha.PmConfig_CONTEXT,
100 "entity_id": voltha.PmConfig_CONTEXT,
101 "configuration_ind": voltha.PmConfig_GAUGE,
102 "oper_status": voltha.PmConfig_GAUGE,
103 "uni_admin_state": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800104}
105
106// UniStatusGroupMetrics specific constants
107const (
Girish Gowdrae0140f02021-02-02 16:55:09 -0800108 UniStatusGroupMetricName = "UNI_Status"
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800109 UniStatusGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
110 UniStatusMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
111)
112
Girish Gowdrae0140f02021-02-02 16:55:09 -0800113// *** Classical L2 PM Counters begin ***
114
115// EthernetBridgeHistory are supported ethernet bridge history counters fetched from
116// Ethernet Frame Performance Monitoring History Data Downstream and Ethernet Frame Performance Monitoring History Data Upstream MEs.
117var EthernetBridgeHistory = map[string]voltha.PmConfig_PmType{
118 "class_id": voltha.PmConfig_CONTEXT,
119 "entity_id": voltha.PmConfig_CONTEXT,
120 "interval_end_time": voltha.PmConfig_CONTEXT,
121 "parent_class_id": voltha.PmConfig_CONTEXT,
122 "parent_entity_id": voltha.PmConfig_CONTEXT,
123 "upstream": voltha.PmConfig_CONTEXT,
124
125 "drop_events": voltha.PmConfig_COUNTER,
126 "octets": voltha.PmConfig_COUNTER,
127 "packets": voltha.PmConfig_COUNTER,
128 "broadcast_packets": voltha.PmConfig_COUNTER,
129 "multicast_packets": voltha.PmConfig_COUNTER,
130 "crc_errored_packets": voltha.PmConfig_COUNTER,
131 "undersize_packets": voltha.PmConfig_COUNTER,
132 "oversize_packets": voltha.PmConfig_COUNTER,
133 "64_octets": voltha.PmConfig_COUNTER,
134 "65_to_127_octets": voltha.PmConfig_COUNTER,
135 "128_to_255_octets": voltha.PmConfig_COUNTER,
136 "256_to_511_octets": voltha.PmConfig_COUNTER,
137 "512_to_1023_octets": voltha.PmConfig_COUNTER,
138 "1024_to_1518_octets": voltha.PmConfig_COUNTER,
139}
140
141// EthernetUniHistory are supported ethernet uni history counters fetched from
142// Ethernet Performance Monitoring History Data ME.
143var EthernetUniHistory = map[string]voltha.PmConfig_PmType{
144 "class_id": voltha.PmConfig_CONTEXT,
145 "entity_id": voltha.PmConfig_CONTEXT,
146 "interval_end_time": voltha.PmConfig_CONTEXT,
147
148 "fcs_errors": voltha.PmConfig_COUNTER,
149 "excessive_collision_counter": voltha.PmConfig_COUNTER,
150 "late_collision_counter": voltha.PmConfig_COUNTER,
151 "frames_too_long": voltha.PmConfig_COUNTER,
152 "buffer_overflows_on_rx": voltha.PmConfig_COUNTER,
153 "buffer_overflows_on_tx": voltha.PmConfig_COUNTER,
154 "single_collision_frame_counter": voltha.PmConfig_COUNTER,
155 "multiple_collisions_frame_counter": voltha.PmConfig_COUNTER,
156 "sqe_counter": voltha.PmConfig_COUNTER,
157 "deferred_tx_counter": voltha.PmConfig_COUNTER,
158 "internal_mac_tx_error_counter": voltha.PmConfig_COUNTER,
159 "carrier_sense_error_counter": voltha.PmConfig_COUNTER,
160 "alignment_error_counter": voltha.PmConfig_COUNTER,
161 "internal_mac_rx_error_counter": voltha.PmConfig_COUNTER,
162}
163
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800164// FecHistory is supported FEC Performance Monitoring History Data related metrics
165var FecHistory = map[string]voltha.PmConfig_PmType{
166 "class_id": voltha.PmConfig_CONTEXT,
167 "entity_id": voltha.PmConfig_CONTEXT,
168 "interval_end_time": voltha.PmConfig_CONTEXT,
169
170 "corrected_bytes": voltha.PmConfig_COUNTER,
171 "corrected_code_words": voltha.PmConfig_COUNTER,
172 "uncorrectable_code_words": voltha.PmConfig_COUNTER,
173 "total_code_words": voltha.PmConfig_COUNTER,
174 "fec_seconds": voltha.PmConfig_COUNTER,
175}
176
177// GemPortHistory is supported GEM Port Network Ctp Performance Monitoring History Data
178// related metrics
179var GemPortHistory = map[string]voltha.PmConfig_PmType{
180 "class_id": voltha.PmConfig_CONTEXT,
181 "entity_id": voltha.PmConfig_CONTEXT,
182 "interval_end_time": voltha.PmConfig_CONTEXT,
183
184 "transmitted_gem_frames": voltha.PmConfig_COUNTER,
185 "received_gem_frames": voltha.PmConfig_COUNTER,
186 "received_payload_bytes": voltha.PmConfig_COUNTER,
187 "transmitted_payload_bytes": voltha.PmConfig_COUNTER,
188 "encryption_key_errors": voltha.PmConfig_COUNTER,
189}
190
Himani Chawla43f95ff2021-06-03 00:24:12 +0530191var maskToEthernetFrameExtendedPM32Bit = map[uint16][]string{
192 0x3F00: {"drop_events", "octets", "frames", "broadcast_frames", "multicast_frames", "crc_errored_frames"},
193 0x00FC: {"undersize_frames", "oversize_frames", "64_octets", "65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
194 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
195}
196
197var maskToEthernetFrameExtendedPM64Bit = map[uint16][]string{
198 0x3800: {"drop_events", "octets", "frames"},
199 0x0700: {"broadcast_frames", "multicast_frames", "crc_errored_frames"},
200 0x00E0: {"undersize_frames", "oversize_frames", "64_octets"},
201 0x001C: {"65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
202 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
203}
204
Girish Gowdrae0140f02021-02-02 16:55:09 -0800205// Constants specific for L2 PM collection
206const (
207 L2PmCollectionInterval = 15 * 60 // Unit in seconds. Do not change this as this fixed by OMCI specification for L2 PM counters
208 SyncTimeRetryInterval = 15 // Unit seconds
209 L2PmCreateAttempts = 3
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800210 L2PmDeleteAttempts = 3
Girish Gowdrae0140f02021-02-02 16:55:09 -0800211 L2PmCollectAttempts = 3
Girish Gowdra453750f2021-02-16 16:36:46 -0800212 // Per Table 11.2.9-1 – OMCI baseline message limitations in G.988 spec, the max GET Response
213 // payload size is 25. We define 24 (one less) to allow for dynamic insertion of IntervalEndTime
214 // attribute (1 byte) in L2 PM GET Requests.
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000215 MaxBaselineL2PMGetPayLoadSize = 24
216 // unused: MaxEthernetFrameExtPmPayloadSize = 25
217 MaxExtendedL2PMGetPayLoadSize = omci.MaxExtendedLength - 17 - 1 - 4 // minus header, attribute IntervalEndTime and MIC
Girish Gowdrae0140f02021-02-02 16:55:09 -0800218)
219
220// EthernetUniHistoryName specific constants
221const (
222 EthernetBridgeHistoryName = "Ethernet_Bridge_Port_History"
223 EthernetBridgeHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
224 EthernetBridgeHistoryFrequency = L2PmCollectionInterval
225)
226
227// EthernetBridgeHistory specific constants
228const (
229 EthernetUniHistoryName = "Ethernet_UNI_History"
230 EthernetUniHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
231 EthernetUniHistoryFrequency = L2PmCollectionInterval
232)
233
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800234// FecHistory specific constants
235const (
236 FecHistoryName = "FEC_History"
237 FecHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
238 FecHistoryFrequency = L2PmCollectionInterval
239)
240
241// GemPortHistory specific constants
242const (
243 GemPortHistoryName = "GEM_Port_History"
244 GemPortHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
245 GemPortHistoryFrequency = L2PmCollectionInterval
246)
247
Holger Hildebrandt60652202021-11-02 11:09:36 +0000248// CPmKvStorePrefixBase - kv store base path of ONU specific PM data
249const CPmKvStorePrefixBase = cmn.CBasePathOnuKVStore + "/pm-data" // <some-base-path>/openonu/pm-data
250
Girish Gowdra0e533642021-03-02 22:02:51 -0800251// KV Store related constants
252const (
Holger Hildebrandt60652202021-11-02 11:09:36 +0000253 cPmKvStorePrefix = CPmKvStorePrefixBase + "/%s" // <some-base-path>/openonu/pm-data/<onu-device-id>
Himani Chawla43f95ff2021-06-03 00:24:12 +0530254 cPmAdd = "add"
255 cPmAdded = "added"
256 cPmRemove = "remove"
257 cPmRemoved = "removed"
258 cExtPmKvStorePrefix = "%s/omci_me" //<some-base-path>/omci_me/<onu_vendor>/<onu_equipment_id>/<onu_sw_version>
Girish Gowdra0e533642021-03-02 22:02:51 -0800259)
260
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800261// Defines the type for generic metric population function
262type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
263
Girish Gowdrae0140f02021-02-02 16:55:09 -0800264// *** Classical L2 PM Counters end ***
265
Girish Gowdra0e533642021-03-02 22:02:51 -0800266type pmMEData struct {
267 InstancesActive []uint16 `json:"instances_active"` // list of active ME instance IDs for the group
268 InstancesToDelete []uint16 `json:"instances_to_delete"` // list of ME instance IDs marked for deletion for the group
269 InstancesToAdd []uint16 `json:"instances_to_add"` // list of ME instance IDs marked for addition for the group
270}
271
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800272type groupMetric struct {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000273 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530274 metricMap map[string]voltha.PmConfig_PmType
Girish Gowdra0e533642021-03-02 22:02:51 -0800275 pmMEData *pmMEData
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530276 groupName string
277 Frequency uint32 // valid only if FrequencyOverride is enabled.
278 collectAttempts uint32 // number of attempts to collect L2 PM data
279 Enabled bool
280 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800281}
282
283type standaloneMetric struct {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000284 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530285 metricName string
286 Frequency uint32 // valid only if FrequencyOverride is enabled.
287 Enabled bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800288}
289
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000290// OnuMetricsManager - TODO: add comment
291type OnuMetricsManager struct {
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530292 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
293
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000294 pDeviceHandler cmn.IdeviceHandler
295 pOnuDeviceEntry cmn.IonuDeviceEntry
296 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800297
Himani Chawlaee10b542021-09-20 16:46:40 +0530298 opticalMetricsChan chan me.AttributeValueMap
299 uniStatusMetricsChan chan me.AttributeValueMap
300 l2PmChan chan me.AttributeValueMap
301 extendedPmMeChan chan me.AttributeValueMap
302 syncTimeResponseChan chan bool // true is success, false is fail
303 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
304 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -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 Gowdra5a7c4922021-01-22 18:33:41 -0800310
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530311 StopTicks chan bool
Girish Gowdraabcceb12022-04-13 23:35:22 -0700312 GarbageCollectionComplete chan bool
313
Girish Gowdra0e533642021-03-02 22:02:51 -0800314 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530315
Himani Chawlac77d5372021-07-12 15:42:26 +0530316 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
317 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530318 extPmKvStore *db.Backend
praneeth nalmas808f43a2023-05-14 12:54:34 +0530319 onuOpticalMetricstimer *time.Timer
320 onuUniStatusMetricstimer *time.Timer
praneeth nalmasf405e962023-08-07 15:02:03 +0530321 opticalMetricsDelCommChan chan bool
322 uniMetricsDelCommChan chan bool
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530323 deviceID string
324
325 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
326 l2PmToDelete []string // list of L2 PMs to delete
327 l2PmToAdd []string // list of L2 PM to add
328
329 maxL2PMGetPayLoadSize int
330
331 OnuMetricsManagerLock sync.RWMutex
332
333 onuEthernetFrameExtendedPmLock sync.RWMutex
334
335 supportedEthernetFrameExtendedPMClass me.ClassID
336 omciProcessingActive bool
337
338 tickGenerationActive bool
339
340 deviceDeletionInProgress bool
341 isDeviceReadyToCollectExtendedPmStats bool
342 isEthernetFrameExtendedPmOperationOngoing bool
343 isExtendedOmci bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800344}
345
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000346// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800347// The metrics manager module is responsible for configuration and management of individual and group metrics.
348// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
349// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
350// the collection interval configurable.
351// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
352// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000353func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800354
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000355 var metricsManager OnuMetricsManager
356 metricsManager.deviceID = dh.GetDeviceID()
357 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800358 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000359 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800360
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000361 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800362 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
363 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800364 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530365 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800366
367 metricsManager.syncTimeResponseChan = make(chan bool)
368 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530369 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800370
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000371 metricsManager.StopProcessingOmciResponses = make(chan bool)
372 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800373
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000374 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
375 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800376
Himani Chawlac77d5372021-07-12 15:42:26 +0530377 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
378 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530379
Girish Gowdraabcceb12022-04-13 23:35:22 -0700380 // make this a buffered channel so that the sender is not blocked for any reason if there is no listener
381 metricsManager.GarbageCollectionComplete = make(chan bool, 1)
382
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000383 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 -0800384 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800385 }
386
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800387 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800388
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800389 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800390 return nil
391 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800392
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800393 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000394 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800395
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000396 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
397 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800398 if metricsManager.pmKvStore == nil {
399 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000400 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800401 return nil
402 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700403 // restore data from KV store
404 if err := metricsManager.restorePmData(ctx); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000405 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700406 // we continue given that it does not effect the actual services for the ONU,
407 // but there may be some negative effect on PM collection (there may be some mismatch in
408 // the actual PM config and what is present on the device).
409 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800410
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000411 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
412 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530413 if metricsManager.extPmKvStore == nil {
414 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000415 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530416 return nil
417 }
418
praneeth nalmas808f43a2023-05-14 12:54:34 +0530419 //Metrics collection timers are initialized with a default timer value, will be stopped immediately and further
420 //timers are reset during the actual stats collection begins.
421 metricsManager.onuOpticalMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
422 metricsManager.onuOpticalMetricstimer.Stop()
423
424 metricsManager.onuUniStatusMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
425 metricsManager.onuUniStatusMetricstimer.Stop()
426
praneeth nalmasf405e962023-08-07 15:02:03 +0530427 metricsManager.opticalMetricsDelCommChan = make(chan bool, 2)
428 metricsManager.uniMetricsDelCommChan = make(chan bool, 2)
429
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000430 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800431 return &metricsManager
432}
433
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000434// InitializeMetricCollectionTime - TODO: add comment
435func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
436 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
437 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
438 mm.OnuMetricsManagerLock.Lock()
439 defer mm.OnuMetricsManagerLock.Unlock()
440 for _, v := range mm.GroupMetricMap {
441 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
442 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800443 }
444 }
445
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000446 for _, v := range mm.StandaloneMetricMap {
447 if v.Enabled {
448 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800449 }
450 }
451 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000452 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
453 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800454 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000455 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800456}
457
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000458// UpdateDefaultFrequency - TODO: add comment
459func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800460 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800461 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800462 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
463 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
464 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000465 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
466 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
467 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
468 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 -0800469 return nil
470}
471
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000472// UpdateGroupFreq - TODO: add comment
473func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800474 var newGroupFreq uint32
475 found := false
476 groupSliceIdx := 0
477 var group *voltha.PmGroupConfig
478 for groupSliceIdx, group = range pmConfigs.Groups {
479 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800480 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
481 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
482 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
483 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800484 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800485 newGroupFreq = group.GroupFreq
486 found = true
487 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800488 }
489 }
490 // if not found update group freq and next collection interval for the group
491 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000492 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800493 return fmt.Errorf("group-name-not-found-%v", aGroupName)
494 }
495
496 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000497 mm.OnuMetricsManagerLock.Lock()
498 defer mm.OnuMetricsManagerLock.Unlock()
499 for k, v := range mm.GroupMetricMap {
500 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
501 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800502 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000503 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800504 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000505 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800506 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000507 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800508 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800509 }
510 }
511 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000512 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800513 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
514 }
515 return nil
516}
517
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000518// UpdateMetricFreq - TODO: add comment
519func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800520 var newMetricFreq uint32
521 found := false
522 metricSliceIdx := 0
523 var metric *voltha.PmConfig
524 for metricSliceIdx, metric = range pmConfigs.Metrics {
525 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800526 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
527 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
528 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
529 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800530 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800531 newMetricFreq = metric.SampleFreq
532 found = true
533 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800534 }
535 }
536 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000537 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800538 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
539 }
540
541 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000542 mm.OnuMetricsManagerLock.Lock()
543 defer mm.OnuMetricsManagerLock.Unlock()
544 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800545 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000546 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800547 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000548 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800549 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000550 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800551 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000552 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800553 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800554 }
555 }
556 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000557 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800558 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
559 }
560 return nil
561}
562
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000563// UpdateGroupSupport - TODO: add comment
564func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800565 groupSliceIdx := 0
566 var group *voltha.PmGroupConfig
567
568 for groupSliceIdx, group = range pmConfigs.Groups {
569 if group.GroupName == aGroupName {
570 break
571 }
572 }
573 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000574 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800575 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
576 }
577
578 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000579 mm.OnuMetricsManagerLock.Lock()
580 defer mm.OnuMetricsManagerLock.Unlock()
581 for k, v := range mm.GroupMetricMap {
582 if k == aGroupName && v.Enabled != group.Enabled {
583 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
584 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800585 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000586 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800587 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800588 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800589 // 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 -0800590 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
591
592 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
593 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
594 // take further action
595 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800596 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800597 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000598 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
599 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800600 }
601 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000602 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800603 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800604 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800605 // 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 -0800606 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
607
608 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
609 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
610 // take further action
611 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800612 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800613 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800614 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800615 }
616 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000617 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800618 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000619 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800620 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000621 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 -0800622 }
623 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800624 }
625 }
626
627 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000628 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800629 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
630 }
631 return nil
632}
633
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000634// UpdateMetricSupport - TODO: add comment
635func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800636 metricSliceIdx := 0
637 var metric *voltha.PmConfig
638
639 for metricSliceIdx, metric = range pmConfigs.Metrics {
640 if metric.Name == aMetricName {
641 break
642 }
643 }
644
645 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000646 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800647 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
648 }
649
650 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000651 mm.OnuMetricsManagerLock.Lock()
652 defer mm.OnuMetricsManagerLock.Unlock()
653 for k, v := range mm.StandaloneMetricMap {
654 if k == aMetricName && v.Enabled != metric.Enabled {
655 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
656 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800657 // 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 +0000658 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
659 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800660 }
661 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000662 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 -0800663 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800664 }
665 }
666 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000667 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800668 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
669 }
670 return nil
671}
672
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000673// CollectAllGroupAndStandaloneMetrics - TODO: add comment
674func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
675 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800676 go mm.collectAllGroupMetrics(ctx)
677 } else {
678 go mm.collectAllStandaloneMetrics(ctx)
679 }
680}
681
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000682func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800683 go func() {
684 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300685 metricInfo, err := mm.collectOpticalMetrics(ctx)
686 if err != nil {
687 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000688 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300689 return
690 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800691 if metricInfo != nil {
692 mm.publishMetrics(ctx, metricInfo)
693 }
694 }()
695
696 go func() {
697 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300698 metricInfo, err := mm.collectUniStatusMetrics(ctx)
699 if err != nil {
700 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000701 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300702 return
703 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800704 if metricInfo != nil {
705 mm.publishMetrics(ctx, metricInfo)
706 }
707 }()
708
709 // Add more here
710}
711
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000712func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800713 // None exists as of now, add when available here
714}
715
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000716// CollectGroupMetric - TODO: add comment
717func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800718 switch groupName {
719 case OpticalPowerGroupMetricName:
720 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300721 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800722 mm.publishMetrics(ctx, mi)
723 }
724 }()
725 case UniStatusGroupMetricName:
726 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300727 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800728 mm.publishMetrics(ctx, mi)
729 }
730 }()
731 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000732 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800733 }
734}
735
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000736// CollectStandaloneMetric - TODO: add comment
737func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800738 switch metricName {
739 // None exist as of now, add when available
740 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000741 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800742 }
743}
744
745// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000746func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
747 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800748
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000749 mm.OnuMetricsManagerLock.RLock()
750 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
751 mm.OnuMetricsManagerLock.RUnlock()
752 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300753 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800754 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000755 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800756
Girish Gowdrae09a6202021-01-12 18:10:59 -0800757 var metricInfoSlice []*voltha.MetricInformation
758 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000759 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
760 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
761 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800762
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800763 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800764 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800765 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800766 Ts: float64(raisedTs),
767 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000768 DeviceId: mm.deviceID,
769 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
770 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800771 }
772
Girish Gowdrae09a6202021-01-12 18:10:59 -0800773 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000774 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800775loop:
776 for _, anigInstID := range anigInstKeys {
777 var meAttributes me.AttributeValueMap
778 opticalMetrics := make(map[string]float32)
779 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000780 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
balaji.nagarajan3cab2b62025-06-23 15:44:54 +0530781 meInstance, err := mm.GetMeInstance(ctx, me.AniGClassID, anigInstID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000782 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300783 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +0530784 if CheckMeInstanceStatusCode(err) {
785 return nil, err // Device is being deleted, so we stop processing
786 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000787 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
788 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300789 return nil, err
790 }
791
792 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530793 mm.onuOpticalMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800794 select {
795 case meAttributes = <-mm.opticalMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530796 mm.onuOpticalMetricstimer.Stop()
797 logger.Debugw(ctx, "received optical metrics, stopping the optical metrics collection timer", log.Fields{"device-id": mm.deviceID})
798 case <-mm.onuOpticalMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000799 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 -0800800 // The metrics will be empty in this case
801 break loop
praneeth nalmasf405e962023-08-07 15:02:03 +0530802 case <-mm.opticalMetricsDelCommChan:
803 logger.Warnw(ctx, "Deleting the device, stopping optical metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
804 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800805 }
806 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800807 for k := range OpticalPowerGroupMetrics {
808 switch k {
809 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000810 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800811 opticalMetrics[k] = float32(val.(uint16))
812 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800813 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000814 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000815 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 -0800816 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800817 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000818 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000819 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 -0800820 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800821 default:
822 // do nothing
823 }
824 }
825 }
826 // create slice of metrics given that there could be more than one ANI-G instance and
827 // optical metrics are collected per ANI-G instance
828 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
829 metricInfoSlice = append(metricInfoSlice, &metricInfo)
830 }
831
ozgecanetsiab36ed572021-04-01 10:38:48 +0300832 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800833}
834
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800835// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800836// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000837func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
838 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
839 mm.OnuMetricsManagerLock.RLock()
840 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
841 mm.OnuMetricsManagerLock.RUnlock()
842 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300843 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800844 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000845 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800846
Girish Gowdrae09a6202021-01-12 18:10:59 -0800847 var metricInfoSlice []*voltha.MetricInformation
848 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000849 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
850 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
851 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800852
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800853 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800854 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700855 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800856 Ts: float64(raisedTs),
857 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000858 DeviceId: mm.deviceID,
859 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
860 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800861 }
862
Girish Gowdrae09a6202021-01-12 18:10:59 -0800863 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000864 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800865loop1:
866 for _, unigInstID := range unigInstKeys {
867 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
868 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
869 unigMetrics := make(map[string]float32)
870 var meAttributes me.AttributeValueMap
871 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000872 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
balaji.nagarajan3cab2b62025-06-23 15:44:54 +0530873 meInstance, err := mm.GetMeInstance(ctx, me.UniGClassID, unigInstID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000874 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300875 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +0530876 if CheckMeInstanceStatusCode(err) {
877 return nil, err // Device is being deleted, so we stop processing
878 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000879 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
880 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300881 return nil, err
882 }
883 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530884 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800885 // Wait for metrics or timeout
886 select {
887 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530888 mm.onuUniStatusMetricstimer.Stop()
889 logger.Debugw(ctx, "received uni-g metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
890 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000891 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 -0800892 // The metrics could be empty in this case
893 break loop1
praneeth nalmasf405e962023-08-07 15:02:03 +0530894 case <-mm.uniMetricsDelCommChan:
895 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
896 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800897 }
898 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800899 for k := range UniStatusGroupMetrics {
900 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800901 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000902 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800903 unigMetrics[k] = float32(val.(byte))
904 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800905 default:
906 // do nothing
907 }
908 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000909 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800910 entityID := val.(uint16)
911 unigMetrics["entity_id"] = float32(entityID)
912 // 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 +0000913 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
914 if uni.EntityID == entityID {
915 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700916 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800917 }
918 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800919 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700920 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800921
Girish Gowdrae09a6202021-01-12 18:10:59 -0800922 // create slice of metrics given that there could be more than one UNI-G instance
923 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
924 metricInfoSlice = append(metricInfoSlice, &metricInfo)
925 }
926 }
927
928 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000929 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800930loop2:
931 for _, pptpInstID := range pptpInstKeys {
932 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
933 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
934 var meAttributes me.AttributeValueMap
935 pptpMetrics := make(map[string]float32)
936
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000937 requestedAttributes := me.AttributeValueMap{
938 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
939 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
940 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
balaji.nagarajan3cab2b62025-06-23 15:44:54 +0530941 meInstance, err := mm.GetMeInstance(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000942 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300943 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +0530944 if CheckMeInstanceStatusCode(err) {
945 return nil, err // Device is being deleted, so we stop processing
946 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000947 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
948 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300949 return nil, err
950 }
951 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530952 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800953 // Wait for metrics or timeout
954 select {
955 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530956 mm.onuUniStatusMetricstimer.Stop()
957 logger.Debugw(ctx, "received pptp metrics, stopping Onu Uni Status metrics timer ", log.Fields{"device-id": mm.deviceID})
958 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000959 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 -0800960 // The metrics could be empty in this case
961 break loop2
praneeth nalmasf405e962023-08-07 15:02:03 +0530962 case <-mm.uniMetricsDelCommChan:
963 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
964 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800965 }
966
967 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800968 for k := range UniStatusGroupMetrics {
969 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700970 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000971 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800972 pptpMetrics[k] = float32(val.(byte))
973 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800974 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000975 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800976 pptpMetrics[k] = float32(val.(byte))
977 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800978 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000979 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800980 pptpMetrics[k] = float32(val.(byte))
981 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800982 default:
983 // do nothing
984 }
985 }
986 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000987 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800988 entityID := val.(uint16)
989 pptpMetrics["entity_id"] = float32(entityID)
990 // 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 +0000991 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
992 if uni.EntityID == entityID {
993 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700994 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800995 }
996 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800997 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700998 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800999
Girish Gowdrae09a6202021-01-12 18:10:59 -08001000 // create slice of metrics given that there could be more than one PPTP instance and
1001 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
1002 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1003 }
1004
1005 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001006 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001007loop3:
1008 for _, veipInstID := range veipInstKeys {
1009 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
1010 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
1011 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001012 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001013
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001014 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0,
1015 me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05301016 meInstance, err := mm.GetMeInstance(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001017 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001018 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05301019 if CheckMeInstanceStatusCode(err) {
1020 return nil, err // Device is being deleted, so we stop processing
1021 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001022 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
1023 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001024 return nil, err
1025 }
1026 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +05301027 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001028 // Wait for metrics or timeout
1029 select {
1030 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +05301031 mm.onuUniStatusMetricstimer.Stop()
1032 logger.Debugw(ctx, "received veip metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
1033 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001034 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 -08001035 // The metrics could be empty in this case
1036 break loop3
praneeth nalmasf405e962023-08-07 15:02:03 +05301037 case <-mm.uniMetricsDelCommChan:
1038 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
1039 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -08001040 }
1041
1042 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001043 for k := range UniStatusGroupMetrics {
1044 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001045 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001046 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001047 veipMetrics[k] = float32(val.(byte))
1048 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001049 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001050 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001051 veipMetrics[k] = float32(val.(byte))
1052 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001053 default:
1054 // do nothing
1055 }
1056 }
1057 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001058
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001059 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001060 entityID := val.(uint16)
1061 veipMetrics["entity_id"] = float32(entityID)
1062 // 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 +00001063 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1064 if uni.EntityID == entityID {
1065 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001066 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001067 }
1068 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001069 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001070 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001071
Girish Gowdrae09a6202021-01-12 18:10:59 -08001072 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001073 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001074 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1075 }
1076
ozgecanetsiab36ed572021-04-01 10:38:48 +03001077 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001078}
1079
1080// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001081func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001082 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001083 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001084 ke.SliceData = metricInfo
1085 ke.Type = voltha.KpiEventType_slice
1086 ke.Ts = float64(ts)
1087
Himani Chawlaf9768882021-12-01 00:18:58 +05301088 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 +00001089 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001090 }
1091}
1092
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001093// ProcessOmciMessages - TODO: add comment
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001094func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context, waitForOmciProcessor *sync.WaitGroup) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001095 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 -08001096 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001097 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001098 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001099 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001100 // is stopped - as a result of ONU going down.
1101 mm.flushMetricCollectionChannels(ctx)
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001102 // when instantiating mm it was too early, but now we can check for ONU's extended OMCI support
1103 mm.isExtendedOmci = mm.pOnuDeviceEntry.GetPersIsExtOmciSupported()
1104 if mm.isExtendedOmci {
1105 mm.maxL2PMGetPayLoadSize = MaxExtendedL2PMGetPayLoadSize
1106 } else {
1107 mm.maxL2PMGetPayLoadSize = MaxBaselineL2PMGetPayLoadSize
1108 }
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001109 mm.updateOmciProcessingStatus(true)
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001110 waitForOmciProcessor.Done()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001111 for {
1112 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001113 case <-mm.StopProcessingOmciResponses: // stop this routine
1114 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 -07001115 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001116 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001117 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001118 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001119 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001120 continue
1121 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001122 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001123
1124 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001125 case cmn.OMCI:
1126 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001127 mm.handleOmciMessage(ctx, msg)
1128 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001129 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001130 }
1131 }
1132 }
1133}
1134
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001135func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1136 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001137 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1138 switch msg.OmciMsg.MessageType {
1139 case omci.GetResponseType:
1140 //TODO: error handling
1141 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001142 case omci.SynchronizeTimeResponseType:
1143 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1144 case omci.CreateResponseType:
1145 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1146 case omci.DeleteResponseType:
1147 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301148 case omci.GetCurrentDataResponseType:
1149 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301150 case omci.SetResponseType:
1151 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001152 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001153 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001154
1155 }
1156}
1157
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001158func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001159 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1160 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001161 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1162 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001163 }
1164 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1165 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001166 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1167 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001168 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001169 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 -08001170 if msgObj.Result == me.Success {
1171 meAttributes := msgObj.Attributes
1172 switch msgObj.EntityClass {
1173 case me.AniGClassID:
1174 mm.opticalMetricsChan <- meAttributes
1175 return nil
1176 case me.UniGClassID:
1177 mm.uniStatusMetricsChan <- meAttributes
1178 return nil
1179 case me.PhysicalPathTerminationPointEthernetUniClassID:
1180 mm.uniStatusMetricsChan <- meAttributes
1181 return nil
1182 case me.VirtualEthernetInterfacePointClassID:
1183 mm.uniStatusMetricsChan <- meAttributes
1184 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001185 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1186 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001187 me.EthernetPerformanceMonitoringHistoryDataClassID,
1188 me.FecPerformanceMonitoringHistoryDataClassID,
1189 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001190 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301191 return nil
1192 case me.EthernetFrameExtendedPmClassID,
1193 me.EthernetFrameExtendedPm64BitClassID:
1194 mm.extendedPmMeChan <- meAttributes
1195 return nil
1196 default:
1197 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001198 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301199 }
1200 } else {
1201 meAttributes := msgObj.Attributes
1202 switch msgObj.EntityClass {
1203 case me.EthernetFrameExtendedPmClassID,
1204 me.EthernetFrameExtendedPm64BitClassID:
1205 // not all counters may be supported in which case we have seen some ONUs throwing
1206 // AttributeFailure error code, while correctly populating other counters it supports
1207 mm.extendedPmMeChan <- meAttributes
1208 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001209 default:
1210 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001211 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001212 }
1213 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001214 return fmt.Errorf("unhandled-omci-get-response-message")
1215}
1216
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001217func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301218 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1219 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001220 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1221 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301222 }
1223 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1224 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001225 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1226 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301227 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001228 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 +05301229 if msgObj.Result == me.Success {
1230 meAttributes := msgObj.Attributes
1231 switch msgObj.EntityClass {
1232 case me.EthernetFrameExtendedPmClassID,
1233 me.EthernetFrameExtendedPm64BitClassID:
1234 mm.extendedPmMeChan <- meAttributes
1235 return nil
1236 default:
1237 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001238 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301239 }
1240 } else {
1241 meAttributes := msgObj.Attributes
1242 switch msgObj.EntityClass {
1243 case me.EthernetFrameExtendedPmClassID,
1244 me.EthernetFrameExtendedPm64BitClassID:
1245 // not all counters may be supported in which case we have seen some ONUs throwing
1246 // AttributeFailure error code, while correctly populating other counters it supports
1247 mm.extendedPmMeChan <- meAttributes
1248 return nil
1249 default:
1250 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001251 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301252 }
1253 }
1254 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1255}
1256
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001257func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001258 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1259 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001260 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1261 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 -08001262 }
1263 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1264 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001265 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1266 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 -08001267 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001268 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001269 if msgObj.Result == me.Success {
1270 switch msgObj.EntityClass {
1271 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001272 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001273 mm.syncTimeResponseChan <- true
1274 return nil
1275 default:
1276 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001277 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001278 }
1279 }
1280 mm.syncTimeResponseChan <- false
1281 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1282 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001283}
1284
Himani Chawlaee10b542021-09-20 16:46:40 +05301285func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1286 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1287 if msgLayer == nil {
1288 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1289 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1290 }
1291 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1292 if !msgOk {
1293 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1294 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1295 }
1296 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1297 switch msgObj.EntityClass {
1298 case me.EthernetFrameExtendedPmClassID,
1299 me.EthernetFrameExtendedPm64BitClassID:
1300 mm.extendedPMMeResponseChan <- msgObj.Result
1301 return nil
1302 default:
1303 logger.Errorw(ctx, "unhandled omci set response message",
1304 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1305 }
1306 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1307}
1308
Girish Gowdrae09a6202021-01-12 18:10:59 -08001309// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001310func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001311 // flush commMetricsChan
1312 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001313 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001314 logger.Debug(ctx, "flushed common metrics channel")
1315 default:
1316 }
1317
1318 // flush opticalMetricsChan
1319 select {
1320 case <-mm.opticalMetricsChan:
1321 logger.Debug(ctx, "flushed optical metrics channel")
1322 default:
1323 }
1324
1325 // flush uniStatusMetricsChan
1326 select {
1327 case <-mm.uniStatusMetricsChan:
1328 logger.Debug(ctx, "flushed uni status metrics channel")
1329 default:
1330 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001331
1332 // flush syncTimeResponseChan
1333 select {
1334 case <-mm.syncTimeResponseChan:
1335 logger.Debug(ctx, "flushed sync time response channel")
1336 default:
1337 }
1338
1339 // flush l2PmChan
1340 select {
1341 case <-mm.l2PmChan:
1342 logger.Debug(ctx, "flushed L2 PM collection channel")
1343 default:
1344 }
1345
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001346 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001347 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001348 case <-mm.StopTicks:
1349 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001350 default:
1351 }
1352
1353}
1354
1355// ** L2 PM FSM Handlers start **
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301356// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001357func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001358 if mm.GetdeviceDeletionInProgress() {
1359 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1360 return
1361 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001362
Girish Gowdrae0140f02021-02-02 16:55:09 -08001363 // Loop through all the group metrics
1364 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1365 // list of active L2 PM list then mark it for creation
1366 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1367 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001368 mm.OnuMetricsManagerLock.Lock()
1369 for n, g := range mm.GroupMetricMap {
1370 if g.IsL2PMCounter { // it is a l2 pm counter
1371 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001372 found := false
1373 inner1:
1374 for _, v := range mm.activeL2Pms {
1375 if v == n {
1376 found = true // metric already present in active l2 pm list
1377 break inner1
1378 }
1379 }
1380 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001381 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001382 }
1383 } else { // metric not enabled.
1384 found := false
1385 inner2:
1386 for _, v := range mm.activeL2Pms {
1387 if v == n {
1388 found = true // metric is found in active l2 pm list
1389 break inner2
1390 }
1391 }
1392 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001393 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001394 }
1395 }
1396 }
1397 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001398 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001399 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001400 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001401 go func() {
1402 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001403 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1404 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001405 }
1406 }()
1407}
1408
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301409// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001410func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001411 if mm.GetdeviceDeletionInProgress() {
1412 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1413 return
1414 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001415 // Sync time with the ONU to establish 15min boundary for PM collection.
1416 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001417 // device could be deleted while waiting on sync time response
1418 if mm.GetdeviceDeletionInProgress() {
1419 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1420 return
1421 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001422 go func() {
1423 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1424 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001425 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1426 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001427 }
1428 }()
1429 }
1430 // Initiate a tick generation routine every L2PmCollectionInterval
1431 go mm.generateTicks(ctx)
1432
1433 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001434 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1435 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001436 }
1437 }()
1438}
1439
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001440func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001441 // 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 +00001442 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001443 mm.activeL2Pms = nil
1444 mm.l2PmToAdd = nil
1445 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001446 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001447 // If the FSM was stopped, then clear PM data from KV store
1448 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001449 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001450 _ = mm.clearPmGroupData(ctx) // ignore error
1451 }
1452
Girish Gowdraabcceb12022-04-13 23:35:22 -07001453 if mm.GetdeviceDeletionInProgress() {
praneeth nalmasf405e962023-08-07 15:02:03 +05301454 mm.onuOpticalMetricstimer.Stop()
1455 mm.onuUniStatusMetricstimer.Stop()
1456 mm.opticalMetricsDelCommChan <- true
1457 mm.uniMetricsDelCommChan <- true
Girish Gowdraabcceb12022-04-13 23:35:22 -07001458 mm.pDeviceHandler = nil
1459 mm.pOnuDeviceEntry = nil
1460 mm.GarbageCollectionComplete <- true
1461 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001462}
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301463
1464// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001465func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1466 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001467 if mm.GetdeviceDeletionInProgress() {
1468 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1469 return
1470 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001471
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001472 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001473 numOfPmToDelete := len(mm.l2PmToDelete)
1474 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001475 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001476
1477 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001478 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 -08001479 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001480 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1481 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001482 }
1483 }()
1484 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001485 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 -08001486 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001487 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1488 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001489 }
1490 }()
1491 }
1492}
1493
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301494// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001495func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1496 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001497 if mm.GetdeviceDeletionInProgress() {
1498 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1499 return
1500 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001501 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001502 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001503 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1504 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001505 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001506
1507 for _, n := range copyOfActiveL2Pms {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05301508 select {
1509 case _, ok := <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
1510 if !ok {
1511 logger.Warnw(ctx, "Deleting the device, stopping l2PmFsmCollectData for the device ", log.Fields{"device-id": mm.deviceID})
1512 return
Girish Gowdrae0140f02021-02-02 16:55:09 -08001513 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001514 default:
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05301515 var metricInfoSlice []*voltha.MetricInformation
1516
1517 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1518 mm.OnuMetricsManagerLock.RLock()
1519 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1520 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1521 mm.OnuMetricsManagerLock.RUnlock()
1522
1523 switch n {
1524 case EthernetBridgeHistoryName:
1525 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
1526 for _, entityID := range copyOfEntityIDs {
1527 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1528 metricInfoSlice = append(metricInfoSlice, metricInfo)
1529 }
1530 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1531 metricInfoSlice = append(metricInfoSlice, metricInfo)
1532 }
1533 }
1534 case EthernetUniHistoryName:
1535 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
1536 for _, entityID := range copyOfEntityIDs {
1537 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1538 metricInfoSlice = append(metricInfoSlice, metricInfo)
1539 }
1540 }
1541
1542 case FecHistoryName:
1543 for _, entityID := range copyOfEntityIDs {
1544 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
1545 metricInfoSlice = append(metricInfoSlice, metricInfo)
1546 }
1547 }
1548 case GemPortHistoryName:
1549 for _, entityID := range copyOfEntityIDs {
1550 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
1551 metricInfoSlice = append(metricInfoSlice, metricInfo)
1552 }
1553 }
1554
1555 default:
1556 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
1557 }
1558 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001559 }
1560 }
1561 // Does not matter we send success or failure here.
1562 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1563 // we have not exceed max attempts to collect the PM data)
1564 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001565 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1566 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001567 }
1568 }()
1569}
1570
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301571// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001572func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001573 if mm.GetdeviceDeletionInProgress() {
1574 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1575 return nil
1576 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001577 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001578 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001579 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1580 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001581 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001582
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001583 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001584 for _, n := range copyOfL2PmToAdd {
1585 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001586 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1587 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001588 switch n {
1589 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001590 // 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 +05301591 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001592 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001593 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001594 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001595 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1596 inner1:
1597 // retry L2PmCreateAttempts times to create the instance of PM
1598 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001599 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1600 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001601 if err != nil {
1602 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001603 log.Fields{"device-id": mm.deviceID})
1604 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001605 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001606 go func(p_pmFsm *cmn.AdapterFsm) {
1607 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001608 }(pPMFsm)
1609 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301610 return fmt.Errorf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
1611 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001612 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001613 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1614 atLeastOneSuccess = true
1615 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1616 break inner1
1617 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001618 if mm.GetdeviceDeletionInProgress() {
1619 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1620 return nil
1621 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001622 }
1623 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1624 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001625 }
1626 }
1627 }
1628 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001629 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1630 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001631 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001632 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001633 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1634 inner2:
1635 // retry L2PmCreateAttempts times to create the instance of PM
1636 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001637 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1638 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001639 if err != nil {
1640 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001641 log.Fields{"device-id": mm.deviceID})
1642 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301643 return fmt.Errorf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
1644 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001645 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001646 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1647 atLeastOneSuccess = true
1648 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1649 break inner2
1650 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001651 if mm.GetdeviceDeletionInProgress() {
1652 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1653 return nil
1654 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001655 }
1656 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1657 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001658 }
1659 }
1660 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001661 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001662 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001663 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001664 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1665 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001666 if err != nil {
1667 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001668 log.Fields{"device-id": mm.deviceID})
1669 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301670 return fmt.Errorf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
1671 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001672 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001673 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1674 inner3:
1675 // retry L2PmCreateAttempts times to create the instance of PM
1676 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1677 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1678 atLeastOneSuccess = true
1679 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1680 break inner3
1681 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001682 if mm.GetdeviceDeletionInProgress() {
1683 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1684 return nil
1685 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001686 }
1687 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1688 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001689 }
1690 }
1691 case GemPortHistoryName:
1692
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001693 mm.OnuMetricsManagerLock.RLock()
1694 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1695 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1696 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001697
1698 if len(copyOfGemPortInstIDsToAdd) == 0 {
1699 // If there are no gemport history MEs to be created, just skip further processing
1700 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1701 // 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 +00001702 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001703 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001704 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001705 continue
1706 }
1707
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001708 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001709 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1710 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001711 if err != nil {
1712 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001713 log.Fields{"device-id": mm.deviceID})
1714 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301715 return fmt.Errorf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
1716 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001717 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001718 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1719 inner4:
1720 // retry L2PmCreateAttempts times to create the instance of PM
1721 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1722 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1723 atLeastOneSuccess = true
1724 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1725 break inner4
1726 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001727 if mm.GetdeviceDeletionInProgress() {
1728 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1729 return nil
1730 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001731 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001732 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1733 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1734 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001735 }
1736
Girish Gowdrae0140f02021-02-02 16:55:09 -08001737 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001738 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001739 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001740 // 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
1741 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001742 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001743 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001744 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1745 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001746 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001747 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1748 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001749 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 +00001750 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001751 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001752 // 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 -08001753 // 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 +00001754 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001755 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001756 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001757 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001758
Girish Gowdrae0140f02021-02-02 16:55:09 -08001759 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001760 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001761 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001762 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001763 }
1764 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001765 mm.OnuMetricsManagerLock.RLock()
1766 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1767 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001768 // Does not matter we send success or failure here.
1769 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1770 // we have not exceed max attempts to create the PM ME)
1771 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001772 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1773 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001774 }
1775 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001776 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001777}
1778
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301779// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001780func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001781 if mm.GetdeviceDeletionInProgress() {
1782 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1783 return nil
1784 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001785 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001786 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001787 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1788 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001789 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001790
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001791 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001792 for _, n := range copyOfL2PmToDelete {
1793 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001794 cnt := 0
1795 atLeastOneDeleteFailure := false
1796
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001797 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1798 mm.OnuMetricsManagerLock.RLock()
1799 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1800 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1801 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001802
1803 if len(copyOfEntityIDs) == 0 {
1804 // 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 +00001805 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001806 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1807 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1808 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 +00001809 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001810 continue
1811 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001812 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001813 switch n {
1814 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001815 // 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 +05301816 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001817 for _, entityID := range copyOfEntityIDs {
1818 inner1:
1819 // retry L2PmDeleteAttempts times to delete the instance of PM
1820 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001821 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1822 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001823 if err != nil {
1824 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001825 log.Fields{"device-id": mm.deviceID})
1826 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001827 if pPMFsm != nil {
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301828 //nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001829 go func(p_pmFsm *cmn.AdapterFsm) {
1830 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001831 }(pPMFsm)
1832 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301833 return fmt.Errorf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
1834 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001835 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001836 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1837 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001838 if mm.GetdeviceDeletionInProgress() {
1839 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1840 return nil
1841 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001842 atLeastOneDeleteFailure = true
1843 } else {
1844 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1845 break inner1
1846 }
1847 }
1848 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1849 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001850 }
1851 }
1852 }
1853 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001854 for _, entityID := range copyOfEntityIDs {
1855 inner2:
1856 // retry L2PmDeleteAttempts times to delete the instance of PM
1857 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001858 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1859 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001860 if err != nil {
1861 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001862 log.Fields{"device-id": mm.deviceID})
1863 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001864 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001865 go func(p_pmFsm *cmn.AdapterFsm) {
1866 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001867 }(pmFsm)
1868 return err
1869 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301870 return fmt.Errorf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
1871 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001872 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001873 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001874 if mm.GetdeviceDeletionInProgress() {
1875 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1876 return nil
1877 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001878 atLeastOneDeleteFailure = true
1879 } else {
1880 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001881 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001882 }
1883 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001884 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1885 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1886 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001887 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001888 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001889 for _, entityID := range copyOfEntityIDs {
1890 inner3:
1891 // retry L2PmDeleteAttempts times to delete the instance of PM
1892 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001893 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1894 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001895 if err != nil {
1896 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001897 log.Fields{"device-id": mm.deviceID})
1898 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301899 return fmt.Errorf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
1900 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001901 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301902 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001903 if mm.GetdeviceDeletionInProgress() {
1904 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1905 return nil
1906 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001907 atLeastOneDeleteFailure = true
1908 } else {
1909 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1910 break inner3
1911 }
1912 }
1913 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1914 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001915 }
1916 }
1917 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001918 for _, entityID := range copyOfEntityIDs {
1919 inner4:
1920 // retry L2PmDeleteAttempts times to delete the instance of PM
1921 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001922 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1923 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001924 if err != nil {
1925 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001926 log.Fields{"device-id": mm.deviceID})
1927 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301928 return fmt.Errorf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
1929 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001930 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001931 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001932 if mm.GetdeviceDeletionInProgress() {
1933 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1934 return nil
1935 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001936 atLeastOneDeleteFailure = true
1937 } else {
1938 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1939 break inner4
1940 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001941 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001942 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1943 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1944 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001945 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001946 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001947 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001948 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001949 // If we could not completely clean up the PM ME then just give up.
1950 if atLeastOneDeleteFailure {
1951 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001952 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001953 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001954 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001955 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1956 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1957 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001958 mm.GroupMetricMap[n].Enabled = false
1959 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001960 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001961 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001962 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001963 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1964 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001965 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001966 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1967 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001968 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 +00001969 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001970 }
1971 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001972 mm.OnuMetricsManagerLock.RLock()
1973 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1974 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001975 // Does not matter we send success or failure here.
1976 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1977 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001978 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1979 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001980 }
1981 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001982 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001983}
1984
1985// ** L2 PM FSM Handlers end **
1986
1987// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001988func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001989 if mm.GetdeviceDeletionInProgress() {
1990 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1991 return nil
1992 }
1993
1994 if !mm.GetOmciProcessingStatus() {
1995 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})
1996 return fmt.Errorf("omci-resp-processor-not-running")
1997 }
1998
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001999 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
2000 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002001 return err
2002 }
2003
2004 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002005 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
2006 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
2007 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002008 case syncTimeRes := <-mm.syncTimeResponseChan:
2009 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002010 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002011 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002012 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002013 return nil
2014 }
2015}
2016
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002017func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002018 var mEnt *me.ManagedEntity
2019 var omciErr me.OmciErrors
2020 var classID me.ClassID
2021 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002022 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002023 meParam := me.ParamData{EntityID: entityID}
2024 if upstream {
2025 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002026 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002027 return nil
2028 }
2029 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
2030 } else {
2031 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002032 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002033 return nil
2034 }
2035 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
2036 }
2037
Girish Gowdrae0140f02021-02-02 16:55:09 -08002038 intervalEndTime := -1
2039 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002040 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
2041 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002042 }
2043
2044 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
2045 ethPMHistData["class_id"] = float32(classID)
2046 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
2047 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
2048 ethPMHistData["parent_entity_id"] = float32(entityID)
2049 if upstream {
2050 ethPMHistData["upstream"] = float32(1)
2051 } else {
2052 ethPMHistData["upstream"] = float32(0)
2053 }
2054
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002055 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002056
Girish Gowdrae0140f02021-02-02 16:55:09 -08002057 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002058 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002059 return &metricInfo
2060}
2061
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002062func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002063 var mEnt *me.ManagedEntity
2064 var omciErr me.OmciErrors
2065 var classID me.ClassID
2066 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002067 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002068 meParam := me.ParamData{EntityID: entityID}
2069 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002070 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002071 return nil
2072 }
2073 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
2074
Girish Gowdrae0140f02021-02-02 16:55:09 -08002075 intervalEndTime := -1
2076 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002077 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
2078 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002079 }
2080
2081 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2082 ethUniHistData["class_id"] = float32(classID)
2083 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
2084
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002085 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002086
Girish Gowdrae0140f02021-02-02 16:55:09 -08002087 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002088 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002089 return &metricInfo
2090}
2091
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002092func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002093 var mEnt *me.ManagedEntity
2094 var omciErr me.OmciErrors
2095 var classID me.ClassID
2096 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002097 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002098 meParam := me.ParamData{EntityID: entityID}
2099 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002100 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002101 return nil
2102 }
2103 classID = me.FecPerformanceMonitoringHistoryDataClassID
2104
2105 intervalEndTime := -1
2106 fecHistData := make(map[string]float32)
2107 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
2108 return nil
2109 }
2110
2111 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2112 fecHistData["class_id"] = float32(classID)
2113 fecHistData["interval_end_time"] = float32(intervalEndTime)
2114
2115 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2116
2117 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002118 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002119 return &metricInfo
2120}
2121
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002122func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002123 var mEnt *me.ManagedEntity
2124 var omciErr me.OmciErrors
2125 var classID me.ClassID
2126 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002127 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002128 meParam := me.ParamData{EntityID: entityID}
2129 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002130 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002131 return nil
2132 }
2133 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2134
2135 intervalEndTime := -1
2136 gemHistData := make(map[string]float32)
2137 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
2138 return nil
2139 }
2140
2141 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2142 gemHistData["class_id"] = float32(classID)
2143 gemHistData["interval_end_time"] = float32(intervalEndTime)
2144
2145 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2146
2147 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002148 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002149 return &metricInfo
2150}
2151
Girish Gowdrae0140f02021-02-02 16:55:09 -08002152// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002153func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002154 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002155 upstream := false
2156 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2157 upstream = true
2158 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002159 // 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 +00002160 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302161 meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002162 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002163 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302164 if CheckMeInstanceStatusCode(err) {
2165 return err // Device is being deleted, so we stop processing
2166 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002167 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2168 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002169 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002170 go func(p_pmFsm *cmn.AdapterFsm) {
2171 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002172 }(pmFsm)
2173 return err
2174 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302175 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002176 }
2177 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002178 select {
2179 case meAttributes = <-mm.l2PmChan:
2180 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002181 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2182 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002183 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002184 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002185 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002186 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302187 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2188 logger.Warnw(ctx, "Deleting the device, stopping Ethernet Performance metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2189 return fmt.Errorf("deleting the device, stopping Ethernet Performance metrics collection for the device %v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002190 }
2191 // 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 -08002192 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002193 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002194 }
2195 }
2196 for k := range EthernetBridgeHistory {
2197 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2198 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2199 if _, ok := ethPMHistData[k]; !ok {
2200 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002201 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002202 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002203 ethPMHistData[k] = float32(val.(uint16))
2204 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002205 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002206 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002207 ethPMHistData[k] = float32(val.(uint32))
2208 }
2209 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002210 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002211 ethPMHistData[k] = float32(val.(uint32))
2212 }
2213 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002214 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002215 ethPMHistData[k] = float32(val.(uint32))
2216 }
2217 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002218 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002219 ethPMHistData[k] = float32(val.(uint32))
2220 }
2221 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002222 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002223 ethPMHistData[k] = float32(val.(uint32))
2224 }
2225 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002226 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002227 ethPMHistData[k] = float32(val.(uint32))
2228 }
2229 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002230 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002231 ethPMHistData[k] = float32(val.(uint32))
2232 }
2233 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002234 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002235 ethPMHistData[k] = float32(val.(uint32))
2236 }
2237 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002238 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002239 ethPMHistData[k] = float32(val.(uint32))
2240 }
2241 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002242 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002243 ethPMHistData[k] = float32(val.(uint32))
2244 }
2245 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002246 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002247 ethPMHistData[k] = float32(val.(uint32))
2248 }
2249 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002250 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002251 ethPMHistData[k] = float32(val.(uint32))
2252 }
2253 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002254 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002255 ethPMHistData[k] = float32(val.(uint32))
2256 }
2257 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002258 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002259 ethPMHistData[k] = float32(val.(uint32))
2260 }
2261 default:
2262 // do nothing
2263 }
2264 }
2265 }
2266 return nil
2267}
2268
2269// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002270func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002271 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002272 // 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 +03002273 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2274 requestedAttributes["IntervalEndTime"] = 0
2275 }
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302276 meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002277 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002278 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302279 if CheckMeInstanceStatusCode(err) {
2280 return err // Device is being deleted, so we stop processing
2281 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002282 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2283 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302284 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002285 }
2286 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002287 select {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302288 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2289 logger.Warnw(ctx, "Deleting the device, stopping EthernetUniHistory metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2290 return fmt.Errorf("deleting the device, stopping EthernetUniHistory metrics collection for the device %v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002291 case meAttributes = <-mm.l2PmChan:
2292 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002293 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2294 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002295 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002296 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002297 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002298 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002299 }
2300 // 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 -08002301 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002302 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002303 }
2304 }
2305 for k := range EthernetUniHistory {
2306 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2307 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2308 if _, ok := ethPMUniHistData[k]; !ok {
2309 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002310 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002311 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002312 ethPMUniHistData[k] = float32(val.(uint16))
2313 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002314 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002315 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002316 ethPMUniHistData[k] = float32(val.(uint32))
2317 }
2318 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002319 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002320 ethPMUniHistData[k] = float32(val.(uint32))
2321 }
2322 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002323 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002324 ethPMUniHistData[k] = float32(val.(uint32))
2325 }
2326 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002327 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002328 ethPMUniHistData[k] = float32(val.(uint32))
2329 }
2330 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002331 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002332 ethPMUniHistData[k] = float32(val.(uint32))
2333 }
2334 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002335 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002336 ethPMUniHistData[k] = float32(val.(uint32))
2337 }
2338 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002339 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002340 ethPMUniHistData[k] = float32(val.(uint32))
2341 }
2342 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002343 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002344 ethPMUniHistData[k] = float32(val.(uint32))
2345 }
2346 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002347 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002348 ethPMUniHistData[k] = float32(val.(uint32))
2349 }
2350 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002351 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002352 ethPMUniHistData[k] = float32(val.(uint32))
2353 }
2354 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002355 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002356 ethPMUniHistData[k] = float32(val.(uint32))
2357 }
2358 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002359 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002360 ethPMUniHistData[k] = float32(val.(uint32))
2361 }
2362 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002363 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002364 ethPMUniHistData[k] = float32(val.(uint32))
2365 }
2366 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002367 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002368 ethPMUniHistData[k] = float32(val.(uint32))
2369 }
2370 default:
2371 // do nothing
2372 }
2373 }
2374 }
2375 return nil
2376}
2377
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002378// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002379func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002380 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002381 // 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 +00002382 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2383 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002384 }
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302385 meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002386 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002387 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302388 if CheckMeInstanceStatusCode(err) {
2389 return err // Device is being deleted, so we stop processing
2390 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002391 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2392 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302393 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002394 }
2395 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002396 select {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302397 case _, ok := <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2398 if !ok {
2399 logger.Warnw(ctx, "Deleting the device, stopping FEC history metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2400 return fmt.Errorf("deleting the device, stopping FEC history metrics collection for the device %v", mm.deviceID)
2401 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002402 case meAttributes = <-mm.l2PmChan:
2403 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002404 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2405 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002406 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002407 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002408 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002409 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002410 }
2411 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2412 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002413 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002414 }
2415 }
2416 for k := range FecHistory {
2417 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2418 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2419 if _, ok := fecHistData[k]; !ok {
2420 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002421 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002422 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002423 fecHistData[k] = float32(val.(uint16))
2424 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002425 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002426 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002427 fecHistData[k] = float32(val.(uint32))
2428 }
2429 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002430 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002431 fecHistData[k] = float32(val.(uint32))
2432 }
2433 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002434 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002435 fecHistData[k] = float32(val.(uint32))
2436 }
2437 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002438 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002439 fecHistData[k] = float32(val.(uint32))
2440 }
2441 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002442 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002443 fecHistData[k] = float32(val.(uint16))
2444 }
2445 default:
2446 // do nothing
2447 }
2448 }
2449 }
2450 return nil
2451}
2452
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302453func (mm *OnuMetricsManager) GetMeInstance(ctx context.Context, classID me.ClassID, entityID uint16, requestedAttributes me.AttributeValueMap,
2454 timeout int, highPrio bool, rxChan chan cmn.Message, isExtendedOmci bool) (*me.ManagedEntity, error) {
2455
2456 select {
2457 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2458 errMsg := "deleting the device, stopping GetMeInstance for the device " + mm.deviceID
2459 logger.Warn(ctx, errMsg)
2460 return nil, status.Error(codes.NotFound, errMsg)
2461 default:
2462 if mm.pOnuDeviceEntry.GetDevOmciCC() != nil {
2463 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2464 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2465 return meInstance, err
2466 }
2467 }
2468 return nil, nil
2469}
2470
2471// CheckMeInstanceStatusCode checked status code if not found returns true
2472func CheckMeInstanceStatusCode(err error) bool {
2473 if err != nil {
2474 st, ok := status.FromError(err)
2475 if ok && st.Code() == codes.NotFound {
2476 return true
2477 }
2478 }
2479 return false
2480}
2481
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002482// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002483func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002484 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002485 // 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 +00002486 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2487 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002488 }
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302489 meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002490 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002491 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302492 if CheckMeInstanceStatusCode(err) {
2493 return err // Device is being deleted, so we stop processing
2494 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002495 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2496 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302497 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002498 }
2499 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002500 select {
2501 case meAttributes = <-mm.l2PmChan:
2502 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002503 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2504 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002505 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002506 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002507 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002508 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302509 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2510 logger.Warnw(ctx, "Deleting the device, stopping GEM port history metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2511 return fmt.Errorf("deleting the device, stopping GEM port history metrics collection for the device %v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002512 }
2513 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2514 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002515 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002516 }
2517 }
2518 for k := range GemPortHistory {
2519 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2520 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2521 if _, ok := gemPortHistData[k]; !ok {
2522 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002523 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002524 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002525 gemPortHistData[k] = float32(val.(uint16))
2526 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002527 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002528 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002529 gemPortHistData[k] = float32(val.(uint32))
2530 }
2531 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002532 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002533 gemPortHistData[k] = float32(val.(uint32))
2534 }
2535 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002536 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002537 gemPortHistData[k] = float32(val.(uint64))
2538 }
2539 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002540 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002541 gemPortHistData[k] = float32(val.(uint64))
2542 }
2543 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002544 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002545 gemPortHistData[k] = float32(val.(uint32))
2546 }
2547 default:
2548 // do nothing
2549 }
2550 }
2551 }
2552 return nil
2553}
2554
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002555func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002556 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2557 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002558 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2559 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 -08002560 }
2561 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2562 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002563 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2564 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 -08002565 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002566 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002567 switch msgObj.EntityClass {
2568 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2569 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002570 me.EthernetPerformanceMonitoringHistoryDataClassID,
2571 me.FecPerformanceMonitoringHistoryDataClassID,
2572 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002573 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2574 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2575 mm.l2PmCreateOrDeleteResponseChan <- true
2576 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002577 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002578 mm.l2PmCreateOrDeleteResponseChan <- false
2579 }
2580 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302581 case me.EthernetFrameExtendedPmClassID,
2582 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302583 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302584 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002585 default:
2586 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002587 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002588 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002589 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002590}
2591
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002592func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002593 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2594 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002595 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2596 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 -08002597 }
2598 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2599 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002600 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2601 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 -08002602 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002603 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002604 switch msgObj.EntityClass {
2605 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2606 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002607 me.EthernetPerformanceMonitoringHistoryDataClassID,
2608 me.FecPerformanceMonitoringHistoryDataClassID,
2609 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002610 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2611 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2612 mm.l2PmCreateOrDeleteResponseChan <- true
2613 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002614 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002615 mm.l2PmCreateOrDeleteResponseChan <- false
2616 }
2617 return nil
2618 default:
2619 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002620 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002621 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002622 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002623}
2624
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002625func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002626 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002627 for {
2628 select {
2629 case <-time.After(L2PmCollectionInterval * time.Second):
2630 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002631 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2632 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002633 }
2634 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002635 case <-mm.StopTicks:
2636 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002637 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002638 return
2639 }
2640 }
2641}
2642
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002643func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002644 // Publish metrics if it is valid
2645 if metricInfoSlice != nil {
2646 mm.publishMetrics(ctx, metricInfoSlice)
2647 } else {
2648 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2649 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002650 mm.OnuMetricsManagerLock.Lock()
2651 mm.GroupMetricMap[metricName].collectAttempts++
2652 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002653 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2654 }
2655 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002656 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2657 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002658 }
2659}
2660
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302661// nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002662func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002663 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2664 var grpFunc groupMetricPopulateFunc
2665 switch classID {
2666 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2667 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2668 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2669 grpFunc = mm.populateEthernetUniHistoryMetrics
2670 case me.FecPerformanceMonitoringHistoryDataClassID:
2671 grpFunc = mm.populateFecHistoryMetrics
2672 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2673 grpFunc = mm.populateGemPortMetrics
2674 default:
2675 return fmt.Errorf("unknown-classid-%v", classID)
2676 }
2677
2678 size := 0
2679 requestedAttributes := make(me.AttributeValueMap)
2680 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002681 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2682 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2683 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2684 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2685 continue
2686 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002687 if v.Size+size <= mm.maxL2PMGetPayLoadSize {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002688 requestedAttributes[v.Name] = v.DefValue
2689 size = v.Size + size
2690 } else { // We exceeded the allow omci get size
2691 // Let's collect the attributes via get now and collect remaining in the next iteration
2692 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2693 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002694 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002695 return err
2696 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002697 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002698 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2699 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002700 }
2701 }
2702 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002703 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2704 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002705 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002706 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002707 }
2708 return nil
2709}
2710
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002711func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002712 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002713 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2714 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2715 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002716
2717 raisedTs := time.Now().Unix()
2718 mmd := voltha.MetricMetaData{
2719 Title: title,
2720 Ts: float64(raisedTs),
2721 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002722 DeviceId: mm.deviceID,
2723 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2724 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002725 }
2726
2727 // create slice of metrics given that there could be more than one VEIP instance
2728 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2729 return metricInfo
2730}
2731
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002732func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002733 valid := false
2734 if *intervalEndTime == -1 { // first time
2735 // Update the interval end time
2736 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2737 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2738 valid = true
2739 }
2740 } else {
2741 var currIntervalEndTime int
2742 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2743 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2744 }
2745 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2746 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002747 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002748 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2749 } else {
2750 valid = true
2751 }
2752 }
2753 return valid
2754}
2755
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002756func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002757 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002758 if !mm.GetOmciProcessingStatus() {
2759 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})
2760 return false
2761 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002762 select {
2763 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002764 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002765 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002766 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002767 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002768 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002769 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002770 }
2771 return false
2772}
2773
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302774// nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002775func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002776 var pmConfigSlice []*voltha.PmConfig
2777 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002778 pmConfigSlice = append(pmConfigSlice,
2779 &voltha.PmConfig{
2780 Name: k,
2781 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002782 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002783 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002784 }
2785 groupMetric := voltha.PmGroupConfig{
2786 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002787 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002788 GroupFreq: grpFreq,
2789 Metrics: pmConfigSlice,
2790 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002791 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002792
2793}
2794
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002795func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2796 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2797 if mm.PAdaptFsm == nil {
2798 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2799 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002800 return fmt.Errorf("nil-adapter-fsm")
2801 }
2802 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002803 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2804 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002805 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002806 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2807 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2808 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2809 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2810 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2811 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2812 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2813 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2814 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002815 },
2816 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002817 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2818 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2819 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2820 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2821 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2822 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2823 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2824 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002825 },
2826 )
2827 return nil
2828}
2829
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002830func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2831 mm.pDeviceHandler.InitPmConfigs()
2832 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2833 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2834 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2835 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002836
2837 // Populate group metrics.
2838 // Lets populate irrespective of GroupMetricEnabled is true or not.
2839 // The group metrics collection will decided on this flag later
2840
2841 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2842 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2843
2844 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2845 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2846
2847 // classical l2 pm counter start
2848
2849 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2850 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2851
2852 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2853 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2854
2855 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2856 FecHistoryEnabled, FecHistoryFrequency)
2857
2858 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2859 GemPortHistoryEnabled, GemPortHistoryFrequency)
2860
2861 // classical l2 pm counter end
2862
2863 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2864}
2865
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002866func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002867 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002868 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2869 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002870 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002871 Enabled: g.Enabled,
2872 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002873 }
2874 switch g.GroupName {
2875 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002876 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002877 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002878 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002879 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002880 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2881 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002882 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002883 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2884 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002885 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002886 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2887 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002888 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002889 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2890 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002891 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002892 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002893 }
2894 }
2895
2896 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002897 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2898 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002899 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002900 Enabled: m.Enabled,
2901 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002902 }
2903 switch m.Name {
2904 // None exist as of now. Add when available.
2905 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002906 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002907 }
2908 }
2909}
2910
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002911// AddGemPortForPerfMonitoring - TODO: add comment
2912func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2913 mm.OnuMetricsManagerLock.Lock()
2914 defer mm.OnuMetricsManagerLock.Unlock()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302915 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002916 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002917 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002918 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002919 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002920 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002921
2922 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2923 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2924 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2925 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2926 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002927
2928 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002929 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2930 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002931 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002932 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002933 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002934 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002935 }
2936 }()
Praneeth Kumar Nalmas8f8f0c02024-10-22 19:29:09 +05302937 mm.pOnuDeviceEntry.GetOnuDB().PutOnuSpeficMe(ctx, me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID, meAttributes)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002938}
2939
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002940// RemoveGemPortForPerfMonitoring - TODO: add comment
2941func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2942 mm.OnuMetricsManagerLock.Lock()
2943 defer mm.OnuMetricsManagerLock.Unlock()
2944 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2945 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002946 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002947 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002948
2949 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2950 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2951 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2952 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2953 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002954
2955 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002956 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2957 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002958 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002959 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002960 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002961 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002962 }
2963 }()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302964 mm.pOnuDeviceEntry.GetOnuDB().DeleteMe(me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002965}
2966
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002967func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2968 if mm.pDeviceHandler.GetOnuTP() != nil {
2969 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002970 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002971 for _, v := range gemPortInstIDs {
2972 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002973 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002974 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002975 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002976 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002977 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002978 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002979 }
2980}
2981
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002982func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2983 if mm.pDeviceHandler.GetOnuTP() != nil {
2984 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002985 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002986 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002987 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002988 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002989 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002990 }
2991 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002992 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002993 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002994}
2995
2996// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002997func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2998 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002999 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003000 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303001 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003002 }
3003 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003004 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003005 group.pmMEData = &pmMEData{}
3006 Value, err := mm.pmKvStore.Get(ctx, groupName)
3007 if err == nil {
3008 if Value != nil {
3009 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003010 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003011 tmpBytes, _ := kvstore.ToByte(Value.Value)
3012
3013 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003014 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303015 errorsList = append(errorsList, fmt.Errorf("unable-to-unmarshal-PM-data-%s-for-group-%s", mm.deviceID, groupName))
Girish Gowdra0e533642021-03-02 22:02:51 -08003016 continue
3017 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003018 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003019 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003020 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003021 continue
3022 }
3023 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003024 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303025 errorsList = append(errorsList, fmt.Errorf("unable-to-read-from-KVstore-%s-for-group-%s", mm.deviceID, groupName))
Girish Gowdra0e533642021-03-02 22:02:51 -08003026 continue
3027 }
3028 }
3029 if len(errorsList) > 0 {
3030 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
3031 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003032 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003033 return nil
3034}
3035
3036// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
3037// the data must be available in cache.
3038// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003039func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
3040 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08003041 return grp.pmMEData, nil
3042 }
3043 // Data not in cache, try to fetch from kv store.
3044 data := &pmMEData{}
3045 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003046 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3047 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003048 }
3049 Value, err := mm.pmKvStore.Get(ctx, groupName)
3050 if err == nil {
3051 if Value != nil {
3052 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003053 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003054 tmpBytes, _ := kvstore.ToByte(Value.Value)
3055
3056 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003057 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003058 return data, err
3059 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003060 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003061 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003062 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003063 return data, err
3064 }
3065 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003066 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003067 return data, err
3068 }
3069
3070 return data, nil
3071}
3072
3073// 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 +00003074func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
3075 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
3076 mm.OnuMetricsManagerLock.Lock()
3077 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08003078
3079 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003080 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303081 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003082 }
3083
3084 pmMEData, err := mm.getPmData(ctx, groupName)
3085 if err != nil || pmMEData == nil {
3086 // error already logged in called function.
3087 return err
3088 }
3089 switch pmAction {
3090 case cPmAdd:
3091 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
3092 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3093 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3094 case cPmAdded:
3095 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
3096 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3097 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3098 case cPmRemove:
3099 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
3100 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3101 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3102 case cPmRemoved:
3103 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3104 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3105 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3106 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003107 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303108 return fmt.Errorf("unknown-pm-action-deviceid-%s-groupName-%s-pmaction-%s", mm.deviceID, groupName, pmAction)
Girish Gowdra0e533642021-03-02 22:02:51 -08003109 }
3110 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003111 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08003112
3113 Value, err := json.Marshal(*pmMEData)
3114 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003115 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
3116 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003117 return err
3118 }
3119 // Update back to kv store
3120 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003121 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
3122 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003123 return err
3124 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003125 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
3126 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08003127
3128 return nil
3129}
3130
3131// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003132func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
3133 mm.OnuMetricsManagerLock.Lock()
3134 defer mm.OnuMetricsManagerLock.Unlock()
3135 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003136 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003137 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303138 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003139 }
3140
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003141 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003142 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003143 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003144 // do not abort this procedure. continue to delete next group.
3145 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003146 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08003147 }
3148 }
3149
3150 return nil
3151}
3152
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003153// ClearAllPmData clears all PM data associated with the device from KV store
3154func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3155 mm.OnuMetricsManagerLock.Lock()
3156 defer mm.OnuMetricsManagerLock.Unlock()
3157 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003158 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003159 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303160 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003161 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003162 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003163 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003164 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003165 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003166 value = err
3167 // do not abort this procedure - continue to delete next group.
3168 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003169 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003170 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003171 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003172 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003173 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003174 }
3175 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003176}
3177
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003178func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3179 mm.OnuMetricsManagerLock.Lock()
3180 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003181 mm.omciProcessingActive = status
3182}
3183
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003184// updateTickGenerationStatus - TODO: add comment
3185func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3186 mm.OnuMetricsManagerLock.Lock()
3187 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003188 mm.tickGenerationActive = status
3189}
3190
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003191// GetOmciProcessingStatus - TODO: add comment
3192func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3193 mm.OnuMetricsManagerLock.RLock()
3194 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003195 return mm.omciProcessingActive
3196}
3197
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003198// GetTickGenerationStatus - TODO: add comment
3199func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3200 mm.OnuMetricsManagerLock.RLock()
3201 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003202 return mm.tickGenerationActive
3203}
3204
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003205func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003206 for _, ele := range slice {
3207 if ele == n {
3208 return slice
3209 }
3210 }
3211 return append(slice, n)
3212}
3213
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003214func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003215 for i, ele := range slice {
3216 if ele == n {
3217 return append(slice[:i], slice[i+1:]...)
3218 }
3219 }
3220 return slice
3221}
3222
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003223func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003224 for _, ele := range slice {
3225 if ele == n {
3226 return slice
3227 }
3228 }
3229 return append(slice, n)
3230}
3231
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003232func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003233 for i, ele := range slice {
3234 if ele == n {
3235 return append(slice[:i], slice[i+1:]...)
3236 }
3237 }
3238 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003239}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303240
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003241func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303242 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3243 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003244 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003245 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003246 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303247 Value, err := mm.extPmKvStore.Get(ctx, key)
3248 if err == nil {
3249 if Value != nil {
3250 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003251 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303252 tmpBytes, _ := kvstore.ToByte(Value.Value)
3253
3254 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003255 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303256 return false, err
3257 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003258 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303259 // We have found the data from db, no need to get through omci get message.
3260 mm.supportedEthernetFrameExtendedPMClass = data
3261 return true, nil
3262 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003263 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303264 return false, nil
3265 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003266 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303267 return false, err
3268}
3269
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003270func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303271 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 -07003272 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3273 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})
3274 return false, fmt.Errorf("omci-processor-shutdown")
3275 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303276 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303277 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303278 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003279 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303280 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3281 if resp == me.Success || resp == me.InstanceExists {
3282 return true, nil
3283 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3284 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3285 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3286 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003287 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 +05303288 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3289 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003290 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303291 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003292 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303293 }
3294 return false, fmt.Errorf("timeout-while-waiting-for-response")
3295}
3296
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003297func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303298 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303299 // 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 +05303300 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003301 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303302 var entityID uint16
3303 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003304 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303305 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003306 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303307 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303308 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303309 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303310 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303311
3312 inner1:
3313 // retry ExtendedPmCreateAttempts times to create the instance of PM
3314 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003315 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3316 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3317 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303318 if err != nil {
3319 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003320 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303321 return false, err
3322 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303323 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3324 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303325 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303326 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303327 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303328 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303329 }
3330 break inner1
3331 } else if err != nil {
3332 if !supported {
3333 // Need to return immediately
3334 return false, err
3335 }
3336 //In case of failure, go for a retry
3337 }
3338 }
3339 if cnt == ExtendedPmCreateAttempts {
3340 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3341 return true, fmt.Errorf("unable-to-create-me")
3342 }
3343 }
3344 }
3345 return true, nil
3346}
3347
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003348func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3349 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003350 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003351 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303352 // check if we get the supported type me for ethernet frame extended pm class id
3353 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3354 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3355 }
3356 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3357 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003358 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303359 }
3360 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003361 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303362 }
3363}
3364
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003365func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303366 mm.onuEthernetFrameExtendedPmLock.Lock()
3367 mm.isDeviceReadyToCollectExtendedPmStats = true
3368 mm.onuEthernetFrameExtendedPmLock.Unlock()
3369}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003370
Himani Chawlaee10b542021-09-20 16:46:40 +05303371// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003372func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303373 //get the type of extended frame pm me supported by onu first
3374 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3375 if err != nil {
3376 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3377 return
3378 }
3379 if exist {
3380 // we have the me type, go ahead with the me type supported.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303381 //nolint:govet
Himani Chawla43f95ff2021-06-03 00:24:12 +05303382 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003383 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303384 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3385 return
3386 }
3387 mm.setAllExtPmMeCreatedFlag()
3388 return
3389 }
3390 // First try with 64 bit me
3391 // we have the me type, go ahead with the me type supported.
3392 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3393 if err != nil && !supported64Bit {
3394 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003395 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303396 "supported": supported64Bit})
3397 // Then Try with 32 bit type
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303398 //nolint:govet
Himani Chawla43f95ff2021-06-03 00:24:12 +05303399 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003400 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303401 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3402 } else if supported32Bit {
3403 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3404 mm.putExtPmMeKvStore(ctx)
3405 mm.setAllExtPmMeCreatedFlag()
3406 }
3407 } else if err == nil && supported64Bit {
3408 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3409 mm.putExtPmMeKvStore(ctx)
3410 mm.setAllExtPmMeCreatedFlag()
3411 }
3412}
3413
Himani Chawlaee10b542021-09-20 16:46:40 +05303414func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3415 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3416 uniPortEntityID := entityID
3417 if upstream {
3418 uniPortEntityID = entityID - 0x100
3419 }
3420 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3421 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3422 mm.pDeviceHandler.GetOmciTimeout(), true,
3423 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3424 if err != nil {
3425 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3426 log.Fields{"device-id": mm.deviceID})
3427 return extension.GetValueResponse_INTERNAL_ERROR, err
3428 }
3429
3430 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3431 return extension.GetValueResponse_REASON_UNDEFINED, nil
3432 }
3433 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3434}
3435
3436func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3437 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 -07003438 if !mm.GetOmciProcessingStatus() {
3439 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})
3440 return false
3441 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303442 select {
3443 case resp := <-mm.extendedPMMeResponseChan:
3444 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3445 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3446 if resp == me.Success {
3447 return true
3448 }
3449 return false
3450 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3451 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3452 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3453 }
3454 return false
3455}
3456
3457func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3458 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3459 className := "EthernetFrameExtendedPm64Bit"
3460 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3461 className = "EthernetFrameExtendedPm"
3462 }
3463 // Reset the counters if option is specified
3464 for entityID := range upstreamEntityMap {
3465 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3466 true)
3467 if err != nil {
3468 return errReason, err
3469 }
3470 }
3471
3472 for entityID := range downstreamEntityMap {
3473 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3474 true)
3475 if err != nil {
3476 return errReason, err
3477 }
3478 }
3479 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3480 // device itself.
3481 // Unset the reset bit if option is specified
3482 for entityID := range upstreamEntityMap {
3483 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3484 false)
3485 if err != nil {
3486 return errReason, err
3487 }
3488 }
3489
3490 for entityID := range downstreamEntityMap {
3491 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3492 false)
3493 if err != nil {
3494 return errReason, err
3495 }
3496 }
3497 return extension.GetValueResponse_REASON_UNDEFINED, nil
3498}
3499
3500func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3501 mm.onuEthernetFrameExtendedPmLock.Lock()
3502 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3503 mm.isEthernetFrameExtendedPmOperationOngoing = val
3504}
3505
3506func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3507 mm.onuEthernetFrameExtendedPmLock.Lock()
3508 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3509 return mm.isEthernetFrameExtendedPmOperationOngoing
3510}
3511
3512// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3513func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3514 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3515 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3516 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303517 return &extension.SingleGetValueResponse{
3518 Response: &extension.GetValueResponse{
3519 Status: extension.GetValueResponse_ERROR,
3520 ErrReason: reason,
3521 },
3522 }
3523 }
3524 mm.onuEthernetFrameExtendedPmLock.RLock()
3525 if !mm.isDeviceReadyToCollectExtendedPmStats {
3526 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303527 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303528 }
3529 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303530
3531 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3532 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3533 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3534 }
3535 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3536 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3537
3538 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3539 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3540 if onuInfo.IsUniIndex != nil {
3541 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3542 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3543 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3544 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3545 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3546 break
3547 }
3548 }
3549 if len(downstreamEntityMap) == 0 {
3550 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3551 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3552 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3553 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3554 }
3555 } else {
3556 // make a copy of all downstream and upstream maps in the local ones
3557 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3558 upstreamEntityMap[entityID] = meEnt
3559 }
3560 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3561 downstreamEntityMap[entityID] = meEnt
3562 }
3563 }
3564 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3565 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3566 // Reset the metrics first for all required me's
3567 if onuInfo.Reset_ {
3568 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3569 if err != nil {
3570 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3571 log.Fields{"device-id": mm.deviceID})
3572 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3573 }
3574 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303575 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3576 var pmUpstream extension.OmciEthernetFrameExtendedPm
3577 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303578 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3579 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3580 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3581 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303582 if !onuInfo.Reset_ {
3583 for entityID, meEnt := range upstreamEntityMap {
3584 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3585 var receivedMask uint16
3586 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3587 if receivedMask == 0 {
3588 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303589 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3590 // It might be possible that still some downstream pms are supported and hence we need to continue
3591 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3592 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303593 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303594 // Aggregate the result for upstream
3595 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3596 } else {
3597 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303598 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303599 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303600
Himani Chawlaee10b542021-09-20 16:46:40 +05303601 for entityID, meEnt := range downstreamEntityMap {
3602 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3603 var receivedMask uint16
3604 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303605 if receivedMask == 0 {
3606 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3607 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3608 // Stop collecting downstream counters for other ME's.
3609 break
3610 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303611 // Aggregate the result for downstream
3612 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3613 } else {
3614 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3615 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303616 }
3617 }
3618 singleValResp := extension.SingleGetValueResponse{
3619 Response: &extension.GetValueResponse{
3620 Status: extension.GetValueResponse_OK,
3621 Response: &extension.GetValueResponse_OnuCounters{
3622 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303623 Upstream: &pmUpstream,
3624 Downstream: &pmDownstream,
3625 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303626 },
3627 },
3628 },
3629 }
3630 return &singleValResp
3631}
3632
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303633// nolint:unparam
Himani Chawlaee10b542021-09-20 16:46:40 +05303634func (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 +05303635 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003636 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 +05303637
3638 classID = mm.supportedEthernetFrameExtendedPMClass
3639 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3640 if classID == me.EthernetFrameExtendedPmClassID {
3641 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3642 }
3643 ethPMData := make(map[string]uint64)
3644 var sumReceivedMask uint16
3645 for mask := range attributeMaskList {
3646 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3647 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003648 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303649 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303650 }
3651 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3652 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3653 //populate all counters as failure and return
3654 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3655 break
3656 }
3657 }
3658 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303659 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303660}
3661
3662// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003663func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303664 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3665 var meAttributes me.AttributeValueMap
3666 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003667 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303668 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003669 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303670 return extension.GetValueResponse_INTERNAL_ERROR, err
3671 }
3672 select {
3673 case meAttributes = <-mm.extendedPmMeChan:
3674 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003675 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3676 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303677 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003678 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303679 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3680 }
3681 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3682 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3683 *sumReceivedMask += mask
3684 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3685 } else {
3686 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3687 *sumReceivedMask += mask
3688 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3689 }
3690
3691 return extension.GetValueResponse_REASON_UNDEFINED, nil
3692}
3693
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003694func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303695 sourceMap := maskToEthernetFrameExtendedPM64Bit
3696 errorCounterValue := UnsupportedCounterValue64bit
3697 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3698 sourceMap = maskToEthernetFrameExtendedPM32Bit
3699 errorCounterValue = UnsupportedCounterValue32bit
3700 }
3701 for _, value := range sourceMap {
3702 for _, k := range value {
3703 if _, ok := ethFrameExtPMData[k]; !ok {
3704 ethFrameExtPMData[k] = errorCounterValue
3705 }
3706 }
3707 }
3708}
3709
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303710// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003711func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303712 receivedMask := uint16(0)
3713 switch requestedAttributesMask {
3714 case 0x3F00:
3715 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3716 if _, ok := ethFrameExtPMData[k]; !ok {
3717 switch k {
3718 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003719 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303720 ethFrameExtPMData[k] = uint64(val.(uint32))
3721 receivedMask |= 0x2000
3722 } else if !ok {
3723 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3724 }
3725 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003726 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303727 ethFrameExtPMData[k] = uint64(val.(uint32))
3728 receivedMask |= 0x1000
3729 } else if !ok {
3730 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3731 }
3732 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003733 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303734 ethFrameExtPMData[k] = uint64(val.(uint32))
3735 receivedMask |= 0x800
3736 } else if !ok {
3737 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3738 }
3739 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003740 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303741 ethFrameExtPMData[k] = uint64(val.(uint32))
3742 receivedMask |= 0x400
3743 } else if !ok {
3744 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3745 }
3746 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003747 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303748 ethFrameExtPMData[k] = uint64(val.(uint32))
3749 receivedMask |= 0x200
3750 } else if !ok {
3751 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3752 }
3753 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003754 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303755 ethFrameExtPMData[k] = uint64(val.(uint32))
3756 receivedMask |= 0x100
3757 } else if !ok {
3758 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3759 }
3760 default:
3761 //do nothing
3762 }
3763 }
3764 }
3765 case 0x00FC:
3766 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3767 if _, ok := ethFrameExtPMData[k]; !ok {
3768 switch k {
3769 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003770 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303771 ethFrameExtPMData[k] = uint64(val.(uint32))
3772 receivedMask |= 0x80
3773 } else if !ok {
3774 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3775 }
3776 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003777 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303778 ethFrameExtPMData[k] = uint64(val.(uint32))
3779 receivedMask |= 0x40
3780 } else if !ok {
3781 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3782 }
3783 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003784 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303785 ethFrameExtPMData[k] = uint64(val.(uint32))
3786 receivedMask |= 0x20
3787 } else if !ok {
3788 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3789 }
3790 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003791 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303792 ethFrameExtPMData[k] = uint64(val.(uint32))
3793 receivedMask |= 0x10
3794 } else if !ok {
3795 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3796 }
3797 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003798 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303799 ethFrameExtPMData[k] = uint64(val.(uint32))
3800 receivedMask |= 0x8
3801 } else if !ok {
3802 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3803 }
3804 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003805 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303806 ethFrameExtPMData[k] = uint64(val.(uint32))
3807 receivedMask |= 0x4
3808 } else if !ok {
3809 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3810 }
3811 default:
3812 //do nothing
3813 }
3814 }
3815 }
3816 case 0x0003:
3817 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3818 if _, ok := ethFrameExtPMData[k]; !ok {
3819 switch k {
3820 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003821 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303822 ethFrameExtPMData[k] = uint64(val.(uint32))
3823 receivedMask |= 0x2
3824 } else if !ok {
3825 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3826 }
3827 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003828 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303829 ethFrameExtPMData[k] = uint64(val.(uint32))
3830 receivedMask |= 0x1
3831 } else if !ok {
3832 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3833 }
3834 default:
3835 //do nothing
3836 }
3837 }
3838 }
3839 default:
3840 //do nothing
3841 }
3842 return receivedMask
3843}
3844
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303845// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003846func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303847 receivedMask := uint16(0)
3848 switch requestedAttributesMask {
3849 case 0x3800:
3850 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3851 if _, ok := ethFrameExtPMData[k]; !ok {
3852 switch k {
3853 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003854 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303855 ethFrameExtPMData[k] = val.(uint64)
3856 receivedMask |= 0x2000
3857 } else if !ok {
3858 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3859 }
3860 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003861 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303862 ethFrameExtPMData[k] = val.(uint64)
3863 receivedMask |= 0x1000
3864 } else if !ok {
3865 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3866 }
3867 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003868 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303869 ethFrameExtPMData[k] = val.(uint64)
3870 receivedMask |= 0x800
3871 } else if !ok {
3872 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3873 }
3874 }
3875 }
3876 }
3877 case 0x0700:
3878 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3879 if _, ok := ethFrameExtPMData[k]; !ok {
3880 switch k {
3881 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003882 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303883 ethFrameExtPMData[k] = val.(uint64)
3884 receivedMask |= 0x400
3885 } else if !ok {
3886 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3887 }
3888 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003889 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303890 ethFrameExtPMData[k] = val.(uint64)
3891 receivedMask |= 0x200
3892 } else if !ok {
3893 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3894 }
3895 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003896 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303897 ethFrameExtPMData[k] = val.(uint64)
3898 receivedMask |= 0x100
3899 } else if !ok {
3900 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3901 }
3902 }
3903 }
3904 }
3905 case 0x00E0:
3906 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3907 if _, ok := ethFrameExtPMData[k]; !ok {
3908 switch k {
3909 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003910 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303911 ethFrameExtPMData[k] = val.(uint64)
3912 receivedMask |= 0x80
3913 } else if !ok {
3914 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3915 }
3916 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003917 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303918 ethFrameExtPMData[k] = val.(uint64)
3919 receivedMask |= 0x40
3920 } else if !ok {
3921 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3922 }
3923 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003924 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303925 ethFrameExtPMData[k] = val.(uint64)
3926 receivedMask |= 0x20
3927 } else if !ok {
3928 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3929 }
3930 }
3931 }
3932 }
3933 case 0x001C:
3934 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3935 if _, ok := ethFrameExtPMData[k]; !ok {
3936 switch k {
3937 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003938 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303939 ethFrameExtPMData[k] = val.(uint64)
3940 receivedMask |= 0x10
3941 } else if !ok {
3942 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3943 }
3944 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003945 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303946 ethFrameExtPMData[k] = val.(uint64)
3947 receivedMask |= 0x8
3948 } else if !ok {
3949 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3950 }
3951 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003952 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303953 ethFrameExtPMData[k] = val.(uint64)
3954 receivedMask |= 0x4
3955 } else if !ok {
3956 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3957 }
3958 default:
3959 //do nothing
3960 }
3961 }
3962 }
3963 case 0x0003:
3964 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3965 if _, ok := ethFrameExtPMData[k]; !ok {
3966 switch k {
3967 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003968 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303969 ethFrameExtPMData[k] = val.(uint64)
3970 receivedMask |= 0x2
3971 } else if !ok {
3972 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3973 }
3974 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003975 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303976 ethFrameExtPMData[k] = val.(uint64)
3977 receivedMask |= 0x1
3978 } else if !ok {
3979 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3980 }
3981 default:
3982 //do nothing
3983 }
3984 }
3985 }
3986 }
3987 return receivedMask
3988}
3989
Himani Chawlaee10b542021-09-20 16:46:40 +05303990func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3991 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303992 errorCounterValue := UnsupportedCounterValue64bit
3993 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3994 errorCounterValue = UnsupportedCounterValue32bit
3995 }
3996 var pmDataOut extension.OmciEthernetFrameExtendedPm
3997 if aggregate {
3998 if pmData.DropEvents != errorCounterValue {
3999 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
4000 } else {
4001 pmDataOut.DropEvents = pmData.DropEvents
4002 }
4003 if pmData.Octets != errorCounterValue {
4004 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
4005 } else {
4006 pmDataOut.Octets = pmData.Octets
4007 }
4008 if pmData.Frames != errorCounterValue {
4009 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
4010 } else {
4011 pmDataOut.Frames = pmData.Frames
4012 }
4013 if pmData.BroadcastFrames != errorCounterValue {
4014 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
4015 } else {
4016 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
4017 }
4018 if pmData.MulticastFrames != errorCounterValue {
4019 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
4020 } else {
4021 pmDataOut.MulticastFrames = pmData.MulticastFrames
4022 }
4023 if pmData.CrcErroredFrames != errorCounterValue {
4024 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
4025 } else {
4026 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
4027 }
4028 if pmData.UndersizeFrames != errorCounterValue {
4029 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
4030 } else {
4031 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
4032 }
4033 if pmData.OversizeFrames != errorCounterValue {
4034 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
4035 } else {
4036 pmDataOut.OversizeFrames = pmData.OversizeFrames
4037 }
4038 if pmData.Frames_64Octets != errorCounterValue {
4039 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
4040 } else {
4041 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
4042 }
4043 if pmData.Frames_65To_127Octets != errorCounterValue {
4044 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
4045 } else {
4046 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
4047 }
4048 if pmData.Frames_128To_255Octets != errorCounterValue {
4049 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
4050 } else {
4051 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
4052 }
4053 if pmData.Frames_256To_511Octets != errorCounterValue {
4054 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
4055 } else {
4056 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
4057 }
4058 if pmData.Frames_512To_1023Octets != errorCounterValue {
4059 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
4060 } else {
4061 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
4062 }
4063 if pmData.Frames_1024To_1518Octets != errorCounterValue {
4064 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
4065 } else {
4066 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
4067 }
4068 } else {
4069 pmDataOut.DropEvents = pmDataIn["drop_events"]
4070 pmDataOut.Octets = pmDataIn["octets"]
4071 pmDataOut.Frames = pmDataIn["frames"]
4072 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
4073 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
4074 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
4075 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
4076 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
4077 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
4078 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
4079 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
4080 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
4081 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
4082 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
4083 }
4084 return pmDataOut
4085}
4086
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05304087//nolint:unparam
Himani Chawlaee10b542021-09-20 16:46:40 +05304088func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304089 controlBlock := make([]uint16, 8)
4090 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
4091 controlBlock[0] = 0
4092 // Next two bytes are for the parent class ID
4093 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
4094 // Next two bytes are for the parent me instance id
4095 controlBlock[2] = entityID
4096 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05304097 if reset {
4098 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
4099 } else {
4100 controlBlock[3] = 0
4101 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05304102 // Next two bytes are for tca disable
4103 controlBlock[4] = 0x4000 //tca global disable
4104 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
4105 if upstream {
4106 controlBlock[5] = 1 << 0
4107 } else {
4108 controlBlock[5] = (1 << 0) | (1 << 1)
4109 }
4110 // Next two bytes are for tci - does not matter here
4111 controlBlock[6] = 0
4112 // Next two bytes are for reserved bits - does not matter here
4113 controlBlock[7] = 0
4114 return controlBlock
4115}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00004116
Girish Gowdraabcceb12022-04-13 23:35:22 -07004117// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
4118func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
4119 mm.OnuMetricsManagerLock.RLock()
4120 defer mm.OnuMetricsManagerLock.RUnlock()
4121 return mm.deviceDeletionInProgress
4122}
4123
4124// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
4125func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
4126 mm.OnuMetricsManagerLock.Lock()
4127 defer mm.OnuMetricsManagerLock.Unlock()
4128 mm.deviceDeletionInProgress = true
4129}
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +05304130
4131// Obtain the ONU GEM counters for the ONU device
4132func (mm *OnuMetricsManager) GetONUGEMCounters(ctx context.Context) *extension.SingleGetValueResponse {
4133
4134 resp := extension.SingleGetValueResponse{
4135 Response: &extension.GetValueResponse{
4136 Status: extension.GetValueResponse_OK,
4137 Response: &extension.GetValueResponse_OnuAllocGemStatsResponse{
4138 OnuAllocGemStatsResponse: &extension.GetOnuAllocGemHistoryResponse{},
4139 },
4140 },
4141 }
4142
4143 if mm.GetdeviceDeletionInProgress() {
4144 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
4145 return nil
4146 }
4147
4148 mm.OnuMetricsManagerLock.RLock()
4149 defer mm.OnuMetricsManagerLock.RUnlock()
4150
4151 gemtoAllocId := mm.pDeviceHandler.GetOnuTP().GetGEMportToAllocIDMappingForONU(ctx, mm.deviceID)
4152 allocIDtoGem := make(map[uint16][]uint16)
4153 for key, value := range gemtoAllocId {
4154 allocIDtoGem[value] = append(allocIDtoGem[value], key)
4155 }
4156
4157 for allocID, gemSlice := range allocIDtoGem {
4158 logger.Infow(ctx, "AllocID", log.Fields{"alloc-id": allocID})
4159 allocIdGemData := extension.OnuAllocGemHistoryData{
4160 OnuAllocIdInfo: &extension.OnuAllocHistoryData{},
4161 GemPortInfo: []*extension.OnuGemPortHistoryData{},
4162 }
4163 allocIdGemData.OnuAllocIdInfo.AllocId = uint32(allocID)
4164
4165 // Loop through each element in the slice
4166 for _, gem := range gemSlice {
4167 logger.Debugw(ctx, "Collecting stats for Gem: ", log.Fields{"GEMID": gem})
4168 if metricInfo := mm.collectGemHistoryData(ctx, gem); metricInfo != nil {
4169 logger.Infow(ctx, "Metricinfo for GEM", log.Fields{"GEMID": gem, "metricInfo": metricInfo})
4170 gemHistoryData := extension.OnuGemPortHistoryData{}
4171 gemHistoryData.GemId = uint32(gem)
4172 gemHistoryData.TransmittedGEMFrames = uint32(metricInfo.GetMetrics()["transmitted_gem_frames"])
4173 gemHistoryData.ReceivedGEMFrames = uint32(metricInfo.GetMetrics()["received_gem_frames"])
4174 gemHistoryData.ReceivedPayloadBytes = uint32(metricInfo.GetMetrics()["received_payload_bytes"])
4175 gemHistoryData.TransmittedPayloadBytes = uint32(metricInfo.GetMetrics()["transmitted_payload_bytes"])
4176 gemHistoryData.EncryptionKeyErrors = uint32(metricInfo.GetMetrics()["encryption_key_errors"])
4177 allocIdGemData.GemPortInfo = append(allocIdGemData.GemPortInfo, &gemHistoryData)
4178 logger.Debugw(ctx, " allocIdGemData value ", log.Fields{"AllocIDGemData": allocIdGemData})
4179
4180 }
4181 }
4182 resp.Response.GetOnuAllocGemStatsResponse().OnuAllocGemHistoryData = append(resp.Response.GetOnuAllocGemStatsResponse().OnuAllocGemHistoryData, &allocIdGemData)
4183 }
4184
4185 logger.Debugw(ctx, "Request to fetch GEM Performance Counters ", log.Fields{"device-id": mm.deviceID, "response": resp})
4186 return &resp
4187
4188}