blob: 11c6435505783fa7be5222dee4e026f7a889bc7d [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"
Girish Gowdrae09a6202021-01-12 18:10:59 -080037)
38
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000039// events of L2 PM FSM
Girish Gowdrae0140f02021-02-02 16:55:09 -080040const (
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000041 L2PmEventInit = "L2PmEventInit"
42 L2PmEventTick = "L2PmEventTick"
43 L2PmEventSuccess = "L2PmEventSuccess"
44 L2PmEventFailure = "L2PmEventFailure"
45 L2PmEventAddMe = "L2PmEventAddMe"
46 L2PmEventDeleteMe = "L2PmEventDeleteMe"
47 L2PmEventStop = "L2PmEventStop"
Girish Gowdrae0140f02021-02-02 16:55:09 -080048)
49
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000050// states of L2 PM FSM
51const (
52 L2PmStNull = "L2PmStNull"
53 L2PmStStarting = "L2PmStStarting"
54 L2PmStSyncTime = "L2PmStSyncTime"
55 L2PmStIdle = "L2PmStIdle"
56 L2PmStCreatePmMe = "L2PmStCreatePm"
57 L2PmStDeletePmMe = "L2PmStDeletePmMe"
58 L2PmStCollectData = "L2PmStCollectData"
59)
60
61// CL2PmFsmIdleState - TODO: add comment
62const CL2PmFsmIdleState = L2PmStIdle
Girish Gowdrae0140f02021-02-02 16:55:09 -080063
Girish Gowdra5a7c4922021-01-22 18:33:41 -080064// general constants used for overall Metric Collection management
65const (
66 DefaultMetricCollectionFrequency = 15 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
67 GroupMetricEnabled = true // This is READONLY and cannot be changed from VOLTHA NBI
68 DefaultFrequencyOverrideEnabled = true // This is READONLY and cannot be changed from VOLTHA NBI
69 FrequencyGranularity = 5 // The frequency (in seconds) has to be multiple of 5. This setting cannot changed later.
Girish Gowdraabcceb12022-04-13 23:35:22 -070070 MaxTimeForPmFsmShutDown = 120 // in seconds
Girish Gowdra5a7c4922021-01-22 18:33:41 -080071)
72
Himani Chawla43f95ff2021-06-03 00:24:12 +053073// constants for ethernet frame extended pm collection
74const (
75 ExtendedPmCreateAttempts = 3
76 UnsupportedCounterValue32bit uint64 = 4294967294
77 UnsupportedCounterValue64bit uint64 = 18446744073709551614
Himani Chawla43f95ff2021-06-03 00:24:12 +053078)
79
Girish Gowdra5a7c4922021-01-22 18:33:41 -080080// OpticalPowerGroupMetrics are supported optical pm names
81var OpticalPowerGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrae20a4f62021-03-09 16:06:23 -080082 "ani_g_instance_id": voltha.PmConfig_CONTEXT,
83 "transmit_power_dBm": voltha.PmConfig_GAUGE,
84 "receive_power_dBm": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -080085}
86
87// OpticalPowerGroupMetrics specific constants
88const (
Girish Gowdrae0140f02021-02-02 16:55:09 -080089 OpticalPowerGroupMetricName = "PON_Optical"
Girish Gowdra5a7c4922021-01-22 18:33:41 -080090 OpticalPowerGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
91 OpticalPowerMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
92)
93
94// UniStatusGroupMetrics are supported UNI status names
95var UniStatusGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrad3436802021-06-28 13:15:40 -070096 "uni_port_no": voltha.PmConfig_CONTEXT,
97 "me_class_id": voltha.PmConfig_CONTEXT,
98 "entity_id": voltha.PmConfig_CONTEXT,
99 "configuration_ind": voltha.PmConfig_GAUGE,
100 "oper_status": voltha.PmConfig_GAUGE,
101 "uni_admin_state": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800102}
103
104// UniStatusGroupMetrics specific constants
105const (
Girish Gowdrae0140f02021-02-02 16:55:09 -0800106 UniStatusGroupMetricName = "UNI_Status"
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800107 UniStatusGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
108 UniStatusMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
109)
110
Girish Gowdrae0140f02021-02-02 16:55:09 -0800111// *** Classical L2 PM Counters begin ***
112
113// EthernetBridgeHistory are supported ethernet bridge history counters fetched from
114// Ethernet Frame Performance Monitoring History Data Downstream and Ethernet Frame Performance Monitoring History Data Upstream MEs.
115var EthernetBridgeHistory = map[string]voltha.PmConfig_PmType{
116 "class_id": voltha.PmConfig_CONTEXT,
117 "entity_id": voltha.PmConfig_CONTEXT,
118 "interval_end_time": voltha.PmConfig_CONTEXT,
119 "parent_class_id": voltha.PmConfig_CONTEXT,
120 "parent_entity_id": voltha.PmConfig_CONTEXT,
121 "upstream": voltha.PmConfig_CONTEXT,
122
123 "drop_events": voltha.PmConfig_COUNTER,
124 "octets": voltha.PmConfig_COUNTER,
125 "packets": voltha.PmConfig_COUNTER,
126 "broadcast_packets": voltha.PmConfig_COUNTER,
127 "multicast_packets": voltha.PmConfig_COUNTER,
128 "crc_errored_packets": voltha.PmConfig_COUNTER,
129 "undersize_packets": voltha.PmConfig_COUNTER,
130 "oversize_packets": voltha.PmConfig_COUNTER,
131 "64_octets": voltha.PmConfig_COUNTER,
132 "65_to_127_octets": voltha.PmConfig_COUNTER,
133 "128_to_255_octets": voltha.PmConfig_COUNTER,
134 "256_to_511_octets": voltha.PmConfig_COUNTER,
135 "512_to_1023_octets": voltha.PmConfig_COUNTER,
136 "1024_to_1518_octets": voltha.PmConfig_COUNTER,
137}
138
139// EthernetUniHistory are supported ethernet uni history counters fetched from
140// Ethernet Performance Monitoring History Data ME.
141var EthernetUniHistory = map[string]voltha.PmConfig_PmType{
142 "class_id": voltha.PmConfig_CONTEXT,
143 "entity_id": voltha.PmConfig_CONTEXT,
144 "interval_end_time": voltha.PmConfig_CONTEXT,
145
146 "fcs_errors": voltha.PmConfig_COUNTER,
147 "excessive_collision_counter": voltha.PmConfig_COUNTER,
148 "late_collision_counter": voltha.PmConfig_COUNTER,
149 "frames_too_long": voltha.PmConfig_COUNTER,
150 "buffer_overflows_on_rx": voltha.PmConfig_COUNTER,
151 "buffer_overflows_on_tx": voltha.PmConfig_COUNTER,
152 "single_collision_frame_counter": voltha.PmConfig_COUNTER,
153 "multiple_collisions_frame_counter": voltha.PmConfig_COUNTER,
154 "sqe_counter": voltha.PmConfig_COUNTER,
155 "deferred_tx_counter": voltha.PmConfig_COUNTER,
156 "internal_mac_tx_error_counter": voltha.PmConfig_COUNTER,
157 "carrier_sense_error_counter": voltha.PmConfig_COUNTER,
158 "alignment_error_counter": voltha.PmConfig_COUNTER,
159 "internal_mac_rx_error_counter": voltha.PmConfig_COUNTER,
160}
161
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800162// FecHistory is supported FEC Performance Monitoring History Data related metrics
163var FecHistory = map[string]voltha.PmConfig_PmType{
164 "class_id": voltha.PmConfig_CONTEXT,
165 "entity_id": voltha.PmConfig_CONTEXT,
166 "interval_end_time": voltha.PmConfig_CONTEXT,
167
168 "corrected_bytes": voltha.PmConfig_COUNTER,
169 "corrected_code_words": voltha.PmConfig_COUNTER,
170 "uncorrectable_code_words": voltha.PmConfig_COUNTER,
171 "total_code_words": voltha.PmConfig_COUNTER,
172 "fec_seconds": voltha.PmConfig_COUNTER,
173}
174
175// GemPortHistory is supported GEM Port Network Ctp Performance Monitoring History Data
176// related metrics
177var GemPortHistory = map[string]voltha.PmConfig_PmType{
178 "class_id": voltha.PmConfig_CONTEXT,
179 "entity_id": voltha.PmConfig_CONTEXT,
180 "interval_end_time": voltha.PmConfig_CONTEXT,
181
182 "transmitted_gem_frames": voltha.PmConfig_COUNTER,
183 "received_gem_frames": voltha.PmConfig_COUNTER,
184 "received_payload_bytes": voltha.PmConfig_COUNTER,
185 "transmitted_payload_bytes": voltha.PmConfig_COUNTER,
186 "encryption_key_errors": voltha.PmConfig_COUNTER,
187}
188
Himani Chawla43f95ff2021-06-03 00:24:12 +0530189var maskToEthernetFrameExtendedPM32Bit = map[uint16][]string{
190 0x3F00: {"drop_events", "octets", "frames", "broadcast_frames", "multicast_frames", "crc_errored_frames"},
191 0x00FC: {"undersize_frames", "oversize_frames", "64_octets", "65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
192 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
193}
194
195var maskToEthernetFrameExtendedPM64Bit = map[uint16][]string{
196 0x3800: {"drop_events", "octets", "frames"},
197 0x0700: {"broadcast_frames", "multicast_frames", "crc_errored_frames"},
198 0x00E0: {"undersize_frames", "oversize_frames", "64_octets"},
199 0x001C: {"65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
200 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
201}
202
Girish Gowdrae0140f02021-02-02 16:55:09 -0800203// Constants specific for L2 PM collection
204const (
205 L2PmCollectionInterval = 15 * 60 // Unit in seconds. Do not change this as this fixed by OMCI specification for L2 PM counters
206 SyncTimeRetryInterval = 15 // Unit seconds
207 L2PmCreateAttempts = 3
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800208 L2PmDeleteAttempts = 3
Girish Gowdrae0140f02021-02-02 16:55:09 -0800209 L2PmCollectAttempts = 3
Girish Gowdra453750f2021-02-16 16:36:46 -0800210 // Per Table 11.2.9-1 – OMCI baseline message limitations in G.988 spec, the max GET Response
211 // payload size is 25. We define 24 (one less) to allow for dynamic insertion of IntervalEndTime
212 // attribute (1 byte) in L2 PM GET Requests.
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000213 MaxBaselineL2PMGetPayLoadSize = 24
214 // unused: MaxEthernetFrameExtPmPayloadSize = 25
215 MaxExtendedL2PMGetPayLoadSize = omci.MaxExtendedLength - 17 - 1 - 4 // minus header, attribute IntervalEndTime and MIC
Girish Gowdrae0140f02021-02-02 16:55:09 -0800216)
217
218// EthernetUniHistoryName specific constants
219const (
220 EthernetBridgeHistoryName = "Ethernet_Bridge_Port_History"
221 EthernetBridgeHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
222 EthernetBridgeHistoryFrequency = L2PmCollectionInterval
223)
224
225// EthernetBridgeHistory specific constants
226const (
227 EthernetUniHistoryName = "Ethernet_UNI_History"
228 EthernetUniHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
229 EthernetUniHistoryFrequency = L2PmCollectionInterval
230)
231
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800232// FecHistory specific constants
233const (
234 FecHistoryName = "FEC_History"
235 FecHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
236 FecHistoryFrequency = L2PmCollectionInterval
237)
238
239// GemPortHistory specific constants
240const (
241 GemPortHistoryName = "GEM_Port_History"
242 GemPortHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
243 GemPortHistoryFrequency = L2PmCollectionInterval
244)
245
Holger Hildebrandt60652202021-11-02 11:09:36 +0000246// CPmKvStorePrefixBase - kv store base path of ONU specific PM data
247const CPmKvStorePrefixBase = cmn.CBasePathOnuKVStore + "/pm-data" // <some-base-path>/openonu/pm-data
248
Girish Gowdra0e533642021-03-02 22:02:51 -0800249// KV Store related constants
250const (
Holger Hildebrandt60652202021-11-02 11:09:36 +0000251 cPmKvStorePrefix = CPmKvStorePrefixBase + "/%s" // <some-base-path>/openonu/pm-data/<onu-device-id>
Himani Chawla43f95ff2021-06-03 00:24:12 +0530252 cPmAdd = "add"
253 cPmAdded = "added"
254 cPmRemove = "remove"
255 cPmRemoved = "removed"
256 cExtPmKvStorePrefix = "%s/omci_me" //<some-base-path>/omci_me/<onu_vendor>/<onu_equipment_id>/<onu_sw_version>
Girish Gowdra0e533642021-03-02 22:02:51 -0800257)
258
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800259// Defines the type for generic metric population function
260type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
261
Girish Gowdrae0140f02021-02-02 16:55:09 -0800262// *** Classical L2 PM Counters end ***
263
Girish Gowdra0e533642021-03-02 22:02:51 -0800264type pmMEData struct {
265 InstancesActive []uint16 `json:"instances_active"` // list of active ME instance IDs for the group
266 InstancesToDelete []uint16 `json:"instances_to_delete"` // list of ME instance IDs marked for deletion for the group
267 InstancesToAdd []uint16 `json:"instances_to_add"` // list of ME instance IDs marked for addition for the group
268}
269
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800270type groupMetric struct {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000271 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530272 metricMap map[string]voltha.PmConfig_PmType
Girish Gowdra0e533642021-03-02 22:02:51 -0800273 pmMEData *pmMEData
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530274 groupName string
275 Frequency uint32 // valid only if FrequencyOverride is enabled.
276 collectAttempts uint32 // number of attempts to collect L2 PM data
277 Enabled bool
278 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800279}
280
281type standaloneMetric struct {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000282 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530283 metricName string
284 Frequency uint32 // valid only if FrequencyOverride is enabled.
285 Enabled bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800286}
287
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000288// OnuMetricsManager - TODO: add comment
289type OnuMetricsManager struct {
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530290 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
291
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000292 pDeviceHandler cmn.IdeviceHandler
293 pOnuDeviceEntry cmn.IonuDeviceEntry
294 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800295
Himani Chawlaee10b542021-09-20 16:46:40 +0530296 opticalMetricsChan chan me.AttributeValueMap
297 uniStatusMetricsChan chan me.AttributeValueMap
298 l2PmChan chan me.AttributeValueMap
299 extendedPmMeChan chan me.AttributeValueMap
300 syncTimeResponseChan chan bool // true is success, false is fail
301 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
302 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -0800303
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000304 GroupMetricMap map[string]*groupMetric
305 StandaloneMetricMap map[string]*standaloneMetric
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800306
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000307 StopProcessingOmciResponses chan bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800308
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530309 StopTicks chan bool
Girish Gowdraabcceb12022-04-13 23:35:22 -0700310 GarbageCollectionComplete chan bool
311
Girish Gowdra0e533642021-03-02 22:02:51 -0800312 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530313
Himani Chawlac77d5372021-07-12 15:42:26 +0530314 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
315 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530316 extPmKvStore *db.Backend
praneeth nalmas808f43a2023-05-14 12:54:34 +0530317 onuOpticalMetricstimer *time.Timer
318 onuUniStatusMetricstimer *time.Timer
praneeth nalmasf405e962023-08-07 15:02:03 +0530319 opticalMetricsDelCommChan chan bool
320 uniMetricsDelCommChan chan bool
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530321 deviceID string
322
323 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
324 l2PmToDelete []string // list of L2 PMs to delete
325 l2PmToAdd []string // list of L2 PM to add
326
327 maxL2PMGetPayLoadSize int
328
329 OnuMetricsManagerLock sync.RWMutex
330
331 onuEthernetFrameExtendedPmLock sync.RWMutex
332
333 supportedEthernetFrameExtendedPMClass me.ClassID
334 omciProcessingActive bool
335
336 tickGenerationActive bool
337
338 deviceDeletionInProgress bool
339 isDeviceReadyToCollectExtendedPmStats bool
340 isEthernetFrameExtendedPmOperationOngoing bool
341 isExtendedOmci bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800342}
343
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000344// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800345// The metrics manager module is responsible for configuration and management of individual and group metrics.
346// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
347// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
348// the collection interval configurable.
349// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
350// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000351func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800352
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000353 var metricsManager OnuMetricsManager
354 metricsManager.deviceID = dh.GetDeviceID()
355 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800356 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000357 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800358
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000359 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800360 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
361 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800362 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530363 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800364
365 metricsManager.syncTimeResponseChan = make(chan bool)
366 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530367 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800368
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000369 metricsManager.StopProcessingOmciResponses = make(chan bool)
370 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800371
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000372 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
373 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800374
Himani Chawlac77d5372021-07-12 15:42:26 +0530375 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
376 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530377
Girish Gowdraabcceb12022-04-13 23:35:22 -0700378 // make this a buffered channel so that the sender is not blocked for any reason if there is no listener
379 metricsManager.GarbageCollectionComplete = make(chan bool, 1)
380
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000381 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 -0800382 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800383 }
384
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800385 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800386
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800387 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800388 return nil
389 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800390
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800391 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000392 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800393
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000394 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
395 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800396 if metricsManager.pmKvStore == nil {
397 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000398 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800399 return nil
400 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700401 // restore data from KV store
402 if err := metricsManager.restorePmData(ctx); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000403 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700404 // we continue given that it does not effect the actual services for the ONU,
405 // but there may be some negative effect on PM collection (there may be some mismatch in
406 // the actual PM config and what is present on the device).
407 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800408
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000409 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
410 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530411 if metricsManager.extPmKvStore == nil {
412 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000413 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530414 return nil
415 }
416
praneeth nalmas808f43a2023-05-14 12:54:34 +0530417 //Metrics collection timers are initialized with a default timer value, will be stopped immediately and further
418 //timers are reset during the actual stats collection begins.
419 metricsManager.onuOpticalMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
420 metricsManager.onuOpticalMetricstimer.Stop()
421
422 metricsManager.onuUniStatusMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
423 metricsManager.onuUniStatusMetricstimer.Stop()
424
praneeth nalmasf405e962023-08-07 15:02:03 +0530425 metricsManager.opticalMetricsDelCommChan = make(chan bool, 2)
426 metricsManager.uniMetricsDelCommChan = make(chan bool, 2)
427
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000428 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800429 return &metricsManager
430}
431
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000432// InitializeMetricCollectionTime - TODO: add comment
433func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
434 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
435 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
436 mm.OnuMetricsManagerLock.Lock()
437 defer mm.OnuMetricsManagerLock.Unlock()
438 for _, v := range mm.GroupMetricMap {
439 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
440 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800441 }
442 }
443
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000444 for _, v := range mm.StandaloneMetricMap {
445 if v.Enabled {
446 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800447 }
448 }
449 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000450 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
451 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800452 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000453 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800454}
455
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000456// UpdateDefaultFrequency - TODO: add comment
457func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800458 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800459 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800460 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
461 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
462 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000463 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
464 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
465 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
466 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 -0800467 return nil
468}
469
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000470// UpdateGroupFreq - TODO: add comment
471func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800472 var newGroupFreq uint32
473 found := false
474 groupSliceIdx := 0
475 var group *voltha.PmGroupConfig
476 for groupSliceIdx, group = range pmConfigs.Groups {
477 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800478 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
479 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
480 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
481 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800482 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800483 newGroupFreq = group.GroupFreq
484 found = true
485 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800486 }
487 }
488 // if not found update group freq and next collection interval for the group
489 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000490 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800491 return fmt.Errorf("group-name-not-found-%v", aGroupName)
492 }
493
494 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000495 mm.OnuMetricsManagerLock.Lock()
496 defer mm.OnuMetricsManagerLock.Unlock()
497 for k, v := range mm.GroupMetricMap {
498 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
499 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800500 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000501 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800502 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000503 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800504 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000505 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800506 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800507 }
508 }
509 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000510 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800511 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
512 }
513 return nil
514}
515
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000516// UpdateMetricFreq - TODO: add comment
517func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800518 var newMetricFreq uint32
519 found := false
520 metricSliceIdx := 0
521 var metric *voltha.PmConfig
522 for metricSliceIdx, metric = range pmConfigs.Metrics {
523 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800524 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
525 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
526 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
527 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800528 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800529 newMetricFreq = metric.SampleFreq
530 found = true
531 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800532 }
533 }
534 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000535 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800536 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
537 }
538
539 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000540 mm.OnuMetricsManagerLock.Lock()
541 defer mm.OnuMetricsManagerLock.Unlock()
542 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800543 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000544 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800545 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000546 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800547 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000548 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800549 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000550 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800551 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800552 }
553 }
554 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000555 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800556 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
557 }
558 return nil
559}
560
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000561// UpdateGroupSupport - TODO: add comment
562func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800563 groupSliceIdx := 0
564 var group *voltha.PmGroupConfig
565
566 for groupSliceIdx, group = range pmConfigs.Groups {
567 if group.GroupName == aGroupName {
568 break
569 }
570 }
571 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000572 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800573 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
574 }
575
576 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000577 mm.OnuMetricsManagerLock.Lock()
578 defer mm.OnuMetricsManagerLock.Unlock()
579 for k, v := range mm.GroupMetricMap {
580 if k == aGroupName && v.Enabled != group.Enabled {
581 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
582 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800583 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000584 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800585 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800586 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800587 // 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 -0800588 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
589
590 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
591 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
592 // take further action
593 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800594 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800595 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000596 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
597 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800598 }
599 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000600 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800601 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800602 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800603 // 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 -0800604 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
605
606 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
607 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
608 // take further action
609 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800610 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800611 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800612 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800613 }
614 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000615 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800616 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000617 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800618 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000619 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 -0800620 }
621 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800622 }
623 }
624
625 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000626 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800627 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
628 }
629 return nil
630}
631
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000632// UpdateMetricSupport - TODO: add comment
633func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800634 metricSliceIdx := 0
635 var metric *voltha.PmConfig
636
637 for metricSliceIdx, metric = range pmConfigs.Metrics {
638 if metric.Name == aMetricName {
639 break
640 }
641 }
642
643 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000644 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800645 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
646 }
647
648 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000649 mm.OnuMetricsManagerLock.Lock()
650 defer mm.OnuMetricsManagerLock.Unlock()
651 for k, v := range mm.StandaloneMetricMap {
652 if k == aMetricName && v.Enabled != metric.Enabled {
653 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
654 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800655 // 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 +0000656 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
657 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800658 }
659 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000660 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 -0800661 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800662 }
663 }
664 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000665 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800666 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
667 }
668 return nil
669}
670
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000671// CollectAllGroupAndStandaloneMetrics - TODO: add comment
672func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
673 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800674 go mm.collectAllGroupMetrics(ctx)
675 } else {
676 go mm.collectAllStandaloneMetrics(ctx)
677 }
678}
679
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000680func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800681 go func() {
682 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300683 metricInfo, err := mm.collectOpticalMetrics(ctx)
684 if err != nil {
685 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000686 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300687 return
688 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800689 if metricInfo != nil {
690 mm.publishMetrics(ctx, metricInfo)
691 }
692 }()
693
694 go func() {
695 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300696 metricInfo, err := mm.collectUniStatusMetrics(ctx)
697 if err != nil {
698 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000699 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300700 return
701 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800702 if metricInfo != nil {
703 mm.publishMetrics(ctx, metricInfo)
704 }
705 }()
706
707 // Add more here
708}
709
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000710func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800711 // None exists as of now, add when available here
712}
713
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000714// CollectGroupMetric - TODO: add comment
715func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800716 switch groupName {
717 case OpticalPowerGroupMetricName:
718 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300719 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800720 mm.publishMetrics(ctx, mi)
721 }
722 }()
723 case UniStatusGroupMetricName:
724 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300725 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800726 mm.publishMetrics(ctx, mi)
727 }
728 }()
729 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000730 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800731 }
732}
733
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000734// CollectStandaloneMetric - TODO: add comment
735func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800736 switch metricName {
737 // None exist as of now, add when available
738 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000739 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800740 }
741}
742
743// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000744func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
745 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800746
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000747 mm.OnuMetricsManagerLock.RLock()
748 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
749 mm.OnuMetricsManagerLock.RUnlock()
750 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300751 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800752 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000753 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800754
Girish Gowdrae09a6202021-01-12 18:10:59 -0800755 var metricInfoSlice []*voltha.MetricInformation
756 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000757 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
758 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
759 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800760
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800761 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800762 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800763 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800764 Ts: float64(raisedTs),
765 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000766 DeviceId: mm.deviceID,
767 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
768 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800769 }
770
Girish Gowdrae09a6202021-01-12 18:10:59 -0800771 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000772 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800773loop:
774 for _, anigInstID := range anigInstKeys {
775 var meAttributes me.AttributeValueMap
776 opticalMetrics := make(map[string]float32)
777 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000778 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000779 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes,
780 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300781 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000782 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
783 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300784 return nil, err
785 }
786
787 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530788 mm.onuOpticalMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800789 select {
790 case meAttributes = <-mm.opticalMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530791 mm.onuOpticalMetricstimer.Stop()
792 logger.Debugw(ctx, "received optical metrics, stopping the optical metrics collection timer", log.Fields{"device-id": mm.deviceID})
793 case <-mm.onuOpticalMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000794 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 -0800795 // The metrics will be empty in this case
796 break loop
praneeth nalmasf405e962023-08-07 15:02:03 +0530797 case <-mm.opticalMetricsDelCommChan:
798 logger.Warnw(ctx, "Deleting the device, stopping optical metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
799 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800800 }
801 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800802 for k := range OpticalPowerGroupMetrics {
803 switch k {
804 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000805 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800806 opticalMetrics[k] = float32(val.(uint16))
807 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800808 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000809 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000810 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 -0800811 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800812 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000813 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000814 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 -0800815 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800816 default:
817 // do nothing
818 }
819 }
820 }
821 // create slice of metrics given that there could be more than one ANI-G instance and
822 // optical metrics are collected per ANI-G instance
823 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
824 metricInfoSlice = append(metricInfoSlice, &metricInfo)
825 }
826
ozgecanetsiab36ed572021-04-01 10:38:48 +0300827 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800828}
829
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800830// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800831// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000832func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
833 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
834 mm.OnuMetricsManagerLock.RLock()
835 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
836 mm.OnuMetricsManagerLock.RUnlock()
837 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300838 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800839 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000840 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800841
Girish Gowdrae09a6202021-01-12 18:10:59 -0800842 var metricInfoSlice []*voltha.MetricInformation
843 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000844 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
845 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
846 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800847
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800848 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800849 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700850 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800851 Ts: float64(raisedTs),
852 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000853 DeviceId: mm.deviceID,
854 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
855 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800856 }
857
Girish Gowdrae09a6202021-01-12 18:10:59 -0800858 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000859 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800860loop1:
861 for _, unigInstID := range unigInstKeys {
862 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
863 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
864 unigMetrics := make(map[string]float32)
865 var meAttributes me.AttributeValueMap
866 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000867 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000868 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes,
869 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300870 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000871 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
872 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300873 return nil, err
874 }
875 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530876 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800877 // Wait for metrics or timeout
878 select {
879 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530880 mm.onuUniStatusMetricstimer.Stop()
881 logger.Debugw(ctx, "received uni-g metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
882 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000883 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 -0800884 // The metrics could be empty in this case
885 break loop1
praneeth nalmasf405e962023-08-07 15:02:03 +0530886 case <-mm.uniMetricsDelCommChan:
887 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
888 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800889 }
890 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800891 for k := range UniStatusGroupMetrics {
892 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800893 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000894 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800895 unigMetrics[k] = float32(val.(byte))
896 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800897 default:
898 // do nothing
899 }
900 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000901 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800902 entityID := val.(uint16)
903 unigMetrics["entity_id"] = float32(entityID)
904 // 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 +0000905 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
906 if uni.EntityID == entityID {
907 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700908 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800909 }
910 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800911 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700912 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800913
Girish Gowdrae09a6202021-01-12 18:10:59 -0800914 // create slice of metrics given that there could be more than one UNI-G instance
915 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
916 metricInfoSlice = append(metricInfoSlice, &metricInfo)
917 }
918 }
919
920 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000921 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800922loop2:
923 for _, pptpInstID := range pptpInstKeys {
924 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
925 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
926 var meAttributes me.AttributeValueMap
927 pptpMetrics := make(map[string]float32)
928
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000929 requestedAttributes := me.AttributeValueMap{
930 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
931 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
932 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
933 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000934 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300935 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000936 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
937 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300938 return nil, err
939 }
940 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530941 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800942 // Wait for metrics or timeout
943 select {
944 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530945 mm.onuUniStatusMetricstimer.Stop()
946 logger.Debugw(ctx, "received pptp metrics, stopping Onu Uni Status metrics timer ", log.Fields{"device-id": mm.deviceID})
947 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000948 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 -0800949 // The metrics could be empty in this case
950 break loop2
praneeth nalmasf405e962023-08-07 15:02:03 +0530951 case <-mm.uniMetricsDelCommChan:
952 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
953 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800954 }
955
956 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800957 for k := range UniStatusGroupMetrics {
958 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700959 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000960 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800961 pptpMetrics[k] = float32(val.(byte))
962 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800963 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000964 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800965 pptpMetrics[k] = float32(val.(byte))
966 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800967 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000968 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800969 pptpMetrics[k] = float32(val.(byte))
970 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800971 default:
972 // do nothing
973 }
974 }
975 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000976 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800977 entityID := val.(uint16)
978 pptpMetrics["entity_id"] = float32(entityID)
979 // 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 +0000980 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
981 if uni.EntityID == entityID {
982 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700983 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800984 }
985 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800986 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700987 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800988
Girish Gowdrae09a6202021-01-12 18:10:59 -0800989 // create slice of metrics given that there could be more than one PPTP instance and
990 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
991 metricInfoSlice = append(metricInfoSlice, &metricInfo)
992 }
993
994 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000995 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800996loop3:
997 for _, veipInstID := range veipInstKeys {
998 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
999 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
1000 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001001 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001002
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001003 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0,
1004 me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
1005 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes,
1006 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001007 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001008 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
1009 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001010 return nil, err
1011 }
1012 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +05301013 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001014 // Wait for metrics or timeout
1015 select {
1016 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +05301017 mm.onuUniStatusMetricstimer.Stop()
1018 logger.Debugw(ctx, "received veip metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
1019 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001020 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 -08001021 // The metrics could be empty in this case
1022 break loop3
praneeth nalmasf405e962023-08-07 15:02:03 +05301023 case <-mm.uniMetricsDelCommChan:
1024 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
1025 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -08001026 }
1027
1028 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001029 for k := range UniStatusGroupMetrics {
1030 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001031 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001032 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001033 veipMetrics[k] = float32(val.(byte))
1034 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001035 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001036 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001037 veipMetrics[k] = float32(val.(byte))
1038 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001039 default:
1040 // do nothing
1041 }
1042 }
1043 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001044
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001045 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001046 entityID := val.(uint16)
1047 veipMetrics["entity_id"] = float32(entityID)
1048 // 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 +00001049 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1050 if uni.EntityID == entityID {
1051 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001052 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001053 }
1054 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001055 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001056 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001057
Girish Gowdrae09a6202021-01-12 18:10:59 -08001058 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001059 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001060 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1061 }
1062
ozgecanetsiab36ed572021-04-01 10:38:48 +03001063 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001064}
1065
1066// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001067func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001068 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001069 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001070 ke.SliceData = metricInfo
1071 ke.Type = voltha.KpiEventType_slice
1072 ke.Ts = float64(ts)
1073
Himani Chawlaf9768882021-12-01 00:18:58 +05301074 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 +00001075 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001076 }
1077}
1078
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001079// ProcessOmciMessages - TODO: add comment
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001080func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context, waitForOmciProcessor *sync.WaitGroup) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001081 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 -08001082 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001083 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001084 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001085 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001086 // is stopped - as a result of ONU going down.
1087 mm.flushMetricCollectionChannels(ctx)
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001088 // when instantiating mm it was too early, but now we can check for ONU's extended OMCI support
1089 mm.isExtendedOmci = mm.pOnuDeviceEntry.GetPersIsExtOmciSupported()
1090 if mm.isExtendedOmci {
1091 mm.maxL2PMGetPayLoadSize = MaxExtendedL2PMGetPayLoadSize
1092 } else {
1093 mm.maxL2PMGetPayLoadSize = MaxBaselineL2PMGetPayLoadSize
1094 }
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001095 mm.updateOmciProcessingStatus(true)
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001096 waitForOmciProcessor.Done()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001097 for {
1098 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001099 case <-mm.StopProcessingOmciResponses: // stop this routine
1100 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 -07001101 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001102 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001103 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001104 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001105 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001106 continue
1107 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001108 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001109
1110 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001111 case cmn.OMCI:
1112 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001113 mm.handleOmciMessage(ctx, msg)
1114 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001115 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001116 }
1117 }
1118 }
1119}
1120
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001121func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1122 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001123 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1124 switch msg.OmciMsg.MessageType {
1125 case omci.GetResponseType:
1126 //TODO: error handling
1127 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001128 case omci.SynchronizeTimeResponseType:
1129 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1130 case omci.CreateResponseType:
1131 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1132 case omci.DeleteResponseType:
1133 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301134 case omci.GetCurrentDataResponseType:
1135 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301136 case omci.SetResponseType:
1137 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001138 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001139 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001140
1141 }
1142}
1143
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001144func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001145 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1146 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001147 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1148 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001149 }
1150 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1151 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001152 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1153 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001154 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001155 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 -08001156 if msgObj.Result == me.Success {
1157 meAttributes := msgObj.Attributes
1158 switch msgObj.EntityClass {
1159 case me.AniGClassID:
1160 mm.opticalMetricsChan <- meAttributes
1161 return nil
1162 case me.UniGClassID:
1163 mm.uniStatusMetricsChan <- meAttributes
1164 return nil
1165 case me.PhysicalPathTerminationPointEthernetUniClassID:
1166 mm.uniStatusMetricsChan <- meAttributes
1167 return nil
1168 case me.VirtualEthernetInterfacePointClassID:
1169 mm.uniStatusMetricsChan <- meAttributes
1170 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001171 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1172 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001173 me.EthernetPerformanceMonitoringHistoryDataClassID,
1174 me.FecPerformanceMonitoringHistoryDataClassID,
1175 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001176 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301177 return nil
1178 case me.EthernetFrameExtendedPmClassID,
1179 me.EthernetFrameExtendedPm64BitClassID:
1180 mm.extendedPmMeChan <- meAttributes
1181 return nil
1182 default:
1183 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001184 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301185 }
1186 } else {
1187 meAttributes := msgObj.Attributes
1188 switch msgObj.EntityClass {
1189 case me.EthernetFrameExtendedPmClassID,
1190 me.EthernetFrameExtendedPm64BitClassID:
1191 // not all counters may be supported in which case we have seen some ONUs throwing
1192 // AttributeFailure error code, while correctly populating other counters it supports
1193 mm.extendedPmMeChan <- meAttributes
1194 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001195 default:
1196 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001197 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001198 }
1199 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001200 return fmt.Errorf("unhandled-omci-get-response-message")
1201}
1202
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001203func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301204 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1205 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001206 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1207 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301208 }
1209 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1210 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001211 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1212 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301213 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001214 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 +05301215 if msgObj.Result == me.Success {
1216 meAttributes := msgObj.Attributes
1217 switch msgObj.EntityClass {
1218 case me.EthernetFrameExtendedPmClassID,
1219 me.EthernetFrameExtendedPm64BitClassID:
1220 mm.extendedPmMeChan <- meAttributes
1221 return nil
1222 default:
1223 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001224 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301225 }
1226 } else {
1227 meAttributes := msgObj.Attributes
1228 switch msgObj.EntityClass {
1229 case me.EthernetFrameExtendedPmClassID,
1230 me.EthernetFrameExtendedPm64BitClassID:
1231 // not all counters may be supported in which case we have seen some ONUs throwing
1232 // AttributeFailure error code, while correctly populating other counters it supports
1233 mm.extendedPmMeChan <- meAttributes
1234 return nil
1235 default:
1236 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001237 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301238 }
1239 }
1240 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1241}
1242
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001243func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001244 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1245 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001246 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1247 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 -08001248 }
1249 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1250 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001251 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1252 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 -08001253 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001254 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001255 if msgObj.Result == me.Success {
1256 switch msgObj.EntityClass {
1257 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001258 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001259 mm.syncTimeResponseChan <- true
1260 return nil
1261 default:
1262 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001263 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001264 }
1265 }
1266 mm.syncTimeResponseChan <- false
1267 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1268 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001269}
1270
Himani Chawlaee10b542021-09-20 16:46:40 +05301271func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1272 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1273 if msgLayer == nil {
1274 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1275 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1276 }
1277 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1278 if !msgOk {
1279 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1280 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1281 }
1282 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1283 switch msgObj.EntityClass {
1284 case me.EthernetFrameExtendedPmClassID,
1285 me.EthernetFrameExtendedPm64BitClassID:
1286 mm.extendedPMMeResponseChan <- msgObj.Result
1287 return nil
1288 default:
1289 logger.Errorw(ctx, "unhandled omci set response message",
1290 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1291 }
1292 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1293}
1294
Girish Gowdrae09a6202021-01-12 18:10:59 -08001295// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001296func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001297 // flush commMetricsChan
1298 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001299 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001300 logger.Debug(ctx, "flushed common metrics channel")
1301 default:
1302 }
1303
1304 // flush opticalMetricsChan
1305 select {
1306 case <-mm.opticalMetricsChan:
1307 logger.Debug(ctx, "flushed optical metrics channel")
1308 default:
1309 }
1310
1311 // flush uniStatusMetricsChan
1312 select {
1313 case <-mm.uniStatusMetricsChan:
1314 logger.Debug(ctx, "flushed uni status metrics channel")
1315 default:
1316 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001317
1318 // flush syncTimeResponseChan
1319 select {
1320 case <-mm.syncTimeResponseChan:
1321 logger.Debug(ctx, "flushed sync time response channel")
1322 default:
1323 }
1324
1325 // flush l2PmChan
1326 select {
1327 case <-mm.l2PmChan:
1328 logger.Debug(ctx, "flushed L2 PM collection channel")
1329 default:
1330 }
1331
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001332 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001333 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001334 case <-mm.StopTicks:
1335 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001336 default:
1337 }
1338
1339}
1340
1341// ** L2 PM FSM Handlers start **
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301342// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001343func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001344 if mm.GetdeviceDeletionInProgress() {
1345 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1346 return
1347 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001348
Girish Gowdrae0140f02021-02-02 16:55:09 -08001349 // Loop through all the group metrics
1350 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1351 // list of active L2 PM list then mark it for creation
1352 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1353 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001354 mm.OnuMetricsManagerLock.Lock()
1355 for n, g := range mm.GroupMetricMap {
1356 if g.IsL2PMCounter { // it is a l2 pm counter
1357 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001358 found := false
1359 inner1:
1360 for _, v := range mm.activeL2Pms {
1361 if v == n {
1362 found = true // metric already present in active l2 pm list
1363 break inner1
1364 }
1365 }
1366 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001367 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001368 }
1369 } else { // metric not enabled.
1370 found := false
1371 inner2:
1372 for _, v := range mm.activeL2Pms {
1373 if v == n {
1374 found = true // metric is found in active l2 pm list
1375 break inner2
1376 }
1377 }
1378 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001379 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001380 }
1381 }
1382 }
1383 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001384 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001385 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001386 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001387 go func() {
1388 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001389 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1390 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001391 }
1392 }()
1393}
1394
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301395// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001396func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001397 if mm.GetdeviceDeletionInProgress() {
1398 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1399 return
1400 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001401 // Sync time with the ONU to establish 15min boundary for PM collection.
1402 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001403 // device could be deleted while waiting on sync time response
1404 if mm.GetdeviceDeletionInProgress() {
1405 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1406 return
1407 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001408 go func() {
1409 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1410 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001411 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1412 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001413 }
1414 }()
1415 }
1416 // Initiate a tick generation routine every L2PmCollectionInterval
1417 go mm.generateTicks(ctx)
1418
1419 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001420 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1421 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001422 }
1423 }()
1424}
1425
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001426func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001427 // 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 +00001428 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001429 mm.activeL2Pms = nil
1430 mm.l2PmToAdd = nil
1431 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001432 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001433 // If the FSM was stopped, then clear PM data from KV store
1434 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001435 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001436 _ = mm.clearPmGroupData(ctx) // ignore error
1437 }
1438
Girish Gowdraabcceb12022-04-13 23:35:22 -07001439 if mm.GetdeviceDeletionInProgress() {
praneeth nalmasf405e962023-08-07 15:02:03 +05301440 mm.onuOpticalMetricstimer.Stop()
1441 mm.onuUniStatusMetricstimer.Stop()
1442 mm.opticalMetricsDelCommChan <- true
1443 mm.uniMetricsDelCommChan <- true
Girish Gowdraabcceb12022-04-13 23:35:22 -07001444 mm.pDeviceHandler = nil
1445 mm.pOnuDeviceEntry = nil
1446 mm.GarbageCollectionComplete <- true
1447 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001448}
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301449
1450// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001451func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1452 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001453 if mm.GetdeviceDeletionInProgress() {
1454 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1455 return
1456 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001457
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001458 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001459 numOfPmToDelete := len(mm.l2PmToDelete)
1460 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001461 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001462
1463 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001464 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 -08001465 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001466 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1467 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001468 }
1469 }()
1470 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001471 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 -08001472 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001473 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1474 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001475 }
1476 }()
1477 }
1478}
1479
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301480// nolint:unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001481func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1482 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001483 if mm.GetdeviceDeletionInProgress() {
1484 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1485 return
1486 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001487 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001488 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001489 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1490 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001491 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001492
1493 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001494 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001495
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001496 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1497 mm.OnuMetricsManagerLock.RLock()
1498 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1499 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1500 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001501
Girish Gowdrae0140f02021-02-02 16:55:09 -08001502 switch n {
1503 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001504 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001505 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001506 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1507 metricInfoSlice = append(metricInfoSlice, metricInfo)
1508 }
1509 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1510 metricInfoSlice = append(metricInfoSlice, metricInfo)
1511 }
1512 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001513 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001514 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001515 for _, entityID := range copyOfEntityIDs {
1516 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1517 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001518 }
1519 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001520
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001521 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001522 for _, entityID := range copyOfEntityIDs {
1523 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001524 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001525 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001526 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001527 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001528 for _, entityID := range copyOfEntityIDs {
1529 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001530 metricInfoSlice = append(metricInfoSlice, metricInfo)
1531 }
1532 }
1533
Girish Gowdrae0140f02021-02-02 16:55:09 -08001534 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001535 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001536 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001537 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001538 }
1539 // Does not matter we send success or failure here.
1540 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1541 // we have not exceed max attempts to collect the PM data)
1542 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001543 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1544 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001545 }
1546 }()
1547}
1548
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301549// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001550func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001551 if mm.GetdeviceDeletionInProgress() {
1552 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1553 return nil
1554 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001555 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001556 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001557 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1558 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001559 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001560
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001561 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001562 for _, n := range copyOfL2PmToAdd {
1563 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001564 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1565 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001566 switch n {
1567 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001568 // 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 +05301569 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001570 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001571 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001572 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001573 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1574 inner1:
1575 // retry L2PmCreateAttempts times to create the instance of PM
1576 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001577 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1578 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001579 if err != nil {
1580 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001581 log.Fields{"device-id": mm.deviceID})
1582 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001583 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001584 go func(p_pmFsm *cmn.AdapterFsm) {
1585 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001586 }(pPMFsm)
1587 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301588 return fmt.Errorf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
1589 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001590 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001591 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1592 atLeastOneSuccess = true
1593 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1594 break inner1
1595 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001596 if mm.GetdeviceDeletionInProgress() {
1597 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1598 return nil
1599 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001600 }
1601 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1602 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001603 }
1604 }
1605 }
1606 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001607 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1608 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001609 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001610 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001611 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1612 inner2:
1613 // retry L2PmCreateAttempts times to create the instance of PM
1614 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001615 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1616 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001617 if err != nil {
1618 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001619 log.Fields{"device-id": mm.deviceID})
1620 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301621 return fmt.Errorf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
1622 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001623 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001624 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1625 atLeastOneSuccess = true
1626 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1627 break inner2
1628 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001629 if mm.GetdeviceDeletionInProgress() {
1630 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1631 return nil
1632 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001633 }
1634 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1635 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001636 }
1637 }
1638 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001639 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001640 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001641 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001642 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1643 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001644 if err != nil {
1645 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001646 log.Fields{"device-id": mm.deviceID})
1647 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301648 return fmt.Errorf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
1649 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001650 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001651 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1652 inner3:
1653 // retry L2PmCreateAttempts times to create the instance of PM
1654 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1655 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1656 atLeastOneSuccess = true
1657 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1658 break inner3
1659 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001660 if mm.GetdeviceDeletionInProgress() {
1661 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1662 return nil
1663 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001664 }
1665 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1666 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001667 }
1668 }
1669 case GemPortHistoryName:
1670
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001671 mm.OnuMetricsManagerLock.RLock()
1672 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1673 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1674 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001675
1676 if len(copyOfGemPortInstIDsToAdd) == 0 {
1677 // If there are no gemport history MEs to be created, just skip further processing
1678 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1679 // 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 +00001680 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001681 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001682 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001683 continue
1684 }
1685
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001686 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001687 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1688 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001689 if err != nil {
1690 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001691 log.Fields{"device-id": mm.deviceID})
1692 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301693 return fmt.Errorf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
1694 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001695 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001696 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1697 inner4:
1698 // retry L2PmCreateAttempts times to create the instance of PM
1699 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1700 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1701 atLeastOneSuccess = true
1702 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1703 break inner4
1704 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001705 if mm.GetdeviceDeletionInProgress() {
1706 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1707 return nil
1708 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001709 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001710 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1711 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1712 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001713 }
1714
Girish Gowdrae0140f02021-02-02 16:55:09 -08001715 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001716 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001717 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001718 // 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
1719 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001720 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001721 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001722 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1723 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001724 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001725 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1726 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001727 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 +00001728 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001729 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001730 // 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 -08001731 // 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 +00001732 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001733 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001734 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001735 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001736
Girish Gowdrae0140f02021-02-02 16:55:09 -08001737 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001738 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001739 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001740 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001741 }
1742 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001743 mm.OnuMetricsManagerLock.RLock()
1744 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1745 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001746 // Does not matter we send success or failure here.
1747 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1748 // we have not exceed max attempts to create the PM ME)
1749 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001750 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1751 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001752 }
1753 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001754 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001755}
1756
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301757// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001758func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001759 if mm.GetdeviceDeletionInProgress() {
1760 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1761 return nil
1762 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001763 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001764 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001765 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1766 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001767 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001768
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001769 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001770 for _, n := range copyOfL2PmToDelete {
1771 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001772 cnt := 0
1773 atLeastOneDeleteFailure := false
1774
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001775 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1776 mm.OnuMetricsManagerLock.RLock()
1777 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1778 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1779 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001780
1781 if len(copyOfEntityIDs) == 0 {
1782 // 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 +00001783 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001784 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1785 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1786 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 +00001787 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001788 continue
1789 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001790 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001791 switch n {
1792 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001793 // 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 +05301794 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001795 for _, entityID := range copyOfEntityIDs {
1796 inner1:
1797 // retry L2PmDeleteAttempts times to delete the instance of PM
1798 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001799 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1800 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001801 if err != nil {
1802 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001803 log.Fields{"device-id": mm.deviceID})
1804 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001805 if pPMFsm != nil {
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301806 //nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001807 go func(p_pmFsm *cmn.AdapterFsm) {
1808 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001809 }(pPMFsm)
1810 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301811 return fmt.Errorf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
1812 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001813 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001814 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1815 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001816 if mm.GetdeviceDeletionInProgress() {
1817 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1818 return nil
1819 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001820 atLeastOneDeleteFailure = true
1821 } else {
1822 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1823 break inner1
1824 }
1825 }
1826 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1827 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001828 }
1829 }
1830 }
1831 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001832 for _, entityID := range copyOfEntityIDs {
1833 inner2:
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().SendCreateOrDeleteEthernetUniHistoryME(
1837 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001838 if err != nil {
1839 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001840 log.Fields{"device-id": mm.deviceID})
1841 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001842 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001843 go func(p_pmFsm *cmn.AdapterFsm) {
1844 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001845 }(pmFsm)
1846 return err
1847 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301848 return fmt.Errorf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
1849 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001850 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001851 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001852 if mm.GetdeviceDeletionInProgress() {
1853 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1854 return nil
1855 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001856 atLeastOneDeleteFailure = true
1857 } else {
1858 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001859 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001860 }
1861 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001862 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1863 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1864 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001865 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001866 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001867 for _, entityID := range copyOfEntityIDs {
1868 inner3:
1869 // retry L2PmDeleteAttempts times to delete the instance of PM
1870 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001871 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1872 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001873 if err != nil {
1874 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001875 log.Fields{"device-id": mm.deviceID})
1876 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301877 return fmt.Errorf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
1878 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001879 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301880 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001881 if mm.GetdeviceDeletionInProgress() {
1882 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1883 return nil
1884 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001885 atLeastOneDeleteFailure = true
1886 } else {
1887 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1888 break inner3
1889 }
1890 }
1891 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1892 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001893 }
1894 }
1895 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001896 for _, entityID := range copyOfEntityIDs {
1897 inner4:
1898 // retry L2PmDeleteAttempts times to delete the instance of PM
1899 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001900 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1901 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001902 if err != nil {
1903 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001904 log.Fields{"device-id": mm.deviceID})
1905 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05301906 return fmt.Errorf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
1907 mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001908 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001909 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001910 if mm.GetdeviceDeletionInProgress() {
1911 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1912 return nil
1913 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001914 atLeastOneDeleteFailure = true
1915 } else {
1916 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1917 break inner4
1918 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001919 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001920 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1921 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1922 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001923 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001924 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001925 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001926 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001927 // If we could not completely clean up the PM ME then just give up.
1928 if atLeastOneDeleteFailure {
1929 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001930 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001931 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001932 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001933 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1934 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1935 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001936 mm.GroupMetricMap[n].Enabled = false
1937 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001938 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001939 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001940 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001941 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1942 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001943 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001944 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1945 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001946 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 +00001947 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001948 }
1949 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001950 mm.OnuMetricsManagerLock.RLock()
1951 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1952 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001953 // Does not matter we send success or failure here.
1954 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1955 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001956 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1957 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001958 }
1959 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001960 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001961}
1962
1963// ** L2 PM FSM Handlers end **
1964
1965// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001966func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001967 if mm.GetdeviceDeletionInProgress() {
1968 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1969 return nil
1970 }
1971
1972 if !mm.GetOmciProcessingStatus() {
1973 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})
1974 return fmt.Errorf("omci-resp-processor-not-running")
1975 }
1976
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001977 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1978 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001979 return err
1980 }
1981
1982 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001983 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1984 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1985 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001986 case syncTimeRes := <-mm.syncTimeResponseChan:
1987 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001988 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001989 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001990 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001991 return nil
1992 }
1993}
1994
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001995func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001996 var mEnt *me.ManagedEntity
1997 var omciErr me.OmciErrors
1998 var classID me.ClassID
1999 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002000 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002001 meParam := me.ParamData{EntityID: entityID}
2002 if upstream {
2003 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002004 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002005 return nil
2006 }
2007 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
2008 } else {
2009 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002010 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002011 return nil
2012 }
2013 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
2014 }
2015
Girish Gowdrae0140f02021-02-02 16:55:09 -08002016 intervalEndTime := -1
2017 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002018 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
2019 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002020 }
2021
2022 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
2023 ethPMHistData["class_id"] = float32(classID)
2024 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
2025 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
2026 ethPMHistData["parent_entity_id"] = float32(entityID)
2027 if upstream {
2028 ethPMHistData["upstream"] = float32(1)
2029 } else {
2030 ethPMHistData["upstream"] = float32(0)
2031 }
2032
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002033 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002034
Girish Gowdrae0140f02021-02-02 16:55:09 -08002035 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002036 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002037 return &metricInfo
2038}
2039
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002040func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002041 var mEnt *me.ManagedEntity
2042 var omciErr me.OmciErrors
2043 var classID me.ClassID
2044 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002045 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002046 meParam := me.ParamData{EntityID: entityID}
2047 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002048 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002049 return nil
2050 }
2051 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
2052
Girish Gowdrae0140f02021-02-02 16:55:09 -08002053 intervalEndTime := -1
2054 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002055 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
2056 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002057 }
2058
2059 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2060 ethUniHistData["class_id"] = float32(classID)
2061 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
2062
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002063 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002064
Girish Gowdrae0140f02021-02-02 16:55:09 -08002065 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002066 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002067 return &metricInfo
2068}
2069
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002070func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002071 var mEnt *me.ManagedEntity
2072 var omciErr me.OmciErrors
2073 var classID me.ClassID
2074 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002075 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002076 meParam := me.ParamData{EntityID: entityID}
2077 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002078 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002079 return nil
2080 }
2081 classID = me.FecPerformanceMonitoringHistoryDataClassID
2082
2083 intervalEndTime := -1
2084 fecHistData := make(map[string]float32)
2085 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
2086 return nil
2087 }
2088
2089 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2090 fecHistData["class_id"] = float32(classID)
2091 fecHistData["interval_end_time"] = float32(intervalEndTime)
2092
2093 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2094
2095 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002096 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002097 return &metricInfo
2098}
2099
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002100func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002101 var mEnt *me.ManagedEntity
2102 var omciErr me.OmciErrors
2103 var classID me.ClassID
2104 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002105 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002106 meParam := me.ParamData{EntityID: entityID}
2107 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002108 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002109 return nil
2110 }
2111 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2112
2113 intervalEndTime := -1
2114 gemHistData := make(map[string]float32)
2115 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
2116 return nil
2117 }
2118
2119 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2120 gemHistData["class_id"] = float32(classID)
2121 gemHistData["interval_end_time"] = float32(intervalEndTime)
2122
2123 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2124
2125 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002126 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002127 return &metricInfo
2128}
2129
Girish Gowdrae0140f02021-02-02 16:55:09 -08002130// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002131func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002132 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002133 upstream := false
2134 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2135 upstream = true
2136 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002137 // 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 +00002138 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002139 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2140 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002141 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002142 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2143 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002144 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002145 go func(p_pmFsm *cmn.AdapterFsm) {
2146 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002147 }(pmFsm)
2148 return err
2149 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302150 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002151 }
2152 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002153 select {
2154 case meAttributes = <-mm.l2PmChan:
2155 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002156 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2157 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002158 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002159 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002160 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002161 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002162 }
2163 // 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 -08002164 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002165 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002166 }
2167 }
2168 for k := range EthernetBridgeHistory {
2169 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2170 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2171 if _, ok := ethPMHistData[k]; !ok {
2172 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002173 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002174 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002175 ethPMHistData[k] = float32(val.(uint16))
2176 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002177 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002178 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002179 ethPMHistData[k] = float32(val.(uint32))
2180 }
2181 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002182 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002183 ethPMHistData[k] = float32(val.(uint32))
2184 }
2185 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002186 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002187 ethPMHistData[k] = float32(val.(uint32))
2188 }
2189 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002190 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002191 ethPMHistData[k] = float32(val.(uint32))
2192 }
2193 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002194 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002195 ethPMHistData[k] = float32(val.(uint32))
2196 }
2197 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002198 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002199 ethPMHistData[k] = float32(val.(uint32))
2200 }
2201 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002202 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002203 ethPMHistData[k] = float32(val.(uint32))
2204 }
2205 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002206 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002207 ethPMHistData[k] = float32(val.(uint32))
2208 }
2209 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002210 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002211 ethPMHistData[k] = float32(val.(uint32))
2212 }
2213 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002214 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002215 ethPMHistData[k] = float32(val.(uint32))
2216 }
2217 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002218 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002219 ethPMHistData[k] = float32(val.(uint32))
2220 }
2221 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002222 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002223 ethPMHistData[k] = float32(val.(uint32))
2224 }
2225 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002226 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002227 ethPMHistData[k] = float32(val.(uint32))
2228 }
2229 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002230 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002231 ethPMHistData[k] = float32(val.(uint32))
2232 }
2233 default:
2234 // do nothing
2235 }
2236 }
2237 }
2238 return nil
2239}
2240
2241// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002242func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002243 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002244 // 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 +03002245 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2246 requestedAttributes["IntervalEndTime"] = 0
2247 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002248 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2249 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002250 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002251 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2252 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302253 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002254 }
2255 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002256 select {
2257 case meAttributes = <-mm.l2PmChan:
2258 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002259 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2260 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002261 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002262 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002263 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002264 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002265 }
2266 // 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 -08002267 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002268 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002269 }
2270 }
2271 for k := range EthernetUniHistory {
2272 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2273 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2274 if _, ok := ethPMUniHistData[k]; !ok {
2275 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002276 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002277 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002278 ethPMUniHistData[k] = float32(val.(uint16))
2279 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002280 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002281 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002282 ethPMUniHistData[k] = float32(val.(uint32))
2283 }
2284 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002285 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002286 ethPMUniHistData[k] = float32(val.(uint32))
2287 }
2288 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002289 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002290 ethPMUniHistData[k] = float32(val.(uint32))
2291 }
2292 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002293 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002294 ethPMUniHistData[k] = float32(val.(uint32))
2295 }
2296 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002297 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002298 ethPMUniHistData[k] = float32(val.(uint32))
2299 }
2300 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002301 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002302 ethPMUniHistData[k] = float32(val.(uint32))
2303 }
2304 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002305 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002306 ethPMUniHistData[k] = float32(val.(uint32))
2307 }
2308 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002309 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002310 ethPMUniHistData[k] = float32(val.(uint32))
2311 }
2312 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002313 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002314 ethPMUniHistData[k] = float32(val.(uint32))
2315 }
2316 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002317 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002318 ethPMUniHistData[k] = float32(val.(uint32))
2319 }
2320 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002321 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002322 ethPMUniHistData[k] = float32(val.(uint32))
2323 }
2324 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002325 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002326 ethPMUniHistData[k] = float32(val.(uint32))
2327 }
2328 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002329 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002330 ethPMUniHistData[k] = float32(val.(uint32))
2331 }
2332 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002333 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002334 ethPMUniHistData[k] = float32(val.(uint32))
2335 }
2336 default:
2337 // do nothing
2338 }
2339 }
2340 }
2341 return nil
2342}
2343
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002344// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002345func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002346 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002347 // 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 +00002348 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2349 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002350 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002351 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2352 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002353 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002354 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2355 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302356 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002357 }
2358 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002359 select {
2360 case meAttributes = <-mm.l2PmChan:
2361 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002362 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2363 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002364 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002365 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002366 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002367 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002368 }
2369 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2370 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002371 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002372 }
2373 }
2374 for k := range FecHistory {
2375 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2376 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2377 if _, ok := fecHistData[k]; !ok {
2378 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002379 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002380 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002381 fecHistData[k] = float32(val.(uint16))
2382 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002383 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002384 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002385 fecHistData[k] = float32(val.(uint32))
2386 }
2387 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002388 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002389 fecHistData[k] = float32(val.(uint32))
2390 }
2391 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002392 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002393 fecHistData[k] = float32(val.(uint32))
2394 }
2395 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002396 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002397 fecHistData[k] = float32(val.(uint32))
2398 }
2399 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002400 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002401 fecHistData[k] = float32(val.(uint16))
2402 }
2403 default:
2404 // do nothing
2405 }
2406 }
2407 }
2408 return nil
2409}
2410
2411// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002412func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002413 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002414 // 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 +00002415 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2416 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002417 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002418 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2419 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002420 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002421 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2422 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302423 return fmt.Errorf("GetME-failed-%s-%s", mm.deviceID, err)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002424 }
2425 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002426 select {
2427 case meAttributes = <-mm.l2PmChan:
2428 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002429 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2430 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002431 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002432 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002433 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002434 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002435 }
2436 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2437 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002438 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002439 }
2440 }
2441 for k := range GemPortHistory {
2442 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2443 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2444 if _, ok := gemPortHistData[k]; !ok {
2445 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002446 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002447 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002448 gemPortHistData[k] = float32(val.(uint16))
2449 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002450 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002451 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002452 gemPortHistData[k] = float32(val.(uint32))
2453 }
2454 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002455 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002456 gemPortHistData[k] = float32(val.(uint32))
2457 }
2458 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002459 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002460 gemPortHistData[k] = float32(val.(uint64))
2461 }
2462 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002463 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002464 gemPortHistData[k] = float32(val.(uint64))
2465 }
2466 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002467 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002468 gemPortHistData[k] = float32(val.(uint32))
2469 }
2470 default:
2471 // do nothing
2472 }
2473 }
2474 }
2475 return nil
2476}
2477
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002478func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002479 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2480 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002481 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2482 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 -08002483 }
2484 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2485 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002486 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2487 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 -08002488 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002489 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002490 switch msgObj.EntityClass {
2491 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2492 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002493 me.EthernetPerformanceMonitoringHistoryDataClassID,
2494 me.FecPerformanceMonitoringHistoryDataClassID,
2495 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002496 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2497 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2498 mm.l2PmCreateOrDeleteResponseChan <- true
2499 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002500 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002501 mm.l2PmCreateOrDeleteResponseChan <- false
2502 }
2503 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302504 case me.EthernetFrameExtendedPmClassID,
2505 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302506 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302507 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002508 default:
2509 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002510 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002511 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002512 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002513}
2514
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002515func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002516 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2517 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002518 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2519 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 -08002520 }
2521 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2522 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002523 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2524 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 -08002525 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002526 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002527 switch msgObj.EntityClass {
2528 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2529 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002530 me.EthernetPerformanceMonitoringHistoryDataClassID,
2531 me.FecPerformanceMonitoringHistoryDataClassID,
2532 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002533 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2534 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2535 mm.l2PmCreateOrDeleteResponseChan <- true
2536 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002537 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002538 mm.l2PmCreateOrDeleteResponseChan <- false
2539 }
2540 return nil
2541 default:
2542 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002543 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002544 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002545 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002546}
2547
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002548func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002549 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002550 for {
2551 select {
2552 case <-time.After(L2PmCollectionInterval * time.Second):
2553 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002554 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2555 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002556 }
2557 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002558 case <-mm.StopTicks:
2559 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002560 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002561 return
2562 }
2563 }
2564}
2565
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002566func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002567 // Publish metrics if it is valid
2568 if metricInfoSlice != nil {
2569 mm.publishMetrics(ctx, metricInfoSlice)
2570 } else {
2571 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2572 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002573 mm.OnuMetricsManagerLock.Lock()
2574 mm.GroupMetricMap[metricName].collectAttempts++
2575 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002576 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2577 }
2578 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002579 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2580 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002581 }
2582}
2583
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302584// nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002585func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002586 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2587 var grpFunc groupMetricPopulateFunc
2588 switch classID {
2589 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2590 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2591 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2592 grpFunc = mm.populateEthernetUniHistoryMetrics
2593 case me.FecPerformanceMonitoringHistoryDataClassID:
2594 grpFunc = mm.populateFecHistoryMetrics
2595 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2596 grpFunc = mm.populateGemPortMetrics
2597 default:
2598 return fmt.Errorf("unknown-classid-%v", classID)
2599 }
2600
2601 size := 0
2602 requestedAttributes := make(me.AttributeValueMap)
2603 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002604 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2605 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2606 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2607 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2608 continue
2609 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002610 if v.Size+size <= mm.maxL2PMGetPayLoadSize {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002611 requestedAttributes[v.Name] = v.DefValue
2612 size = v.Size + size
2613 } else { // We exceeded the allow omci get size
2614 // Let's collect the attributes via get now and collect remaining in the next iteration
2615 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2616 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002617 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002618 return err
2619 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002620 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002621 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2622 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002623 }
2624 }
2625 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002626 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2627 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002628 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002629 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002630 }
2631 return nil
2632}
2633
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002634func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002635 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002636 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2637 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2638 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002639
2640 raisedTs := time.Now().Unix()
2641 mmd := voltha.MetricMetaData{
2642 Title: title,
2643 Ts: float64(raisedTs),
2644 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002645 DeviceId: mm.deviceID,
2646 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2647 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002648 }
2649
2650 // create slice of metrics given that there could be more than one VEIP instance
2651 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2652 return metricInfo
2653}
2654
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002655func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002656 valid := false
2657 if *intervalEndTime == -1 { // first time
2658 // Update the interval end time
2659 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2660 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2661 valid = true
2662 }
2663 } else {
2664 var currIntervalEndTime int
2665 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2666 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2667 }
2668 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2669 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002670 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002671 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2672 } else {
2673 valid = true
2674 }
2675 }
2676 return valid
2677}
2678
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002679func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002680 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002681 if !mm.GetOmciProcessingStatus() {
2682 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})
2683 return false
2684 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002685 select {
2686 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002687 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002688 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002689 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002690 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002691 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002692 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002693 }
2694 return false
2695}
2696
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302697// nolint: unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002698func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002699 var pmConfigSlice []*voltha.PmConfig
2700 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002701 pmConfigSlice = append(pmConfigSlice,
2702 &voltha.PmConfig{
2703 Name: k,
2704 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002705 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002706 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002707 }
2708 groupMetric := voltha.PmGroupConfig{
2709 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002710 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002711 GroupFreq: grpFreq,
2712 Metrics: pmConfigSlice,
2713 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002714 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002715
2716}
2717
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002718func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2719 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2720 if mm.PAdaptFsm == nil {
2721 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2722 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002723 return fmt.Errorf("nil-adapter-fsm")
2724 }
2725 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002726 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2727 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002728 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002729 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2730 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2731 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2732 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2733 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2734 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2735 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2736 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2737 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002738 },
2739 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002740 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2741 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2742 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2743 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2744 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2745 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2746 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2747 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002748 },
2749 )
2750 return nil
2751}
2752
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002753func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2754 mm.pDeviceHandler.InitPmConfigs()
2755 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2756 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2757 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2758 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002759
2760 // Populate group metrics.
2761 // Lets populate irrespective of GroupMetricEnabled is true or not.
2762 // The group metrics collection will decided on this flag later
2763
2764 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2765 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2766
2767 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2768 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2769
2770 // classical l2 pm counter start
2771
2772 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2773 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2774
2775 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2776 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2777
2778 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2779 FecHistoryEnabled, FecHistoryFrequency)
2780
2781 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2782 GemPortHistoryEnabled, GemPortHistoryFrequency)
2783
2784 // classical l2 pm counter end
2785
2786 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2787}
2788
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002789func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002790 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002791 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2792 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002793 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002794 Enabled: g.Enabled,
2795 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002796 }
2797 switch g.GroupName {
2798 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002799 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002800 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002801 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002802 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002803 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2804 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002805 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002806 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2807 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002808 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002809 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2810 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002811 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002812 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2813 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002814 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002815 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002816 }
2817 }
2818
2819 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002820 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2821 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002822 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002823 Enabled: m.Enabled,
2824 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002825 }
2826 switch m.Name {
2827 // None exist as of now. Add when available.
2828 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002829 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002830 }
2831 }
2832}
2833
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002834// AddGemPortForPerfMonitoring - TODO: add comment
2835func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2836 mm.OnuMetricsManagerLock.Lock()
2837 defer mm.OnuMetricsManagerLock.Unlock()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302838 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002839 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002840 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002841 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002842 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002843 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002844
2845 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2846 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2847 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2848 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2849 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002850
2851 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002852 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2853 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002854 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002855 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002856 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002857 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002858 }
2859 }()
Praneeth Kumar Nalmas8f8f0c02024-10-22 19:29:09 +05302860 mm.pOnuDeviceEntry.GetOnuDB().PutOnuSpeficMe(ctx, me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID, meAttributes)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002861}
2862
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002863// RemoveGemPortForPerfMonitoring - TODO: add comment
2864func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2865 mm.OnuMetricsManagerLock.Lock()
2866 defer mm.OnuMetricsManagerLock.Unlock()
2867 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2868 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002869 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002870 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002871
2872 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2873 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2874 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2875 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2876 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002877
2878 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002879 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2880 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002881 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002882 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002883 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002884 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002885 }
2886 }()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302887 mm.pOnuDeviceEntry.GetOnuDB().DeleteMe(me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002888}
2889
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002890func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2891 if mm.pDeviceHandler.GetOnuTP() != nil {
2892 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002893 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002894 for _, v := range gemPortInstIDs {
2895 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002896 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002897 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002898 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002899 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002900 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002901 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002902 }
2903}
2904
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002905func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2906 if mm.pDeviceHandler.GetOnuTP() != nil {
2907 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002908 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002909 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002910 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002911 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002912 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002913 }
2914 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002915 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002916 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002917}
2918
2919// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002920func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2921 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002922 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002923 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302924 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002925 }
2926 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002927 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002928 group.pmMEData = &pmMEData{}
2929 Value, err := mm.pmKvStore.Get(ctx, groupName)
2930 if err == nil {
2931 if Value != nil {
2932 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002933 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002934 tmpBytes, _ := kvstore.ToByte(Value.Value)
2935
2936 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002937 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302938 errorsList = append(errorsList, fmt.Errorf("unable-to-unmarshal-PM-data-%s-for-group-%s", mm.deviceID, groupName))
Girish Gowdra0e533642021-03-02 22:02:51 -08002939 continue
2940 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002941 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002942 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002943 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002944 continue
2945 }
2946 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002947 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05302948 errorsList = append(errorsList, fmt.Errorf("unable-to-read-from-KVstore-%s-for-group-%s", mm.deviceID, groupName))
Girish Gowdra0e533642021-03-02 22:02:51 -08002949 continue
2950 }
2951 }
2952 if len(errorsList) > 0 {
2953 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2954 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002955 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002956 return nil
2957}
2958
2959// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2960// the data must be available in cache.
2961// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002962func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2963 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002964 return grp.pmMEData, nil
2965 }
2966 // Data not in cache, try to fetch from kv store.
2967 data := &pmMEData{}
2968 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002969 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2970 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002971 }
2972 Value, err := mm.pmKvStore.Get(ctx, groupName)
2973 if err == nil {
2974 if Value != nil {
2975 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002976 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002977 tmpBytes, _ := kvstore.ToByte(Value.Value)
2978
2979 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002980 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002981 return data, err
2982 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002983 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002984 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002985 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002986 return data, err
2987 }
2988 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002989 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002990 return data, err
2991 }
2992
2993 return data, nil
2994}
2995
2996// 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 +00002997func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2998 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2999 mm.OnuMetricsManagerLock.Lock()
3000 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08003001
3002 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003003 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303004 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003005 }
3006
3007 pmMEData, err := mm.getPmData(ctx, groupName)
3008 if err != nil || pmMEData == nil {
3009 // error already logged in called function.
3010 return err
3011 }
3012 switch pmAction {
3013 case cPmAdd:
3014 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
3015 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3016 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3017 case cPmAdded:
3018 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
3019 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3020 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3021 case cPmRemove:
3022 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
3023 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3024 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3025 case cPmRemoved:
3026 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3027 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3028 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3029 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003030 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303031 return fmt.Errorf("unknown-pm-action-deviceid-%s-groupName-%s-pmaction-%s", mm.deviceID, groupName, pmAction)
Girish Gowdra0e533642021-03-02 22:02:51 -08003032 }
3033 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003034 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08003035
3036 Value, err := json.Marshal(*pmMEData)
3037 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003038 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
3039 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003040 return err
3041 }
3042 // Update back to kv store
3043 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003044 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
3045 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003046 return err
3047 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003048 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
3049 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08003050
3051 return nil
3052}
3053
3054// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003055func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
3056 mm.OnuMetricsManagerLock.Lock()
3057 defer mm.OnuMetricsManagerLock.Unlock()
3058 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003059 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003060 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303061 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003062 }
3063
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003064 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003065 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003066 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003067 // do not abort this procedure. continue to delete next group.
3068 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003069 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08003070 }
3071 }
3072
3073 return nil
3074}
3075
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003076// ClearAllPmData clears all PM data associated with the device from KV store
3077func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3078 mm.OnuMetricsManagerLock.Lock()
3079 defer mm.OnuMetricsManagerLock.Unlock()
3080 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003081 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003082 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303083 return fmt.Errorf("pmKvStore-not-set-abort-%s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08003084 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003085 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003086 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003087 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003088 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003089 value = err
3090 // do not abort this procedure - continue to delete next group.
3091 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003092 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003093 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003094 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003095 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003096 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003097 }
3098 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003099}
3100
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003101func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3102 mm.OnuMetricsManagerLock.Lock()
3103 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003104 mm.omciProcessingActive = status
3105}
3106
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003107// updateTickGenerationStatus - TODO: add comment
3108func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3109 mm.OnuMetricsManagerLock.Lock()
3110 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003111 mm.tickGenerationActive = status
3112}
3113
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003114// GetOmciProcessingStatus - TODO: add comment
3115func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3116 mm.OnuMetricsManagerLock.RLock()
3117 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003118 return mm.omciProcessingActive
3119}
3120
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003121// GetTickGenerationStatus - TODO: add comment
3122func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3123 mm.OnuMetricsManagerLock.RLock()
3124 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003125 return mm.tickGenerationActive
3126}
3127
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003128func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003129 for _, ele := range slice {
3130 if ele == n {
3131 return slice
3132 }
3133 }
3134 return append(slice, n)
3135}
3136
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003137func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003138 for i, ele := range slice {
3139 if ele == n {
3140 return append(slice[:i], slice[i+1:]...)
3141 }
3142 }
3143 return slice
3144}
3145
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003146func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003147 for _, ele := range slice {
3148 if ele == n {
3149 return slice
3150 }
3151 }
3152 return append(slice, n)
3153}
3154
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003155func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003156 for i, ele := range slice {
3157 if ele == n {
3158 return append(slice[:i], slice[i+1:]...)
3159 }
3160 }
3161 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003162}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303163
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003164func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303165 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3166 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003167 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003168 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003169 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303170 Value, err := mm.extPmKvStore.Get(ctx, key)
3171 if err == nil {
3172 if Value != nil {
3173 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003174 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303175 tmpBytes, _ := kvstore.ToByte(Value.Value)
3176
3177 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003178 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303179 return false, err
3180 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003181 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303182 // We have found the data from db, no need to get through omci get message.
3183 mm.supportedEthernetFrameExtendedPMClass = data
3184 return true, nil
3185 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003186 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303187 return false, nil
3188 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003189 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303190 return false, err
3191}
3192
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003193func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303194 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 -07003195 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3196 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})
3197 return false, fmt.Errorf("omci-processor-shutdown")
3198 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303199 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303200 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303201 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003202 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303203 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3204 if resp == me.Success || resp == me.InstanceExists {
3205 return true, nil
3206 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3207 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3208 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3209 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003210 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 +05303211 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3212 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003213 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303214 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003215 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303216 }
3217 return false, fmt.Errorf("timeout-while-waiting-for-response")
3218}
3219
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003220func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303221 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303222 // 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 +05303223 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003224 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303225 var entityID uint16
3226 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003227 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303228 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003229 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303230 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303231 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303232 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303233 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303234
3235 inner1:
3236 // retry ExtendedPmCreateAttempts times to create the instance of PM
3237 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003238 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3239 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3240 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303241 if err != nil {
3242 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003243 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303244 return false, err
3245 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303246 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3247 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303248 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303249 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303250 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303251 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303252 }
3253 break inner1
3254 } else if err != nil {
3255 if !supported {
3256 // Need to return immediately
3257 return false, err
3258 }
3259 //In case of failure, go for a retry
3260 }
3261 }
3262 if cnt == ExtendedPmCreateAttempts {
3263 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3264 return true, fmt.Errorf("unable-to-create-me")
3265 }
3266 }
3267 }
3268 return true, nil
3269}
3270
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003271func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3272 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003273 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003274 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303275 // check if we get the supported type me for ethernet frame extended pm class id
3276 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3277 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3278 }
3279 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3280 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003281 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303282 }
3283 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003284 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303285 }
3286}
3287
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003288func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303289 mm.onuEthernetFrameExtendedPmLock.Lock()
3290 mm.isDeviceReadyToCollectExtendedPmStats = true
3291 mm.onuEthernetFrameExtendedPmLock.Unlock()
3292}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003293
Himani Chawlaee10b542021-09-20 16:46:40 +05303294// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003295func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303296 //get the type of extended frame pm me supported by onu first
3297 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3298 if err != nil {
3299 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3300 return
3301 }
3302 if exist {
3303 // we have the me type, go ahead with the me type supported.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303304 //nolint:govet
Himani Chawla43f95ff2021-06-03 00:24:12 +05303305 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003306 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303307 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3308 return
3309 }
3310 mm.setAllExtPmMeCreatedFlag()
3311 return
3312 }
3313 // First try with 64 bit me
3314 // we have the me type, go ahead with the me type supported.
3315 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3316 if err != nil && !supported64Bit {
3317 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003318 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303319 "supported": supported64Bit})
3320 // Then Try with 32 bit type
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303321 //nolint:govet
Himani Chawla43f95ff2021-06-03 00:24:12 +05303322 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003323 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303324 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3325 } else if supported32Bit {
3326 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3327 mm.putExtPmMeKvStore(ctx)
3328 mm.setAllExtPmMeCreatedFlag()
3329 }
3330 } else if err == nil && supported64Bit {
3331 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3332 mm.putExtPmMeKvStore(ctx)
3333 mm.setAllExtPmMeCreatedFlag()
3334 }
3335}
3336
Himani Chawlaee10b542021-09-20 16:46:40 +05303337func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3338 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3339 uniPortEntityID := entityID
3340 if upstream {
3341 uniPortEntityID = entityID - 0x100
3342 }
3343 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3344 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3345 mm.pDeviceHandler.GetOmciTimeout(), true,
3346 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3347 if err != nil {
3348 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3349 log.Fields{"device-id": mm.deviceID})
3350 return extension.GetValueResponse_INTERNAL_ERROR, err
3351 }
3352
3353 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3354 return extension.GetValueResponse_REASON_UNDEFINED, nil
3355 }
3356 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3357}
3358
3359func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3360 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 -07003361 if !mm.GetOmciProcessingStatus() {
3362 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})
3363 return false
3364 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303365 select {
3366 case resp := <-mm.extendedPMMeResponseChan:
3367 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3368 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3369 if resp == me.Success {
3370 return true
3371 }
3372 return false
3373 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3374 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3375 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3376 }
3377 return false
3378}
3379
3380func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3381 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3382 className := "EthernetFrameExtendedPm64Bit"
3383 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3384 className = "EthernetFrameExtendedPm"
3385 }
3386 // Reset the counters if option is specified
3387 for entityID := range upstreamEntityMap {
3388 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3389 true)
3390 if err != nil {
3391 return errReason, err
3392 }
3393 }
3394
3395 for entityID := range downstreamEntityMap {
3396 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3397 true)
3398 if err != nil {
3399 return errReason, err
3400 }
3401 }
3402 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3403 // device itself.
3404 // Unset the reset bit if option is specified
3405 for entityID := range upstreamEntityMap {
3406 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3407 false)
3408 if err != nil {
3409 return errReason, err
3410 }
3411 }
3412
3413 for entityID := range downstreamEntityMap {
3414 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3415 false)
3416 if err != nil {
3417 return errReason, err
3418 }
3419 }
3420 return extension.GetValueResponse_REASON_UNDEFINED, nil
3421}
3422
3423func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3424 mm.onuEthernetFrameExtendedPmLock.Lock()
3425 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3426 mm.isEthernetFrameExtendedPmOperationOngoing = val
3427}
3428
3429func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3430 mm.onuEthernetFrameExtendedPmLock.Lock()
3431 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3432 return mm.isEthernetFrameExtendedPmOperationOngoing
3433}
3434
3435// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3436func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3437 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3438 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3439 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303440 return &extension.SingleGetValueResponse{
3441 Response: &extension.GetValueResponse{
3442 Status: extension.GetValueResponse_ERROR,
3443 ErrReason: reason,
3444 },
3445 }
3446 }
3447 mm.onuEthernetFrameExtendedPmLock.RLock()
3448 if !mm.isDeviceReadyToCollectExtendedPmStats {
3449 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303450 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303451 }
3452 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303453
3454 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3455 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3456 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3457 }
3458 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3459 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3460
3461 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3462 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3463 if onuInfo.IsUniIndex != nil {
3464 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3465 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3466 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3467 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3468 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3469 break
3470 }
3471 }
3472 if len(downstreamEntityMap) == 0 {
3473 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3474 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3475 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3476 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3477 }
3478 } else {
3479 // make a copy of all downstream and upstream maps in the local ones
3480 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3481 upstreamEntityMap[entityID] = meEnt
3482 }
3483 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3484 downstreamEntityMap[entityID] = meEnt
3485 }
3486 }
3487 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3488 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3489 // Reset the metrics first for all required me's
3490 if onuInfo.Reset_ {
3491 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3492 if err != nil {
3493 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3494 log.Fields{"device-id": mm.deviceID})
3495 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3496 }
3497 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303498 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3499 var pmUpstream extension.OmciEthernetFrameExtendedPm
3500 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303501 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3502 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3503 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3504 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303505 if !onuInfo.Reset_ {
3506 for entityID, meEnt := range upstreamEntityMap {
3507 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3508 var receivedMask uint16
3509 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3510 if receivedMask == 0 {
3511 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303512 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3513 // It might be possible that still some downstream pms are supported and hence we need to continue
3514 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3515 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303516 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303517 // Aggregate the result for upstream
3518 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3519 } else {
3520 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303521 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303522 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303523
Himani Chawlaee10b542021-09-20 16:46:40 +05303524 for entityID, meEnt := range downstreamEntityMap {
3525 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3526 var receivedMask uint16
3527 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303528 if receivedMask == 0 {
3529 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3530 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3531 // Stop collecting downstream counters for other ME's.
3532 break
3533 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303534 // Aggregate the result for downstream
3535 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3536 } else {
3537 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3538 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303539 }
3540 }
3541 singleValResp := extension.SingleGetValueResponse{
3542 Response: &extension.GetValueResponse{
3543 Status: extension.GetValueResponse_OK,
3544 Response: &extension.GetValueResponse_OnuCounters{
3545 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303546 Upstream: &pmUpstream,
3547 Downstream: &pmDownstream,
3548 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303549 },
3550 },
3551 },
3552 }
3553 return &singleValResp
3554}
3555
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303556// nolint:unparam
Himani Chawlaee10b542021-09-20 16:46:40 +05303557func (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 +05303558 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003559 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 +05303560
3561 classID = mm.supportedEthernetFrameExtendedPMClass
3562 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3563 if classID == me.EthernetFrameExtendedPmClassID {
3564 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3565 }
3566 ethPMData := make(map[string]uint64)
3567 var sumReceivedMask uint16
3568 for mask := range attributeMaskList {
3569 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3570 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003571 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303572 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303573 }
3574 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3575 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3576 //populate all counters as failure and return
3577 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3578 break
3579 }
3580 }
3581 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303582 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303583}
3584
3585// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003586func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303587 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3588 var meAttributes me.AttributeValueMap
3589 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003590 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303591 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003592 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303593 return extension.GetValueResponse_INTERNAL_ERROR, err
3594 }
3595 select {
3596 case meAttributes = <-mm.extendedPmMeChan:
3597 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003598 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3599 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303600 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003601 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303602 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3603 }
3604 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3605 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3606 *sumReceivedMask += mask
3607 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3608 } else {
3609 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3610 *sumReceivedMask += mask
3611 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3612 }
3613
3614 return extension.GetValueResponse_REASON_UNDEFINED, nil
3615}
3616
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003617func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303618 sourceMap := maskToEthernetFrameExtendedPM64Bit
3619 errorCounterValue := UnsupportedCounterValue64bit
3620 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3621 sourceMap = maskToEthernetFrameExtendedPM32Bit
3622 errorCounterValue = UnsupportedCounterValue32bit
3623 }
3624 for _, value := range sourceMap {
3625 for _, k := range value {
3626 if _, ok := ethFrameExtPMData[k]; !ok {
3627 ethFrameExtPMData[k] = errorCounterValue
3628 }
3629 }
3630 }
3631}
3632
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303633// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003634func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303635 receivedMask := uint16(0)
3636 switch requestedAttributesMask {
3637 case 0x3F00:
3638 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3639 if _, ok := ethFrameExtPMData[k]; !ok {
3640 switch k {
3641 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003642 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303643 ethFrameExtPMData[k] = uint64(val.(uint32))
3644 receivedMask |= 0x2000
3645 } else if !ok {
3646 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3647 }
3648 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003649 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303650 ethFrameExtPMData[k] = uint64(val.(uint32))
3651 receivedMask |= 0x1000
3652 } else if !ok {
3653 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3654 }
3655 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003656 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303657 ethFrameExtPMData[k] = uint64(val.(uint32))
3658 receivedMask |= 0x800
3659 } else if !ok {
3660 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3661 }
3662 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003663 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303664 ethFrameExtPMData[k] = uint64(val.(uint32))
3665 receivedMask |= 0x400
3666 } else if !ok {
3667 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3668 }
3669 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003670 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303671 ethFrameExtPMData[k] = uint64(val.(uint32))
3672 receivedMask |= 0x200
3673 } else if !ok {
3674 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3675 }
3676 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003677 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303678 ethFrameExtPMData[k] = uint64(val.(uint32))
3679 receivedMask |= 0x100
3680 } else if !ok {
3681 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3682 }
3683 default:
3684 //do nothing
3685 }
3686 }
3687 }
3688 case 0x00FC:
3689 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3690 if _, ok := ethFrameExtPMData[k]; !ok {
3691 switch k {
3692 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003693 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303694 ethFrameExtPMData[k] = uint64(val.(uint32))
3695 receivedMask |= 0x80
3696 } else if !ok {
3697 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3698 }
3699 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003700 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303701 ethFrameExtPMData[k] = uint64(val.(uint32))
3702 receivedMask |= 0x40
3703 } else if !ok {
3704 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3705 }
3706 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003707 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303708 ethFrameExtPMData[k] = uint64(val.(uint32))
3709 receivedMask |= 0x20
3710 } else if !ok {
3711 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3712 }
3713 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003714 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303715 ethFrameExtPMData[k] = uint64(val.(uint32))
3716 receivedMask |= 0x10
3717 } else if !ok {
3718 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3719 }
3720 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003721 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303722 ethFrameExtPMData[k] = uint64(val.(uint32))
3723 receivedMask |= 0x8
3724 } else if !ok {
3725 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3726 }
3727 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003728 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303729 ethFrameExtPMData[k] = uint64(val.(uint32))
3730 receivedMask |= 0x4
3731 } else if !ok {
3732 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3733 }
3734 default:
3735 //do nothing
3736 }
3737 }
3738 }
3739 case 0x0003:
3740 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3741 if _, ok := ethFrameExtPMData[k]; !ok {
3742 switch k {
3743 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003744 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303745 ethFrameExtPMData[k] = uint64(val.(uint32))
3746 receivedMask |= 0x2
3747 } else if !ok {
3748 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3749 }
3750 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003751 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303752 ethFrameExtPMData[k] = uint64(val.(uint32))
3753 receivedMask |= 0x1
3754 } else if !ok {
3755 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3756 }
3757 default:
3758 //do nothing
3759 }
3760 }
3761 }
3762 default:
3763 //do nothing
3764 }
3765 return receivedMask
3766}
3767
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05303768// nolint: gocyclo,unparam
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003769func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303770 receivedMask := uint16(0)
3771 switch requestedAttributesMask {
3772 case 0x3800:
3773 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3774 if _, ok := ethFrameExtPMData[k]; !ok {
3775 switch k {
3776 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003777 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303778 ethFrameExtPMData[k] = val.(uint64)
3779 receivedMask |= 0x2000
3780 } else if !ok {
3781 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3782 }
3783 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003784 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303785 ethFrameExtPMData[k] = val.(uint64)
3786 receivedMask |= 0x1000
3787 } else if !ok {
3788 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3789 }
3790 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003791 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303792 ethFrameExtPMData[k] = val.(uint64)
3793 receivedMask |= 0x800
3794 } else if !ok {
3795 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3796 }
3797 }
3798 }
3799 }
3800 case 0x0700:
3801 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3802 if _, ok := ethFrameExtPMData[k]; !ok {
3803 switch k {
3804 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003805 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303806 ethFrameExtPMData[k] = val.(uint64)
3807 receivedMask |= 0x400
3808 } else if !ok {
3809 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3810 }
3811 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003812 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303813 ethFrameExtPMData[k] = val.(uint64)
3814 receivedMask |= 0x200
3815 } else if !ok {
3816 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3817 }
3818 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003819 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303820 ethFrameExtPMData[k] = val.(uint64)
3821 receivedMask |= 0x100
3822 } else if !ok {
3823 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3824 }
3825 }
3826 }
3827 }
3828 case 0x00E0:
3829 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3830 if _, ok := ethFrameExtPMData[k]; !ok {
3831 switch k {
3832 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003833 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303834 ethFrameExtPMData[k] = val.(uint64)
3835 receivedMask |= 0x80
3836 } else if !ok {
3837 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3838 }
3839 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003840 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303841 ethFrameExtPMData[k] = val.(uint64)
3842 receivedMask |= 0x40
3843 } else if !ok {
3844 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3845 }
3846 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003847 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303848 ethFrameExtPMData[k] = val.(uint64)
3849 receivedMask |= 0x20
3850 } else if !ok {
3851 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3852 }
3853 }
3854 }
3855 }
3856 case 0x001C:
3857 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3858 if _, ok := ethFrameExtPMData[k]; !ok {
3859 switch k {
3860 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003861 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303862 ethFrameExtPMData[k] = val.(uint64)
3863 receivedMask |= 0x10
3864 } else if !ok {
3865 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3866 }
3867 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003868 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303869 ethFrameExtPMData[k] = val.(uint64)
3870 receivedMask |= 0x8
3871 } else if !ok {
3872 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3873 }
3874 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003875 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303876 ethFrameExtPMData[k] = val.(uint64)
3877 receivedMask |= 0x4
3878 } else if !ok {
3879 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3880 }
3881 default:
3882 //do nothing
3883 }
3884 }
3885 }
3886 case 0x0003:
3887 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3888 if _, ok := ethFrameExtPMData[k]; !ok {
3889 switch k {
3890 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003891 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303892 ethFrameExtPMData[k] = val.(uint64)
3893 receivedMask |= 0x2
3894 } else if !ok {
3895 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3896 }
3897 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003898 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303899 ethFrameExtPMData[k] = val.(uint64)
3900 receivedMask |= 0x1
3901 } else if !ok {
3902 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3903 }
3904 default:
3905 //do nothing
3906 }
3907 }
3908 }
3909 }
3910 return receivedMask
3911}
3912
Himani Chawlaee10b542021-09-20 16:46:40 +05303913func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3914 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303915 errorCounterValue := UnsupportedCounterValue64bit
3916 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3917 errorCounterValue = UnsupportedCounterValue32bit
3918 }
3919 var pmDataOut extension.OmciEthernetFrameExtendedPm
3920 if aggregate {
3921 if pmData.DropEvents != errorCounterValue {
3922 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3923 } else {
3924 pmDataOut.DropEvents = pmData.DropEvents
3925 }
3926 if pmData.Octets != errorCounterValue {
3927 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3928 } else {
3929 pmDataOut.Octets = pmData.Octets
3930 }
3931 if pmData.Frames != errorCounterValue {
3932 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3933 } else {
3934 pmDataOut.Frames = pmData.Frames
3935 }
3936 if pmData.BroadcastFrames != errorCounterValue {
3937 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3938 } else {
3939 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3940 }
3941 if pmData.MulticastFrames != errorCounterValue {
3942 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3943 } else {
3944 pmDataOut.MulticastFrames = pmData.MulticastFrames
3945 }
3946 if pmData.CrcErroredFrames != errorCounterValue {
3947 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3948 } else {
3949 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3950 }
3951 if pmData.UndersizeFrames != errorCounterValue {
3952 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3953 } else {
3954 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3955 }
3956 if pmData.OversizeFrames != errorCounterValue {
3957 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3958 } else {
3959 pmDataOut.OversizeFrames = pmData.OversizeFrames
3960 }
3961 if pmData.Frames_64Octets != errorCounterValue {
3962 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3963 } else {
3964 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3965 }
3966 if pmData.Frames_65To_127Octets != errorCounterValue {
3967 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3968 } else {
3969 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3970 }
3971 if pmData.Frames_128To_255Octets != errorCounterValue {
3972 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3973 } else {
3974 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3975 }
3976 if pmData.Frames_256To_511Octets != errorCounterValue {
3977 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3978 } else {
3979 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3980 }
3981 if pmData.Frames_512To_1023Octets != errorCounterValue {
3982 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3983 } else {
3984 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3985 }
3986 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3987 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3988 } else {
3989 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3990 }
3991 } else {
3992 pmDataOut.DropEvents = pmDataIn["drop_events"]
3993 pmDataOut.Octets = pmDataIn["octets"]
3994 pmDataOut.Frames = pmDataIn["frames"]
3995 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3996 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3997 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3998 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3999 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
4000 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
4001 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
4002 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
4003 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
4004 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
4005 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
4006 }
4007 return pmDataOut
4008}
4009
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +05304010//nolint:unparam
Himani Chawlaee10b542021-09-20 16:46:40 +05304011func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05304012 controlBlock := make([]uint16, 8)
4013 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
4014 controlBlock[0] = 0
4015 // Next two bytes are for the parent class ID
4016 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
4017 // Next two bytes are for the parent me instance id
4018 controlBlock[2] = entityID
4019 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05304020 if reset {
4021 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
4022 } else {
4023 controlBlock[3] = 0
4024 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05304025 // Next two bytes are for tca disable
4026 controlBlock[4] = 0x4000 //tca global disable
4027 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
4028 if upstream {
4029 controlBlock[5] = 1 << 0
4030 } else {
4031 controlBlock[5] = (1 << 0) | (1 << 1)
4032 }
4033 // Next two bytes are for tci - does not matter here
4034 controlBlock[6] = 0
4035 // Next two bytes are for reserved bits - does not matter here
4036 controlBlock[7] = 0
4037 return controlBlock
4038}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00004039
Girish Gowdraabcceb12022-04-13 23:35:22 -07004040// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
4041func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
4042 mm.OnuMetricsManagerLock.RLock()
4043 defer mm.OnuMetricsManagerLock.RUnlock()
4044 return mm.deviceDeletionInProgress
4045}
4046
4047// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
4048func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
4049 mm.OnuMetricsManagerLock.Lock()
4050 defer mm.OnuMetricsManagerLock.Unlock()
4051 mm.deviceDeletionInProgress = true
4052}