blob: e6eda1c7a4af51b2e5122dc4810cd83ffe7e1356 [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 {
mgoudad611f4c2025-10-30 14:49:27 +05302155 //nolint:staticcheck
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002156 upstream := false
2157 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2158 upstream = true
2159 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002160 // 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 +00002161 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302162 meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002163 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002164 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302165 if CheckMeInstanceStatusCode(err) {
2166 return err // Device is being deleted, so we stop processing
2167 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002168 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2169 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002170 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002171 go func(p_pmFsm *cmn.AdapterFsm) {
2172 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002173 }(pmFsm)
2174 return err
2175 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302176 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002177 }
2178 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002179 select {
2180 case meAttributes = <-mm.l2PmChan:
2181 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002182 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2183 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002184 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002185 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002186 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002187 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302188 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2189 logger.Warnw(ctx, "Deleting the device, stopping Ethernet Performance metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2190 return fmt.Errorf("deleting the device, stopping Ethernet Performance metrics collection for the device %v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002191 }
2192 // 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 -08002193 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002194 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002195 }
2196 }
2197 for k := range EthernetBridgeHistory {
2198 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2199 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2200 if _, ok := ethPMHistData[k]; !ok {
2201 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002202 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002203 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002204 ethPMHistData[k] = float32(val.(uint16))
2205 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002206 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002207 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002208 ethPMHistData[k] = float32(val.(uint32))
2209 }
2210 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002211 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002212 ethPMHistData[k] = float32(val.(uint32))
2213 }
2214 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002215 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002216 ethPMHistData[k] = float32(val.(uint32))
2217 }
2218 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002219 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002220 ethPMHistData[k] = float32(val.(uint32))
2221 }
2222 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002223 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002224 ethPMHistData[k] = float32(val.(uint32))
2225 }
2226 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002227 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002228 ethPMHistData[k] = float32(val.(uint32))
2229 }
2230 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002231 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002232 ethPMHistData[k] = float32(val.(uint32))
2233 }
2234 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002235 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002236 ethPMHistData[k] = float32(val.(uint32))
2237 }
2238 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002239 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002240 ethPMHistData[k] = float32(val.(uint32))
2241 }
2242 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002243 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002244 ethPMHistData[k] = float32(val.(uint32))
2245 }
2246 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002247 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002248 ethPMHistData[k] = float32(val.(uint32))
2249 }
2250 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002251 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002252 ethPMHistData[k] = float32(val.(uint32))
2253 }
2254 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002255 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002256 ethPMHistData[k] = float32(val.(uint32))
2257 }
2258 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002259 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002260 ethPMHistData[k] = float32(val.(uint32))
2261 }
2262 default:
2263 // do nothing
2264 }
2265 }
2266 }
2267 return nil
2268}
2269
2270// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002271func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002272 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002273 // 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 +03002274 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2275 requestedAttributes["IntervalEndTime"] = 0
2276 }
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302277 meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002278 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002279 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302280 if CheckMeInstanceStatusCode(err) {
2281 return err // Device is being deleted, so we stop processing
2282 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002283 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2284 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302285 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002286 }
2287 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002288 select {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302289 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2290 logger.Warnw(ctx, "Deleting the device, stopping EthernetUniHistory metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2291 return fmt.Errorf("deleting the device, stopping EthernetUniHistory metrics collection for the device %v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002292 case meAttributes = <-mm.l2PmChan:
2293 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002294 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2295 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002296 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002297 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002298 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002299 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002300 }
2301 // 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 -08002302 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002303 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002304 }
2305 }
2306 for k := range EthernetUniHistory {
2307 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2308 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2309 if _, ok := ethPMUniHistData[k]; !ok {
2310 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002311 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002312 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002313 ethPMUniHistData[k] = float32(val.(uint16))
2314 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002315 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002316 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002317 ethPMUniHistData[k] = float32(val.(uint32))
2318 }
2319 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002320 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002321 ethPMUniHistData[k] = float32(val.(uint32))
2322 }
2323 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002324 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002325 ethPMUniHistData[k] = float32(val.(uint32))
2326 }
2327 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002328 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002329 ethPMUniHistData[k] = float32(val.(uint32))
2330 }
2331 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002332 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002333 ethPMUniHistData[k] = float32(val.(uint32))
2334 }
2335 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002336 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002337 ethPMUniHistData[k] = float32(val.(uint32))
2338 }
2339 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002340 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002341 ethPMUniHistData[k] = float32(val.(uint32))
2342 }
2343 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002344 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002345 ethPMUniHistData[k] = float32(val.(uint32))
2346 }
2347 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002348 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002349 ethPMUniHistData[k] = float32(val.(uint32))
2350 }
2351 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002352 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002353 ethPMUniHistData[k] = float32(val.(uint32))
2354 }
2355 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002356 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002357 ethPMUniHistData[k] = float32(val.(uint32))
2358 }
2359 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002360 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002361 ethPMUniHistData[k] = float32(val.(uint32))
2362 }
2363 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002364 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002365 ethPMUniHistData[k] = float32(val.(uint32))
2366 }
2367 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002368 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002369 ethPMUniHistData[k] = float32(val.(uint32))
2370 }
2371 default:
2372 // do nothing
2373 }
2374 }
2375 }
2376 return nil
2377}
2378
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002379// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002380func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002381 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002382 // 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 +00002383 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2384 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002385 }
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302386 meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002387 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002388 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302389 if CheckMeInstanceStatusCode(err) {
2390 return err // Device is being deleted, so we stop processing
2391 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002392 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2393 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302394 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002395 }
2396 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002397 select {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302398 case _, ok := <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2399 if !ok {
2400 logger.Warnw(ctx, "Deleting the device, stopping FEC history metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2401 return fmt.Errorf("deleting the device, stopping FEC history metrics collection for the device %v", mm.deviceID)
2402 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002403 case meAttributes = <-mm.l2PmChan:
2404 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002405 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2406 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002407 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002408 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002409 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002410 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002411 }
2412 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2413 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002414 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002415 }
2416 }
2417 for k := range FecHistory {
2418 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2419 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2420 if _, ok := fecHistData[k]; !ok {
2421 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002422 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002423 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002424 fecHistData[k] = float32(val.(uint16))
2425 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002426 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002427 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002428 fecHistData[k] = float32(val.(uint32))
2429 }
2430 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002431 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002432 fecHistData[k] = float32(val.(uint32))
2433 }
2434 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002435 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002436 fecHistData[k] = float32(val.(uint32))
2437 }
2438 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002439 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002440 fecHistData[k] = float32(val.(uint32))
2441 }
2442 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002443 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002444 fecHistData[k] = float32(val.(uint16))
2445 }
2446 default:
2447 // do nothing
2448 }
2449 }
2450 }
2451 return nil
2452}
2453
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302454func (mm *OnuMetricsManager) GetMeInstance(ctx context.Context, classID me.ClassID, entityID uint16, requestedAttributes me.AttributeValueMap,
2455 timeout int, highPrio bool, rxChan chan cmn.Message, isExtendedOmci bool) (*me.ManagedEntity, error) {
2456
2457 select {
2458 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2459 errMsg := "deleting the device, stopping GetMeInstance for the device " + mm.deviceID
2460 logger.Warn(ctx, errMsg)
2461 return nil, status.Error(codes.NotFound, errMsg)
2462 default:
2463 if mm.pOnuDeviceEntry.GetDevOmciCC() != nil {
2464 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2465 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2466 return meInstance, err
2467 }
2468 }
2469 return nil, nil
2470}
2471
2472// CheckMeInstanceStatusCode checked status code if not found returns true
2473func CheckMeInstanceStatusCode(err error) bool {
2474 if err != nil {
2475 st, ok := status.FromError(err)
2476 if ok && st.Code() == codes.NotFound {
2477 return true
2478 }
2479 }
2480 return false
2481}
2482
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002483// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002484func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002485 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002486 // 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 +00002487 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2488 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002489 }
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302490 meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002491 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002492 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302493 if CheckMeInstanceStatusCode(err) {
2494 return err // Device is being deleted, so we stop processing
2495 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002496 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2497 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302498 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002499 }
2500 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002501 select {
2502 case meAttributes = <-mm.l2PmChan:
2503 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002504 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2505 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002506 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002507 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002508 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002509 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302510 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2511 logger.Warnw(ctx, "Deleting the device, stopping GEM port history metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2512 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 -08002513 }
2514 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2515 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002516 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002517 }
2518 }
2519 for k := range GemPortHistory {
2520 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2521 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2522 if _, ok := gemPortHistData[k]; !ok {
2523 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002524 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002525 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002526 gemPortHistData[k] = float32(val.(uint16))
2527 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002528 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002529 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002530 gemPortHistData[k] = float32(val.(uint32))
2531 }
2532 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002533 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002534 gemPortHistData[k] = float32(val.(uint32))
2535 }
2536 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002537 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002538 gemPortHistData[k] = float32(val.(uint64))
2539 }
2540 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002541 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002542 gemPortHistData[k] = float32(val.(uint64))
2543 }
2544 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002545 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002546 gemPortHistData[k] = float32(val.(uint32))
2547 }
2548 default:
2549 // do nothing
2550 }
2551 }
2552 }
2553 return nil
2554}
2555
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002556func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002557 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2558 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002559 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2560 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 -08002561 }
2562 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2563 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002564 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2565 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 -08002566 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002567 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002568 switch msgObj.EntityClass {
2569 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2570 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002571 me.EthernetPerformanceMonitoringHistoryDataClassID,
2572 me.FecPerformanceMonitoringHistoryDataClassID,
2573 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002574 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2575 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2576 mm.l2PmCreateOrDeleteResponseChan <- true
2577 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002578 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002579 mm.l2PmCreateOrDeleteResponseChan <- false
2580 }
2581 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302582 case me.EthernetFrameExtendedPmClassID,
2583 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302584 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302585 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002586 default:
2587 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002588 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002589 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002590 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002591}
2592
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002593func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002594 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2595 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002596 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2597 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 -08002598 }
2599 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2600 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002601 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2602 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 -08002603 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002604 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002605 switch msgObj.EntityClass {
2606 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2607 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002608 me.EthernetPerformanceMonitoringHistoryDataClassID,
2609 me.FecPerformanceMonitoringHistoryDataClassID,
2610 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002611 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2612 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2613 mm.l2PmCreateOrDeleteResponseChan <- true
2614 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002615 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002616 mm.l2PmCreateOrDeleteResponseChan <- false
2617 }
2618 return nil
2619 default:
2620 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002621 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002622 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002623 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002624}
2625
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002626func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002627 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002628 for {
2629 select {
2630 case <-time.After(L2PmCollectionInterval * time.Second):
2631 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002632 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2633 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002634 }
2635 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002636 case <-mm.StopTicks:
2637 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002638 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002639 return
2640 }
2641 }
2642}
2643
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002644func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002645 // Publish metrics if it is valid
2646 if metricInfoSlice != nil {
2647 mm.publishMetrics(ctx, metricInfoSlice)
2648 } else {
2649 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2650 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002651 mm.OnuMetricsManagerLock.Lock()
2652 mm.GroupMetricMap[metricName].collectAttempts++
2653 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002654 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2655 }
2656 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002657 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2658 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002659 }
2660}
2661
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302662// nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002663func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002664 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2665 var grpFunc groupMetricPopulateFunc
2666 switch classID {
2667 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2668 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2669 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2670 grpFunc = mm.populateEthernetUniHistoryMetrics
2671 case me.FecPerformanceMonitoringHistoryDataClassID:
2672 grpFunc = mm.populateFecHistoryMetrics
2673 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2674 grpFunc = mm.populateGemPortMetrics
2675 default:
2676 return fmt.Errorf("unknown-classid-%v", classID)
2677 }
2678
2679 size := 0
2680 requestedAttributes := make(me.AttributeValueMap)
2681 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002682 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2683 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2684 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2685 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2686 continue
2687 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002688 if v.Size+size <= mm.maxL2PMGetPayLoadSize {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002689 requestedAttributes[v.Name] = v.DefValue
2690 size = v.Size + size
2691 } else { // We exceeded the allow omci get size
2692 // Let's collect the attributes via get now and collect remaining in the next iteration
2693 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2694 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002695 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002696 return err
2697 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002698 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002699 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2700 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002701 }
2702 }
2703 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002704 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2705 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002706 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002707 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002708 }
2709 return nil
2710}
2711
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002712func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002713 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002714 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2715 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2716 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002717
2718 raisedTs := time.Now().Unix()
2719 mmd := voltha.MetricMetaData{
2720 Title: title,
2721 Ts: float64(raisedTs),
2722 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002723 DeviceId: mm.deviceID,
2724 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2725 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002726 }
2727
2728 // create slice of metrics given that there could be more than one VEIP instance
2729 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2730 return metricInfo
2731}
2732
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002733func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002734 valid := false
2735 if *intervalEndTime == -1 { // first time
2736 // Update the interval end time
2737 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2738 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2739 valid = true
2740 }
2741 } else {
2742 var currIntervalEndTime int
2743 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2744 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2745 }
2746 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2747 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002748 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002749 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2750 } else {
2751 valid = true
2752 }
2753 }
2754 return valid
2755}
2756
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002757func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002758 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002759 if !mm.GetOmciProcessingStatus() {
2760 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})
2761 return false
2762 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002763 select {
2764 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002765 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002766 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002767 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002768 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002769 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002770 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002771 }
2772 return false
2773}
2774
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302775// nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002776func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002777 var pmConfigSlice []*voltha.PmConfig
2778 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002779 pmConfigSlice = append(pmConfigSlice,
2780 &voltha.PmConfig{
2781 Name: k,
2782 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002783 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002784 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002785 }
2786 groupMetric := voltha.PmGroupConfig{
2787 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002788 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002789 GroupFreq: grpFreq,
2790 Metrics: pmConfigSlice,
2791 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002792 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002793
2794}
2795
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002796func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2797 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2798 if mm.PAdaptFsm == nil {
2799 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2800 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002801 return fmt.Errorf("nil-adapter-fsm")
2802 }
2803 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002804 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2805 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002806 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002807 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2808 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2809 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2810 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2811 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2812 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2813 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2814 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2815 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002816 },
2817 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002818 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2819 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2820 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2821 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2822 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2823 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2824 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2825 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002826 },
2827 )
2828 return nil
2829}
2830
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002831func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2832 mm.pDeviceHandler.InitPmConfigs()
2833 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2834 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2835 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2836 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002837
2838 // Populate group metrics.
2839 // Lets populate irrespective of GroupMetricEnabled is true or not.
2840 // The group metrics collection will decided on this flag later
2841
2842 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2843 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2844
2845 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2846 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2847
2848 // classical l2 pm counter start
2849
2850 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2851 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2852
2853 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2854 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2855
2856 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2857 FecHistoryEnabled, FecHistoryFrequency)
2858
2859 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2860 GemPortHistoryEnabled, GemPortHistoryFrequency)
2861
2862 // classical l2 pm counter end
2863
2864 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2865}
2866
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002867func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002868 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002869 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2870 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002871 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002872 Enabled: g.Enabled,
2873 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002874 }
2875 switch g.GroupName {
2876 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002877 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002878 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002879 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002880 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002881 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2882 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002883 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002884 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2885 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002886 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002887 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2888 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002889 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002890 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2891 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002892 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002893 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002894 }
2895 }
2896
2897 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002898 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2899 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002900 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002901 Enabled: m.Enabled,
2902 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002903 }
2904 switch m.Name {
2905 // None exist as of now. Add when available.
2906 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002907 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002908 }
2909 }
2910}
2911
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002912// AddGemPortForPerfMonitoring - TODO: add comment
2913func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2914 mm.OnuMetricsManagerLock.Lock()
2915 defer mm.OnuMetricsManagerLock.Unlock()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302916 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002917 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002918 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002919 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002920 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002921 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002922
2923 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2924 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2925 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2926 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2927 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002928
2929 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002930 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2931 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002932 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002933 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002934 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002935 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002936 }
2937 }()
Praneeth Kumar Nalmas8f8f0c02024-10-22 19:29:09 +05302938 mm.pOnuDeviceEntry.GetOnuDB().PutOnuSpeficMe(ctx, me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID, meAttributes)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002939}
2940
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002941// RemoveGemPortForPerfMonitoring - TODO: add comment
2942func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2943 mm.OnuMetricsManagerLock.Lock()
2944 defer mm.OnuMetricsManagerLock.Unlock()
2945 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2946 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002947 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002948 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002949
2950 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2951 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2952 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2953 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2954 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002955
2956 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002957 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2958 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002959 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002960 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002961 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002962 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002963 }
2964 }()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302965 mm.pOnuDeviceEntry.GetOnuDB().DeleteMe(me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002966}
2967
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002968func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2969 if mm.pDeviceHandler.GetOnuTP() != nil {
2970 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002971 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002972 for _, v := range gemPortInstIDs {
2973 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002974 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002975 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002976 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002977 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002978 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002979 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002980 }
2981}
2982
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002983func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2984 if mm.pDeviceHandler.GetOnuTP() != nil {
2985 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002986 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002987 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002988 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002989 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002990 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002991 }
2992 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002993 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002994 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002995}
2996
2997// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002998func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2999 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003000 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003001 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303002 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003003 }
3004 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003005 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003006 group.pmMEData = &pmMEData{}
3007 Value, err := mm.pmKvStore.Get(ctx, groupName)
3008 if err == nil {
3009 if Value != nil {
3010 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003011 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003012 tmpBytes, _ := kvstore.ToByte(Value.Value)
3013
3014 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003015 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303016 errorsList = append(errorsList, fmt.Errorf("unable-to-unmarshal-PM-data-%s-for-group-%s", mm.deviceID, groupName))
Girish Gowdra0e533642021-03-02 22:02:51 -08003017 continue
3018 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003019 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003020 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003021 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003022 continue
3023 }
3024 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003025 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303026 errorsList = append(errorsList, fmt.Errorf("unable-to-read-from-KVstore-%s-for-group-%s", mm.deviceID, groupName))
Girish Gowdra0e533642021-03-02 22:02:51 -08003027 continue
3028 }
3029 }
3030 if len(errorsList) > 0 {
3031 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
3032 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003033 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003034 return nil
3035}
3036
3037// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
3038// the data must be available in cache.
3039// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003040func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
3041 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08003042 return grp.pmMEData, nil
3043 }
3044 // Data not in cache, try to fetch from kv store.
3045 data := &pmMEData{}
3046 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003047 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3048 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003049 }
3050 Value, err := mm.pmKvStore.Get(ctx, groupName)
3051 if err == nil {
3052 if Value != nil {
3053 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003054 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003055 tmpBytes, _ := kvstore.ToByte(Value.Value)
3056
3057 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003058 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003059 return data, err
3060 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003061 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003062 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003063 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003064 return data, err
3065 }
3066 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003067 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003068 return data, err
3069 }
3070
3071 return data, nil
3072}
3073
3074// 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 +00003075func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
3076 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
3077 mm.OnuMetricsManagerLock.Lock()
3078 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08003079
3080 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003081 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303082 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003083 }
3084
3085 pmMEData, err := mm.getPmData(ctx, groupName)
3086 if err != nil || pmMEData == nil {
3087 // error already logged in called function.
3088 return err
3089 }
3090 switch pmAction {
3091 case cPmAdd:
3092 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
3093 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3094 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3095 case cPmAdded:
3096 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
3097 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3098 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3099 case cPmRemove:
3100 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
3101 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3102 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3103 case cPmRemoved:
3104 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3105 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3106 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3107 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003108 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303109 return fmt.Errorf("unknown-pm-action-deviceid-%s-groupName-%s-pmaction-%s", mm.deviceID, groupName, pmAction)
Girish Gowdra0e533642021-03-02 22:02:51 -08003110 }
3111 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003112 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08003113
3114 Value, err := json.Marshal(*pmMEData)
3115 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003116 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
3117 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003118 return err
3119 }
3120 // Update back to kv store
3121 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003122 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
3123 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003124 return err
3125 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003126 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
3127 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08003128
3129 return nil
3130}
3131
3132// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003133func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
3134 mm.OnuMetricsManagerLock.Lock()
3135 defer mm.OnuMetricsManagerLock.Unlock()
3136 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003137 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003138 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303139 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003140 }
3141
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003142 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003143 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003144 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003145 // do not abort this procedure. continue to delete next group.
3146 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003147 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08003148 }
3149 }
3150
3151 return nil
3152}
3153
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003154// ClearAllPmData clears all PM data associated with the device from KV store
3155func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3156 mm.OnuMetricsManagerLock.Lock()
3157 defer mm.OnuMetricsManagerLock.Unlock()
3158 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003159 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003160 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303161 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003162 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003163 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003164 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003165 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003166 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003167 value = err
3168 // do not abort this procedure - continue to delete next group.
3169 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003170 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003171 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003172 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003173 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003174 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003175 }
3176 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003177}
3178
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003179func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3180 mm.OnuMetricsManagerLock.Lock()
3181 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003182 mm.omciProcessingActive = status
3183}
3184
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003185// updateTickGenerationStatus - TODO: add comment
3186func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3187 mm.OnuMetricsManagerLock.Lock()
3188 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003189 mm.tickGenerationActive = status
3190}
3191
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003192// GetOmciProcessingStatus - TODO: add comment
3193func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3194 mm.OnuMetricsManagerLock.RLock()
3195 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003196 return mm.omciProcessingActive
3197}
3198
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003199// GetTickGenerationStatus - TODO: add comment
3200func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3201 mm.OnuMetricsManagerLock.RLock()
3202 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003203 return mm.tickGenerationActive
3204}
3205
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003206func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003207 for _, ele := range slice {
3208 if ele == n {
3209 return slice
3210 }
3211 }
3212 return append(slice, n)
3213}
3214
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003215func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003216 for i, ele := range slice {
3217 if ele == n {
3218 return append(slice[:i], slice[i+1:]...)
3219 }
3220 }
3221 return slice
3222}
3223
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003224func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003225 for _, ele := range slice {
3226 if ele == n {
3227 return slice
3228 }
3229 }
3230 return append(slice, n)
3231}
3232
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003233func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003234 for i, ele := range slice {
3235 if ele == n {
3236 return append(slice[:i], slice[i+1:]...)
3237 }
3238 }
3239 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003240}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303241
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003242func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303243 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3244 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003245 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003246 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003247 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303248 Value, err := mm.extPmKvStore.Get(ctx, key)
3249 if err == nil {
3250 if Value != nil {
3251 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003252 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303253 tmpBytes, _ := kvstore.ToByte(Value.Value)
3254
3255 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003256 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303257 return false, err
3258 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003259 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303260 // We have found the data from db, no need to get through omci get message.
3261 mm.supportedEthernetFrameExtendedPMClass = data
3262 return true, nil
3263 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003264 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303265 return false, nil
3266 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003267 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303268 return false, err
3269}
3270
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003271func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303272 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 -07003273 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3274 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})
3275 return false, fmt.Errorf("omci-processor-shutdown")
3276 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303277 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303278 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303279 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003280 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303281 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
mgoudad611f4c2025-10-30 14:49:27 +05303282 switch resp {
3283 case me.Success, me.InstanceExists:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303284 return true, nil
mgoudad611f4c2025-10-30 14:49:27 +05303285 case me.UnknownEntity, me.ParameterError,
3286 me.ProcessingError, me.NotSupported, me.AttributeFailure:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303287 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
mgoudad611f4c2025-10-30 14:49:27 +05303288 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003289 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 +05303290 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3291 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003292 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303293 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003294 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303295 }
3296 return false, fmt.Errorf("timeout-while-waiting-for-response")
3297}
3298
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003299func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303300 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303301 // 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 +05303302 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003303 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303304 var entityID uint16
3305 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003306 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303307 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003308 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303309 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303310 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303311 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303312 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303313
3314 inner1:
3315 // retry ExtendedPmCreateAttempts times to create the instance of PM
3316 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003317 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3318 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3319 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303320 if err != nil {
3321 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003322 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303323 return false, err
3324 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303325 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3326 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303327 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303328 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303329 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303330 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303331 }
3332 break inner1
3333 } else if err != nil {
3334 if !supported {
3335 // Need to return immediately
3336 return false, err
3337 }
3338 //In case of failure, go for a retry
3339 }
3340 }
3341 if cnt == ExtendedPmCreateAttempts {
3342 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3343 return true, fmt.Errorf("unable-to-create-me")
3344 }
3345 }
3346 }
3347 return true, nil
3348}
3349
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003350func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3351 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003352 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003353 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303354 // check if we get the supported type me for ethernet frame extended pm class id
3355 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3356 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3357 }
3358 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3359 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003360 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303361 }
3362 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003363 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303364 }
3365}
3366
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003367func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303368 mm.onuEthernetFrameExtendedPmLock.Lock()
3369 mm.isDeviceReadyToCollectExtendedPmStats = true
3370 mm.onuEthernetFrameExtendedPmLock.Unlock()
3371}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003372
Himani Chawlaee10b542021-09-20 16:46:40 +05303373// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003374func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303375 //get the type of extended frame pm me supported by onu first
3376 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3377 if err != nil {
3378 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3379 return
3380 }
3381 if exist {
3382 // we have the me type, go ahead with the me type supported.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303383 //nolint:govet
Himani Chawla43f95ff2021-06-03 00:24:12 +05303384 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003385 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303386 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3387 return
3388 }
3389 mm.setAllExtPmMeCreatedFlag()
3390 return
3391 }
3392 // First try with 64 bit me
3393 // we have the me type, go ahead with the me type supported.
3394 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3395 if err != nil && !supported64Bit {
3396 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003397 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303398 "supported": supported64Bit})
3399 // Then Try with 32 bit type
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303400 //nolint:govet
Himani Chawla43f95ff2021-06-03 00:24:12 +05303401 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003402 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303403 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3404 } else if supported32Bit {
3405 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3406 mm.putExtPmMeKvStore(ctx)
3407 mm.setAllExtPmMeCreatedFlag()
3408 }
3409 } else if err == nil && supported64Bit {
3410 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3411 mm.putExtPmMeKvStore(ctx)
3412 mm.setAllExtPmMeCreatedFlag()
3413 }
3414}
3415
Himani Chawlaee10b542021-09-20 16:46:40 +05303416func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3417 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3418 uniPortEntityID := entityID
3419 if upstream {
3420 uniPortEntityID = entityID - 0x100
3421 }
3422 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3423 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3424 mm.pDeviceHandler.GetOmciTimeout(), true,
3425 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3426 if err != nil {
3427 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3428 log.Fields{"device-id": mm.deviceID})
3429 return extension.GetValueResponse_INTERNAL_ERROR, err
3430 }
3431
3432 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3433 return extension.GetValueResponse_REASON_UNDEFINED, nil
3434 }
3435 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3436}
3437
3438func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3439 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 -07003440 if !mm.GetOmciProcessingStatus() {
3441 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})
3442 return false
3443 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303444 select {
3445 case resp := <-mm.extendedPMMeResponseChan:
3446 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3447 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3448 if resp == me.Success {
3449 return true
3450 }
3451 return false
3452 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3453 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3454 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3455 }
3456 return false
3457}
3458
3459func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3460 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3461 className := "EthernetFrameExtendedPm64Bit"
3462 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3463 className = "EthernetFrameExtendedPm"
3464 }
3465 // Reset the counters if option is specified
3466 for entityID := range upstreamEntityMap {
3467 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3468 true)
3469 if err != nil {
3470 return errReason, err
3471 }
3472 }
3473
3474 for entityID := range downstreamEntityMap {
3475 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3476 true)
3477 if err != nil {
3478 return errReason, err
3479 }
3480 }
3481 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3482 // device itself.
3483 // Unset the reset bit if option is specified
3484 for entityID := range upstreamEntityMap {
3485 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3486 false)
3487 if err != nil {
3488 return errReason, err
3489 }
3490 }
3491
3492 for entityID := range downstreamEntityMap {
3493 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3494 false)
3495 if err != nil {
3496 return errReason, err
3497 }
3498 }
3499 return extension.GetValueResponse_REASON_UNDEFINED, nil
3500}
3501
3502func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3503 mm.onuEthernetFrameExtendedPmLock.Lock()
3504 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3505 mm.isEthernetFrameExtendedPmOperationOngoing = val
3506}
3507
3508func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3509 mm.onuEthernetFrameExtendedPmLock.Lock()
3510 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3511 return mm.isEthernetFrameExtendedPmOperationOngoing
3512}
3513
3514// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3515func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3516 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3517 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3518 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303519 return &extension.SingleGetValueResponse{
3520 Response: &extension.GetValueResponse{
3521 Status: extension.GetValueResponse_ERROR,
3522 ErrReason: reason,
3523 },
3524 }
3525 }
3526 mm.onuEthernetFrameExtendedPmLock.RLock()
3527 if !mm.isDeviceReadyToCollectExtendedPmStats {
3528 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303529 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303530 }
3531 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303532
3533 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3534 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3535 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3536 }
3537 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3538 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3539
3540 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3541 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3542 if onuInfo.IsUniIndex != nil {
3543 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3544 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3545 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3546 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3547 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3548 break
3549 }
3550 }
3551 if len(downstreamEntityMap) == 0 {
3552 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3553 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3554 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3555 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3556 }
3557 } else {
3558 // make a copy of all downstream and upstream maps in the local ones
3559 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3560 upstreamEntityMap[entityID] = meEnt
3561 }
3562 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3563 downstreamEntityMap[entityID] = meEnt
3564 }
3565 }
3566 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3567 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3568 // Reset the metrics first for all required me's
3569 if onuInfo.Reset_ {
3570 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3571 if err != nil {
3572 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3573 log.Fields{"device-id": mm.deviceID})
3574 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3575 }
3576 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303577 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3578 var pmUpstream extension.OmciEthernetFrameExtendedPm
3579 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303580 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3581 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3582 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3583 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303584 if !onuInfo.Reset_ {
3585 for entityID, meEnt := range upstreamEntityMap {
3586 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3587 var receivedMask uint16
3588 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3589 if receivedMask == 0 {
3590 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303591 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3592 // It might be possible that still some downstream pms are supported and hence we need to continue
3593 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3594 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303595 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303596 // Aggregate the result for upstream
3597 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3598 } else {
3599 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303600 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303601 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303602
Himani Chawlaee10b542021-09-20 16:46:40 +05303603 for entityID, meEnt := range downstreamEntityMap {
3604 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3605 var receivedMask uint16
3606 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303607 if receivedMask == 0 {
3608 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3609 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3610 // Stop collecting downstream counters for other ME's.
3611 break
3612 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303613 // Aggregate the result for downstream
3614 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3615 } else {
3616 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3617 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303618 }
3619 }
3620 singleValResp := extension.SingleGetValueResponse{
3621 Response: &extension.GetValueResponse{
3622 Status: extension.GetValueResponse_OK,
3623 Response: &extension.GetValueResponse_OnuCounters{
3624 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303625 Upstream: &pmUpstream,
3626 Downstream: &pmDownstream,
3627 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303628 },
3629 },
3630 },
3631 }
3632 return &singleValResp
3633}
3634
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303635// nolint:unparam
Himani Chawlaee10b542021-09-20 16:46:40 +05303636func (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 +05303637 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003638 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 +05303639
3640 classID = mm.supportedEthernetFrameExtendedPMClass
3641 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3642 if classID == me.EthernetFrameExtendedPmClassID {
3643 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3644 }
3645 ethPMData := make(map[string]uint64)
3646 var sumReceivedMask uint16
3647 for mask := range attributeMaskList {
3648 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3649 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003650 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303651 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303652 }
3653 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3654 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3655 //populate all counters as failure and return
3656 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3657 break
3658 }
3659 }
3660 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303661 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303662}
3663
3664// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003665func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303666 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3667 var meAttributes me.AttributeValueMap
3668 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003669 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303670 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003671 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303672 return extension.GetValueResponse_INTERNAL_ERROR, err
3673 }
3674 select {
3675 case meAttributes = <-mm.extendedPmMeChan:
3676 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003677 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3678 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303679 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003680 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303681 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3682 }
3683 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3684 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3685 *sumReceivedMask += mask
3686 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3687 } else {
3688 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3689 *sumReceivedMask += mask
3690 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3691 }
3692
3693 return extension.GetValueResponse_REASON_UNDEFINED, nil
3694}
3695
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003696func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303697 sourceMap := maskToEthernetFrameExtendedPM64Bit
3698 errorCounterValue := UnsupportedCounterValue64bit
3699 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3700 sourceMap = maskToEthernetFrameExtendedPM32Bit
3701 errorCounterValue = UnsupportedCounterValue32bit
3702 }
3703 for _, value := range sourceMap {
3704 for _, k := range value {
3705 if _, ok := ethFrameExtPMData[k]; !ok {
3706 ethFrameExtPMData[k] = errorCounterValue
3707 }
3708 }
3709 }
3710}
3711
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303712// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003713func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303714 receivedMask := uint16(0)
3715 switch requestedAttributesMask {
3716 case 0x3F00:
3717 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3718 if _, ok := ethFrameExtPMData[k]; !ok {
3719 switch k {
3720 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003721 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303722 ethFrameExtPMData[k] = uint64(val.(uint32))
3723 receivedMask |= 0x2000
3724 } else if !ok {
3725 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3726 }
3727 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003728 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303729 ethFrameExtPMData[k] = uint64(val.(uint32))
3730 receivedMask |= 0x1000
3731 } else if !ok {
3732 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3733 }
3734 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003735 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303736 ethFrameExtPMData[k] = uint64(val.(uint32))
3737 receivedMask |= 0x800
3738 } else if !ok {
3739 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3740 }
3741 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003742 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303743 ethFrameExtPMData[k] = uint64(val.(uint32))
3744 receivedMask |= 0x400
3745 } else if !ok {
3746 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3747 }
3748 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003749 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303750 ethFrameExtPMData[k] = uint64(val.(uint32))
3751 receivedMask |= 0x200
3752 } else if !ok {
3753 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3754 }
3755 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003756 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303757 ethFrameExtPMData[k] = uint64(val.(uint32))
3758 receivedMask |= 0x100
3759 } else if !ok {
3760 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3761 }
3762 default:
3763 //do nothing
3764 }
3765 }
3766 }
3767 case 0x00FC:
3768 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3769 if _, ok := ethFrameExtPMData[k]; !ok {
3770 switch k {
3771 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003772 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303773 ethFrameExtPMData[k] = uint64(val.(uint32))
3774 receivedMask |= 0x80
3775 } else if !ok {
3776 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3777 }
3778 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003779 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303780 ethFrameExtPMData[k] = uint64(val.(uint32))
3781 receivedMask |= 0x40
3782 } else if !ok {
3783 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3784 }
3785 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003786 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303787 ethFrameExtPMData[k] = uint64(val.(uint32))
3788 receivedMask |= 0x20
3789 } else if !ok {
3790 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3791 }
3792 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003793 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303794 ethFrameExtPMData[k] = uint64(val.(uint32))
3795 receivedMask |= 0x10
3796 } else if !ok {
3797 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3798 }
3799 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003800 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303801 ethFrameExtPMData[k] = uint64(val.(uint32))
3802 receivedMask |= 0x8
3803 } else if !ok {
3804 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3805 }
3806 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003807 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303808 ethFrameExtPMData[k] = uint64(val.(uint32))
3809 receivedMask |= 0x4
3810 } else if !ok {
3811 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3812 }
3813 default:
3814 //do nothing
3815 }
3816 }
3817 }
3818 case 0x0003:
3819 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3820 if _, ok := ethFrameExtPMData[k]; !ok {
3821 switch k {
3822 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003823 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303824 ethFrameExtPMData[k] = uint64(val.(uint32))
3825 receivedMask |= 0x2
3826 } else if !ok {
3827 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3828 }
3829 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003830 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303831 ethFrameExtPMData[k] = uint64(val.(uint32))
3832 receivedMask |= 0x1
3833 } else if !ok {
3834 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3835 }
3836 default:
3837 //do nothing
3838 }
3839 }
3840 }
3841 default:
3842 //do nothing
3843 }
3844 return receivedMask
3845}
3846
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303847// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003848func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303849 receivedMask := uint16(0)
3850 switch requestedAttributesMask {
3851 case 0x3800:
3852 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3853 if _, ok := ethFrameExtPMData[k]; !ok {
3854 switch k {
3855 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003856 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303857 ethFrameExtPMData[k] = val.(uint64)
3858 receivedMask |= 0x2000
3859 } else if !ok {
3860 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3861 }
3862 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003863 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303864 ethFrameExtPMData[k] = val.(uint64)
3865 receivedMask |= 0x1000
3866 } else if !ok {
3867 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3868 }
3869 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003870 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303871 ethFrameExtPMData[k] = val.(uint64)
3872 receivedMask |= 0x800
3873 } else if !ok {
3874 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3875 }
3876 }
3877 }
3878 }
3879 case 0x0700:
3880 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3881 if _, ok := ethFrameExtPMData[k]; !ok {
3882 switch k {
3883 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003884 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303885 ethFrameExtPMData[k] = val.(uint64)
3886 receivedMask |= 0x400
3887 } else if !ok {
3888 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3889 }
3890 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003891 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303892 ethFrameExtPMData[k] = val.(uint64)
3893 receivedMask |= 0x200
3894 } else if !ok {
3895 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3896 }
3897 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003898 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303899 ethFrameExtPMData[k] = val.(uint64)
3900 receivedMask |= 0x100
3901 } else if !ok {
3902 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3903 }
3904 }
3905 }
3906 }
3907 case 0x00E0:
3908 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3909 if _, ok := ethFrameExtPMData[k]; !ok {
3910 switch k {
3911 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003912 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303913 ethFrameExtPMData[k] = val.(uint64)
3914 receivedMask |= 0x80
3915 } else if !ok {
3916 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3917 }
3918 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003919 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303920 ethFrameExtPMData[k] = val.(uint64)
3921 receivedMask |= 0x40
3922 } else if !ok {
3923 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3924 }
3925 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003926 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303927 ethFrameExtPMData[k] = val.(uint64)
3928 receivedMask |= 0x20
3929 } else if !ok {
3930 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3931 }
3932 }
3933 }
3934 }
3935 case 0x001C:
3936 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3937 if _, ok := ethFrameExtPMData[k]; !ok {
3938 switch k {
3939 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003940 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303941 ethFrameExtPMData[k] = val.(uint64)
3942 receivedMask |= 0x10
3943 } else if !ok {
3944 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3945 }
3946 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003947 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303948 ethFrameExtPMData[k] = val.(uint64)
3949 receivedMask |= 0x8
3950 } else if !ok {
3951 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3952 }
3953 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003954 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303955 ethFrameExtPMData[k] = val.(uint64)
3956 receivedMask |= 0x4
3957 } else if !ok {
3958 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3959 }
3960 default:
3961 //do nothing
3962 }
3963 }
3964 }
3965 case 0x0003:
3966 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3967 if _, ok := ethFrameExtPMData[k]; !ok {
3968 switch k {
3969 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003970 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303971 ethFrameExtPMData[k] = val.(uint64)
3972 receivedMask |= 0x2
3973 } else if !ok {
3974 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3975 }
3976 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003977 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303978 ethFrameExtPMData[k] = val.(uint64)
3979 receivedMask |= 0x1
3980 } else if !ok {
3981 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3982 }
3983 default:
3984 //do nothing
3985 }
3986 }
3987 }
3988 }
3989 return receivedMask
3990}
3991
Himani Chawlaee10b542021-09-20 16:46:40 +05303992func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3993 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303994 errorCounterValue := UnsupportedCounterValue64bit
3995 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3996 errorCounterValue = UnsupportedCounterValue32bit
3997 }
3998 var pmDataOut extension.OmciEthernetFrameExtendedPm
3999 if aggregate {
4000 if pmData.DropEvents != errorCounterValue {
4001 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
4002 } else {
4003 pmDataOut.DropEvents = pmData.DropEvents
4004 }
4005 if pmData.Octets != errorCounterValue {
4006 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
4007 } else {
4008 pmDataOut.Octets = pmData.Octets
4009 }
4010 if pmData.Frames != errorCounterValue {
4011 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
4012 } else {
4013 pmDataOut.Frames = pmData.Frames
4014 }
4015 if pmData.BroadcastFrames != errorCounterValue {
4016 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
4017 } else {
4018 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
4019 }
4020 if pmData.MulticastFrames != errorCounterValue {
4021 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
4022 } else {
4023 pmDataOut.MulticastFrames = pmData.MulticastFrames
4024 }
4025 if pmData.CrcErroredFrames != errorCounterValue {
4026 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
4027 } else {
4028 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
4029 }
4030 if pmData.UndersizeFrames != errorCounterValue {
4031 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
4032 } else {
4033 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
4034 }
4035 if pmData.OversizeFrames != errorCounterValue {
4036 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
4037 } else {
4038 pmDataOut.OversizeFrames = pmData.OversizeFrames
4039 }
4040 if pmData.Frames_64Octets != errorCounterValue {
4041 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
4042 } else {
4043 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
4044 }
4045 if pmData.Frames_65To_127Octets != errorCounterValue {
4046 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
4047 } else {
4048 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
4049 }
4050 if pmData.Frames_128To_255Octets != errorCounterValue {
4051 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
4052 } else {
4053 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
4054 }
4055 if pmData.Frames_256To_511Octets != errorCounterValue {
4056 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
4057 } else {
4058 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
4059 }
4060 if pmData.Frames_512To_1023Octets != errorCounterValue {
4061 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
4062 } else {
4063 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
4064 }
4065 if pmData.Frames_1024To_1518Octets != errorCounterValue {
4066 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
4067 } else {
4068 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
4069 }
4070 } else {
4071 pmDataOut.DropEvents = pmDataIn["drop_events"]
4072 pmDataOut.Octets = pmDataIn["octets"]
4073 pmDataOut.Frames = pmDataIn["frames"]
4074 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
4075 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
4076 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
4077 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
4078 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
4079 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
4080 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
4081 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
4082 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
4083 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
4084 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
4085 }
4086 return pmDataOut
4087}
4088
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05304089//nolint:unparam
Himani Chawlaee10b542021-09-20 16:46:40 +05304090func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304091 controlBlock := make([]uint16, 8)
4092 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
4093 controlBlock[0] = 0
4094 // Next two bytes are for the parent class ID
4095 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
4096 // Next two bytes are for the parent me instance id
4097 controlBlock[2] = entityID
4098 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05304099 if reset {
4100 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
4101 } else {
4102 controlBlock[3] = 0
4103 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05304104 // Next two bytes are for tca disable
4105 controlBlock[4] = 0x4000 //tca global disable
4106 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
4107 if upstream {
4108 controlBlock[5] = 1 << 0
4109 } else {
4110 controlBlock[5] = (1 << 0) | (1 << 1)
4111 }
4112 // Next two bytes are for tci - does not matter here
4113 controlBlock[6] = 0
4114 // Next two bytes are for reserved bits - does not matter here
4115 controlBlock[7] = 0
4116 return controlBlock
4117}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00004118
Girish Gowdraabcceb12022-04-13 23:35:22 -07004119// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
4120func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
4121 mm.OnuMetricsManagerLock.RLock()
4122 defer mm.OnuMetricsManagerLock.RUnlock()
4123 return mm.deviceDeletionInProgress
4124}
4125
4126// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
4127func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
4128 mm.OnuMetricsManagerLock.Lock()
4129 defer mm.OnuMetricsManagerLock.Unlock()
4130 mm.deviceDeletionInProgress = true
4131}
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +05304132
4133// Obtain the ONU GEM counters for the ONU device
4134func (mm *OnuMetricsManager) GetONUGEMCounters(ctx context.Context) *extension.SingleGetValueResponse {
4135
4136 resp := extension.SingleGetValueResponse{
4137 Response: &extension.GetValueResponse{
4138 Status: extension.GetValueResponse_OK,
4139 Response: &extension.GetValueResponse_OnuAllocGemStatsResponse{
4140 OnuAllocGemStatsResponse: &extension.GetOnuAllocGemHistoryResponse{},
4141 },
4142 },
4143 }
4144
4145 if mm.GetdeviceDeletionInProgress() {
4146 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
4147 return nil
4148 }
4149
4150 mm.OnuMetricsManagerLock.RLock()
4151 defer mm.OnuMetricsManagerLock.RUnlock()
4152
4153 gemtoAllocId := mm.pDeviceHandler.GetOnuTP().GetGEMportToAllocIDMappingForONU(ctx, mm.deviceID)
4154 allocIDtoGem := make(map[uint16][]uint16)
4155 for key, value := range gemtoAllocId {
4156 allocIDtoGem[value] = append(allocIDtoGem[value], key)
4157 }
4158
4159 for allocID, gemSlice := range allocIDtoGem {
4160 logger.Infow(ctx, "AllocID", log.Fields{"alloc-id": allocID})
4161 allocIdGemData := extension.OnuAllocGemHistoryData{
4162 OnuAllocIdInfo: &extension.OnuAllocHistoryData{},
4163 GemPortInfo: []*extension.OnuGemPortHistoryData{},
4164 }
4165 allocIdGemData.OnuAllocIdInfo.AllocId = uint32(allocID)
4166
4167 // Loop through each element in the slice
4168 for _, gem := range gemSlice {
4169 logger.Debugw(ctx, "Collecting stats for Gem: ", log.Fields{"GEMID": gem})
4170 if metricInfo := mm.collectGemHistoryData(ctx, gem); metricInfo != nil {
4171 logger.Infow(ctx, "Metricinfo for GEM", log.Fields{"GEMID": gem, "metricInfo": metricInfo})
4172 gemHistoryData := extension.OnuGemPortHistoryData{}
4173 gemHistoryData.GemId = uint32(gem)
4174 gemHistoryData.TransmittedGEMFrames = uint32(metricInfo.GetMetrics()["transmitted_gem_frames"])
4175 gemHistoryData.ReceivedGEMFrames = uint32(metricInfo.GetMetrics()["received_gem_frames"])
4176 gemHistoryData.ReceivedPayloadBytes = uint32(metricInfo.GetMetrics()["received_payload_bytes"])
4177 gemHistoryData.TransmittedPayloadBytes = uint32(metricInfo.GetMetrics()["transmitted_payload_bytes"])
4178 gemHistoryData.EncryptionKeyErrors = uint32(metricInfo.GetMetrics()["encryption_key_errors"])
4179 allocIdGemData.GemPortInfo = append(allocIdGemData.GemPortInfo, &gemHistoryData)
4180 logger.Debugw(ctx, " allocIdGemData value ", log.Fields{"AllocIDGemData": allocIdGemData})
4181
4182 }
4183 }
4184 resp.Response.GetOnuAllocGemStatsResponse().OnuAllocGemHistoryData = append(resp.Response.GetOnuAllocGemStatsResponse().OnuAllocGemHistoryData, &allocIdGemData)
4185 }
4186
4187 logger.Debugw(ctx, "Request to fetch GEM Performance Counters ", log.Fields{"device-id": mm.deviceID, "response": resp})
4188 return &resp
4189
4190}