blob: c333ba49c6c86731309994050300ebbb50c06c48 [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
pnalmas6d6b7d72025-10-23 16:34:22 +0530262type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int, bool) error
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800263
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
pnalmas6d6b7d72025-10-23 16:34:22 +05301236 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
1237 mm.l2PmChan <- meAttributes
1238 return nil
1239 case me.FecPerformanceMonitoringHistoryDataClassID:
1240 mm.opticalMetricsChan <- meAttributes
1241 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05301242 default:
1243 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001244 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301245 }
1246 } else {
1247 meAttributes := msgObj.Attributes
1248 switch msgObj.EntityClass {
1249 case me.EthernetFrameExtendedPmClassID,
1250 me.EthernetFrameExtendedPm64BitClassID:
1251 // not all counters may be supported in which case we have seen some ONUs throwing
1252 // AttributeFailure error code, while correctly populating other counters it supports
1253 mm.extendedPmMeChan <- meAttributes
1254 return nil
pnalmas6d6b7d72025-10-23 16:34:22 +05301255 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
1256 // Handle attribute failure for GemPort data similar to Extended PM
1257 mm.l2PmChan <- meAttributes
1258 return nil
1259 case me.FecPerformanceMonitoringHistoryDataClassID:
1260 // Handle attribute failure for FEC data similar to Extended PM
1261 mm.opticalMetricsChan <- meAttributes
1262 return nil
1263
Himani Chawla43f95ff2021-06-03 00:24:12 +05301264 default:
1265 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001266 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301267 }
1268 }
1269 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1270}
1271
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001272func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001273 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1274 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001275 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1276 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 -08001277 }
1278 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1279 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001280 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1281 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 -08001282 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001283 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001284 if msgObj.Result == me.Success {
1285 switch msgObj.EntityClass {
1286 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001287 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001288 mm.syncTimeResponseChan <- true
1289 return nil
1290 default:
1291 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001292 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001293 }
1294 }
1295 mm.syncTimeResponseChan <- false
1296 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1297 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001298}
1299
Himani Chawlaee10b542021-09-20 16:46:40 +05301300func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1301 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1302 if msgLayer == nil {
1303 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1304 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1305 }
1306 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1307 if !msgOk {
1308 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1309 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1310 }
1311 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1312 switch msgObj.EntityClass {
1313 case me.EthernetFrameExtendedPmClassID,
1314 me.EthernetFrameExtendedPm64BitClassID:
1315 mm.extendedPMMeResponseChan <- msgObj.Result
1316 return nil
1317 default:
1318 logger.Errorw(ctx, "unhandled omci set response message",
1319 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1320 }
1321 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1322}
1323
Girish Gowdrae09a6202021-01-12 18:10:59 -08001324// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001325func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001326 // flush commMetricsChan
1327 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001328 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001329 logger.Debug(ctx, "flushed common metrics channel")
1330 default:
1331 }
1332
1333 // flush opticalMetricsChan
1334 select {
1335 case <-mm.opticalMetricsChan:
1336 logger.Debug(ctx, "flushed optical metrics channel")
1337 default:
1338 }
1339
1340 // flush uniStatusMetricsChan
1341 select {
1342 case <-mm.uniStatusMetricsChan:
1343 logger.Debug(ctx, "flushed uni status metrics channel")
1344 default:
1345 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001346
1347 // flush syncTimeResponseChan
1348 select {
1349 case <-mm.syncTimeResponseChan:
1350 logger.Debug(ctx, "flushed sync time response channel")
1351 default:
1352 }
1353
1354 // flush l2PmChan
1355 select {
1356 case <-mm.l2PmChan:
1357 logger.Debug(ctx, "flushed L2 PM collection channel")
1358 default:
1359 }
1360
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001361 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001362 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001363 case <-mm.StopTicks:
1364 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001365 default:
1366 }
1367
1368}
1369
1370// ** L2 PM FSM Handlers start **
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301371// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001372func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001373 if mm.GetdeviceDeletionInProgress() {
1374 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1375 return
1376 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001377
Girish Gowdrae0140f02021-02-02 16:55:09 -08001378 // Loop through all the group metrics
1379 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1380 // list of active L2 PM list then mark it for creation
1381 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1382 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001383 mm.OnuMetricsManagerLock.Lock()
1384 for n, g := range mm.GroupMetricMap {
1385 if g.IsL2PMCounter { // it is a l2 pm counter
1386 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001387 found := false
1388 inner1:
1389 for _, v := range mm.activeL2Pms {
1390 if v == n {
1391 found = true // metric already present in active l2 pm list
1392 break inner1
1393 }
1394 }
1395 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001396 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001397 }
1398 } else { // metric not enabled.
1399 found := false
1400 inner2:
1401 for _, v := range mm.activeL2Pms {
1402 if v == n {
1403 found = true // metric is found in active l2 pm list
1404 break inner2
1405 }
1406 }
1407 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001408 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001409 }
1410 }
1411 }
1412 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001413 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001414 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001415 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001416 go func() {
1417 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001418 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1419 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001420 }
1421 }()
1422}
1423
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301424// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001425func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001426 if mm.GetdeviceDeletionInProgress() {
1427 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1428 return
1429 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001430 // Sync time with the ONU to establish 15min boundary for PM collection.
1431 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001432 // device could be deleted while waiting on sync time response
1433 if mm.GetdeviceDeletionInProgress() {
1434 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1435 return
1436 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001437 go func() {
1438 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1439 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001440 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1441 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001442 }
1443 }()
1444 }
1445 // Initiate a tick generation routine every L2PmCollectionInterval
1446 go mm.generateTicks(ctx)
1447
1448 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001449 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1450 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001451 }
1452 }()
1453}
1454
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001455func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001456 // 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 +00001457 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001458 mm.activeL2Pms = nil
1459 mm.l2PmToAdd = nil
1460 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001461 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001462 // If the FSM was stopped, then clear PM data from KV store
1463 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001464 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001465 _ = mm.clearPmGroupData(ctx) // ignore error
1466 }
1467
Girish Gowdraabcceb12022-04-13 23:35:22 -07001468 if mm.GetdeviceDeletionInProgress() {
praneeth nalmasf405e962023-08-07 15:02:03 +05301469 mm.onuOpticalMetricstimer.Stop()
1470 mm.onuUniStatusMetricstimer.Stop()
1471 mm.opticalMetricsDelCommChan <- true
1472 mm.uniMetricsDelCommChan <- true
Girish Gowdraabcceb12022-04-13 23:35:22 -07001473 mm.pDeviceHandler = nil
1474 mm.pOnuDeviceEntry = nil
1475 mm.GarbageCollectionComplete <- true
1476 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001477}
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301478
1479// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001480func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1481 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001482 if mm.GetdeviceDeletionInProgress() {
1483 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1484 return
1485 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001486
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001487 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001488 numOfPmToDelete := len(mm.l2PmToDelete)
1489 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001490 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001491
1492 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001493 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 -08001494 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001495 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1496 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001497 }
1498 }()
1499 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001500 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 -08001501 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001502 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1503 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001504 }
1505 }()
1506 }
1507}
1508
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301509// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001510func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1511 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001512 if mm.GetdeviceDeletionInProgress() {
1513 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1514 return
1515 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001516 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001517 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001518 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1519 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001520 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001521
1522 for _, n := range copyOfActiveL2Pms {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05301523 select {
1524 case _, ok := <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
1525 if !ok {
1526 logger.Warnw(ctx, "Deleting the device, stopping l2PmFsmCollectData for the device ", log.Fields{"device-id": mm.deviceID})
1527 return
Girish Gowdrae0140f02021-02-02 16:55:09 -08001528 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001529 default:
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05301530 var metricInfoSlice []*voltha.MetricInformation
1531
1532 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1533 mm.OnuMetricsManagerLock.RLock()
1534 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1535 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1536 mm.OnuMetricsManagerLock.RUnlock()
1537
1538 switch n {
1539 case EthernetBridgeHistoryName:
1540 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
1541 for _, entityID := range copyOfEntityIDs {
1542 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1543 metricInfoSlice = append(metricInfoSlice, metricInfo)
1544 }
1545 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1546 metricInfoSlice = append(metricInfoSlice, metricInfo)
1547 }
1548 }
1549 case EthernetUniHistoryName:
1550 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
1551 for _, entityID := range copyOfEntityIDs {
1552 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1553 metricInfoSlice = append(metricInfoSlice, metricInfo)
1554 }
1555 }
1556
1557 case FecHistoryName:
1558 for _, entityID := range copyOfEntityIDs {
pnalmas6d6b7d72025-10-23 16:34:22 +05301559 if metricInfo := mm.collectFecHistoryData(ctx, entityID, false); metricInfo != nil { // upstream
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05301560 metricInfoSlice = append(metricInfoSlice, metricInfo)
1561 }
1562 }
1563 case GemPortHistoryName:
1564 for _, entityID := range copyOfEntityIDs {
pnalmas6d6b7d72025-10-23 16:34:22 +05301565 if metricInfo := mm.collectGemHistoryData(ctx, entityID, false); metricInfo != nil { // upstream
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05301566 metricInfoSlice = append(metricInfoSlice, metricInfo)
1567 }
1568 }
1569
1570 default:
1571 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
1572 }
1573 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001574 }
1575 }
1576 // Does not matter we send success or failure here.
1577 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1578 // we have not exceed max attempts to collect the PM data)
1579 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001580 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1581 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001582 }
1583 }()
1584}
1585
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301586// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001587func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001588 if mm.GetdeviceDeletionInProgress() {
1589 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1590 return nil
1591 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001592 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001593 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001594 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1595 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001596 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001597
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001598 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001599 for _, n := range copyOfL2PmToAdd {
1600 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001601 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1602 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001603 switch n {
1604 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001605 // 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 +05301606 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001607 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001608 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001609 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001610 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1611 inner1:
1612 // retry L2PmCreateAttempts times to create the instance of PM
1613 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001614 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1615 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001616 if err != nil {
1617 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001618 log.Fields{"device-id": mm.deviceID})
1619 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001620 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001621 go func(p_pmFsm *cmn.AdapterFsm) {
1622 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001623 }(pPMFsm)
1624 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301625 return fmt.Errorf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
1626 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001627 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001628 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1629 atLeastOneSuccess = true
1630 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1631 break inner1
1632 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001633 if mm.GetdeviceDeletionInProgress() {
1634 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1635 return nil
1636 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001637 }
1638 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1639 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001640 }
1641 }
1642 }
1643 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001644 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1645 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001646 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001647 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001648 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1649 inner2:
1650 // retry L2PmCreateAttempts times to create the instance of PM
1651 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001652 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1653 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001654 if err != nil {
1655 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001656 log.Fields{"device-id": mm.deviceID})
1657 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301658 return fmt.Errorf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
1659 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001660 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001661 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1662 atLeastOneSuccess = true
1663 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1664 break inner2
1665 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001666 if mm.GetdeviceDeletionInProgress() {
1667 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1668 return nil
1669 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001670 }
1671 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1672 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001673 }
1674 }
1675 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001676 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001677 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001678 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001679 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1680 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001681 if err != nil {
1682 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001683 log.Fields{"device-id": mm.deviceID})
1684 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301685 return fmt.Errorf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
1686 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001687 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001688 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1689 inner3:
1690 // retry L2PmCreateAttempts times to create the instance of PM
1691 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1692 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1693 atLeastOneSuccess = true
1694 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1695 break inner3
1696 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001697 if mm.GetdeviceDeletionInProgress() {
1698 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1699 return nil
1700 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001701 }
1702 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1703 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001704 }
1705 }
1706 case GemPortHistoryName:
1707
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001708 mm.OnuMetricsManagerLock.RLock()
1709 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1710 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1711 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001712
1713 if len(copyOfGemPortInstIDsToAdd) == 0 {
1714 // If there are no gemport history MEs to be created, just skip further processing
1715 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1716 // 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 +00001717 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001718 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001719 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001720 continue
1721 }
1722
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001723 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001724 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1725 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001726 if err != nil {
1727 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001728 log.Fields{"device-id": mm.deviceID})
1729 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301730 return fmt.Errorf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
1731 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001732 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001733 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1734 inner4:
1735 // retry L2PmCreateAttempts times to create the instance of PM
1736 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1737 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1738 atLeastOneSuccess = true
1739 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1740 break inner4
1741 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001742 if mm.GetdeviceDeletionInProgress() {
1743 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1744 return nil
1745 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001746 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001747 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1748 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1749 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001750 }
1751
Girish Gowdrae0140f02021-02-02 16:55:09 -08001752 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001753 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001754 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001755 // 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
1756 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001757 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001758 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001759 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1760 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001761 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001762 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1763 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001764 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 +00001765 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001766 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001767 // 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 -08001768 // 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 +00001769 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001770 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001771 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001772 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001773
Girish Gowdrae0140f02021-02-02 16:55:09 -08001774 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001775 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001776 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001777 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001778 }
1779 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001780 mm.OnuMetricsManagerLock.RLock()
1781 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1782 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001783 // Does not matter we send success or failure here.
1784 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1785 // we have not exceed max attempts to create the PM ME)
1786 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001787 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1788 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001789 }
1790 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001791 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001792}
1793
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301794// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001795func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001796 if mm.GetdeviceDeletionInProgress() {
1797 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1798 return nil
1799 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001800 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001801 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001802 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1803 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001804 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001805
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001806 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001807 for _, n := range copyOfL2PmToDelete {
1808 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001809 cnt := 0
1810 atLeastOneDeleteFailure := false
1811
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001812 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1813 mm.OnuMetricsManagerLock.RLock()
1814 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1815 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1816 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001817
1818 if len(copyOfEntityIDs) == 0 {
1819 // 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 +00001820 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001821 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1822 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1823 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 +00001824 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001825 continue
1826 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001827 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001828 switch n {
1829 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001830 // 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 +05301831 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001832 for _, entityID := range copyOfEntityIDs {
1833 inner1:
1834 // retry L2PmDeleteAttempts times to delete the instance of PM
1835 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001836 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1837 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001838 if err != nil {
1839 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001840 log.Fields{"device-id": mm.deviceID})
1841 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001842 if pPMFsm != nil {
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301843 //nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001844 go func(p_pmFsm *cmn.AdapterFsm) {
1845 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001846 }(pPMFsm)
1847 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301848 return fmt.Errorf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
1849 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001850 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001851 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1852 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001853 if mm.GetdeviceDeletionInProgress() {
1854 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1855 return nil
1856 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001857 atLeastOneDeleteFailure = true
1858 } else {
1859 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1860 break inner1
1861 }
1862 }
1863 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1864 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001865 }
1866 }
1867 }
1868 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001869 for _, entityID := range copyOfEntityIDs {
1870 inner2:
1871 // retry L2PmDeleteAttempts times to delete the instance of PM
1872 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001873 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1874 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001875 if err != nil {
1876 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001877 log.Fields{"device-id": mm.deviceID})
1878 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001879 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001880 go func(p_pmFsm *cmn.AdapterFsm) {
1881 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001882 }(pmFsm)
1883 return err
1884 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301885 return fmt.Errorf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
1886 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001887 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001888 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001889 if mm.GetdeviceDeletionInProgress() {
1890 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1891 return nil
1892 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001893 atLeastOneDeleteFailure = true
1894 } else {
1895 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001896 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001897 }
1898 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001899 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1900 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1901 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001902 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001903 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001904 for _, entityID := range copyOfEntityIDs {
1905 inner3:
1906 // retry L2PmDeleteAttempts times to delete the instance of PM
1907 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001908 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1909 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001910 if err != nil {
1911 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001912 log.Fields{"device-id": mm.deviceID})
1913 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301914 return fmt.Errorf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
1915 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001916 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301917 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001918 if mm.GetdeviceDeletionInProgress() {
1919 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1920 return nil
1921 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001922 atLeastOneDeleteFailure = true
1923 } else {
1924 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1925 break inner3
1926 }
1927 }
1928 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1929 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001930 }
1931 }
1932 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001933 for _, entityID := range copyOfEntityIDs {
1934 inner4:
1935 // retry L2PmDeleteAttempts times to delete the instance of PM
1936 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001937 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1938 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001939 if err != nil {
1940 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001941 log.Fields{"device-id": mm.deviceID})
1942 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301943 return fmt.Errorf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
1944 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001945 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001946 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001947 if mm.GetdeviceDeletionInProgress() {
1948 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1949 return nil
1950 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001951 atLeastOneDeleteFailure = true
1952 } else {
1953 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1954 break inner4
1955 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001956 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001957 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1958 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1959 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001960 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001961 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001962 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001963 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001964 // If we could not completely clean up the PM ME then just give up.
1965 if atLeastOneDeleteFailure {
1966 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001967 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001968 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001969 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001970 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1971 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1972 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001973 mm.GroupMetricMap[n].Enabled = false
1974 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001975 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001976 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001977 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001978 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1979 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001980 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001981 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1982 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001983 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 +00001984 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001985 }
1986 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001987 mm.OnuMetricsManagerLock.RLock()
1988 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1989 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001990 // Does not matter we send success or failure here.
1991 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1992 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001993 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1994 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001995 }
1996 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001997 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001998}
1999
2000// ** L2 PM FSM Handlers end **
2001
2002// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002003func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07002004 if mm.GetdeviceDeletionInProgress() {
2005 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
2006 return nil
2007 }
2008
2009 if !mm.GetOmciProcessingStatus() {
2010 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})
2011 return fmt.Errorf("omci-resp-processor-not-running")
2012 }
2013
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002014 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
2015 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002016 return err
2017 }
2018
2019 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002020 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
2021 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
2022 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002023 case syncTimeRes := <-mm.syncTimeResponseChan:
2024 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002025 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002026 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002027 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002028 return nil
2029 }
2030}
2031
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002032func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002033 var mEnt *me.ManagedEntity
2034 var omciErr me.OmciErrors
2035 var classID me.ClassID
2036 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002037 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002038 meParam := me.ParamData{EntityID: entityID}
2039 if upstream {
2040 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002041 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002042 return nil
2043 }
2044 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
2045 } else {
2046 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002047 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002048 return nil
2049 }
2050 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
2051 }
2052
Girish Gowdrae0140f02021-02-02 16:55:09 -08002053 intervalEndTime := -1
2054 ethPMHistData := make(map[string]float32)
pnalmas6d6b7d72025-10-23 16:34:22 +05302055 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime, false); err != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002056 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002057 }
2058
2059 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
2060 ethPMHistData["class_id"] = float32(classID)
2061 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
2062 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
2063 ethPMHistData["parent_entity_id"] = float32(entityID)
2064 if upstream {
2065 ethPMHistData["upstream"] = float32(1)
2066 } else {
2067 ethPMHistData["upstream"] = float32(0)
2068 }
2069
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002070 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002071
Girish Gowdrae0140f02021-02-02 16:55:09 -08002072 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002073 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002074 return &metricInfo
2075}
2076
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002077func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002078 var mEnt *me.ManagedEntity
2079 var omciErr me.OmciErrors
2080 var classID me.ClassID
2081 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002082 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002083 meParam := me.ParamData{EntityID: entityID}
2084 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002085 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002086 return nil
2087 }
2088 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
2089
Girish Gowdrae0140f02021-02-02 16:55:09 -08002090 intervalEndTime := -1
2091 ethUniHistData := make(map[string]float32)
pnalmas6d6b7d72025-10-23 16:34:22 +05302092 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime, false); err != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002093 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002094 }
2095
2096 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2097 ethUniHistData["class_id"] = float32(classID)
2098 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
2099
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002100 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002101
Girish Gowdrae0140f02021-02-02 16:55:09 -08002102 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002103 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002104 return &metricInfo
2105}
2106
pnalmas6d6b7d72025-10-23 16:34:22 +05302107func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16, isCurrent bool) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002108 var mEnt *me.ManagedEntity
2109 var omciErr me.OmciErrors
2110 var classID me.ClassID
2111 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002112 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002113 meParam := me.ParamData{EntityID: entityID}
2114 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002115 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002116 return nil
2117 }
2118 classID = me.FecPerformanceMonitoringHistoryDataClassID
2119
2120 intervalEndTime := -1
2121 fecHistData := make(map[string]float32)
pnalmas6d6b7d72025-10-23 16:34:22 +05302122 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime, isCurrent); err != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002123 return nil
2124 }
2125
2126 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2127 fecHistData["class_id"] = float32(classID)
2128 fecHistData["interval_end_time"] = float32(intervalEndTime)
2129
2130 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2131
2132 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002133 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002134 return &metricInfo
2135}
2136
pnalmas6d6b7d72025-10-23 16:34:22 +05302137func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16, isCurrent bool) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002138 var mEnt *me.ManagedEntity
2139 var omciErr me.OmciErrors
2140 var classID me.ClassID
2141 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002142 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002143 meParam := me.ParamData{EntityID: entityID}
2144 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002145 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002146 return nil
2147 }
2148 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2149
2150 intervalEndTime := -1
2151 gemHistData := make(map[string]float32)
pnalmas6d6b7d72025-10-23 16:34:22 +05302152 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime, isCurrent); err != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002153 return nil
2154 }
2155
2156 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2157 gemHistData["class_id"] = float32(classID)
2158 gemHistData["interval_end_time"] = float32(intervalEndTime)
2159
2160 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2161
2162 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002163 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002164 return &metricInfo
2165}
2166
Girish Gowdrae0140f02021-02-02 16:55:09 -08002167// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002168func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
pnalmas6d6b7d72025-10-23 16:34:22 +05302169 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int, isCurrent bool) error {
2170 upstream := classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002171 // 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 +00002172 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
pnalmas6d6b7d72025-10-23 16:34:22 +05302173 var meInstance *me.ManagedEntity
2174 var err error
2175
2176 // Use GetCurrentDataMEInstance if isCurrent is true, otherwise use GetMeInstance
2177 if isCurrent {
2178 meInstance, err = mm.GetCurrentDataMEInstance(ctx, classID, entityID, requestedAttributes,
2179 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2180 } else {
2181 meInstance, err = mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
2182 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2183 }
2184
ozgecanetsiab36ed572021-04-01 10:38:48 +03002185 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302186 if CheckMeInstanceStatusCode(err) {
2187 return err // Device is being deleted, so we stop processing
2188 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002189 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2190 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002191 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002192 go func(p_pmFsm *cmn.AdapterFsm) {
2193 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002194 }(pmFsm)
2195 return err
2196 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302197 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002198 }
2199 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002200 select {
2201 case meAttributes = <-mm.l2PmChan:
2202 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002203 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2204 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002205 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002206 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002207 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002208 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302209 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2210 logger.Warnw(ctx, "Deleting the device, stopping Ethernet Performance metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2211 return fmt.Errorf("deleting the device, stopping Ethernet Performance metrics collection for the device %v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002212 }
2213 // 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 -08002214 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002215 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002216 }
2217 }
2218 for k := range EthernetBridgeHistory {
2219 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2220 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2221 if _, ok := ethPMHistData[k]; !ok {
2222 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002223 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002224 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002225 ethPMHistData[k] = float32(val.(uint16))
2226 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002227 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002228 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002229 ethPMHistData[k] = float32(val.(uint32))
2230 }
2231 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002232 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002233 ethPMHistData[k] = float32(val.(uint32))
2234 }
2235 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002236 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002237 ethPMHistData[k] = float32(val.(uint32))
2238 }
2239 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002240 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002241 ethPMHistData[k] = float32(val.(uint32))
2242 }
2243 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002244 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002245 ethPMHistData[k] = float32(val.(uint32))
2246 }
2247 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002248 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002249 ethPMHistData[k] = float32(val.(uint32))
2250 }
2251 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002252 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002253 ethPMHistData[k] = float32(val.(uint32))
2254 }
2255 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002256 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002257 ethPMHistData[k] = float32(val.(uint32))
2258 }
2259 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002260 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002261 ethPMHistData[k] = float32(val.(uint32))
2262 }
2263 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002264 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002265 ethPMHistData[k] = float32(val.(uint32))
2266 }
2267 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002268 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002269 ethPMHistData[k] = float32(val.(uint32))
2270 }
2271 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002272 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002273 ethPMHistData[k] = float32(val.(uint32))
2274 }
2275 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002276 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002277 ethPMHistData[k] = float32(val.(uint32))
2278 }
2279 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002280 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002281 ethPMHistData[k] = float32(val.(uint32))
2282 }
2283 default:
2284 // do nothing
2285 }
2286 }
2287 }
2288 return nil
2289}
2290
2291// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002292func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
pnalmas6d6b7d72025-10-23 16:34:22 +05302293 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int, isCurrent bool) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002294 // 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 +03002295 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2296 requestedAttributes["IntervalEndTime"] = 0
2297 }
pnalmas6d6b7d72025-10-23 16:34:22 +05302298 var meInstance *me.ManagedEntity
2299 var err error
2300
2301 // Use GetCurrentDataMEInstance if isCurrent is true, otherwise use GetMeInstance
2302 if isCurrent {
2303 meInstance, err = mm.GetCurrentDataMEInstance(ctx, classID, entityID, requestedAttributes,
2304 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2305 } else {
2306 meInstance, err = mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
2307 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2308 }
2309
ozgecanetsiab36ed572021-04-01 10:38:48 +03002310 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302311 if CheckMeInstanceStatusCode(err) {
2312 return err // Device is being deleted, so we stop processing
2313 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002314 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2315 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302316 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002317 }
2318 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002319 select {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302320 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2321 logger.Warnw(ctx, "Deleting the device, stopping EthernetUniHistory metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2322 return fmt.Errorf("deleting the device, stopping EthernetUniHistory metrics collection for the device %v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002323 case meAttributes = <-mm.l2PmChan:
2324 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002325 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2326 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002327 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002328 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002329 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002330 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002331 }
2332 // 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 -08002333 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002334 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002335 }
2336 }
2337 for k := range EthernetUniHistory {
2338 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2339 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2340 if _, ok := ethPMUniHistData[k]; !ok {
2341 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002342 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002343 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002344 ethPMUniHistData[k] = float32(val.(uint16))
2345 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002346 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002347 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002348 ethPMUniHistData[k] = float32(val.(uint32))
2349 }
2350 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002351 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002352 ethPMUniHistData[k] = float32(val.(uint32))
2353 }
2354 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002355 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002356 ethPMUniHistData[k] = float32(val.(uint32))
2357 }
2358 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002359 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002360 ethPMUniHistData[k] = float32(val.(uint32))
2361 }
2362 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002363 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002364 ethPMUniHistData[k] = float32(val.(uint32))
2365 }
2366 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002367 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002368 ethPMUniHistData[k] = float32(val.(uint32))
2369 }
2370 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002371 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002372 ethPMUniHistData[k] = float32(val.(uint32))
2373 }
2374 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002375 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002376 ethPMUniHistData[k] = float32(val.(uint32))
2377 }
2378 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002379 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002380 ethPMUniHistData[k] = float32(val.(uint32))
2381 }
2382 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002383 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002384 ethPMUniHistData[k] = float32(val.(uint32))
2385 }
2386 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002387 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002388 ethPMUniHistData[k] = float32(val.(uint32))
2389 }
2390 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002391 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002392 ethPMUniHistData[k] = float32(val.(uint32))
2393 }
2394 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002395 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002396 ethPMUniHistData[k] = float32(val.(uint32))
2397 }
2398 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002399 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002400 ethPMUniHistData[k] = float32(val.(uint32))
2401 }
2402 default:
2403 // do nothing
2404 }
2405 }
2406 }
2407 return nil
2408}
2409
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002410// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002411func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
pnalmas6d6b7d72025-10-23 16:34:22 +05302412 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int, isCurrent bool) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002413 // 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 +00002414 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2415 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002416 }
pnalmas6d6b7d72025-10-23 16:34:22 +05302417 var meInstance *me.ManagedEntity
2418 var err error
2419
2420 // Use GetCurrentDataMEInstance if isCurrent is true, otherwise use GetMeInstance
2421 if isCurrent {
2422 meInstance, err = mm.GetCurrentDataMEInstance(ctx, classID, entityID, requestedAttributes,
2423 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2424 } else {
2425 meInstance, err = mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
2426 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2427 }
2428
ozgecanetsiab36ed572021-04-01 10:38:48 +03002429 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302430 if CheckMeInstanceStatusCode(err) {
2431 return err // Device is being deleted, so we stop processing
2432 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002433 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2434 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302435 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002436 }
2437 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002438 select {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302439 case _, ok := <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2440 if !ok {
2441 logger.Warnw(ctx, "Deleting the device, stopping FEC history metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2442 return fmt.Errorf("deleting the device, stopping FEC history metrics collection for the device %v", mm.deviceID)
2443 }
pnalmas6d6b7d72025-10-23 16:34:22 +05302444 case meAttributes = <-func() chan me.AttributeValueMap {
2445 if isCurrent {
2446 return mm.opticalMetricsChan
2447 }
2448 return mm.l2PmChan
2449 }():
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002450 logger.Debugw(ctx, "received fec history data metrics",
pnalmas6d6b7d72025-10-23 16:34:22 +05302451 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "isCurrent": isCurrent})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002452 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002453 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002454 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002455 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002456 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002457 }
2458 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2459 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002460 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002461 }
2462 }
2463 for k := range FecHistory {
2464 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2465 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2466 if _, ok := fecHistData[k]; !ok {
2467 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002468 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002469 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002470 fecHistData[k] = float32(val.(uint16))
2471 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002472 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002473 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002474 fecHistData[k] = float32(val.(uint32))
2475 }
2476 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002477 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002478 fecHistData[k] = float32(val.(uint32))
2479 }
2480 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002481 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002482 fecHistData[k] = float32(val.(uint32))
2483 }
2484 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002485 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002486 fecHistData[k] = float32(val.(uint32))
2487 }
2488 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002489 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002490 fecHistData[k] = float32(val.(uint16))
2491 }
2492 default:
2493 // do nothing
2494 }
2495 }
2496 }
2497 return nil
2498}
2499
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302500func (mm *OnuMetricsManager) GetMeInstance(ctx context.Context, classID me.ClassID, entityID uint16, requestedAttributes me.AttributeValueMap,
2501 timeout int, highPrio bool, rxChan chan cmn.Message, isExtendedOmci bool) (*me.ManagedEntity, error) {
2502
2503 select {
2504 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2505 errMsg := "deleting the device, stopping GetMeInstance for the device " + mm.deviceID
2506 logger.Warn(ctx, errMsg)
2507 return nil, status.Error(codes.NotFound, errMsg)
2508 default:
2509 if mm.pOnuDeviceEntry.GetDevOmciCC() != nil {
2510 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2511 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2512 return meInstance, err
2513 }
2514 }
2515 return nil, nil
2516}
2517
pnalmas6d6b7d72025-10-23 16:34:22 +05302518// GetCurrentDataMEInstance gets current performance monitoring data from ME instance
2519func (mm *OnuMetricsManager) GetCurrentDataMEInstance(ctx context.Context, classID me.ClassID, entityID uint16, requestedAttributes me.AttributeValueMap,
2520 timeout int, highPrio bool, rxChan chan cmn.Message, isExtendedOmci bool) (*me.ManagedEntity, error) {
2521
2522 select {
2523 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2524 errMsg := "deleting the device, stopping GetCurrentDataMEInstance for the device " + mm.deviceID
2525 logger.Warn(ctx, errMsg)
2526 return nil, status.Error(codes.NotFound, errMsg)
2527 default:
2528 if mm.pOnuDeviceEntry.GetDevOmciCC() != nil {
2529 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetCurrentDataME(ctx, classID, entityID, requestedAttributes,
2530 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2531 return meInstance, err
2532 }
2533 }
2534 return nil, nil
2535}
2536
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302537// CheckMeInstanceStatusCode checked status code if not found returns true
2538func CheckMeInstanceStatusCode(err error) bool {
2539 if err != nil {
2540 st, ok := status.FromError(err)
2541 if ok && st.Code() == codes.NotFound {
2542 return true
2543 }
2544 }
2545 return false
2546}
2547
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002548// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002549func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
pnalmas6d6b7d72025-10-23 16:34:22 +05302550 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int, isCurrent bool) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002551 // 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 +00002552 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2553 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002554 }
pnalmas6d6b7d72025-10-23 16:34:22 +05302555 var meInstance *me.ManagedEntity
2556 var err error
2557
2558 // Use GetCurrentDataMEInstance if isCurrent is true, otherwise use GetMeInstance
2559 if isCurrent {
2560 meInstance, err = mm.GetCurrentDataMEInstance(ctx, classID, entityID, requestedAttributes,
2561 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2562 } else {
2563 meInstance, err = mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
2564 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
2565 }
2566
ozgecanetsiab36ed572021-04-01 10:38:48 +03002567 if err != nil {
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302568 if CheckMeInstanceStatusCode(err) {
2569 return err // Device is being deleted, so we stop processing
2570 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002571 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2572 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302573 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002574 }
2575 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002576 select {
2577 case meAttributes = <-mm.l2PmChan:
2578 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002579 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2580 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002581 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002582 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002583 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002584 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
balaji.nagarajan3cab2b62025-06-23 15:44:54 +05302585 case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
2586 logger.Warnw(ctx, "Deleting the device, stopping GEM port history metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
2587 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 -08002588 }
2589 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2590 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002591 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002592 }
2593 }
2594 for k := range GemPortHistory {
2595 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2596 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2597 if _, ok := gemPortHistData[k]; !ok {
2598 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002599 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002600 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002601 gemPortHistData[k] = float32(val.(uint16))
2602 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002603 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002604 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002605 gemPortHistData[k] = float32(val.(uint32))
2606 }
2607 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002608 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002609 gemPortHistData[k] = float32(val.(uint32))
2610 }
2611 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002612 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002613 gemPortHistData[k] = float32(val.(uint64))
2614 }
2615 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002616 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002617 gemPortHistData[k] = float32(val.(uint64))
2618 }
2619 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002620 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002621 gemPortHistData[k] = float32(val.(uint32))
2622 }
2623 default:
2624 // do nothing
2625 }
2626 }
2627 }
2628 return nil
2629}
2630
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002631func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002632 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2633 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002634 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2635 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 -08002636 }
2637 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2638 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002639 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2640 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 -08002641 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002642 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002643 switch msgObj.EntityClass {
2644 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2645 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002646 me.EthernetPerformanceMonitoringHistoryDataClassID,
2647 me.FecPerformanceMonitoringHistoryDataClassID,
2648 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002649 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2650 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2651 mm.l2PmCreateOrDeleteResponseChan <- true
2652 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002653 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002654 mm.l2PmCreateOrDeleteResponseChan <- false
2655 }
2656 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302657 case me.EthernetFrameExtendedPmClassID,
2658 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302659 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302660 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002661 default:
2662 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002663 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002664 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002665 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002666}
2667
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002668func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002669 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2670 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002671 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2672 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 -08002673 }
2674 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2675 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002676 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2677 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 -08002678 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002679 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002680 switch msgObj.EntityClass {
2681 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2682 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002683 me.EthernetPerformanceMonitoringHistoryDataClassID,
2684 me.FecPerformanceMonitoringHistoryDataClassID,
2685 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002686 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2687 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2688 mm.l2PmCreateOrDeleteResponseChan <- true
2689 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002690 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002691 mm.l2PmCreateOrDeleteResponseChan <- false
2692 }
2693 return nil
2694 default:
2695 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002696 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002697 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002698 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002699}
2700
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002701func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002702 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002703 for {
2704 select {
2705 case <-time.After(L2PmCollectionInterval * time.Second):
2706 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002707 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2708 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002709 }
2710 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002711 case <-mm.StopTicks:
2712 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002713 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002714 return
2715 }
2716 }
2717}
2718
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002719func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002720 // Publish metrics if it is valid
2721 if metricInfoSlice != nil {
2722 mm.publishMetrics(ctx, metricInfoSlice)
2723 } else {
2724 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2725 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002726 mm.OnuMetricsManagerLock.Lock()
2727 mm.GroupMetricMap[metricName].collectAttempts++
2728 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002729 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2730 }
2731 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002732 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2733 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002734 }
2735}
2736
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302737// nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002738func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
pnalmas6d6b7d72025-10-23 16:34:22 +05302739 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int, isCurrent bool) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002740 var grpFunc groupMetricPopulateFunc
2741 switch classID {
2742 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2743 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2744 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2745 grpFunc = mm.populateEthernetUniHistoryMetrics
2746 case me.FecPerformanceMonitoringHistoryDataClassID:
2747 grpFunc = mm.populateFecHistoryMetrics
2748 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2749 grpFunc = mm.populateGemPortMetrics
2750 default:
2751 return fmt.Errorf("unknown-classid-%v", classID)
2752 }
2753
2754 size := 0
2755 requestedAttributes := make(me.AttributeValueMap)
2756 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002757 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2758 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2759 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2760 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2761 continue
2762 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002763 if v.Size+size <= mm.maxL2PMGetPayLoadSize {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002764 requestedAttributes[v.Name] = v.DefValue
2765 size = v.Size + size
2766 } else { // We exceeded the allow omci get size
2767 // Let's collect the attributes via get now and collect remaining in the next iteration
pnalmas6d6b7d72025-10-23 16:34:22 +05302768 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime, isCurrent); err != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002769 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002770 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002771 return err
2772 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002773 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002774 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2775 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002776 }
2777 }
2778 // Collect the omci get attributes for the last bunch of attributes.
pnalmas6d6b7d72025-10-23 16:34:22 +05302779 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime, isCurrent); err != nil {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002780 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002781 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002782 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002783 }
2784 return nil
2785}
2786
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002787func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002788 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002789 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2790 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2791 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002792
2793 raisedTs := time.Now().Unix()
2794 mmd := voltha.MetricMetaData{
2795 Title: title,
2796 Ts: float64(raisedTs),
2797 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002798 DeviceId: mm.deviceID,
2799 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2800 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002801 }
2802
2803 // create slice of metrics given that there could be more than one VEIP instance
2804 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2805 return metricInfo
2806}
2807
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002808func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002809 valid := false
2810 if *intervalEndTime == -1 { // first time
2811 // Update the interval end time
2812 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2813 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2814 valid = true
2815 }
2816 } else {
2817 var currIntervalEndTime int
2818 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2819 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2820 }
2821 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2822 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002823 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002824 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2825 } else {
2826 valid = true
2827 }
2828 }
2829 return valid
2830}
2831
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002832func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002833 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002834 if !mm.GetOmciProcessingStatus() {
2835 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})
2836 return false
2837 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002838 select {
2839 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002840 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002841 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002842 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002843 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002844 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002845 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002846 }
2847 return false
2848}
2849
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302850// nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002851func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002852 var pmConfigSlice []*voltha.PmConfig
2853 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002854 pmConfigSlice = append(pmConfigSlice,
2855 &voltha.PmConfig{
2856 Name: k,
2857 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002858 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002859 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002860 }
2861 groupMetric := voltha.PmGroupConfig{
2862 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002863 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002864 GroupFreq: grpFreq,
2865 Metrics: pmConfigSlice,
2866 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002867 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002868
2869}
2870
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002871func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2872 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2873 if mm.PAdaptFsm == nil {
2874 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2875 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002876 return fmt.Errorf("nil-adapter-fsm")
2877 }
2878 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002879 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2880 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002881 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002882 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2883 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2884 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2885 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2886 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2887 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2888 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2889 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2890 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002891 },
2892 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002893 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2894 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2895 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2896 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2897 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2898 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2899 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2900 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002901 },
2902 )
2903 return nil
2904}
2905
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002906func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2907 mm.pDeviceHandler.InitPmConfigs()
2908 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2909 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2910 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2911 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002912
2913 // Populate group metrics.
2914 // Lets populate irrespective of GroupMetricEnabled is true or not.
2915 // The group metrics collection will decided on this flag later
2916
2917 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2918 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2919
2920 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2921 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2922
2923 // classical l2 pm counter start
2924
2925 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2926 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2927
2928 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2929 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2930
2931 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2932 FecHistoryEnabled, FecHistoryFrequency)
2933
2934 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2935 GemPortHistoryEnabled, GemPortHistoryFrequency)
2936
2937 // classical l2 pm counter end
2938
2939 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2940}
2941
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002942func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002943 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002944 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2945 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002946 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002947 Enabled: g.Enabled,
2948 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002949 }
2950 switch g.GroupName {
2951 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002952 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002953 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002954 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002955 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002956 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2957 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002958 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002959 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2960 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002961 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002962 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2963 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002964 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002965 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2966 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002967 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002968 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002969 }
2970 }
2971
2972 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002973 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2974 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002975 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002976 Enabled: m.Enabled,
2977 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002978 }
2979 switch m.Name {
2980 // None exist as of now. Add when available.
2981 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002982 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002983 }
2984 }
2985}
2986
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002987// AddGemPortForPerfMonitoring - TODO: add comment
2988func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2989 mm.OnuMetricsManagerLock.Lock()
2990 defer mm.OnuMetricsManagerLock.Unlock()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302991 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002992 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002993 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002994 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002995 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002996 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002997
2998 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2999 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
3000 // GemPortPerfHistory ME simultaneously for different instances of the ME.
3001 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
3002 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07003003
3004 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003005 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
3006 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07003007 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003008 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07003009 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003010 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07003011 }
3012 }()
Praneeth Kumar Nalmas8f8f0c02024-10-22 19:29:09 +05303013 mm.pOnuDeviceEntry.GetOnuDB().PutOnuSpeficMe(ctx, me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID, meAttributes)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003014}
3015
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003016// RemoveGemPortForPerfMonitoring - TODO: add comment
3017func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
3018 mm.OnuMetricsManagerLock.Lock()
3019 defer mm.OnuMetricsManagerLock.Unlock()
3020 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
3021 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003022 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003023 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003024
3025 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
3026 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
3027 // GemPortPerfHistory ME simultaneously for different instances of the ME.
3028 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
3029 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07003030
3031 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003032 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
3033 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07003034 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003035 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07003036 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003037 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07003038 }
3039 }()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05303040 mm.pOnuDeviceEntry.GetOnuDB().DeleteMe(me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003041}
3042
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003043func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
3044 if mm.pDeviceHandler.GetOnuTP() != nil {
3045 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08003046 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003047 for _, v := range gemPortInstIDs {
3048 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003049 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003050 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003051 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003052 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08003053 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003054 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003055 }
3056}
3057
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003058func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
3059 if mm.pDeviceHandler.GetOnuTP() != nil {
3060 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08003061 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003062 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003063 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003064 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003065 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003066 }
3067 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08003068 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003069 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08003070}
3071
3072// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003073func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
3074 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003075 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003076 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303077 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003078 }
3079 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003080 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003081 group.pmMEData = &pmMEData{}
3082 Value, err := mm.pmKvStore.Get(ctx, groupName)
3083 if err == nil {
3084 if Value != nil {
3085 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003086 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003087 tmpBytes, _ := kvstore.ToByte(Value.Value)
3088
3089 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003090 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303091 errorsList = append(errorsList, fmt.Errorf("unable-to-unmarshal-PM-data-%s-for-group-%s", mm.deviceID, groupName))
Girish Gowdra0e533642021-03-02 22:02:51 -08003092 continue
3093 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003094 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003095 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003096 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003097 continue
3098 }
3099 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003100 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303101 errorsList = append(errorsList, fmt.Errorf("unable-to-read-from-KVstore-%s-for-group-%s", mm.deviceID, groupName))
Girish Gowdra0e533642021-03-02 22:02:51 -08003102 continue
3103 }
3104 }
3105 if len(errorsList) > 0 {
3106 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
3107 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003108 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003109 return nil
3110}
3111
3112// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
3113// the data must be available in cache.
3114// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003115func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
3116 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08003117 return grp.pmMEData, nil
3118 }
3119 // Data not in cache, try to fetch from kv store.
3120 data := &pmMEData{}
3121 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003122 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3123 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003124 }
3125 Value, err := mm.pmKvStore.Get(ctx, groupName)
3126 if err == nil {
3127 if Value != nil {
3128 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003129 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003130 tmpBytes, _ := kvstore.ToByte(Value.Value)
3131
3132 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003133 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003134 return data, err
3135 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003136 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003137 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003138 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003139 return data, err
3140 }
3141 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003142 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003143 return data, err
3144 }
3145
3146 return data, nil
3147}
3148
3149// 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 +00003150func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
3151 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
3152 mm.OnuMetricsManagerLock.Lock()
3153 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08003154
3155 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003156 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303157 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003158 }
3159
3160 pmMEData, err := mm.getPmData(ctx, groupName)
3161 if err != nil || pmMEData == nil {
3162 // error already logged in called function.
3163 return err
3164 }
3165 switch pmAction {
3166 case cPmAdd:
3167 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
3168 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3169 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3170 case cPmAdded:
3171 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
3172 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3173 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3174 case cPmRemove:
3175 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
3176 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3177 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3178 case cPmRemoved:
3179 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3180 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3181 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3182 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003183 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303184 return fmt.Errorf("unknown-pm-action-deviceid-%s-groupName-%s-pmaction-%s", mm.deviceID, groupName, pmAction)
Girish Gowdra0e533642021-03-02 22:02:51 -08003185 }
3186 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003187 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08003188
3189 Value, err := json.Marshal(*pmMEData)
3190 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003191 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
3192 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003193 return err
3194 }
3195 // Update back to kv store
3196 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003197 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
3198 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003199 return err
3200 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003201 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
3202 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08003203
3204 return nil
3205}
3206
3207// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003208func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
3209 mm.OnuMetricsManagerLock.Lock()
3210 defer mm.OnuMetricsManagerLock.Unlock()
3211 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003212 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003213 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303214 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003215 }
3216
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003217 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003218 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003219 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003220 // do not abort this procedure. continue to delete next group.
3221 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003222 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08003223 }
3224 }
3225
3226 return nil
3227}
3228
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003229// ClearAllPmData clears all PM data associated with the device from KV store
3230func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3231 mm.OnuMetricsManagerLock.Lock()
3232 defer mm.OnuMetricsManagerLock.Unlock()
3233 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003234 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003235 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303236 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003237 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003238 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003239 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003240 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003241 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003242 value = err
3243 // do not abort this procedure - continue to delete next group.
3244 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003245 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003246 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003247 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003248 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003249 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003250 }
3251 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003252}
3253
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003254func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3255 mm.OnuMetricsManagerLock.Lock()
3256 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003257 mm.omciProcessingActive = status
3258}
3259
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003260// updateTickGenerationStatus - TODO: add comment
3261func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3262 mm.OnuMetricsManagerLock.Lock()
3263 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003264 mm.tickGenerationActive = status
3265}
3266
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003267// GetOmciProcessingStatus - TODO: add comment
3268func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3269 mm.OnuMetricsManagerLock.RLock()
3270 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003271 return mm.omciProcessingActive
3272}
3273
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003274// GetTickGenerationStatus - TODO: add comment
3275func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3276 mm.OnuMetricsManagerLock.RLock()
3277 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003278 return mm.tickGenerationActive
3279}
3280
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003281func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003282 for _, ele := range slice {
3283 if ele == n {
3284 return slice
3285 }
3286 }
3287 return append(slice, n)
3288}
3289
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003290func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003291 for i, ele := range slice {
3292 if ele == n {
3293 return append(slice[:i], slice[i+1:]...)
3294 }
3295 }
3296 return slice
3297}
3298
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003299func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003300 for _, ele := range slice {
3301 if ele == n {
3302 return slice
3303 }
3304 }
3305 return append(slice, n)
3306}
3307
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003308func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003309 for i, ele := range slice {
3310 if ele == n {
3311 return append(slice[:i], slice[i+1:]...)
3312 }
3313 }
3314 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003315}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303316
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003317func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303318 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3319 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003320 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003321 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003322 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303323 Value, err := mm.extPmKvStore.Get(ctx, key)
3324 if err == nil {
3325 if Value != nil {
3326 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003327 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303328 tmpBytes, _ := kvstore.ToByte(Value.Value)
3329
3330 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003331 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303332 return false, err
3333 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003334 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303335 // We have found the data from db, no need to get through omci get message.
3336 mm.supportedEthernetFrameExtendedPMClass = data
3337 return true, nil
3338 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003339 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303340 return false, nil
3341 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003342 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303343 return false, err
3344}
3345
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003346func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303347 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 -07003348 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3349 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})
3350 return false, fmt.Errorf("omci-processor-shutdown")
3351 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303352 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303353 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303354 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003355 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303356 // 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 +05303357 switch resp {
3358 case me.Success, me.InstanceExists:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303359 return true, nil
mgoudad611f4c2025-10-30 14:49:27 +05303360 case me.UnknownEntity, me.ParameterError,
3361 me.ProcessingError, me.NotSupported, me.AttributeFailure:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303362 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
mgoudad611f4c2025-10-30 14:49:27 +05303363 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003364 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 +05303365 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3366 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003367 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303368 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003369 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303370 }
3371 return false, fmt.Errorf("timeout-while-waiting-for-response")
3372}
3373
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003374func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303375 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303376 // 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 +05303377 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003378 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303379 var entityID uint16
3380 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003381 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303382 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003383 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303384 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303385 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303386 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303387 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303388
3389 inner1:
3390 // retry ExtendedPmCreateAttempts times to create the instance of PM
3391 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003392 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3393 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3394 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303395 if err != nil {
3396 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003397 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303398 return false, err
3399 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303400 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3401 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303402 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303403 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303404 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303405 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303406 }
3407 break inner1
3408 } else if err != nil {
3409 if !supported {
3410 // Need to return immediately
3411 return false, err
3412 }
3413 //In case of failure, go for a retry
3414 }
3415 }
3416 if cnt == ExtendedPmCreateAttempts {
3417 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3418 return true, fmt.Errorf("unable-to-create-me")
3419 }
3420 }
3421 }
3422 return true, nil
3423}
3424
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003425func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3426 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003427 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003428 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303429 // check if we get the supported type me for ethernet frame extended pm class id
3430 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3431 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3432 }
3433 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3434 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003435 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303436 }
3437 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003438 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303439 }
3440}
3441
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003442func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303443 mm.onuEthernetFrameExtendedPmLock.Lock()
3444 mm.isDeviceReadyToCollectExtendedPmStats = true
3445 mm.onuEthernetFrameExtendedPmLock.Unlock()
3446}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003447
Himani Chawlaee10b542021-09-20 16:46:40 +05303448// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003449func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303450 //get the type of extended frame pm me supported by onu first
3451 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3452 if err != nil {
3453 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3454 return
3455 }
3456 if exist {
3457 // we have the me type, go ahead with the me type supported.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303458 //nolint:govet
Himani Chawla43f95ff2021-06-03 00:24:12 +05303459 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003460 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303461 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3462 return
3463 }
3464 mm.setAllExtPmMeCreatedFlag()
3465 return
3466 }
3467 // First try with 64 bit me
3468 // we have the me type, go ahead with the me type supported.
3469 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3470 if err != nil && !supported64Bit {
3471 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003472 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303473 "supported": supported64Bit})
3474 // Then Try with 32 bit type
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303475 //nolint:govet
Himani Chawla43f95ff2021-06-03 00:24:12 +05303476 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003477 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303478 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3479 } else if supported32Bit {
3480 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3481 mm.putExtPmMeKvStore(ctx)
3482 mm.setAllExtPmMeCreatedFlag()
3483 }
3484 } else if err == nil && supported64Bit {
3485 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3486 mm.putExtPmMeKvStore(ctx)
3487 mm.setAllExtPmMeCreatedFlag()
3488 }
3489}
3490
Himani Chawlaee10b542021-09-20 16:46:40 +05303491func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3492 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3493 uniPortEntityID := entityID
3494 if upstream {
3495 uniPortEntityID = entityID - 0x100
3496 }
3497 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3498 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3499 mm.pDeviceHandler.GetOmciTimeout(), true,
3500 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3501 if err != nil {
3502 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3503 log.Fields{"device-id": mm.deviceID})
3504 return extension.GetValueResponse_INTERNAL_ERROR, err
3505 }
3506
3507 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3508 return extension.GetValueResponse_REASON_UNDEFINED, nil
3509 }
3510 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3511}
3512
3513func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3514 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 -07003515 if !mm.GetOmciProcessingStatus() {
3516 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})
3517 return false
3518 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303519 select {
3520 case resp := <-mm.extendedPMMeResponseChan:
3521 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3522 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3523 if resp == me.Success {
3524 return true
3525 }
3526 return false
3527 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3528 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3529 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3530 }
3531 return false
3532}
3533
3534func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3535 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3536 className := "EthernetFrameExtendedPm64Bit"
3537 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3538 className = "EthernetFrameExtendedPm"
3539 }
3540 // Reset the counters if option is specified
3541 for entityID := range upstreamEntityMap {
3542 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3543 true)
3544 if err != nil {
3545 return errReason, err
3546 }
3547 }
3548
3549 for entityID := range downstreamEntityMap {
3550 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3551 true)
3552 if err != nil {
3553 return errReason, err
3554 }
3555 }
3556 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3557 // device itself.
3558 // Unset the reset bit if option is specified
3559 for entityID := range upstreamEntityMap {
3560 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3561 false)
3562 if err != nil {
3563 return errReason, err
3564 }
3565 }
3566
3567 for entityID := range downstreamEntityMap {
3568 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3569 false)
3570 if err != nil {
3571 return errReason, err
3572 }
3573 }
3574 return extension.GetValueResponse_REASON_UNDEFINED, nil
3575}
3576
3577func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3578 mm.onuEthernetFrameExtendedPmLock.Lock()
3579 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3580 mm.isEthernetFrameExtendedPmOperationOngoing = val
3581}
3582
3583func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3584 mm.onuEthernetFrameExtendedPmLock.Lock()
3585 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3586 return mm.isEthernetFrameExtendedPmOperationOngoing
3587}
3588
3589// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3590func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3591 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3592 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3593 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303594 return &extension.SingleGetValueResponse{
3595 Response: &extension.GetValueResponse{
3596 Status: extension.GetValueResponse_ERROR,
3597 ErrReason: reason,
3598 },
3599 }
3600 }
3601 mm.onuEthernetFrameExtendedPmLock.RLock()
3602 if !mm.isDeviceReadyToCollectExtendedPmStats {
3603 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303604 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303605 }
3606 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303607
3608 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3609 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3610 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3611 }
3612 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3613 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3614
3615 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3616 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3617 if onuInfo.IsUniIndex != nil {
3618 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3619 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3620 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3621 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3622 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3623 break
3624 }
3625 }
3626 if len(downstreamEntityMap) == 0 {
3627 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3628 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3629 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3630 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3631 }
3632 } else {
3633 // make a copy of all downstream and upstream maps in the local ones
3634 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3635 upstreamEntityMap[entityID] = meEnt
3636 }
3637 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3638 downstreamEntityMap[entityID] = meEnt
3639 }
3640 }
3641 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3642 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3643 // Reset the metrics first for all required me's
3644 if onuInfo.Reset_ {
3645 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3646 if err != nil {
3647 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3648 log.Fields{"device-id": mm.deviceID})
3649 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3650 }
3651 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303652 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3653 var pmUpstream extension.OmciEthernetFrameExtendedPm
3654 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303655 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3656 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3657 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3658 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303659 if !onuInfo.Reset_ {
3660 for entityID, meEnt := range upstreamEntityMap {
3661 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3662 var receivedMask uint16
3663 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3664 if receivedMask == 0 {
3665 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303666 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3667 // It might be possible that still some downstream pms are supported and hence we need to continue
3668 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3669 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303670 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303671 // Aggregate the result for upstream
3672 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3673 } else {
3674 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303675 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303676 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303677
Himani Chawlaee10b542021-09-20 16:46:40 +05303678 for entityID, meEnt := range downstreamEntityMap {
3679 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3680 var receivedMask uint16
3681 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303682 if receivedMask == 0 {
3683 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3684 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3685 // Stop collecting downstream counters for other ME's.
3686 break
3687 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303688 // Aggregate the result for downstream
3689 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3690 } else {
3691 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3692 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303693 }
3694 }
3695 singleValResp := extension.SingleGetValueResponse{
3696 Response: &extension.GetValueResponse{
3697 Status: extension.GetValueResponse_OK,
3698 Response: &extension.GetValueResponse_OnuCounters{
3699 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303700 Upstream: &pmUpstream,
3701 Downstream: &pmDownstream,
3702 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303703 },
3704 },
3705 },
3706 }
3707 return &singleValResp
3708}
3709
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303710// nolint:unparam
Himani Chawlaee10b542021-09-20 16:46:40 +05303711func (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 +05303712 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003713 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 +05303714
3715 classID = mm.supportedEthernetFrameExtendedPMClass
3716 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3717 if classID == me.EthernetFrameExtendedPmClassID {
3718 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3719 }
3720 ethPMData := make(map[string]uint64)
3721 var sumReceivedMask uint16
3722 for mask := range attributeMaskList {
3723 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3724 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003725 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303726 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303727 }
3728 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3729 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3730 //populate all counters as failure and return
3731 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3732 break
3733 }
3734 }
3735 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303736 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303737}
3738
3739// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003740func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303741 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3742 var meAttributes me.AttributeValueMap
3743 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003744 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303745 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003746 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303747 return extension.GetValueResponse_INTERNAL_ERROR, err
3748 }
3749 select {
3750 case meAttributes = <-mm.extendedPmMeChan:
3751 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003752 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3753 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303754 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003755 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303756 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3757 }
3758 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3759 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3760 *sumReceivedMask += mask
3761 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3762 } else {
3763 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3764 *sumReceivedMask += mask
3765 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3766 }
3767
3768 return extension.GetValueResponse_REASON_UNDEFINED, nil
3769}
3770
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003771func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303772 sourceMap := maskToEthernetFrameExtendedPM64Bit
3773 errorCounterValue := UnsupportedCounterValue64bit
3774 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3775 sourceMap = maskToEthernetFrameExtendedPM32Bit
3776 errorCounterValue = UnsupportedCounterValue32bit
3777 }
3778 for _, value := range sourceMap {
3779 for _, k := range value {
3780 if _, ok := ethFrameExtPMData[k]; !ok {
3781 ethFrameExtPMData[k] = errorCounterValue
3782 }
3783 }
3784 }
3785}
3786
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303787// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003788func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303789 receivedMask := uint16(0)
3790 switch requestedAttributesMask {
3791 case 0x3F00:
3792 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3793 if _, ok := ethFrameExtPMData[k]; !ok {
3794 switch k {
3795 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003796 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303797 ethFrameExtPMData[k] = uint64(val.(uint32))
3798 receivedMask |= 0x2000
3799 } else if !ok {
3800 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3801 }
3802 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003803 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303804 ethFrameExtPMData[k] = uint64(val.(uint32))
3805 receivedMask |= 0x1000
3806 } else if !ok {
3807 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3808 }
3809 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003810 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303811 ethFrameExtPMData[k] = uint64(val.(uint32))
3812 receivedMask |= 0x800
3813 } else if !ok {
3814 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3815 }
3816 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003817 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303818 ethFrameExtPMData[k] = uint64(val.(uint32))
3819 receivedMask |= 0x400
3820 } else if !ok {
3821 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3822 }
3823 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003824 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303825 ethFrameExtPMData[k] = uint64(val.(uint32))
3826 receivedMask |= 0x200
3827 } else if !ok {
3828 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3829 }
3830 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003831 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303832 ethFrameExtPMData[k] = uint64(val.(uint32))
3833 receivedMask |= 0x100
3834 } else if !ok {
3835 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3836 }
3837 default:
3838 //do nothing
3839 }
3840 }
3841 }
3842 case 0x00FC:
3843 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3844 if _, ok := ethFrameExtPMData[k]; !ok {
3845 switch k {
3846 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003847 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303848 ethFrameExtPMData[k] = uint64(val.(uint32))
3849 receivedMask |= 0x80
3850 } else if !ok {
3851 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3852 }
3853 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003854 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303855 ethFrameExtPMData[k] = uint64(val.(uint32))
3856 receivedMask |= 0x40
3857 } else if !ok {
3858 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3859 }
3860 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003861 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303862 ethFrameExtPMData[k] = uint64(val.(uint32))
3863 receivedMask |= 0x20
3864 } else if !ok {
3865 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3866 }
3867 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003868 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303869 ethFrameExtPMData[k] = uint64(val.(uint32))
3870 receivedMask |= 0x10
3871 } else if !ok {
3872 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3873 }
3874 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003875 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303876 ethFrameExtPMData[k] = uint64(val.(uint32))
3877 receivedMask |= 0x8
3878 } else if !ok {
3879 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3880 }
3881 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003882 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303883 ethFrameExtPMData[k] = uint64(val.(uint32))
3884 receivedMask |= 0x4
3885 } else if !ok {
3886 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3887 }
3888 default:
3889 //do nothing
3890 }
3891 }
3892 }
3893 case 0x0003:
3894 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3895 if _, ok := ethFrameExtPMData[k]; !ok {
3896 switch k {
3897 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003898 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303899 ethFrameExtPMData[k] = uint64(val.(uint32))
3900 receivedMask |= 0x2
3901 } else if !ok {
3902 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3903 }
3904 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003905 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303906 ethFrameExtPMData[k] = uint64(val.(uint32))
3907 receivedMask |= 0x1
3908 } else if !ok {
3909 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3910 }
3911 default:
3912 //do nothing
3913 }
3914 }
3915 }
3916 default:
3917 //do nothing
3918 }
3919 return receivedMask
3920}
3921
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303922// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003923func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303924 receivedMask := uint16(0)
3925 switch requestedAttributesMask {
3926 case 0x3800:
3927 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3928 if _, ok := ethFrameExtPMData[k]; !ok {
3929 switch k {
3930 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003931 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303932 ethFrameExtPMData[k] = val.(uint64)
3933 receivedMask |= 0x2000
3934 } else if !ok {
3935 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3936 }
3937 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003938 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303939 ethFrameExtPMData[k] = val.(uint64)
3940 receivedMask |= 0x1000
3941 } else if !ok {
3942 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3943 }
3944 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003945 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303946 ethFrameExtPMData[k] = val.(uint64)
3947 receivedMask |= 0x800
3948 } else if !ok {
3949 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3950 }
3951 }
3952 }
3953 }
3954 case 0x0700:
3955 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3956 if _, ok := ethFrameExtPMData[k]; !ok {
3957 switch k {
3958 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003959 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303960 ethFrameExtPMData[k] = val.(uint64)
3961 receivedMask |= 0x400
3962 } else if !ok {
3963 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3964 }
3965 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003966 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303967 ethFrameExtPMData[k] = val.(uint64)
3968 receivedMask |= 0x200
3969 } else if !ok {
3970 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3971 }
3972 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003973 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303974 ethFrameExtPMData[k] = val.(uint64)
3975 receivedMask |= 0x100
3976 } else if !ok {
3977 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3978 }
3979 }
3980 }
3981 }
3982 case 0x00E0:
3983 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3984 if _, ok := ethFrameExtPMData[k]; !ok {
3985 switch k {
3986 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003987 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303988 ethFrameExtPMData[k] = val.(uint64)
3989 receivedMask |= 0x80
3990 } else if !ok {
3991 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3992 }
3993 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003994 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303995 ethFrameExtPMData[k] = val.(uint64)
3996 receivedMask |= 0x40
3997 } else if !ok {
3998 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3999 }
4000 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00004001 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304002 ethFrameExtPMData[k] = val.(uint64)
4003 receivedMask |= 0x20
4004 } else if !ok {
4005 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
4006 }
4007 }
4008 }
4009 }
4010 case 0x001C:
4011 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
4012 if _, ok := ethFrameExtPMData[k]; !ok {
4013 switch k {
4014 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00004015 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304016 ethFrameExtPMData[k] = val.(uint64)
4017 receivedMask |= 0x10
4018 } else if !ok {
4019 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
4020 }
4021 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00004022 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304023 ethFrameExtPMData[k] = val.(uint64)
4024 receivedMask |= 0x8
4025 } else if !ok {
4026 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
4027 }
4028 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00004029 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304030 ethFrameExtPMData[k] = val.(uint64)
4031 receivedMask |= 0x4
4032 } else if !ok {
4033 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
4034 }
4035 default:
4036 //do nothing
4037 }
4038 }
4039 }
4040 case 0x0003:
4041 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
4042 if _, ok := ethFrameExtPMData[k]; !ok {
4043 switch k {
4044 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00004045 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304046 ethFrameExtPMData[k] = val.(uint64)
4047 receivedMask |= 0x2
4048 } else if !ok {
4049 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
4050 }
4051 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00004052 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304053 ethFrameExtPMData[k] = val.(uint64)
4054 receivedMask |= 0x1
4055 } else if !ok {
4056 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
4057 }
4058 default:
4059 //do nothing
4060 }
4061 }
4062 }
4063 }
4064 return receivedMask
4065}
4066
Himani Chawlaee10b542021-09-20 16:46:40 +05304067func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
4068 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304069 errorCounterValue := UnsupportedCounterValue64bit
4070 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
4071 errorCounterValue = UnsupportedCounterValue32bit
4072 }
4073 var pmDataOut extension.OmciEthernetFrameExtendedPm
4074 if aggregate {
4075 if pmData.DropEvents != errorCounterValue {
4076 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
4077 } else {
4078 pmDataOut.DropEvents = pmData.DropEvents
4079 }
4080 if pmData.Octets != errorCounterValue {
4081 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
4082 } else {
4083 pmDataOut.Octets = pmData.Octets
4084 }
4085 if pmData.Frames != errorCounterValue {
4086 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
4087 } else {
4088 pmDataOut.Frames = pmData.Frames
4089 }
4090 if pmData.BroadcastFrames != errorCounterValue {
4091 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
4092 } else {
4093 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
4094 }
4095 if pmData.MulticastFrames != errorCounterValue {
4096 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
4097 } else {
4098 pmDataOut.MulticastFrames = pmData.MulticastFrames
4099 }
4100 if pmData.CrcErroredFrames != errorCounterValue {
4101 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
4102 } else {
4103 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
4104 }
4105 if pmData.UndersizeFrames != errorCounterValue {
4106 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
4107 } else {
4108 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
4109 }
4110 if pmData.OversizeFrames != errorCounterValue {
4111 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
4112 } else {
4113 pmDataOut.OversizeFrames = pmData.OversizeFrames
4114 }
4115 if pmData.Frames_64Octets != errorCounterValue {
4116 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
4117 } else {
4118 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
4119 }
4120 if pmData.Frames_65To_127Octets != errorCounterValue {
4121 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
4122 } else {
4123 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
4124 }
4125 if pmData.Frames_128To_255Octets != errorCounterValue {
4126 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
4127 } else {
4128 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
4129 }
4130 if pmData.Frames_256To_511Octets != errorCounterValue {
4131 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
4132 } else {
4133 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
4134 }
4135 if pmData.Frames_512To_1023Octets != errorCounterValue {
4136 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
4137 } else {
4138 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
4139 }
4140 if pmData.Frames_1024To_1518Octets != errorCounterValue {
4141 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
4142 } else {
4143 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
4144 }
4145 } else {
4146 pmDataOut.DropEvents = pmDataIn["drop_events"]
4147 pmDataOut.Octets = pmDataIn["octets"]
4148 pmDataOut.Frames = pmDataIn["frames"]
4149 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
4150 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
4151 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
4152 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
4153 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
4154 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
4155 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
4156 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
4157 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
4158 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
4159 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
4160 }
4161 return pmDataOut
4162}
4163
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05304164//nolint:unparam
Himani Chawlaee10b542021-09-20 16:46:40 +05304165func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304166 controlBlock := make([]uint16, 8)
4167 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
4168 controlBlock[0] = 0
4169 // Next two bytes are for the parent class ID
4170 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
4171 // Next two bytes are for the parent me instance id
4172 controlBlock[2] = entityID
4173 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05304174 if reset {
4175 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
4176 } else {
4177 controlBlock[3] = 0
4178 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05304179 // Next two bytes are for tca disable
4180 controlBlock[4] = 0x4000 //tca global disable
4181 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
4182 if upstream {
4183 controlBlock[5] = 1 << 0
4184 } else {
4185 controlBlock[5] = (1 << 0) | (1 << 1)
4186 }
4187 // Next two bytes are for tci - does not matter here
4188 controlBlock[6] = 0
4189 // Next two bytes are for reserved bits - does not matter here
4190 controlBlock[7] = 0
4191 return controlBlock
4192}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00004193
Girish Gowdraabcceb12022-04-13 23:35:22 -07004194// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
4195func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
4196 mm.OnuMetricsManagerLock.RLock()
4197 defer mm.OnuMetricsManagerLock.RUnlock()
4198 return mm.deviceDeletionInProgress
4199}
4200
4201// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
4202func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
4203 mm.OnuMetricsManagerLock.Lock()
4204 defer mm.OnuMetricsManagerLock.Unlock()
4205 mm.deviceDeletionInProgress = true
4206}
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +05304207
pnalmas6d6b7d72025-10-23 16:34:22 +05304208// safeGetMetricValue safely extracts a metric value from the metrics map
4209// Returns 0 if the map is nil, key doesn't exist, or value is 0
4210// Logs warnings for missing keys to aid in debugging
4211func (mm *OnuMetricsManager) safeGetMetricValue(ctx context.Context, metrics map[string]float32, key string, deviceID string) uint32 {
4212 if metrics == nil {
4213 logger.Warnw(ctx, "Metrics map is nil", log.Fields{"device-id": deviceID, "key": key})
4214 return 0
4215 }
4216
4217 value, exists := metrics[key]
4218 if !exists {
4219 logger.Warnw(ctx, "Metric key not found in metrics map", log.Fields{"device-id": deviceID, "key": key})
4220 return 0
4221 }
4222
4223 if value < 0 {
4224 logger.Warnw(ctx, "Negative metric value, setting to 0", log.Fields{"device-id": deviceID, "key": key, "value": value})
4225 return 0
4226 }
4227
4228 return uint32(value)
4229}
4230
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +05304231// Obtain the ONU GEM counters for the ONU device
4232func (mm *OnuMetricsManager) GetONUGEMCounters(ctx context.Context) *extension.SingleGetValueResponse {
4233
4234 resp := extension.SingleGetValueResponse{
4235 Response: &extension.GetValueResponse{
4236 Status: extension.GetValueResponse_OK,
4237 Response: &extension.GetValueResponse_OnuAllocGemStatsResponse{
4238 OnuAllocGemStatsResponse: &extension.GetOnuAllocGemHistoryResponse{},
4239 },
4240 },
4241 }
4242
4243 if mm.GetdeviceDeletionInProgress() {
4244 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
4245 return nil
4246 }
4247
4248 mm.OnuMetricsManagerLock.RLock()
4249 defer mm.OnuMetricsManagerLock.RUnlock()
4250
4251 gemtoAllocId := mm.pDeviceHandler.GetOnuTP().GetGEMportToAllocIDMappingForONU(ctx, mm.deviceID)
4252 allocIDtoGem := make(map[uint16][]uint16)
4253 for key, value := range gemtoAllocId {
4254 allocIDtoGem[value] = append(allocIDtoGem[value], key)
4255 }
4256
4257 for allocID, gemSlice := range allocIDtoGem {
4258 logger.Infow(ctx, "AllocID", log.Fields{"alloc-id": allocID})
4259 allocIdGemData := extension.OnuAllocGemHistoryData{
4260 OnuAllocIdInfo: &extension.OnuAllocHistoryData{},
4261 GemPortInfo: []*extension.OnuGemPortHistoryData{},
4262 }
4263 allocIdGemData.OnuAllocIdInfo.AllocId = uint32(allocID)
4264
4265 // Loop through each element in the slice
4266 for _, gem := range gemSlice {
4267 logger.Debugw(ctx, "Collecting stats for Gem: ", log.Fields{"GEMID": gem})
pnalmas6d6b7d72025-10-23 16:34:22 +05304268 if metricInfo := mm.collectGemHistoryData(ctx, gem, true); metricInfo != nil {
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +05304269 logger.Infow(ctx, "Metricinfo for GEM", log.Fields{"GEMID": gem, "metricInfo": metricInfo})
4270 gemHistoryData := extension.OnuGemPortHistoryData{}
4271 gemHistoryData.GemId = uint32(gem)
pnalmas6d6b7d72025-10-23 16:34:22 +05304272 metrics := metricInfo.GetMetrics()
4273 gemHistoryData.TransmittedGEMFrames = mm.safeGetMetricValue(ctx, metrics, "transmitted_gem_frames", mm.deviceID)
4274 gemHistoryData.ReceivedGEMFrames = mm.safeGetMetricValue(ctx, metrics, "received_gem_frames", mm.deviceID)
4275 gemHistoryData.ReceivedPayloadBytes = mm.safeGetMetricValue(ctx, metrics, "received_payload_bytes", mm.deviceID)
4276 gemHistoryData.TransmittedPayloadBytes = mm.safeGetMetricValue(ctx, metrics, "transmitted_payload_bytes", mm.deviceID)
4277 gemHistoryData.EncryptionKeyErrors = mm.safeGetMetricValue(ctx, metrics, "encryption_key_errors", mm.deviceID)
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +05304278 allocIdGemData.GemPortInfo = append(allocIdGemData.GemPortInfo, &gemHistoryData)
4279 logger.Debugw(ctx, " allocIdGemData value ", log.Fields{"AllocIDGemData": allocIdGemData})
4280
4281 }
4282 }
4283 resp.Response.GetOnuAllocGemStatsResponse().OnuAllocGemHistoryData = append(resp.Response.GetOnuAllocGemStatsResponse().OnuAllocGemHistoryData, &allocIdGemData)
4284 }
4285
4286 logger.Debugw(ctx, "Request to fetch GEM Performance Counters ", log.Fields{"device-id": mm.deviceID, "response": resp})
4287 return &resp
4288
4289}
pnalmas6d6b7d72025-10-23 16:34:22 +05304290
4291// Obtain the ONU FEC counters for the ONU device
4292func (mm *OnuMetricsManager) GetONUFECCounters(ctx context.Context) *extension.SingleGetValueResponse {
4293
4294 resp := extension.SingleGetValueResponse{
4295 Response: &extension.GetValueResponse{
4296 Status: extension.GetValueResponse_OK,
4297 Response: &extension.GetValueResponse_FecHistory{
4298 FecHistory: &extension.GetOnuFecHistoryResponse{},
4299 },
4300 },
4301 }
4302
4303 if mm.GetdeviceDeletionInProgress() {
4304 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
4305 return nil
4306 }
4307
4308 mm.OnuMetricsManagerLock.RLock()
4309 defer mm.OnuMetricsManagerLock.RUnlock()
4310
4311 FecHistoryInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
4312 if len(FecHistoryInstKeys) > 0 {
4313 firstInstanceKey := FecHistoryInstKeys[0]
4314 logger.Debugw(ctx, "First FEC History Instance Key and Length", log.Fields{"InstanceKey": firstInstanceKey, "FecHistoryInstKeys": FecHistoryInstKeys, "Length": len(FecHistoryInstKeys)})
4315
4316 logger.Debugw(ctx, "Collecting FEC stats for ONU", log.Fields{"EntityID": firstInstanceKey})
4317 if metricInfo := mm.collectFecHistoryData(ctx, firstInstanceKey, true); metricInfo != nil {
4318 // Process FEC metrics data here
4319 logger.Debugw(ctx, "FEC metrics collected successfully", log.Fields{"metricInfo": metricInfo})
4320
4321 // Populate the response with the collected FEC metrics directly
4322 fecResponse := resp.Response.GetFecHistory()
4323 metrics := metricInfo.GetMetrics()
4324 fecResponse.CorrectedBytes = mm.safeGetMetricValue(ctx, metrics, "corrected_bytes", mm.deviceID)
4325 fecResponse.CorrectedCodeWords = mm.safeGetMetricValue(ctx, metrics, "corrected_code_words", mm.deviceID)
4326 fecResponse.UncorrectableCodeWords = mm.safeGetMetricValue(ctx, metrics, "uncorrectable_code_words", mm.deviceID)
4327 fecResponse.TotalCodeWords = mm.safeGetMetricValue(ctx, metrics, "total_code_words", mm.deviceID)
4328 fecResponse.FecSeconds = mm.safeGetMetricValue(ctx, metrics, "fec_seconds", mm.deviceID)
4329
4330 logger.Debugw(ctx, "FEC response populated successfully",
4331 log.Fields{"device-id": mm.deviceID, "correctedBytes": fecResponse.CorrectedBytes,
4332 "correctedCodeWords": fecResponse.CorrectedCodeWords, "fecSeconds": fecResponse.FecSeconds})
4333 } else {
4334 logger.Warnw(ctx, "Failed to collect FEC metrics", log.Fields{"device-id": mm.deviceID, "EntityID": firstInstanceKey})
4335 }
4336 }
4337
4338 logger.Debugw(ctx, "FEC History collection completed", log.Fields{"device-id": mm.deviceID})
4339 return &resp
4340}