blob: f38fd54c2e253bf7d0e512680060dcc91262af6b [file] [log] [blame]
Girish Gowdrae09a6202021-01-12 18:10:59 -08001/*
Joey Armstronge8c091f2023-01-17 16:56:26 -05002 * Copyright 2021-2023 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 {
271 groupName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000272 Enabled bool
273 Frequency uint32 // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800274 metricMap map[string]voltha.PmConfig_PmType
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000275 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
276 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdrae0140f02021-02-02 16:55:09 -0800277 collectAttempts uint32 // number of attempts to collect L2 PM data
Girish Gowdra0e533642021-03-02 22:02:51 -0800278 pmMEData *pmMEData
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800279}
280
281type standaloneMetric struct {
282 metricName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000283 Enabled bool
284 Frequency uint32 // valid only if FrequencyOverride is enabled.
285 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800286}
287
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000288// OnuMetricsManager - TODO: add comment
289type OnuMetricsManager struct {
290 deviceID string
291 pDeviceHandler cmn.IdeviceHandler
292 pOnuDeviceEntry cmn.IonuDeviceEntry
293 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800294
Himani Chawlaee10b542021-09-20 16:46:40 +0530295 opticalMetricsChan chan me.AttributeValueMap
296 uniStatusMetricsChan chan me.AttributeValueMap
297 l2PmChan chan me.AttributeValueMap
298 extendedPmMeChan chan me.AttributeValueMap
299 syncTimeResponseChan chan bool // true is success, false is fail
300 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
301 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -0800302
303 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
304 l2PmToDelete []string // list of L2 PMs to delete
305 l2PmToAdd []string // list of L2 PM to add
Girish Gowdrae09a6202021-01-12 18:10:59 -0800306
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000307 GroupMetricMap map[string]*groupMetric
308 StandaloneMetricMap map[string]*standaloneMetric
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800309
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000310 StopProcessingOmciResponses chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700311 omciProcessingActive bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800312
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000313 StopTicks chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700314 tickGenerationActive bool
Girish Gowdrae0140f02021-02-02 16:55:09 -0800315
Girish Gowdraabcceb12022-04-13 23:35:22 -0700316 deviceDeletionInProgress bool
317 GarbageCollectionComplete chan bool
318
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000319 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800320
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000321 OnuMetricsManagerLock sync.RWMutex
Girish Gowdra0e533642021-03-02 22:02:51 -0800322
323 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530324
325 supportedEthernetFrameExtendedPMClass me.ClassID
Himani Chawlac77d5372021-07-12 15:42:26 +0530326 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
327 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530328 extPmKvStore *db.Backend
329 onuEthernetFrameExtendedPmLock sync.RWMutex
330 isDeviceReadyToCollectExtendedPmStats bool
Himani Chawlaee10b542021-09-20 16:46:40 +0530331 isEthernetFrameExtendedPmOperationOngoing bool
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000332 isExtendedOmci bool
333 maxL2PMGetPayLoadSize int
praneeth nalmas808f43a2023-05-14 12:54:34 +0530334 onuOpticalMetricstimer *time.Timer
335 onuUniStatusMetricstimer *time.Timer
praneeth nalmasf405e962023-08-07 15:02:03 +0530336 opticalMetricsDelCommChan chan bool
337 uniMetricsDelCommChan chan bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800338}
339
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000340// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800341// The metrics manager module is responsible for configuration and management of individual and group metrics.
342// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
343// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
344// the collection interval configurable.
345// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
346// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000347func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800348
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000349 var metricsManager OnuMetricsManager
350 metricsManager.deviceID = dh.GetDeviceID()
351 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800352 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000353 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800354
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000355 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800356 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
357 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800358 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530359 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800360
361 metricsManager.syncTimeResponseChan = make(chan bool)
362 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530363 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800364
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000365 metricsManager.StopProcessingOmciResponses = make(chan bool)
366 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800367
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000368 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
369 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800370
Himani Chawlac77d5372021-07-12 15:42:26 +0530371 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
372 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530373
Girish Gowdraabcceb12022-04-13 23:35:22 -0700374 // make this a buffered channel so that the sender is not blocked for any reason if there is no listener
375 metricsManager.GarbageCollectionComplete = make(chan bool, 1)
376
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000377 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 -0800378 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800379 }
380
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800381 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800382
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800383 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800384 return nil
385 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800386
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800387 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000388 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800389
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000390 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
391 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800392 if metricsManager.pmKvStore == nil {
393 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000394 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800395 return nil
396 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700397 // restore data from KV store
398 if err := metricsManager.restorePmData(ctx); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000399 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700400 // we continue given that it does not effect the actual services for the ONU,
401 // but there may be some negative effect on PM collection (there may be some mismatch in
402 // the actual PM config and what is present on the device).
403 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800404
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000405 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
406 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530407 if metricsManager.extPmKvStore == nil {
408 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000409 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530410 return nil
411 }
412
praneeth nalmas808f43a2023-05-14 12:54:34 +0530413 //Metrics collection timers are initialized with a default timer value, will be stopped immediately and further
414 //timers are reset during the actual stats collection begins.
415 metricsManager.onuOpticalMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
416 metricsManager.onuOpticalMetricstimer.Stop()
417
418 metricsManager.onuUniStatusMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
419 metricsManager.onuUniStatusMetricstimer.Stop()
420
praneeth nalmasf405e962023-08-07 15:02:03 +0530421 metricsManager.opticalMetricsDelCommChan = make(chan bool, 2)
422 metricsManager.uniMetricsDelCommChan = make(chan bool, 2)
423
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000424 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800425 return &metricsManager
426}
427
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000428// InitializeMetricCollectionTime - TODO: add comment
429func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
430 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
431 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
432 mm.OnuMetricsManagerLock.Lock()
433 defer mm.OnuMetricsManagerLock.Unlock()
434 for _, v := range mm.GroupMetricMap {
435 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
436 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800437 }
438 }
439
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000440 for _, v := range mm.StandaloneMetricMap {
441 if v.Enabled {
442 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800443 }
444 }
445 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000446 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
447 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800448 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000449 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800450}
451
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000452// UpdateDefaultFrequency - TODO: add comment
453func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800454 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800455 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800456 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
457 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
458 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000459 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
460 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
461 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
462 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 -0800463 return nil
464}
465
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000466// UpdateGroupFreq - TODO: add comment
467func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800468 var newGroupFreq uint32
469 found := false
470 groupSliceIdx := 0
471 var group *voltha.PmGroupConfig
472 for groupSliceIdx, group = range pmConfigs.Groups {
473 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800474 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
475 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
476 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
477 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800478 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800479 newGroupFreq = group.GroupFreq
480 found = true
481 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800482 }
483 }
484 // if not found update group freq and next collection interval for the group
485 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000486 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800487 return fmt.Errorf("group-name-not-found-%v", aGroupName)
488 }
489
490 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000491 mm.OnuMetricsManagerLock.Lock()
492 defer mm.OnuMetricsManagerLock.Unlock()
493 for k, v := range mm.GroupMetricMap {
494 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
495 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800496 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000497 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800498 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000499 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800500 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000501 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800502 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800503 }
504 }
505 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000506 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800507 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
508 }
509 return nil
510}
511
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000512// UpdateMetricFreq - TODO: add comment
513func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800514 var newMetricFreq uint32
515 found := false
516 metricSliceIdx := 0
517 var metric *voltha.PmConfig
518 for metricSliceIdx, metric = range pmConfigs.Metrics {
519 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800520 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
521 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
522 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
523 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800524 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800525 newMetricFreq = metric.SampleFreq
526 found = true
527 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800528 }
529 }
530 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000531 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800532 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
533 }
534
535 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000536 mm.OnuMetricsManagerLock.Lock()
537 defer mm.OnuMetricsManagerLock.Unlock()
538 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800539 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000540 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800541 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000542 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800543 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000544 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800545 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000546 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800547 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800548 }
549 }
550 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000551 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800552 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
553 }
554 return nil
555}
556
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000557// UpdateGroupSupport - TODO: add comment
558func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800559 groupSliceIdx := 0
560 var group *voltha.PmGroupConfig
561
562 for groupSliceIdx, group = range pmConfigs.Groups {
563 if group.GroupName == aGroupName {
564 break
565 }
566 }
567 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000568 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800569 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
570 }
571
572 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000573 mm.OnuMetricsManagerLock.Lock()
574 defer mm.OnuMetricsManagerLock.Unlock()
575 for k, v := range mm.GroupMetricMap {
576 if k == aGroupName && v.Enabled != group.Enabled {
577 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
578 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800579 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000580 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800581 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800582 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800583 // 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 -0800584 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
585
586 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
587 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
588 // take further action
589 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800590 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800591 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000592 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
593 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800594 }
595 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000596 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800597 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800598 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800599 // 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 -0800600 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
601
602 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
603 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
604 // take further action
605 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800606 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800607 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800608 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800609 }
610 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000611 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800612 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000613 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800614 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000615 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 -0800616 }
617 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800618 }
619 }
620
621 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000622 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800623 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
624 }
625 return nil
626}
627
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000628// UpdateMetricSupport - TODO: add comment
629func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800630 metricSliceIdx := 0
631 var metric *voltha.PmConfig
632
633 for metricSliceIdx, metric = range pmConfigs.Metrics {
634 if metric.Name == aMetricName {
635 break
636 }
637 }
638
639 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000640 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800641 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
642 }
643
644 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000645 mm.OnuMetricsManagerLock.Lock()
646 defer mm.OnuMetricsManagerLock.Unlock()
647 for k, v := range mm.StandaloneMetricMap {
648 if k == aMetricName && v.Enabled != metric.Enabled {
649 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
650 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800651 // 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 +0000652 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
653 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800654 }
655 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000656 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 -0800657 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800658 }
659 }
660 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000661 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800662 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
663 }
664 return nil
665}
666
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000667// CollectAllGroupAndStandaloneMetrics - TODO: add comment
668func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
669 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800670 go mm.collectAllGroupMetrics(ctx)
671 } else {
672 go mm.collectAllStandaloneMetrics(ctx)
673 }
674}
675
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000676func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800677 go func() {
678 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300679 metricInfo, err := mm.collectOpticalMetrics(ctx)
680 if err != nil {
681 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000682 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300683 return
684 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800685 if metricInfo != nil {
686 mm.publishMetrics(ctx, metricInfo)
687 }
688 }()
689
690 go func() {
691 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300692 metricInfo, err := mm.collectUniStatusMetrics(ctx)
693 if err != nil {
694 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000695 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300696 return
697 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800698 if metricInfo != nil {
699 mm.publishMetrics(ctx, metricInfo)
700 }
701 }()
702
703 // Add more here
704}
705
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000706func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800707 // None exists as of now, add when available here
708}
709
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000710// CollectGroupMetric - TODO: add comment
711func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800712 switch groupName {
713 case OpticalPowerGroupMetricName:
714 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300715 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800716 mm.publishMetrics(ctx, mi)
717 }
718 }()
719 case UniStatusGroupMetricName:
720 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300721 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800722 mm.publishMetrics(ctx, mi)
723 }
724 }()
725 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000726 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800727 }
728}
729
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000730// CollectStandaloneMetric - TODO: add comment
731func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800732 switch metricName {
733 // None exist as of now, add when available
734 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000735 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800736 }
737}
738
739// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000740func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
741 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800742
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000743 mm.OnuMetricsManagerLock.RLock()
744 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
745 mm.OnuMetricsManagerLock.RUnlock()
746 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300747 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800748 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000749 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800750
Girish Gowdrae09a6202021-01-12 18:10:59 -0800751 var metricInfoSlice []*voltha.MetricInformation
752 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000753 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
754 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
755 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800756
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800757 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800758 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800759 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800760 Ts: float64(raisedTs),
761 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000762 DeviceId: mm.deviceID,
763 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
764 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800765 }
766
Girish Gowdrae09a6202021-01-12 18:10:59 -0800767 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000768 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800769loop:
770 for _, anigInstID := range anigInstKeys {
771 var meAttributes me.AttributeValueMap
772 opticalMetrics := make(map[string]float32)
773 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000774 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000775 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes,
776 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300777 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000778 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
779 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300780 return nil, err
781 }
782
783 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530784 mm.onuOpticalMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800785 select {
786 case meAttributes = <-mm.opticalMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530787 mm.onuOpticalMetricstimer.Stop()
788 logger.Debugw(ctx, "received optical metrics, stopping the optical metrics collection timer", log.Fields{"device-id": mm.deviceID})
789 case <-mm.onuOpticalMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000790 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 -0800791 // The metrics will be empty in this case
792 break loop
praneeth nalmasf405e962023-08-07 15:02:03 +0530793 case <-mm.opticalMetricsDelCommChan:
794 logger.Warnw(ctx, "Deleting the device, stopping optical metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
795 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800796 }
797 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800798 for k := range OpticalPowerGroupMetrics {
799 switch k {
800 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000801 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800802 opticalMetrics[k] = float32(val.(uint16))
803 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800804 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000805 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000806 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 -0800807 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800808 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000809 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; 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 Gowdrae09a6202021-01-12 18:10:59 -0800812 default:
813 // do nothing
814 }
815 }
816 }
817 // create slice of metrics given that there could be more than one ANI-G instance and
818 // optical metrics are collected per ANI-G instance
819 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
820 metricInfoSlice = append(metricInfoSlice, &metricInfo)
821 }
822
ozgecanetsiab36ed572021-04-01 10:38:48 +0300823 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800824}
825
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800826// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800827// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000828func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
829 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
830 mm.OnuMetricsManagerLock.RLock()
831 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
832 mm.OnuMetricsManagerLock.RUnlock()
833 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300834 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800835 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000836 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800837
Girish Gowdrae09a6202021-01-12 18:10:59 -0800838 var metricInfoSlice []*voltha.MetricInformation
839 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000840 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
841 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
842 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800843
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800844 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800845 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700846 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800847 Ts: float64(raisedTs),
848 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000849 DeviceId: mm.deviceID,
850 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
851 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800852 }
853
Girish Gowdrae09a6202021-01-12 18:10:59 -0800854 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000855 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800856loop1:
857 for _, unigInstID := range unigInstKeys {
858 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
859 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
860 unigMetrics := make(map[string]float32)
861 var meAttributes me.AttributeValueMap
862 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000863 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000864 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes,
865 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300866 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000867 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
868 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300869 return nil, err
870 }
871 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530872 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800873 // Wait for metrics or timeout
874 select {
875 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530876 mm.onuUniStatusMetricstimer.Stop()
877 logger.Debugw(ctx, "received uni-g metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
878 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000879 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 -0800880 // The metrics could be empty in this case
881 break loop1
praneeth nalmasf405e962023-08-07 15:02:03 +0530882 case <-mm.uniMetricsDelCommChan:
883 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
884 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800885 }
886 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800887 for k := range UniStatusGroupMetrics {
888 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800889 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000890 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800891 unigMetrics[k] = float32(val.(byte))
892 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800893 default:
894 // do nothing
895 }
896 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000897 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800898 entityID := val.(uint16)
899 unigMetrics["entity_id"] = float32(entityID)
900 // 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 +0000901 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
902 if uni.EntityID == entityID {
903 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700904 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800905 }
906 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800907 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700908 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800909
Girish Gowdrae09a6202021-01-12 18:10:59 -0800910 // create slice of metrics given that there could be more than one UNI-G instance
911 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
912 metricInfoSlice = append(metricInfoSlice, &metricInfo)
913 }
914 }
915
916 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000917 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800918loop2:
919 for _, pptpInstID := range pptpInstKeys {
920 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
921 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
922 var meAttributes me.AttributeValueMap
923 pptpMetrics := make(map[string]float32)
924
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000925 requestedAttributes := me.AttributeValueMap{
926 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
927 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
928 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
929 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000930 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300931 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000932 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
933 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300934 return nil, err
935 }
936 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530937 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800938 // Wait for metrics or timeout
939 select {
940 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530941 mm.onuUniStatusMetricstimer.Stop()
942 logger.Debugw(ctx, "received pptp metrics, stopping Onu Uni Status metrics timer ", log.Fields{"device-id": mm.deviceID})
943 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000944 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 -0800945 // The metrics could be empty in this case
946 break loop2
praneeth nalmasf405e962023-08-07 15:02:03 +0530947 case <-mm.uniMetricsDelCommChan:
948 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
949 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800950 }
951
952 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800953 for k := range UniStatusGroupMetrics {
954 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700955 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000956 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800957 pptpMetrics[k] = float32(val.(byte))
958 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800959 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000960 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; 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 "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000964 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; 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 default:
968 // do nothing
969 }
970 }
971 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000972 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800973 entityID := val.(uint16)
974 pptpMetrics["entity_id"] = float32(entityID)
975 // 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 +0000976 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
977 if uni.EntityID == entityID {
978 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700979 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800980 }
981 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800982 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700983 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800984
Girish Gowdrae09a6202021-01-12 18:10:59 -0800985 // create slice of metrics given that there could be more than one PPTP instance and
986 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
987 metricInfoSlice = append(metricInfoSlice, &metricInfo)
988 }
989
990 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000991 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800992loop3:
993 for _, veipInstID := range veipInstKeys {
994 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
995 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
996 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800997 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800998
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000999 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0,
1000 me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
1001 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes,
1002 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001003 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001004 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
1005 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001006 return nil, err
1007 }
1008 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +05301009 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001010 // Wait for metrics or timeout
1011 select {
1012 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +05301013 mm.onuUniStatusMetricstimer.Stop()
1014 logger.Debugw(ctx, "received veip metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
1015 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001016 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 -08001017 // The metrics could be empty in this case
1018 break loop3
praneeth nalmasf405e962023-08-07 15:02:03 +05301019 case <-mm.uniMetricsDelCommChan:
1020 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
1021 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -08001022 }
1023
1024 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001025 for k := range UniStatusGroupMetrics {
1026 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001027 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001028 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001029 veipMetrics[k] = float32(val.(byte))
1030 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001031 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001032 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; 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 default:
1036 // do nothing
1037 }
1038 }
1039 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001040
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001041 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001042 entityID := val.(uint16)
1043 veipMetrics["entity_id"] = float32(entityID)
1044 // 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 +00001045 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1046 if uni.EntityID == entityID {
1047 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001048 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001049 }
1050 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001051 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001052 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001053
Girish Gowdrae09a6202021-01-12 18:10:59 -08001054 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001055 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001056 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1057 }
1058
ozgecanetsiab36ed572021-04-01 10:38:48 +03001059 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001060}
1061
1062// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001063func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001064 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001065 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001066 ke.SliceData = metricInfo
1067 ke.Type = voltha.KpiEventType_slice
1068 ke.Ts = float64(ts)
1069
Himani Chawlaf9768882021-12-01 00:18:58 +05301070 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 +00001071 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001072 }
1073}
1074
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001075// ProcessOmciMessages - TODO: add comment
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001076func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context, waitForOmciProcessor *sync.WaitGroup) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001077 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 -08001078 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001079 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001080 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001081 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001082 // is stopped - as a result of ONU going down.
1083 mm.flushMetricCollectionChannels(ctx)
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001084 // when instantiating mm it was too early, but now we can check for ONU's extended OMCI support
1085 mm.isExtendedOmci = mm.pOnuDeviceEntry.GetPersIsExtOmciSupported()
1086 if mm.isExtendedOmci {
1087 mm.maxL2PMGetPayLoadSize = MaxExtendedL2PMGetPayLoadSize
1088 } else {
1089 mm.maxL2PMGetPayLoadSize = MaxBaselineL2PMGetPayLoadSize
1090 }
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001091 mm.updateOmciProcessingStatus(true)
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001092 waitForOmciProcessor.Done()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001093 for {
1094 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001095 case <-mm.StopProcessingOmciResponses: // stop this routine
1096 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 -07001097 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001098 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001099 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001100 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001101 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001102 continue
1103 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001104 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001105
1106 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001107 case cmn.OMCI:
1108 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001109 mm.handleOmciMessage(ctx, msg)
1110 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001111 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001112 }
1113 }
1114 }
1115}
1116
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001117func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1118 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001119 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1120 switch msg.OmciMsg.MessageType {
1121 case omci.GetResponseType:
1122 //TODO: error handling
1123 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001124 case omci.SynchronizeTimeResponseType:
1125 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1126 case omci.CreateResponseType:
1127 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1128 case omci.DeleteResponseType:
1129 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301130 case omci.GetCurrentDataResponseType:
1131 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301132 case omci.SetResponseType:
1133 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001134 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001135 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001136
1137 }
1138}
1139
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001140func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001141 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1142 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001143 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1144 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001145 }
1146 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1147 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001148 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1149 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001150 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001151 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 -08001152 if msgObj.Result == me.Success {
1153 meAttributes := msgObj.Attributes
1154 switch msgObj.EntityClass {
1155 case me.AniGClassID:
1156 mm.opticalMetricsChan <- meAttributes
1157 return nil
1158 case me.UniGClassID:
1159 mm.uniStatusMetricsChan <- meAttributes
1160 return nil
1161 case me.PhysicalPathTerminationPointEthernetUniClassID:
1162 mm.uniStatusMetricsChan <- meAttributes
1163 return nil
1164 case me.VirtualEthernetInterfacePointClassID:
1165 mm.uniStatusMetricsChan <- meAttributes
1166 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001167 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1168 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001169 me.EthernetPerformanceMonitoringHistoryDataClassID,
1170 me.FecPerformanceMonitoringHistoryDataClassID,
1171 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001172 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301173 return nil
1174 case me.EthernetFrameExtendedPmClassID,
1175 me.EthernetFrameExtendedPm64BitClassID:
1176 mm.extendedPmMeChan <- meAttributes
1177 return nil
1178 default:
1179 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001180 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301181 }
1182 } else {
1183 meAttributes := msgObj.Attributes
1184 switch msgObj.EntityClass {
1185 case me.EthernetFrameExtendedPmClassID,
1186 me.EthernetFrameExtendedPm64BitClassID:
1187 // not all counters may be supported in which case we have seen some ONUs throwing
1188 // AttributeFailure error code, while correctly populating other counters it supports
1189 mm.extendedPmMeChan <- meAttributes
1190 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001191 default:
1192 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001193 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001194 }
1195 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001196 return fmt.Errorf("unhandled-omci-get-response-message")
1197}
1198
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001199func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301200 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1201 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001202 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1203 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301204 }
1205 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1206 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001207 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1208 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301209 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001210 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 +05301211 if msgObj.Result == me.Success {
1212 meAttributes := msgObj.Attributes
1213 switch msgObj.EntityClass {
1214 case me.EthernetFrameExtendedPmClassID,
1215 me.EthernetFrameExtendedPm64BitClassID:
1216 mm.extendedPmMeChan <- meAttributes
1217 return nil
1218 default:
1219 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001220 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301221 }
1222 } else {
1223 meAttributes := msgObj.Attributes
1224 switch msgObj.EntityClass {
1225 case me.EthernetFrameExtendedPmClassID,
1226 me.EthernetFrameExtendedPm64BitClassID:
1227 // not all counters may be supported in which case we have seen some ONUs throwing
1228 // AttributeFailure error code, while correctly populating other counters it supports
1229 mm.extendedPmMeChan <- meAttributes
1230 return nil
1231 default:
1232 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001233 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301234 }
1235 }
1236 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1237}
1238
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001239func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001240 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1241 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001242 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1243 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 -08001244 }
1245 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1246 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001247 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1248 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 -08001249 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001250 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001251 if msgObj.Result == me.Success {
1252 switch msgObj.EntityClass {
1253 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001254 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001255 mm.syncTimeResponseChan <- true
1256 return nil
1257 default:
1258 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001259 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001260 }
1261 }
1262 mm.syncTimeResponseChan <- false
1263 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1264 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001265}
1266
Himani Chawlaee10b542021-09-20 16:46:40 +05301267func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1268 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1269 if msgLayer == nil {
1270 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1271 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1272 }
1273 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1274 if !msgOk {
1275 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1276 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1277 }
1278 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1279 switch msgObj.EntityClass {
1280 case me.EthernetFrameExtendedPmClassID,
1281 me.EthernetFrameExtendedPm64BitClassID:
1282 mm.extendedPMMeResponseChan <- msgObj.Result
1283 return nil
1284 default:
1285 logger.Errorw(ctx, "unhandled omci set response message",
1286 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1287 }
1288 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1289}
1290
Girish Gowdrae09a6202021-01-12 18:10:59 -08001291// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001292func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001293 // flush commMetricsChan
1294 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001295 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001296 logger.Debug(ctx, "flushed common metrics channel")
1297 default:
1298 }
1299
1300 // flush opticalMetricsChan
1301 select {
1302 case <-mm.opticalMetricsChan:
1303 logger.Debug(ctx, "flushed optical metrics channel")
1304 default:
1305 }
1306
1307 // flush uniStatusMetricsChan
1308 select {
1309 case <-mm.uniStatusMetricsChan:
1310 logger.Debug(ctx, "flushed uni status metrics channel")
1311 default:
1312 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001313
1314 // flush syncTimeResponseChan
1315 select {
1316 case <-mm.syncTimeResponseChan:
1317 logger.Debug(ctx, "flushed sync time response channel")
1318 default:
1319 }
1320
1321 // flush l2PmChan
1322 select {
1323 case <-mm.l2PmChan:
1324 logger.Debug(ctx, "flushed L2 PM collection channel")
1325 default:
1326 }
1327
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001328 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001329 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001330 case <-mm.StopTicks:
1331 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001332 default:
1333 }
1334
1335}
1336
1337// ** L2 PM FSM Handlers start **
1338
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001339func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001340 if mm.GetdeviceDeletionInProgress() {
1341 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1342 return
1343 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001344
Girish Gowdrae0140f02021-02-02 16:55:09 -08001345 // Loop through all the group metrics
1346 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1347 // list of active L2 PM list then mark it for creation
1348 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1349 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001350 mm.OnuMetricsManagerLock.Lock()
1351 for n, g := range mm.GroupMetricMap {
1352 if g.IsL2PMCounter { // it is a l2 pm counter
1353 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001354 found := false
1355 inner1:
1356 for _, v := range mm.activeL2Pms {
1357 if v == n {
1358 found = true // metric already present in active l2 pm list
1359 break inner1
1360 }
1361 }
1362 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001363 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001364 }
1365 } else { // metric not enabled.
1366 found := false
1367 inner2:
1368 for _, v := range mm.activeL2Pms {
1369 if v == n {
1370 found = true // metric is found in active l2 pm list
1371 break inner2
1372 }
1373 }
1374 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001375 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001376 }
1377 }
1378 }
1379 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001380 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001381 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001382 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001383 go func() {
1384 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001385 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1386 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001387 }
1388 }()
1389}
1390
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001391func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001392 if mm.GetdeviceDeletionInProgress() {
1393 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1394 return
1395 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001396 // Sync time with the ONU to establish 15min boundary for PM collection.
1397 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001398 // device could be deleted while waiting on sync time response
1399 if mm.GetdeviceDeletionInProgress() {
1400 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1401 return
1402 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001403 go func() {
1404 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1405 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001406 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1407 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001408 }
1409 }()
1410 }
1411 // Initiate a tick generation routine every L2PmCollectionInterval
1412 go mm.generateTicks(ctx)
1413
1414 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001415 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1416 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001417 }
1418 }()
1419}
1420
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001421func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001422 // 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 +00001423 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001424 mm.activeL2Pms = nil
1425 mm.l2PmToAdd = nil
1426 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001427 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001428 // If the FSM was stopped, then clear PM data from KV store
1429 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001430 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001431 _ = mm.clearPmGroupData(ctx) // ignore error
1432 }
1433
Girish Gowdraabcceb12022-04-13 23:35:22 -07001434 if mm.GetdeviceDeletionInProgress() {
praneeth nalmasf405e962023-08-07 15:02:03 +05301435 mm.onuOpticalMetricstimer.Stop()
1436 mm.onuUniStatusMetricstimer.Stop()
1437 mm.opticalMetricsDelCommChan <- true
1438 mm.uniMetricsDelCommChan <- true
Girish Gowdraabcceb12022-04-13 23:35:22 -07001439 mm.pDeviceHandler = nil
1440 mm.pOnuDeviceEntry = nil
1441 mm.GarbageCollectionComplete <- true
1442 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001443}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001444func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1445 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001446 if mm.GetdeviceDeletionInProgress() {
1447 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1448 return
1449 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001450
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001451 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001452 numOfPmToDelete := len(mm.l2PmToDelete)
1453 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001454 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001455
1456 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001457 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 -08001458 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001459 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1460 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001461 }
1462 }()
1463 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001464 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 -08001465 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001466 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); 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 }
1471}
1472
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001473func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1474 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001475 if mm.GetdeviceDeletionInProgress() {
1476 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1477 return
1478 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001479 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001480 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001481 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1482 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001483 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001484
1485 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001486 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001487
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001488 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1489 mm.OnuMetricsManagerLock.RLock()
1490 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1491 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1492 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001493
Girish Gowdrae0140f02021-02-02 16:55:09 -08001494 switch n {
1495 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001496 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001497 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001498 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1499 metricInfoSlice = append(metricInfoSlice, metricInfo)
1500 }
1501 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1502 metricInfoSlice = append(metricInfoSlice, metricInfo)
1503 }
1504 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001505 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001506 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001507 for _, entityID := range copyOfEntityIDs {
1508 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1509 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001510 }
1511 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001512
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001513 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001514 for _, entityID := range copyOfEntityIDs {
1515 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001516 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001517 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001518 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001519 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001520 for _, entityID := range copyOfEntityIDs {
1521 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001522 metricInfoSlice = append(metricInfoSlice, metricInfo)
1523 }
1524 }
1525
Girish Gowdrae0140f02021-02-02 16:55:09 -08001526 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001527 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001528 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001529 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001530 }
1531 // Does not matter we send success or failure here.
1532 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1533 // we have not exceed max attempts to collect the PM data)
1534 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001535 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1536 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001537 }
1538 }()
1539}
1540
Girish Gowdra0e533642021-03-02 22:02:51 -08001541// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001542func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001543 if mm.GetdeviceDeletionInProgress() {
1544 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1545 return nil
1546 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001547 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001548 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001549 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1550 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001551 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001552
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001553 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001554 for _, n := range copyOfL2PmToAdd {
1555 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001556 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1557 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001558 switch n {
1559 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001560 // 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 +05301561 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001562 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001563 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001564 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001565 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1566 inner1:
1567 // retry L2PmCreateAttempts times to create the instance of PM
1568 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001569 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1570 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001571 if err != nil {
1572 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001573 log.Fields{"device-id": mm.deviceID})
1574 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001575 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001576 go func(p_pmFsm *cmn.AdapterFsm) {
1577 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001578 }(pPMFsm)
1579 }
1580 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001581 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001582 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001583 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1584 atLeastOneSuccess = true
1585 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1586 break inner1
1587 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001588 if mm.GetdeviceDeletionInProgress() {
1589 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1590 return nil
1591 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001592 }
1593 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1594 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001595 }
1596 }
1597 }
1598 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001599 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1600 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001601 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001602 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001603 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1604 inner2:
1605 // retry L2PmCreateAttempts times to create the instance of PM
1606 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001607 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1608 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001609 if err != nil {
1610 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001611 log.Fields{"device-id": mm.deviceID})
1612 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001613 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001614 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001615 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001616 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1617 atLeastOneSuccess = true
1618 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1619 break inner2
1620 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001621 if mm.GetdeviceDeletionInProgress() {
1622 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1623 return nil
1624 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001625 }
1626 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1627 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001628 }
1629 }
1630 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001631 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001632 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001633 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001634 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1635 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001636 if err != nil {
1637 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001638 log.Fields{"device-id": mm.deviceID})
1639 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001640 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001641 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001642 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001643 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1644 inner3:
1645 // retry L2PmCreateAttempts times to create the instance of PM
1646 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1647 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1648 atLeastOneSuccess = true
1649 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1650 break inner3
1651 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001652 if mm.GetdeviceDeletionInProgress() {
1653 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1654 return nil
1655 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001656 }
1657 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1658 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001659 }
1660 }
1661 case GemPortHistoryName:
1662
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001663 mm.OnuMetricsManagerLock.RLock()
1664 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1665 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1666 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001667
1668 if len(copyOfGemPortInstIDsToAdd) == 0 {
1669 // If there are no gemport history MEs to be created, just skip further processing
1670 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1671 // 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 +00001672 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001673 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001674 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001675 continue
1676 }
1677
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001678 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001679 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1680 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001681 if err != nil {
1682 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001683 log.Fields{"device-id": mm.deviceID})
1684 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001685 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001686 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001687 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001688 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1689 inner4:
1690 // retry L2PmCreateAttempts times to create the instance of PM
1691 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1692 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1693 atLeastOneSuccess = true
1694 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1695 break inner4
1696 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001697 if mm.GetdeviceDeletionInProgress() {
1698 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1699 return nil
1700 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001701 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001702 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1703 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1704 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001705 }
1706
Girish Gowdrae0140f02021-02-02 16:55:09 -08001707 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001708 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001709 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001710 // 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
1711 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001712 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001713 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001714 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1715 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001716 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001717 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1718 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001719 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 +00001720 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001721 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001722 // 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 -08001723 // 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 +00001724 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001725 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001726 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001727 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001728
Girish Gowdrae0140f02021-02-02 16:55:09 -08001729 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001730 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001731 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001732 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001733 }
1734 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001735 mm.OnuMetricsManagerLock.RLock()
1736 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1737 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001738 // Does not matter we send success or failure here.
1739 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1740 // we have not exceed max attempts to create the PM ME)
1741 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001742 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1743 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001744 }
1745 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001746 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001747}
1748
Girish Gowdra0e533642021-03-02 22:02:51 -08001749// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001750func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001751 if mm.GetdeviceDeletionInProgress() {
1752 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1753 return nil
1754 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001755 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001756 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001757 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1758 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001759 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001760
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001761 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001762 for _, n := range copyOfL2PmToDelete {
1763 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001764 cnt := 0
1765 atLeastOneDeleteFailure := false
1766
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001767 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1768 mm.OnuMetricsManagerLock.RLock()
1769 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1770 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1771 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001772
1773 if len(copyOfEntityIDs) == 0 {
1774 // 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 +00001775 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001776 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1777 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1778 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 +00001779 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001780 continue
1781 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001782 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001783 switch n {
1784 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001785 // 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 +05301786 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001787 for _, entityID := range copyOfEntityIDs {
1788 inner1:
1789 // retry L2PmDeleteAttempts times to delete the instance of PM
1790 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001791 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1792 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001793 if err != nil {
1794 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001795 log.Fields{"device-id": mm.deviceID})
1796 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001797 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001798 go func(p_pmFsm *cmn.AdapterFsm) {
1799 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001800 }(pPMFsm)
1801 }
1802 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001803 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001804 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001805 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1806 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001807 if mm.GetdeviceDeletionInProgress() {
1808 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1809 return nil
1810 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001811 atLeastOneDeleteFailure = true
1812 } else {
1813 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1814 break inner1
1815 }
1816 }
1817 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1818 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001819 }
1820 }
1821 }
1822 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001823 for _, entityID := range copyOfEntityIDs {
1824 inner2:
1825 // retry L2PmDeleteAttempts times to delete the instance of PM
1826 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001827 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1828 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001829 if err != nil {
1830 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001831 log.Fields{"device-id": mm.deviceID})
1832 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001833 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001834 go func(p_pmFsm *cmn.AdapterFsm) {
1835 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001836 }(pmFsm)
1837 return err
1838 }
1839 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001840 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001841 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001842 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001843 if mm.GetdeviceDeletionInProgress() {
1844 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1845 return nil
1846 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001847 atLeastOneDeleteFailure = true
1848 } else {
1849 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001850 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001851 }
1852 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001853 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1854 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1855 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001856 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001857 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001858 for _, entityID := range copyOfEntityIDs {
1859 inner3:
1860 // retry L2PmDeleteAttempts times to delete the instance of PM
1861 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001862 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1863 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001864 if err != nil {
1865 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001866 log.Fields{"device-id": mm.deviceID})
1867 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001868 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001869 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001870 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001871 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001872 if mm.GetdeviceDeletionInProgress() {
1873 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1874 return nil
1875 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001876 atLeastOneDeleteFailure = true
1877 } else {
1878 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1879 break inner3
1880 }
1881 }
1882 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1883 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001884 }
1885 }
1886 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001887 for _, entityID := range copyOfEntityIDs {
1888 inner4:
1889 // retry L2PmDeleteAttempts times to delete the instance of PM
1890 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001891 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1892 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001893 if err != nil {
1894 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001895 log.Fields{"device-id": mm.deviceID})
1896 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001897 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001898 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001899 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001900 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001901 if mm.GetdeviceDeletionInProgress() {
1902 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1903 return nil
1904 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001905 atLeastOneDeleteFailure = true
1906 } else {
1907 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1908 break inner4
1909 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001910 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001911 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1912 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1913 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001914 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001915 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001916 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001917 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001918 // If we could not completely clean up the PM ME then just give up.
1919 if atLeastOneDeleteFailure {
1920 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001921 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001922 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001923 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001924 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1925 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1926 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001927 mm.GroupMetricMap[n].Enabled = false
1928 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001929 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001930 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001931 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001932 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1933 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001934 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001935 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1936 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001937 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 +00001938 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001939 }
1940 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001941 mm.OnuMetricsManagerLock.RLock()
1942 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1943 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001944 // Does not matter we send success or failure here.
1945 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1946 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001947 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1948 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001949 }
1950 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001951 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001952}
1953
1954// ** L2 PM FSM Handlers end **
1955
1956// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001957func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001958 if mm.GetdeviceDeletionInProgress() {
1959 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1960 return nil
1961 }
1962
1963 if !mm.GetOmciProcessingStatus() {
1964 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})
1965 return fmt.Errorf("omci-resp-processor-not-running")
1966 }
1967
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001968 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1969 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001970 return err
1971 }
1972
1973 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001974 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1975 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1976 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001977 case syncTimeRes := <-mm.syncTimeResponseChan:
1978 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001979 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001980 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001981 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001982 return nil
1983 }
1984}
1985
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001986func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001987 var mEnt *me.ManagedEntity
1988 var omciErr me.OmciErrors
1989 var classID me.ClassID
1990 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001991 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001992 meParam := me.ParamData{EntityID: entityID}
1993 if upstream {
1994 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001995 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001996 return nil
1997 }
1998 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1999 } else {
2000 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002001 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002002 return nil
2003 }
2004 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
2005 }
2006
Girish Gowdrae0140f02021-02-02 16:55:09 -08002007 intervalEndTime := -1
2008 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002009 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
2010 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002011 }
2012
2013 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
2014 ethPMHistData["class_id"] = float32(classID)
2015 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
2016 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
2017 ethPMHistData["parent_entity_id"] = float32(entityID)
2018 if upstream {
2019 ethPMHistData["upstream"] = float32(1)
2020 } else {
2021 ethPMHistData["upstream"] = float32(0)
2022 }
2023
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002024 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002025
Girish Gowdrae0140f02021-02-02 16:55:09 -08002026 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002027 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002028 return &metricInfo
2029}
2030
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002031func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002032 var mEnt *me.ManagedEntity
2033 var omciErr me.OmciErrors
2034 var classID me.ClassID
2035 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002036 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002037 meParam := me.ParamData{EntityID: entityID}
2038 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002039 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002040 return nil
2041 }
2042 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
2043
Girish Gowdrae0140f02021-02-02 16:55:09 -08002044 intervalEndTime := -1
2045 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002046 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
2047 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002048 }
2049
2050 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2051 ethUniHistData["class_id"] = float32(classID)
2052 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
2053
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002054 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002055
Girish Gowdrae0140f02021-02-02 16:55:09 -08002056 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002057 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002058 return &metricInfo
2059}
2060
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002061func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002062 var mEnt *me.ManagedEntity
2063 var omciErr me.OmciErrors
2064 var classID me.ClassID
2065 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002066 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002067 meParam := me.ParamData{EntityID: entityID}
2068 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002069 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002070 return nil
2071 }
2072 classID = me.FecPerformanceMonitoringHistoryDataClassID
2073
2074 intervalEndTime := -1
2075 fecHistData := make(map[string]float32)
2076 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
2077 return nil
2078 }
2079
2080 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2081 fecHistData["class_id"] = float32(classID)
2082 fecHistData["interval_end_time"] = float32(intervalEndTime)
2083
2084 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2085
2086 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002087 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002088 return &metricInfo
2089}
2090
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002091func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002092 var mEnt *me.ManagedEntity
2093 var omciErr me.OmciErrors
2094 var classID me.ClassID
2095 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002096 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002097 meParam := me.ParamData{EntityID: entityID}
2098 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002099 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002100 return nil
2101 }
2102 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2103
2104 intervalEndTime := -1
2105 gemHistData := make(map[string]float32)
2106 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
2107 return nil
2108 }
2109
2110 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2111 gemHistData["class_id"] = float32(classID)
2112 gemHistData["interval_end_time"] = float32(intervalEndTime)
2113
2114 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2115
2116 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002117 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002118 return &metricInfo
2119}
2120
Girish Gowdrae0140f02021-02-02 16:55:09 -08002121// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002122func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002123 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002124 upstream := false
2125 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2126 upstream = true
2127 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002128 // 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 +00002129 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002130 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2131 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002132 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002133 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2134 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002135 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002136 go func(p_pmFsm *cmn.AdapterFsm) {
2137 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002138 }(pmFsm)
2139 return err
2140 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002141 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002142 }
2143 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002144 select {
2145 case meAttributes = <-mm.l2PmChan:
2146 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002147 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2148 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002149 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002150 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002151 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002152 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002153 }
2154 // 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 -08002155 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002156 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002157 }
2158 }
2159 for k := range EthernetBridgeHistory {
2160 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2161 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2162 if _, ok := ethPMHistData[k]; !ok {
2163 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002164 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002165 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002166 ethPMHistData[k] = float32(val.(uint16))
2167 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002168 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002169 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002170 ethPMHistData[k] = float32(val.(uint32))
2171 }
2172 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002173 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002174 ethPMHistData[k] = float32(val.(uint32))
2175 }
2176 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002177 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002178 ethPMHistData[k] = float32(val.(uint32))
2179 }
2180 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002181 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002182 ethPMHistData[k] = float32(val.(uint32))
2183 }
2184 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002185 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002186 ethPMHistData[k] = float32(val.(uint32))
2187 }
2188 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002189 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002190 ethPMHistData[k] = float32(val.(uint32))
2191 }
2192 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002193 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002194 ethPMHistData[k] = float32(val.(uint32))
2195 }
2196 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002197 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002198 ethPMHistData[k] = float32(val.(uint32))
2199 }
2200 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002201 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002202 ethPMHistData[k] = float32(val.(uint32))
2203 }
2204 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002205 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002206 ethPMHistData[k] = float32(val.(uint32))
2207 }
2208 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002209 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002210 ethPMHistData[k] = float32(val.(uint32))
2211 }
2212 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002213 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002214 ethPMHistData[k] = float32(val.(uint32))
2215 }
2216 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002217 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002218 ethPMHistData[k] = float32(val.(uint32))
2219 }
2220 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002221 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002222 ethPMHistData[k] = float32(val.(uint32))
2223 }
2224 default:
2225 // do nothing
2226 }
2227 }
2228 }
2229 return nil
2230}
2231
2232// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002233func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002234 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002235 // 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 +03002236 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2237 requestedAttributes["IntervalEndTime"] = 0
2238 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002239 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2240 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002241 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002242 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2243 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2244 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002245 }
2246 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002247 select {
2248 case meAttributes = <-mm.l2PmChan:
2249 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002250 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2251 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002252 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002253 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002254 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002255 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002256 }
2257 // 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 -08002258 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002259 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002260 }
2261 }
2262 for k := range EthernetUniHistory {
2263 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2264 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2265 if _, ok := ethPMUniHistData[k]; !ok {
2266 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002267 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002268 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002269 ethPMUniHistData[k] = float32(val.(uint16))
2270 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002271 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002272 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002273 ethPMUniHistData[k] = float32(val.(uint32))
2274 }
2275 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002276 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002277 ethPMUniHistData[k] = float32(val.(uint32))
2278 }
2279 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002280 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002281 ethPMUniHistData[k] = float32(val.(uint32))
2282 }
2283 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002284 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002285 ethPMUniHistData[k] = float32(val.(uint32))
2286 }
2287 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002288 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002289 ethPMUniHistData[k] = float32(val.(uint32))
2290 }
2291 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002292 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002293 ethPMUniHistData[k] = float32(val.(uint32))
2294 }
2295 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002296 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002297 ethPMUniHistData[k] = float32(val.(uint32))
2298 }
2299 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002300 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002301 ethPMUniHistData[k] = float32(val.(uint32))
2302 }
2303 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002304 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002305 ethPMUniHistData[k] = float32(val.(uint32))
2306 }
2307 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002308 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002309 ethPMUniHistData[k] = float32(val.(uint32))
2310 }
2311 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002312 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002313 ethPMUniHistData[k] = float32(val.(uint32))
2314 }
2315 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002316 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002317 ethPMUniHistData[k] = float32(val.(uint32))
2318 }
2319 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002320 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002321 ethPMUniHistData[k] = float32(val.(uint32))
2322 }
2323 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002324 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002325 ethPMUniHistData[k] = float32(val.(uint32))
2326 }
2327 default:
2328 // do nothing
2329 }
2330 }
2331 }
2332 return nil
2333}
2334
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002335// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002336func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002337 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002338 // 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 +00002339 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2340 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002341 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002342 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2343 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002344 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002345 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2346 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2347 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002348 }
2349 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002350 select {
2351 case meAttributes = <-mm.l2PmChan:
2352 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002353 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2354 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002355 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002356 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002357 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002358 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002359 }
2360 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2361 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002362 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002363 }
2364 }
2365 for k := range FecHistory {
2366 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2367 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2368 if _, ok := fecHistData[k]; !ok {
2369 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002370 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002371 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002372 fecHistData[k] = float32(val.(uint16))
2373 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002374 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002375 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002376 fecHistData[k] = float32(val.(uint32))
2377 }
2378 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002379 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002380 fecHistData[k] = float32(val.(uint32))
2381 }
2382 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002383 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002384 fecHistData[k] = float32(val.(uint32))
2385 }
2386 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002387 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002388 fecHistData[k] = float32(val.(uint32))
2389 }
2390 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002391 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002392 fecHistData[k] = float32(val.(uint16))
2393 }
2394 default:
2395 // do nothing
2396 }
2397 }
2398 }
2399 return nil
2400}
2401
2402// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002403func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002404 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002405 // 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 +00002406 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2407 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002408 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002409 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2410 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002411 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002412 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2413 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2414 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002415 }
2416 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002417 select {
2418 case meAttributes = <-mm.l2PmChan:
2419 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002420 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2421 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002422 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002423 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002424 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002425 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002426 }
2427 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2428 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002429 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002430 }
2431 }
2432 for k := range GemPortHistory {
2433 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2434 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2435 if _, ok := gemPortHistData[k]; !ok {
2436 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002437 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002438 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002439 gemPortHistData[k] = float32(val.(uint16))
2440 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002441 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002442 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002443 gemPortHistData[k] = float32(val.(uint32))
2444 }
2445 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002446 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002447 gemPortHistData[k] = float32(val.(uint32))
2448 }
2449 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002450 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002451 gemPortHistData[k] = float32(val.(uint64))
2452 }
2453 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002454 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002455 gemPortHistData[k] = float32(val.(uint64))
2456 }
2457 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002458 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002459 gemPortHistData[k] = float32(val.(uint32))
2460 }
2461 default:
2462 // do nothing
2463 }
2464 }
2465 }
2466 return nil
2467}
2468
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002469func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002470 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2471 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002472 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2473 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 -08002474 }
2475 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2476 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002477 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2478 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 -08002479 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002480 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002481 switch msgObj.EntityClass {
2482 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2483 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002484 me.EthernetPerformanceMonitoringHistoryDataClassID,
2485 me.FecPerformanceMonitoringHistoryDataClassID,
2486 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002487 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2488 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2489 mm.l2PmCreateOrDeleteResponseChan <- true
2490 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002491 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002492 mm.l2PmCreateOrDeleteResponseChan <- false
2493 }
2494 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302495 case me.EthernetFrameExtendedPmClassID,
2496 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302497 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302498 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002499 default:
2500 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002501 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002502 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002503 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002504}
2505
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002506func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002507 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2508 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002509 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2510 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 -08002511 }
2512 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2513 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002514 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2515 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 -08002516 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002517 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002518 switch msgObj.EntityClass {
2519 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2520 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002521 me.EthernetPerformanceMonitoringHistoryDataClassID,
2522 me.FecPerformanceMonitoringHistoryDataClassID,
2523 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002524 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2525 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2526 mm.l2PmCreateOrDeleteResponseChan <- true
2527 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002528 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002529 mm.l2PmCreateOrDeleteResponseChan <- false
2530 }
2531 return nil
2532 default:
2533 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002534 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002535 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002536 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002537}
2538
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002539func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002540 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002541 for {
2542 select {
2543 case <-time.After(L2PmCollectionInterval * time.Second):
2544 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002545 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2546 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002547 }
2548 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002549 case <-mm.StopTicks:
2550 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002551 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002552 return
2553 }
2554 }
2555}
2556
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002557func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002558 // Publish metrics if it is valid
2559 if metricInfoSlice != nil {
2560 mm.publishMetrics(ctx, metricInfoSlice)
2561 } else {
2562 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2563 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002564 mm.OnuMetricsManagerLock.Lock()
2565 mm.GroupMetricMap[metricName].collectAttempts++
2566 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002567 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2568 }
2569 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002570 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2571 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002572 }
2573}
2574
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002575func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002576 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2577 var grpFunc groupMetricPopulateFunc
2578 switch classID {
2579 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2580 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2581 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2582 grpFunc = mm.populateEthernetUniHistoryMetrics
2583 case me.FecPerformanceMonitoringHistoryDataClassID:
2584 grpFunc = mm.populateFecHistoryMetrics
2585 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2586 grpFunc = mm.populateGemPortMetrics
2587 default:
2588 return fmt.Errorf("unknown-classid-%v", classID)
2589 }
2590
2591 size := 0
2592 requestedAttributes := make(me.AttributeValueMap)
2593 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002594 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2595 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2596 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2597 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2598 continue
2599 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002600 if v.Size+size <= mm.maxL2PMGetPayLoadSize {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002601 requestedAttributes[v.Name] = v.DefValue
2602 size = v.Size + size
2603 } else { // We exceeded the allow omci get size
2604 // Let's collect the attributes via get now and collect remaining in the next iteration
2605 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2606 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002607 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002608 return err
2609 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002610 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002611 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2612 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002613 }
2614 }
2615 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002616 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2617 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002618 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002619 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002620 }
2621 return nil
2622}
2623
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002624func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002625 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002626 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2627 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2628 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002629
2630 raisedTs := time.Now().Unix()
2631 mmd := voltha.MetricMetaData{
2632 Title: title,
2633 Ts: float64(raisedTs),
2634 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002635 DeviceId: mm.deviceID,
2636 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2637 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002638 }
2639
2640 // create slice of metrics given that there could be more than one VEIP instance
2641 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2642 return metricInfo
2643}
2644
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002645func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002646 valid := false
2647 if *intervalEndTime == -1 { // first time
2648 // Update the interval end time
2649 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2650 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2651 valid = true
2652 }
2653 } else {
2654 var currIntervalEndTime int
2655 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2656 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2657 }
2658 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2659 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002660 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002661 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2662 } else {
2663 valid = true
2664 }
2665 }
2666 return valid
2667}
2668
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002669func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002670 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002671 if !mm.GetOmciProcessingStatus() {
2672 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})
2673 return false
2674 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002675 select {
2676 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002677 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002678 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002679 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002680 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002681 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002682 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002683 }
2684 return false
2685}
2686
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002687func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002688 var pmConfigSlice []*voltha.PmConfig
2689 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002690 pmConfigSlice = append(pmConfigSlice,
2691 &voltha.PmConfig{
2692 Name: k,
2693 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002694 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002695 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002696 }
2697 groupMetric := voltha.PmGroupConfig{
2698 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002699 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002700 GroupFreq: grpFreq,
2701 Metrics: pmConfigSlice,
2702 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002703 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002704
2705}
2706
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002707func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2708 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2709 if mm.PAdaptFsm == nil {
2710 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2711 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002712 return fmt.Errorf("nil-adapter-fsm")
2713 }
2714 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002715 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2716 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002717 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002718 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2719 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2720 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2721 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2722 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2723 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2724 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2725 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2726 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002727 },
2728 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002729 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2730 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2731 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2732 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2733 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2734 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2735 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2736 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002737 },
2738 )
2739 return nil
2740}
2741
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002742func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2743 mm.pDeviceHandler.InitPmConfigs()
2744 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2745 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2746 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2747 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002748
2749 // Populate group metrics.
2750 // Lets populate irrespective of GroupMetricEnabled is true or not.
2751 // The group metrics collection will decided on this flag later
2752
2753 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2754 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2755
2756 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2757 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2758
2759 // classical l2 pm counter start
2760
2761 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2762 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2763
2764 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2765 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2766
2767 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2768 FecHistoryEnabled, FecHistoryFrequency)
2769
2770 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2771 GemPortHistoryEnabled, GemPortHistoryFrequency)
2772
2773 // classical l2 pm counter end
2774
2775 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2776}
2777
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002778func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002779 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002780 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2781 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002782 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002783 Enabled: g.Enabled,
2784 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002785 }
2786 switch g.GroupName {
2787 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002788 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002789 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002790 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002791 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002792 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2793 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002794 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002795 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2796 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002797 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002798 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2799 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002800 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002801 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2802 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002803 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002804 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002805 }
2806 }
2807
2808 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002809 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2810 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002811 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002812 Enabled: m.Enabled,
2813 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002814 }
2815 switch m.Name {
2816 // None exist as of now. Add when available.
2817 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002818 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002819 }
2820 }
2821}
2822
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002823// AddGemPortForPerfMonitoring - TODO: add comment
2824func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2825 mm.OnuMetricsManagerLock.Lock()
2826 defer mm.OnuMetricsManagerLock.Unlock()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302827 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002828 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002829 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002830 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002831 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002832 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002833
2834 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2835 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2836 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2837 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2838 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002839
2840 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002841 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2842 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002843 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002844 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002845 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002846 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002847 }
2848 }()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302849 mm.pOnuDeviceEntry.GetOnuDB().PutMe(ctx, me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID, meAttributes)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002850}
2851
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002852// RemoveGemPortForPerfMonitoring - TODO: add comment
2853func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2854 mm.OnuMetricsManagerLock.Lock()
2855 defer mm.OnuMetricsManagerLock.Unlock()
2856 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2857 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002858 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002859 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002860
2861 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2862 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2863 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2864 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2865 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002866
2867 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002868 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2869 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002870 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002871 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002872 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002873 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002874 }
2875 }()
praneeth kumar nalmas3947c582023-12-13 15:38:50 +05302876 mm.pOnuDeviceEntry.GetOnuDB().DeleteMe(me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002877}
2878
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002879func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2880 if mm.pDeviceHandler.GetOnuTP() != nil {
2881 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002882 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002883 for _, v := range gemPortInstIDs {
2884 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002885 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002886 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002887 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002888 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002889 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002890 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002891 }
2892}
2893
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002894func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2895 if mm.pDeviceHandler.GetOnuTP() != nil {
2896 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002897 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002898 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002899 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002900 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002901 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002902 }
2903 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002904 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002905 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002906}
2907
2908// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002909func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2910 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002911 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002912 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2913 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002914 }
2915 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002916 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002917 group.pmMEData = &pmMEData{}
2918 Value, err := mm.pmKvStore.Get(ctx, groupName)
2919 if err == nil {
2920 if Value != nil {
2921 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002922 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002923 tmpBytes, _ := kvstore.ToByte(Value.Value)
2924
2925 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002926 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2927 errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-PM-data-%s-for-group-%s", mm.deviceID, groupName)))
Girish Gowdra0e533642021-03-02 22:02:51 -08002928 continue
2929 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002930 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002931 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002932 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002933 continue
2934 }
2935 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002936 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2937 errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s-for-group-%s", mm.deviceID, groupName)))
Girish Gowdra0e533642021-03-02 22:02:51 -08002938 continue
2939 }
2940 }
2941 if len(errorsList) > 0 {
2942 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2943 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002944 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002945 return nil
2946}
2947
2948// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2949// the data must be available in cache.
2950// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002951func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2952 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002953 return grp.pmMEData, nil
2954 }
2955 // Data not in cache, try to fetch from kv store.
2956 data := &pmMEData{}
2957 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002958 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2959 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002960 }
2961 Value, err := mm.pmKvStore.Get(ctx, groupName)
2962 if err == nil {
2963 if Value != nil {
2964 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002965 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002966 tmpBytes, _ := kvstore.ToByte(Value.Value)
2967
2968 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002969 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002970 return data, err
2971 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002972 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002973 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002974 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002975 return data, err
2976 }
2977 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002978 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002979 return data, err
2980 }
2981
2982 return data, nil
2983}
2984
2985// 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 +00002986func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2987 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2988 mm.OnuMetricsManagerLock.Lock()
2989 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002990
2991 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002992 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2993 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002994 }
2995
2996 pmMEData, err := mm.getPmData(ctx, groupName)
2997 if err != nil || pmMEData == nil {
2998 // error already logged in called function.
2999 return err
3000 }
3001 switch pmAction {
3002 case cPmAdd:
3003 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
3004 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3005 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3006 case cPmAdded:
3007 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
3008 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3009 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3010 case cPmRemove:
3011 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
3012 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3013 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3014 case cPmRemoved:
3015 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3016 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3017 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3018 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003019 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
3020 return fmt.Errorf(fmt.Sprintf("unknown-pm-action-deviceid-%s-groupName-%s-pmaction-%s", mm.deviceID, groupName, pmAction))
Girish Gowdra0e533642021-03-02 22:02:51 -08003021 }
3022 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003023 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08003024
3025 Value, err := json.Marshal(*pmMEData)
3026 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003027 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
3028 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003029 return err
3030 }
3031 // Update back to kv store
3032 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003033 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
3034 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003035 return err
3036 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003037 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
3038 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08003039
3040 return nil
3041}
3042
3043// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003044func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
3045 mm.OnuMetricsManagerLock.Lock()
3046 defer mm.OnuMetricsManagerLock.Unlock()
3047 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003048 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003049 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3050 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003051 }
3052
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003053 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003054 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003055 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003056 // do not abort this procedure. continue to delete next group.
3057 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003058 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08003059 }
3060 }
3061
3062 return nil
3063}
3064
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003065// ClearAllPmData clears all PM data associated with the device from KV store
3066func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3067 mm.OnuMetricsManagerLock.Lock()
3068 defer mm.OnuMetricsManagerLock.Unlock()
3069 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003070 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003071 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3072 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003073 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003074 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003075 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003076 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003077 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003078 value = err
3079 // do not abort this procedure - continue to delete next group.
3080 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003081 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003082 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003083 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003084 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003085 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003086 }
3087 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003088}
3089
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003090func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3091 mm.OnuMetricsManagerLock.Lock()
3092 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003093 mm.omciProcessingActive = status
3094}
3095
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003096// updateTickGenerationStatus - TODO: add comment
3097func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3098 mm.OnuMetricsManagerLock.Lock()
3099 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003100 mm.tickGenerationActive = status
3101}
3102
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003103// GetOmciProcessingStatus - TODO: add comment
3104func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3105 mm.OnuMetricsManagerLock.RLock()
3106 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003107 return mm.omciProcessingActive
3108}
3109
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003110// GetTickGenerationStatus - TODO: add comment
3111func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3112 mm.OnuMetricsManagerLock.RLock()
3113 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003114 return mm.tickGenerationActive
3115}
3116
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003117func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003118 for _, ele := range slice {
3119 if ele == n {
3120 return slice
3121 }
3122 }
3123 return append(slice, n)
3124}
3125
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003126func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003127 for i, ele := range slice {
3128 if ele == n {
3129 return append(slice[:i], slice[i+1:]...)
3130 }
3131 }
3132 return slice
3133}
3134
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003135func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003136 for _, ele := range slice {
3137 if ele == n {
3138 return slice
3139 }
3140 }
3141 return append(slice, n)
3142}
3143
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003144func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003145 for i, ele := range slice {
3146 if ele == n {
3147 return append(slice[:i], slice[i+1:]...)
3148 }
3149 }
3150 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003151}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303152
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003153func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303154 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3155 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003156 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003157 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003158 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303159 Value, err := mm.extPmKvStore.Get(ctx, key)
3160 if err == nil {
3161 if Value != nil {
3162 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003163 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303164 tmpBytes, _ := kvstore.ToByte(Value.Value)
3165
3166 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003167 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303168 return false, err
3169 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003170 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303171 // We have found the data from db, no need to get through omci get message.
3172 mm.supportedEthernetFrameExtendedPMClass = data
3173 return true, nil
3174 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003175 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303176 return false, nil
3177 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003178 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303179 return false, err
3180}
3181
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003182func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303183 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 -07003184 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3185 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})
3186 return false, fmt.Errorf("omci-processor-shutdown")
3187 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303188 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303189 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303190 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003191 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303192 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3193 if resp == me.Success || resp == me.InstanceExists {
3194 return true, nil
3195 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3196 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3197 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3198 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003199 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 +05303200 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3201 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003202 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303203 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003204 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303205 }
3206 return false, fmt.Errorf("timeout-while-waiting-for-response")
3207}
3208
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003209func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303210 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303211 // 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 +05303212 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003213 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303214 var entityID uint16
3215 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003216 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303217 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003218 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303219 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303220 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303221 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303222 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303223
3224 inner1:
3225 // retry ExtendedPmCreateAttempts times to create the instance of PM
3226 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003227 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3228 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3229 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303230 if err != nil {
3231 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003232 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303233 return false, err
3234 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303235 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3236 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303237 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303238 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303239 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303240 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303241 }
3242 break inner1
3243 } else if err != nil {
3244 if !supported {
3245 // Need to return immediately
3246 return false, err
3247 }
3248 //In case of failure, go for a retry
3249 }
3250 }
3251 if cnt == ExtendedPmCreateAttempts {
3252 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3253 return true, fmt.Errorf("unable-to-create-me")
3254 }
3255 }
3256 }
3257 return true, nil
3258}
3259
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003260func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3261 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003262 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003263 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303264 // check if we get the supported type me for ethernet frame extended pm class id
3265 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3266 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3267 }
3268 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3269 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003270 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303271 }
3272 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003273 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303274 }
3275}
3276
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003277func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303278 mm.onuEthernetFrameExtendedPmLock.Lock()
3279 mm.isDeviceReadyToCollectExtendedPmStats = true
3280 mm.onuEthernetFrameExtendedPmLock.Unlock()
3281}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003282
Himani Chawlaee10b542021-09-20 16:46:40 +05303283// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003284func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303285 //get the type of extended frame pm me supported by onu first
3286 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3287 if err != nil {
3288 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3289 return
3290 }
3291 if exist {
3292 // we have the me type, go ahead with the me type supported.
3293 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003294 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303295 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3296 return
3297 }
3298 mm.setAllExtPmMeCreatedFlag()
3299 return
3300 }
3301 // First try with 64 bit me
3302 // we have the me type, go ahead with the me type supported.
3303 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3304 if err != nil && !supported64Bit {
3305 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003306 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303307 "supported": supported64Bit})
3308 // Then Try with 32 bit type
3309 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003310 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303311 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3312 } else if supported32Bit {
3313 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3314 mm.putExtPmMeKvStore(ctx)
3315 mm.setAllExtPmMeCreatedFlag()
3316 }
3317 } else if err == nil && supported64Bit {
3318 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3319 mm.putExtPmMeKvStore(ctx)
3320 mm.setAllExtPmMeCreatedFlag()
3321 }
3322}
3323
Himani Chawlaee10b542021-09-20 16:46:40 +05303324func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3325 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3326 uniPortEntityID := entityID
3327 if upstream {
3328 uniPortEntityID = entityID - 0x100
3329 }
3330 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3331 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3332 mm.pDeviceHandler.GetOmciTimeout(), true,
3333 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3334 if err != nil {
3335 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3336 log.Fields{"device-id": mm.deviceID})
3337 return extension.GetValueResponse_INTERNAL_ERROR, err
3338 }
3339
3340 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3341 return extension.GetValueResponse_REASON_UNDEFINED, nil
3342 }
3343 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3344}
3345
3346func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3347 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 -07003348 if !mm.GetOmciProcessingStatus() {
3349 logger.Errorw(ctx, "not waiting for omci resp, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
3350 return false
3351 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303352 select {
3353 case resp := <-mm.extendedPMMeResponseChan:
3354 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3355 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3356 if resp == me.Success {
3357 return true
3358 }
3359 return false
3360 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3361 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3362 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3363 }
3364 return false
3365}
3366
3367func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3368 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3369 className := "EthernetFrameExtendedPm64Bit"
3370 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3371 className = "EthernetFrameExtendedPm"
3372 }
3373 // Reset the counters if option is specified
3374 for entityID := range upstreamEntityMap {
3375 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3376 true)
3377 if err != nil {
3378 return errReason, err
3379 }
3380 }
3381
3382 for entityID := range downstreamEntityMap {
3383 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3384 true)
3385 if err != nil {
3386 return errReason, err
3387 }
3388 }
3389 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3390 // device itself.
3391 // Unset the reset bit if option is specified
3392 for entityID := range upstreamEntityMap {
3393 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3394 false)
3395 if err != nil {
3396 return errReason, err
3397 }
3398 }
3399
3400 for entityID := range downstreamEntityMap {
3401 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3402 false)
3403 if err != nil {
3404 return errReason, err
3405 }
3406 }
3407 return extension.GetValueResponse_REASON_UNDEFINED, nil
3408}
3409
3410func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3411 mm.onuEthernetFrameExtendedPmLock.Lock()
3412 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3413 mm.isEthernetFrameExtendedPmOperationOngoing = val
3414}
3415
3416func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3417 mm.onuEthernetFrameExtendedPmLock.Lock()
3418 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3419 return mm.isEthernetFrameExtendedPmOperationOngoing
3420}
3421
3422// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3423func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3424 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3425 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3426 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303427 return &extension.SingleGetValueResponse{
3428 Response: &extension.GetValueResponse{
3429 Status: extension.GetValueResponse_ERROR,
3430 ErrReason: reason,
3431 },
3432 }
3433 }
3434 mm.onuEthernetFrameExtendedPmLock.RLock()
3435 if !mm.isDeviceReadyToCollectExtendedPmStats {
3436 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303437 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303438 }
3439 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303440
3441 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3442 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3443 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3444 }
3445 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3446 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3447
3448 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3449 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3450 if onuInfo.IsUniIndex != nil {
3451 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3452 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3453 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3454 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3455 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3456 break
3457 }
3458 }
3459 if len(downstreamEntityMap) == 0 {
3460 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3461 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3462 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3463 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3464 }
3465 } else {
3466 // make a copy of all downstream and upstream maps in the local ones
3467 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3468 upstreamEntityMap[entityID] = meEnt
3469 }
3470 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3471 downstreamEntityMap[entityID] = meEnt
3472 }
3473 }
3474 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3475 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3476 // Reset the metrics first for all required me's
3477 if onuInfo.Reset_ {
3478 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3479 if err != nil {
3480 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3481 log.Fields{"device-id": mm.deviceID})
3482 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3483 }
3484 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303485 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3486 var pmUpstream extension.OmciEthernetFrameExtendedPm
3487 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303488 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3489 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3490 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3491 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303492 if !onuInfo.Reset_ {
3493 for entityID, meEnt := range upstreamEntityMap {
3494 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3495 var receivedMask uint16
3496 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3497 if receivedMask == 0 {
3498 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303499 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3500 // It might be possible that still some downstream pms are supported and hence we need to continue
3501 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3502 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303503 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303504 // Aggregate the result for upstream
3505 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3506 } else {
3507 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303508 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303509 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303510
Himani Chawlaee10b542021-09-20 16:46:40 +05303511 for entityID, meEnt := range downstreamEntityMap {
3512 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3513 var receivedMask uint16
3514 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303515 if receivedMask == 0 {
3516 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3517 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3518 // Stop collecting downstream counters for other ME's.
3519 break
3520 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303521 // Aggregate the result for downstream
3522 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3523 } else {
3524 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3525 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303526 }
3527 }
3528 singleValResp := extension.SingleGetValueResponse{
3529 Response: &extension.GetValueResponse{
3530 Status: extension.GetValueResponse_OK,
3531 Response: &extension.GetValueResponse_OnuCounters{
3532 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303533 Upstream: &pmUpstream,
3534 Downstream: &pmDownstream,
3535 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303536 },
3537 },
3538 },
3539 }
3540 return &singleValResp
3541}
3542
Himani Chawlaee10b542021-09-20 16:46:40 +05303543func (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 +05303544 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003545 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 +05303546
3547 classID = mm.supportedEthernetFrameExtendedPMClass
3548 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3549 if classID == me.EthernetFrameExtendedPmClassID {
3550 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3551 }
3552 ethPMData := make(map[string]uint64)
3553 var sumReceivedMask uint16
3554 for mask := range attributeMaskList {
3555 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3556 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003557 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303558 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303559 }
3560 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3561 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3562 //populate all counters as failure and return
3563 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3564 break
3565 }
3566 }
3567 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303568 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303569}
3570
3571// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003572func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303573 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3574 var meAttributes me.AttributeValueMap
3575 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003576 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303577 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003578 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303579 return extension.GetValueResponse_INTERNAL_ERROR, err
3580 }
3581 select {
3582 case meAttributes = <-mm.extendedPmMeChan:
3583 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003584 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3585 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303586 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003587 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303588 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3589 }
3590 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3591 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3592 *sumReceivedMask += mask
3593 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3594 } else {
3595 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3596 *sumReceivedMask += mask
3597 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3598 }
3599
3600 return extension.GetValueResponse_REASON_UNDEFINED, nil
3601}
3602
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003603func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303604 sourceMap := maskToEthernetFrameExtendedPM64Bit
3605 errorCounterValue := UnsupportedCounterValue64bit
3606 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3607 sourceMap = maskToEthernetFrameExtendedPM32Bit
3608 errorCounterValue = UnsupportedCounterValue32bit
3609 }
3610 for _, value := range sourceMap {
3611 for _, k := range value {
3612 if _, ok := ethFrameExtPMData[k]; !ok {
3613 ethFrameExtPMData[k] = errorCounterValue
3614 }
3615 }
3616 }
3617}
3618
3619// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003620func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303621 receivedMask := uint16(0)
3622 switch requestedAttributesMask {
3623 case 0x3F00:
3624 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3625 if _, ok := ethFrameExtPMData[k]; !ok {
3626 switch k {
3627 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003628 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303629 ethFrameExtPMData[k] = uint64(val.(uint32))
3630 receivedMask |= 0x2000
3631 } else if !ok {
3632 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3633 }
3634 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003635 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303636 ethFrameExtPMData[k] = uint64(val.(uint32))
3637 receivedMask |= 0x1000
3638 } else if !ok {
3639 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3640 }
3641 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003642 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303643 ethFrameExtPMData[k] = uint64(val.(uint32))
3644 receivedMask |= 0x800
3645 } else if !ok {
3646 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3647 }
3648 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003649 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303650 ethFrameExtPMData[k] = uint64(val.(uint32))
3651 receivedMask |= 0x400
3652 } else if !ok {
3653 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3654 }
3655 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003656 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303657 ethFrameExtPMData[k] = uint64(val.(uint32))
3658 receivedMask |= 0x200
3659 } else if !ok {
3660 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3661 }
3662 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003663 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303664 ethFrameExtPMData[k] = uint64(val.(uint32))
3665 receivedMask |= 0x100
3666 } else if !ok {
3667 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3668 }
3669 default:
3670 //do nothing
3671 }
3672 }
3673 }
3674 case 0x00FC:
3675 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3676 if _, ok := ethFrameExtPMData[k]; !ok {
3677 switch k {
3678 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003679 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303680 ethFrameExtPMData[k] = uint64(val.(uint32))
3681 receivedMask |= 0x80
3682 } else if !ok {
3683 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3684 }
3685 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003686 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303687 ethFrameExtPMData[k] = uint64(val.(uint32))
3688 receivedMask |= 0x40
3689 } else if !ok {
3690 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3691 }
3692 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003693 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303694 ethFrameExtPMData[k] = uint64(val.(uint32))
3695 receivedMask |= 0x20
3696 } else if !ok {
3697 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3698 }
3699 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003700 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303701 ethFrameExtPMData[k] = uint64(val.(uint32))
3702 receivedMask |= 0x10
3703 } else if !ok {
3704 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3705 }
3706 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003707 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303708 ethFrameExtPMData[k] = uint64(val.(uint32))
3709 receivedMask |= 0x8
3710 } else if !ok {
3711 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3712 }
3713 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003714 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303715 ethFrameExtPMData[k] = uint64(val.(uint32))
3716 receivedMask |= 0x4
3717 } else if !ok {
3718 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3719 }
3720 default:
3721 //do nothing
3722 }
3723 }
3724 }
3725 case 0x0003:
3726 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3727 if _, ok := ethFrameExtPMData[k]; !ok {
3728 switch k {
3729 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003730 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303731 ethFrameExtPMData[k] = uint64(val.(uint32))
3732 receivedMask |= 0x2
3733 } else if !ok {
3734 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3735 }
3736 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003737 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303738 ethFrameExtPMData[k] = uint64(val.(uint32))
3739 receivedMask |= 0x1
3740 } else if !ok {
3741 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3742 }
3743 default:
3744 //do nothing
3745 }
3746 }
3747 }
3748 default:
3749 //do nothing
3750 }
3751 return receivedMask
3752}
3753
3754// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003755func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303756 receivedMask := uint16(0)
3757 switch requestedAttributesMask {
3758 case 0x3800:
3759 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3760 if _, ok := ethFrameExtPMData[k]; !ok {
3761 switch k {
3762 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003763 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303764 ethFrameExtPMData[k] = val.(uint64)
3765 receivedMask |= 0x2000
3766 } else if !ok {
3767 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3768 }
3769 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003770 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303771 ethFrameExtPMData[k] = val.(uint64)
3772 receivedMask |= 0x1000
3773 } else if !ok {
3774 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3775 }
3776 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003777 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303778 ethFrameExtPMData[k] = val.(uint64)
3779 receivedMask |= 0x800
3780 } else if !ok {
3781 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3782 }
3783 }
3784 }
3785 }
3786 case 0x0700:
3787 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3788 if _, ok := ethFrameExtPMData[k]; !ok {
3789 switch k {
3790 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003791 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303792 ethFrameExtPMData[k] = val.(uint64)
3793 receivedMask |= 0x400
3794 } else if !ok {
3795 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3796 }
3797 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003798 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303799 ethFrameExtPMData[k] = val.(uint64)
3800 receivedMask |= 0x200
3801 } else if !ok {
3802 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3803 }
3804 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003805 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303806 ethFrameExtPMData[k] = val.(uint64)
3807 receivedMask |= 0x100
3808 } else if !ok {
3809 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3810 }
3811 }
3812 }
3813 }
3814 case 0x00E0:
3815 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3816 if _, ok := ethFrameExtPMData[k]; !ok {
3817 switch k {
3818 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003819 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303820 ethFrameExtPMData[k] = val.(uint64)
3821 receivedMask |= 0x80
3822 } else if !ok {
3823 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3824 }
3825 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003826 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303827 ethFrameExtPMData[k] = val.(uint64)
3828 receivedMask |= 0x40
3829 } else if !ok {
3830 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3831 }
3832 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003833 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303834 ethFrameExtPMData[k] = val.(uint64)
3835 receivedMask |= 0x20
3836 } else if !ok {
3837 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3838 }
3839 }
3840 }
3841 }
3842 case 0x001C:
3843 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3844 if _, ok := ethFrameExtPMData[k]; !ok {
3845 switch k {
3846 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003847 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303848 ethFrameExtPMData[k] = val.(uint64)
3849 receivedMask |= 0x10
3850 } else if !ok {
3851 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3852 }
3853 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003854 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303855 ethFrameExtPMData[k] = val.(uint64)
3856 receivedMask |= 0x8
3857 } else if !ok {
3858 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3859 }
3860 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003861 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303862 ethFrameExtPMData[k] = val.(uint64)
3863 receivedMask |= 0x4
3864 } else if !ok {
3865 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3866 }
3867 default:
3868 //do nothing
3869 }
3870 }
3871 }
3872 case 0x0003:
3873 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3874 if _, ok := ethFrameExtPMData[k]; !ok {
3875 switch k {
3876 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003877 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303878 ethFrameExtPMData[k] = val.(uint64)
3879 receivedMask |= 0x2
3880 } else if !ok {
3881 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3882 }
3883 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003884 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303885 ethFrameExtPMData[k] = val.(uint64)
3886 receivedMask |= 0x1
3887 } else if !ok {
3888 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3889 }
3890 default:
3891 //do nothing
3892 }
3893 }
3894 }
3895 }
3896 return receivedMask
3897}
3898
Himani Chawlaee10b542021-09-20 16:46:40 +05303899func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3900 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303901 errorCounterValue := UnsupportedCounterValue64bit
3902 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3903 errorCounterValue = UnsupportedCounterValue32bit
3904 }
3905 var pmDataOut extension.OmciEthernetFrameExtendedPm
3906 if aggregate {
3907 if pmData.DropEvents != errorCounterValue {
3908 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3909 } else {
3910 pmDataOut.DropEvents = pmData.DropEvents
3911 }
3912 if pmData.Octets != errorCounterValue {
3913 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3914 } else {
3915 pmDataOut.Octets = pmData.Octets
3916 }
3917 if pmData.Frames != errorCounterValue {
3918 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3919 } else {
3920 pmDataOut.Frames = pmData.Frames
3921 }
3922 if pmData.BroadcastFrames != errorCounterValue {
3923 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3924 } else {
3925 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3926 }
3927 if pmData.MulticastFrames != errorCounterValue {
3928 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3929 } else {
3930 pmDataOut.MulticastFrames = pmData.MulticastFrames
3931 }
3932 if pmData.CrcErroredFrames != errorCounterValue {
3933 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3934 } else {
3935 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3936 }
3937 if pmData.UndersizeFrames != errorCounterValue {
3938 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3939 } else {
3940 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3941 }
3942 if pmData.OversizeFrames != errorCounterValue {
3943 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3944 } else {
3945 pmDataOut.OversizeFrames = pmData.OversizeFrames
3946 }
3947 if pmData.Frames_64Octets != errorCounterValue {
3948 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3949 } else {
3950 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3951 }
3952 if pmData.Frames_65To_127Octets != errorCounterValue {
3953 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3954 } else {
3955 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3956 }
3957 if pmData.Frames_128To_255Octets != errorCounterValue {
3958 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3959 } else {
3960 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3961 }
3962 if pmData.Frames_256To_511Octets != errorCounterValue {
3963 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3964 } else {
3965 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3966 }
3967 if pmData.Frames_512To_1023Octets != errorCounterValue {
3968 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3969 } else {
3970 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3971 }
3972 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3973 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3974 } else {
3975 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3976 }
3977 } else {
3978 pmDataOut.DropEvents = pmDataIn["drop_events"]
3979 pmDataOut.Octets = pmDataIn["octets"]
3980 pmDataOut.Frames = pmDataIn["frames"]
3981 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3982 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3983 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3984 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3985 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3986 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3987 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3988 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3989 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3990 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3991 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3992 }
3993 return pmDataOut
3994}
3995
Himani Chawlaee10b542021-09-20 16:46:40 +05303996func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303997 controlBlock := make([]uint16, 8)
3998 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3999 controlBlock[0] = 0
4000 // Next two bytes are for the parent class ID
4001 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
4002 // Next two bytes are for the parent me instance id
4003 controlBlock[2] = entityID
4004 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05304005 if reset {
4006 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
4007 } else {
4008 controlBlock[3] = 0
4009 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05304010 // Next two bytes are for tca disable
4011 controlBlock[4] = 0x4000 //tca global disable
4012 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
4013 if upstream {
4014 controlBlock[5] = 1 << 0
4015 } else {
4016 controlBlock[5] = (1 << 0) | (1 << 1)
4017 }
4018 // Next two bytes are for tci - does not matter here
4019 controlBlock[6] = 0
4020 // Next two bytes are for reserved bits - does not matter here
4021 controlBlock[7] = 0
4022 return controlBlock
4023}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00004024
Girish Gowdraabcceb12022-04-13 23:35:22 -07004025// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
4026func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
4027 mm.OnuMetricsManagerLock.RLock()
4028 defer mm.OnuMetricsManagerLock.RUnlock()
4029 return mm.deviceDeletionInProgress
4030}
4031
4032// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
4033func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
4034 mm.OnuMetricsManagerLock.Lock()
4035 defer mm.OnuMetricsManagerLock.Unlock()
4036 mm.deviceDeletionInProgress = true
4037}