blob: 43ab2a0fe2a182a0d78c0a5634943d2a09b74733 [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
Girish Gowdrae09a6202021-01-12 18:10:59 -0800336}
337
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000338// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800339// The metrics manager module is responsible for configuration and management of individual and group metrics.
340// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
341// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
342// the collection interval configurable.
343// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
344// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000345func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800346
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000347 var metricsManager OnuMetricsManager
348 metricsManager.deviceID = dh.GetDeviceID()
349 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800350 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000351 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800352
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000353 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800354 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
355 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800356 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530357 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800358
359 metricsManager.syncTimeResponseChan = make(chan bool)
360 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530361 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800362
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000363 metricsManager.StopProcessingOmciResponses = make(chan bool)
364 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800365
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000366 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
367 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800368
Himani Chawlac77d5372021-07-12 15:42:26 +0530369 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
370 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530371
Girish Gowdraabcceb12022-04-13 23:35:22 -0700372 // make this a buffered channel so that the sender is not blocked for any reason if there is no listener
373 metricsManager.GarbageCollectionComplete = make(chan bool, 1)
374
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000375 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 -0800376 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800377 }
378
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800379 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800380
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800381 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800382 return nil
383 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800384
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800385 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000386 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800387
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000388 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
389 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800390 if metricsManager.pmKvStore == nil {
391 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000392 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800393 return nil
394 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700395 // restore data from KV store
396 if err := metricsManager.restorePmData(ctx); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000397 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700398 // we continue given that it does not effect the actual services for the ONU,
399 // but there may be some negative effect on PM collection (there may be some mismatch in
400 // the actual PM config and what is present on the device).
401 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800402
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000403 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
404 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530405 if metricsManager.extPmKvStore == nil {
406 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000407 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530408 return nil
409 }
410
praneeth nalmas808f43a2023-05-14 12:54:34 +0530411 //Metrics collection timers are initialized with a default timer value, will be stopped immediately and further
412 //timers are reset during the actual stats collection begins.
413 metricsManager.onuOpticalMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
414 metricsManager.onuOpticalMetricstimer.Stop()
415
416 metricsManager.onuUniStatusMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
417 metricsManager.onuUniStatusMetricstimer.Stop()
418
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000419 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800420 return &metricsManager
421}
422
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000423// InitializeMetricCollectionTime - TODO: add comment
424func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
425 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
426 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
427 mm.OnuMetricsManagerLock.Lock()
428 defer mm.OnuMetricsManagerLock.Unlock()
429 for _, v := range mm.GroupMetricMap {
430 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
431 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800432 }
433 }
434
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000435 for _, v := range mm.StandaloneMetricMap {
436 if v.Enabled {
437 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800438 }
439 }
440 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000441 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
442 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800443 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000444 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800445}
446
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000447// UpdateDefaultFrequency - TODO: add comment
448func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800449 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800450 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800451 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
452 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
453 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000454 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
455 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
456 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
457 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 -0800458 return nil
459}
460
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000461// UpdateGroupFreq - TODO: add comment
462func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800463 var newGroupFreq uint32
464 found := false
465 groupSliceIdx := 0
466 var group *voltha.PmGroupConfig
467 for groupSliceIdx, group = range pmConfigs.Groups {
468 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800469 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
470 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
471 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
472 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800473 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800474 newGroupFreq = group.GroupFreq
475 found = true
476 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800477 }
478 }
479 // if not found update group freq and next collection interval for the group
480 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000481 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800482 return fmt.Errorf("group-name-not-found-%v", aGroupName)
483 }
484
485 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000486 mm.OnuMetricsManagerLock.Lock()
487 defer mm.OnuMetricsManagerLock.Unlock()
488 for k, v := range mm.GroupMetricMap {
489 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
490 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800491 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000492 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800493 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000494 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800495 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000496 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800497 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800498 }
499 }
500 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000501 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800502 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
503 }
504 return nil
505}
506
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000507// UpdateMetricFreq - TODO: add comment
508func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800509 var newMetricFreq uint32
510 found := false
511 metricSliceIdx := 0
512 var metric *voltha.PmConfig
513 for metricSliceIdx, metric = range pmConfigs.Metrics {
514 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800515 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
516 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
517 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
518 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800519 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800520 newMetricFreq = metric.SampleFreq
521 found = true
522 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800523 }
524 }
525 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000526 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800527 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
528 }
529
530 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000531 mm.OnuMetricsManagerLock.Lock()
532 defer mm.OnuMetricsManagerLock.Unlock()
533 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800534 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000535 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800536 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000537 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800538 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000539 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800540 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000541 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800542 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800543 }
544 }
545 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000546 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800547 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
548 }
549 return nil
550}
551
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000552// UpdateGroupSupport - TODO: add comment
553func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800554 groupSliceIdx := 0
555 var group *voltha.PmGroupConfig
556
557 for groupSliceIdx, group = range pmConfigs.Groups {
558 if group.GroupName == aGroupName {
559 break
560 }
561 }
562 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000563 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800564 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
565 }
566
567 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000568 mm.OnuMetricsManagerLock.Lock()
569 defer mm.OnuMetricsManagerLock.Unlock()
570 for k, v := range mm.GroupMetricMap {
571 if k == aGroupName && v.Enabled != group.Enabled {
572 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
573 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800574 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000575 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800576 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800577 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800578 // 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 -0800579 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
580
581 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
582 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
583 // take further action
584 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800585 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800586 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000587 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
588 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800589 }
590 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000591 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800592 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800593 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800594 // 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 -0800595 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
596
597 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
598 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
599 // take further action
600 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800601 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800602 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800603 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800604 }
605 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000606 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800607 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000608 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800609 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000610 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 -0800611 }
612 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800613 }
614 }
615
616 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000617 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800618 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
619 }
620 return nil
621}
622
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000623// UpdateMetricSupport - TODO: add comment
624func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800625 metricSliceIdx := 0
626 var metric *voltha.PmConfig
627
628 for metricSliceIdx, metric = range pmConfigs.Metrics {
629 if metric.Name == aMetricName {
630 break
631 }
632 }
633
634 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000635 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800636 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
637 }
638
639 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000640 mm.OnuMetricsManagerLock.Lock()
641 defer mm.OnuMetricsManagerLock.Unlock()
642 for k, v := range mm.StandaloneMetricMap {
643 if k == aMetricName && v.Enabled != metric.Enabled {
644 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
645 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800646 // 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 +0000647 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
648 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800649 }
650 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000651 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 -0800652 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800653 }
654 }
655 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000656 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800657 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
658 }
659 return nil
660}
661
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000662// CollectAllGroupAndStandaloneMetrics - TODO: add comment
663func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
664 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800665 go mm.collectAllGroupMetrics(ctx)
666 } else {
667 go mm.collectAllStandaloneMetrics(ctx)
668 }
669}
670
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000671func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800672 go func() {
673 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300674 metricInfo, err := mm.collectOpticalMetrics(ctx)
675 if err != nil {
676 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000677 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300678 return
679 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800680 if metricInfo != nil {
681 mm.publishMetrics(ctx, metricInfo)
682 }
683 }()
684
685 go func() {
686 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300687 metricInfo, err := mm.collectUniStatusMetrics(ctx)
688 if err != nil {
689 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000690 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300691 return
692 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800693 if metricInfo != nil {
694 mm.publishMetrics(ctx, metricInfo)
695 }
696 }()
697
698 // Add more here
699}
700
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000701func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800702 // None exists as of now, add when available here
703}
704
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000705// CollectGroupMetric - TODO: add comment
706func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800707 switch groupName {
708 case OpticalPowerGroupMetricName:
709 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300710 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800711 mm.publishMetrics(ctx, mi)
712 }
713 }()
714 case UniStatusGroupMetricName:
715 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300716 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800717 mm.publishMetrics(ctx, mi)
718 }
719 }()
720 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000721 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800722 }
723}
724
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000725// CollectStandaloneMetric - TODO: add comment
726func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800727 switch metricName {
728 // None exist as of now, add when available
729 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000730 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800731 }
732}
733
734// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000735func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
736 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800737
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000738 mm.OnuMetricsManagerLock.RLock()
739 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
740 mm.OnuMetricsManagerLock.RUnlock()
741 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300742 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800743 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000744 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800745
Girish Gowdrae09a6202021-01-12 18:10:59 -0800746 var metricInfoSlice []*voltha.MetricInformation
747 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000748 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
749 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
750 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800751
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800752 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800753 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800754 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800755 Ts: float64(raisedTs),
756 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000757 DeviceId: mm.deviceID,
758 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
759 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800760 }
761
Girish Gowdrae09a6202021-01-12 18:10:59 -0800762 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000763 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800764loop:
765 for _, anigInstID := range anigInstKeys {
766 var meAttributes me.AttributeValueMap
767 opticalMetrics := make(map[string]float32)
768 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000769 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000770 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes,
771 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300772 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000773 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
774 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300775 return nil, err
776 }
777
778 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530779 mm.onuOpticalMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800780 select {
781 case meAttributes = <-mm.opticalMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530782 mm.onuOpticalMetricstimer.Stop()
783 logger.Debugw(ctx, "received optical metrics, stopping the optical metrics collection timer", log.Fields{"device-id": mm.deviceID})
784 case <-mm.onuOpticalMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000785 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 -0800786 // The metrics will be empty in this case
787 break loop
788 }
789 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800790 for k := range OpticalPowerGroupMetrics {
791 switch k {
792 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000793 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800794 opticalMetrics[k] = float32(val.(uint16))
795 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800796 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000797 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000798 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 -0800799 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800800 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000801 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000802 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 -0800803 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800804 default:
805 // do nothing
806 }
807 }
808 }
809 // create slice of metrics given that there could be more than one ANI-G instance and
810 // optical metrics are collected per ANI-G instance
811 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
812 metricInfoSlice = append(metricInfoSlice, &metricInfo)
813 }
814
ozgecanetsiab36ed572021-04-01 10:38:48 +0300815 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800816}
817
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800818// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800819// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000820func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
821 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
822 mm.OnuMetricsManagerLock.RLock()
823 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
824 mm.OnuMetricsManagerLock.RUnlock()
825 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300826 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800827 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000828 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800829
Girish Gowdrae09a6202021-01-12 18:10:59 -0800830 var metricInfoSlice []*voltha.MetricInformation
831 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000832 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
833 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
834 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800835
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800836 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800837 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700838 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800839 Ts: float64(raisedTs),
840 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000841 DeviceId: mm.deviceID,
842 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
843 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800844 }
845
Girish Gowdrae09a6202021-01-12 18:10:59 -0800846 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000847 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800848loop1:
849 for _, unigInstID := range unigInstKeys {
850 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
851 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
852 unigMetrics := make(map[string]float32)
853 var meAttributes me.AttributeValueMap
854 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000855 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000856 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes,
857 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300858 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000859 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
860 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300861 return nil, err
862 }
863 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530864 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800865 // Wait for metrics or timeout
866 select {
867 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530868 mm.onuUniStatusMetricstimer.Stop()
869 logger.Debugw(ctx, "received uni-g metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
870 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000871 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 -0800872 // The metrics could be empty in this case
873 break loop1
874 }
875 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800876 for k := range UniStatusGroupMetrics {
877 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800878 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000879 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800880 unigMetrics[k] = float32(val.(byte))
881 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800882 default:
883 // do nothing
884 }
885 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000886 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800887 entityID := val.(uint16)
888 unigMetrics["entity_id"] = float32(entityID)
889 // 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 +0000890 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
891 if uni.EntityID == entityID {
892 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700893 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800894 }
895 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800896 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700897 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800898
Girish Gowdrae09a6202021-01-12 18:10:59 -0800899 // create slice of metrics given that there could be more than one UNI-G instance
900 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
901 metricInfoSlice = append(metricInfoSlice, &metricInfo)
902 }
903 }
904
905 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000906 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800907loop2:
908 for _, pptpInstID := range pptpInstKeys {
909 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
910 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
911 var meAttributes me.AttributeValueMap
912 pptpMetrics := make(map[string]float32)
913
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000914 requestedAttributes := me.AttributeValueMap{
915 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
916 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
917 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
918 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000919 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300920 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000921 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
922 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300923 return nil, err
924 }
925 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530926 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800927 // Wait for metrics or timeout
928 select {
929 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530930 mm.onuUniStatusMetricstimer.Stop()
931 logger.Debugw(ctx, "received pptp metrics, stopping Onu Uni Status metrics timer ", log.Fields{"device-id": mm.deviceID})
932 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000933 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 -0800934 // The metrics could be empty in this case
935 break loop2
936 }
937
938 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800939 for k := range UniStatusGroupMetrics {
940 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700941 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000942 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800943 pptpMetrics[k] = float32(val.(byte))
944 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800945 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000946 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800947 pptpMetrics[k] = float32(val.(byte))
948 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800949 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000950 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800951 pptpMetrics[k] = float32(val.(byte))
952 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800953 default:
954 // do nothing
955 }
956 }
957 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000958 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800959 entityID := val.(uint16)
960 pptpMetrics["entity_id"] = float32(entityID)
961 // 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 +0000962 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
963 if uni.EntityID == entityID {
964 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700965 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800966 }
967 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800968 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700969 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800970
Girish Gowdrae09a6202021-01-12 18:10:59 -0800971 // create slice of metrics given that there could be more than one PPTP instance and
972 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
973 metricInfoSlice = append(metricInfoSlice, &metricInfo)
974 }
975
976 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000977 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800978loop3:
979 for _, veipInstID := range veipInstKeys {
980 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
981 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
982 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800983 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800984
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000985 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0,
986 me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
987 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes,
988 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300989 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000990 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
991 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300992 return nil, err
993 }
994 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530995 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800996 // Wait for metrics or timeout
997 select {
998 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530999 mm.onuUniStatusMetricstimer.Stop()
1000 logger.Debugw(ctx, "received veip metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
1001 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001002 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 -08001003 // The metrics could be empty in this case
1004 break loop3
1005 }
1006
1007 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001008 for k := range UniStatusGroupMetrics {
1009 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001010 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001011 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001012 veipMetrics[k] = float32(val.(byte))
1013 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001014 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001015 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001016 veipMetrics[k] = float32(val.(byte))
1017 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001018 default:
1019 // do nothing
1020 }
1021 }
1022 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001023
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001024 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001025 entityID := val.(uint16)
1026 veipMetrics["entity_id"] = float32(entityID)
1027 // 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 +00001028 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1029 if uni.EntityID == entityID {
1030 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001031 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001032 }
1033 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001034 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001035 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001036
Girish Gowdrae09a6202021-01-12 18:10:59 -08001037 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001038 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001039 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1040 }
1041
ozgecanetsiab36ed572021-04-01 10:38:48 +03001042 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001043}
1044
1045// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001046func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001047 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001048 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001049 ke.SliceData = metricInfo
1050 ke.Type = voltha.KpiEventType_slice
1051 ke.Ts = float64(ts)
1052
Himani Chawlaf9768882021-12-01 00:18:58 +05301053 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 +00001054 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001055 }
1056}
1057
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001058// ProcessOmciMessages - TODO: add comment
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001059func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context, waitForOmciProcessor *sync.WaitGroup) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001060 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 -08001061 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001062 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001063 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001064 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001065 // is stopped - as a result of ONU going down.
1066 mm.flushMetricCollectionChannels(ctx)
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001067 // when instantiating mm it was too early, but now we can check for ONU's extended OMCI support
1068 mm.isExtendedOmci = mm.pOnuDeviceEntry.GetPersIsExtOmciSupported()
1069 if mm.isExtendedOmci {
1070 mm.maxL2PMGetPayLoadSize = MaxExtendedL2PMGetPayLoadSize
1071 } else {
1072 mm.maxL2PMGetPayLoadSize = MaxBaselineL2PMGetPayLoadSize
1073 }
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001074 mm.updateOmciProcessingStatus(true)
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001075 waitForOmciProcessor.Done()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001076 for {
1077 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001078 case <-mm.StopProcessingOmciResponses: // stop this routine
1079 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 -07001080 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001081 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001082 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001083 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001084 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001085 continue
1086 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001087 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001088
1089 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001090 case cmn.OMCI:
1091 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001092 mm.handleOmciMessage(ctx, msg)
1093 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001094 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001095 }
1096 }
1097 }
1098}
1099
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001100func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1101 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001102 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1103 switch msg.OmciMsg.MessageType {
1104 case omci.GetResponseType:
1105 //TODO: error handling
1106 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001107 case omci.SynchronizeTimeResponseType:
1108 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1109 case omci.CreateResponseType:
1110 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1111 case omci.DeleteResponseType:
1112 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301113 case omci.GetCurrentDataResponseType:
1114 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301115 case omci.SetResponseType:
1116 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001117 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001118 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001119
1120 }
1121}
1122
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001123func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001124 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1125 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001126 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1127 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001128 }
1129 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1130 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001131 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1132 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001133 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001134 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 -08001135 if msgObj.Result == me.Success {
1136 meAttributes := msgObj.Attributes
1137 switch msgObj.EntityClass {
1138 case me.AniGClassID:
1139 mm.opticalMetricsChan <- meAttributes
1140 return nil
1141 case me.UniGClassID:
1142 mm.uniStatusMetricsChan <- meAttributes
1143 return nil
1144 case me.PhysicalPathTerminationPointEthernetUniClassID:
1145 mm.uniStatusMetricsChan <- meAttributes
1146 return nil
1147 case me.VirtualEthernetInterfacePointClassID:
1148 mm.uniStatusMetricsChan <- meAttributes
1149 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001150 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1151 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001152 me.EthernetPerformanceMonitoringHistoryDataClassID,
1153 me.FecPerformanceMonitoringHistoryDataClassID,
1154 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001155 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301156 return nil
1157 case me.EthernetFrameExtendedPmClassID,
1158 me.EthernetFrameExtendedPm64BitClassID:
1159 mm.extendedPmMeChan <- meAttributes
1160 return nil
1161 default:
1162 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001163 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301164 }
1165 } else {
1166 meAttributes := msgObj.Attributes
1167 switch msgObj.EntityClass {
1168 case me.EthernetFrameExtendedPmClassID,
1169 me.EthernetFrameExtendedPm64BitClassID:
1170 // not all counters may be supported in which case we have seen some ONUs throwing
1171 // AttributeFailure error code, while correctly populating other counters it supports
1172 mm.extendedPmMeChan <- meAttributes
1173 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001174 default:
1175 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001176 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001177 }
1178 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001179 return fmt.Errorf("unhandled-omci-get-response-message")
1180}
1181
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001182func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301183 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1184 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001185 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1186 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301187 }
1188 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1189 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001190 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1191 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301192 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001193 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 +05301194 if msgObj.Result == me.Success {
1195 meAttributes := msgObj.Attributes
1196 switch msgObj.EntityClass {
1197 case me.EthernetFrameExtendedPmClassID,
1198 me.EthernetFrameExtendedPm64BitClassID:
1199 mm.extendedPmMeChan <- meAttributes
1200 return nil
1201 default:
1202 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001203 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301204 }
1205 } else {
1206 meAttributes := msgObj.Attributes
1207 switch msgObj.EntityClass {
1208 case me.EthernetFrameExtendedPmClassID,
1209 me.EthernetFrameExtendedPm64BitClassID:
1210 // not all counters may be supported in which case we have seen some ONUs throwing
1211 // AttributeFailure error code, while correctly populating other counters it supports
1212 mm.extendedPmMeChan <- meAttributes
1213 return nil
1214 default:
1215 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001216 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301217 }
1218 }
1219 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1220}
1221
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001222func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001223 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1224 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001225 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1226 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 -08001227 }
1228 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1229 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001230 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1231 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 -08001232 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001233 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001234 if msgObj.Result == me.Success {
1235 switch msgObj.EntityClass {
1236 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001237 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001238 mm.syncTimeResponseChan <- true
1239 return nil
1240 default:
1241 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001242 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001243 }
1244 }
1245 mm.syncTimeResponseChan <- false
1246 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1247 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001248}
1249
Himani Chawlaee10b542021-09-20 16:46:40 +05301250func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1251 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1252 if msgLayer == nil {
1253 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1254 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1255 }
1256 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1257 if !msgOk {
1258 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1259 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1260 }
1261 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1262 switch msgObj.EntityClass {
1263 case me.EthernetFrameExtendedPmClassID,
1264 me.EthernetFrameExtendedPm64BitClassID:
1265 mm.extendedPMMeResponseChan <- msgObj.Result
1266 return nil
1267 default:
1268 logger.Errorw(ctx, "unhandled omci set response message",
1269 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1270 }
1271 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1272}
1273
Girish Gowdrae09a6202021-01-12 18:10:59 -08001274// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001275func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001276 // flush commMetricsChan
1277 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001278 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001279 logger.Debug(ctx, "flushed common metrics channel")
1280 default:
1281 }
1282
1283 // flush opticalMetricsChan
1284 select {
1285 case <-mm.opticalMetricsChan:
1286 logger.Debug(ctx, "flushed optical metrics channel")
1287 default:
1288 }
1289
1290 // flush uniStatusMetricsChan
1291 select {
1292 case <-mm.uniStatusMetricsChan:
1293 logger.Debug(ctx, "flushed uni status metrics channel")
1294 default:
1295 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001296
1297 // flush syncTimeResponseChan
1298 select {
1299 case <-mm.syncTimeResponseChan:
1300 logger.Debug(ctx, "flushed sync time response channel")
1301 default:
1302 }
1303
1304 // flush l2PmChan
1305 select {
1306 case <-mm.l2PmChan:
1307 logger.Debug(ctx, "flushed L2 PM collection channel")
1308 default:
1309 }
1310
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001311 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001312 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001313 case <-mm.StopTicks:
1314 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001315 default:
1316 }
1317
1318}
1319
1320// ** L2 PM FSM Handlers start **
1321
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001322func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001323 if mm.GetdeviceDeletionInProgress() {
1324 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1325 return
1326 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001327
Girish Gowdrae0140f02021-02-02 16:55:09 -08001328 // Loop through all the group metrics
1329 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1330 // list of active L2 PM list then mark it for creation
1331 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1332 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001333 mm.OnuMetricsManagerLock.Lock()
1334 for n, g := range mm.GroupMetricMap {
1335 if g.IsL2PMCounter { // it is a l2 pm counter
1336 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001337 found := false
1338 inner1:
1339 for _, v := range mm.activeL2Pms {
1340 if v == n {
1341 found = true // metric already present in active l2 pm list
1342 break inner1
1343 }
1344 }
1345 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001346 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001347 }
1348 } else { // metric not enabled.
1349 found := false
1350 inner2:
1351 for _, v := range mm.activeL2Pms {
1352 if v == n {
1353 found = true // metric is found in active l2 pm list
1354 break inner2
1355 }
1356 }
1357 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001358 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001359 }
1360 }
1361 }
1362 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001363 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001364 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001365 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001366 go func() {
1367 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001368 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1369 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001370 }
1371 }()
1372}
1373
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001374func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001375 if mm.GetdeviceDeletionInProgress() {
1376 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1377 return
1378 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001379 // Sync time with the ONU to establish 15min boundary for PM collection.
1380 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001381 // device could be deleted while waiting on sync time response
1382 if mm.GetdeviceDeletionInProgress() {
1383 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1384 return
1385 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001386 go func() {
1387 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1388 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001389 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1390 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001391 }
1392 }()
1393 }
1394 // Initiate a tick generation routine every L2PmCollectionInterval
1395 go mm.generateTicks(ctx)
1396
1397 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001398 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1399 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001400 }
1401 }()
1402}
1403
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001404func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001405 // 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 +00001406 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001407 mm.activeL2Pms = nil
1408 mm.l2PmToAdd = nil
1409 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001410 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001411 // If the FSM was stopped, then clear PM data from KV store
1412 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001413 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001414 _ = mm.clearPmGroupData(ctx) // ignore error
1415 }
1416
Girish Gowdraabcceb12022-04-13 23:35:22 -07001417 if mm.GetdeviceDeletionInProgress() {
1418 mm.pDeviceHandler = nil
1419 mm.pOnuDeviceEntry = nil
1420 mm.GarbageCollectionComplete <- true
1421 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001422}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001423func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1424 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001425 if mm.GetdeviceDeletionInProgress() {
1426 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1427 return
1428 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001429
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001430 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001431 numOfPmToDelete := len(mm.l2PmToDelete)
1432 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001433 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001434
1435 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001436 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 -08001437 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001438 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1439 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001440 }
1441 }()
1442 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001443 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 -08001444 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001445 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1446 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001447 }
1448 }()
1449 }
1450}
1451
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001452func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1453 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001454 if mm.GetdeviceDeletionInProgress() {
1455 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1456 return
1457 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001458 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001459 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001460 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1461 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001462 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001463
1464 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001465 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001466
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001467 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1468 mm.OnuMetricsManagerLock.RLock()
1469 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1470 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1471 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001472
Girish Gowdrae0140f02021-02-02 16:55:09 -08001473 switch n {
1474 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001475 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001476 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001477 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1478 metricInfoSlice = append(metricInfoSlice, metricInfo)
1479 }
1480 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1481 metricInfoSlice = append(metricInfoSlice, metricInfo)
1482 }
1483 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001484 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001485 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001486 for _, entityID := range copyOfEntityIDs {
1487 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1488 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001489 }
1490 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001491
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001492 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001493 for _, entityID := range copyOfEntityIDs {
1494 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001495 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001496 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001497 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001498 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001499 for _, entityID := range copyOfEntityIDs {
1500 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001501 metricInfoSlice = append(metricInfoSlice, metricInfo)
1502 }
1503 }
1504
Girish Gowdrae0140f02021-02-02 16:55:09 -08001505 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001506 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001507 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001508 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001509 }
1510 // Does not matter we send success or failure here.
1511 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1512 // we have not exceed max attempts to collect the PM data)
1513 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001514 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1515 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001516 }
1517 }()
1518}
1519
Girish Gowdra0e533642021-03-02 22:02:51 -08001520// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001521func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001522 if mm.GetdeviceDeletionInProgress() {
1523 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1524 return nil
1525 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001526 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001527 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001528 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1529 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001530 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001531
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001532 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001533 for _, n := range copyOfL2PmToAdd {
1534 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001535 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1536 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001537 switch n {
1538 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001539 // 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 +05301540 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001541 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001542 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001543 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001544 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1545 inner1:
1546 // retry L2PmCreateAttempts times to create the instance of PM
1547 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001548 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1549 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001550 if err != nil {
1551 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001552 log.Fields{"device-id": mm.deviceID})
1553 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001554 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001555 go func(p_pmFsm *cmn.AdapterFsm) {
1556 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001557 }(pPMFsm)
1558 }
1559 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001560 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001561 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001562 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1563 atLeastOneSuccess = true
1564 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1565 break inner1
1566 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001567 if mm.GetdeviceDeletionInProgress() {
1568 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1569 return nil
1570 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001571 }
1572 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1573 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001574 }
1575 }
1576 }
1577 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001578 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1579 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001580 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001581 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001582 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1583 inner2:
1584 // retry L2PmCreateAttempts times to create the instance of PM
1585 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001586 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1587 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001588 if err != nil {
1589 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001590 log.Fields{"device-id": mm.deviceID})
1591 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001592 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001593 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001594 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001595 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1596 atLeastOneSuccess = true
1597 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1598 break inner2
1599 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001600 if mm.GetdeviceDeletionInProgress() {
1601 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1602 return nil
1603 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001604 }
1605 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1606 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001607 }
1608 }
1609 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001610 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001611 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001612 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001613 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1614 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001615 if err != nil {
1616 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001617 log.Fields{"device-id": mm.deviceID})
1618 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001619 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001620 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001621 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001622 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1623 inner3:
1624 // retry L2PmCreateAttempts times to create the instance of PM
1625 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1626 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1627 atLeastOneSuccess = true
1628 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1629 break inner3
1630 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001631 if mm.GetdeviceDeletionInProgress() {
1632 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1633 return nil
1634 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001635 }
1636 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1637 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001638 }
1639 }
1640 case GemPortHistoryName:
1641
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001642 mm.OnuMetricsManagerLock.RLock()
1643 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1644 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1645 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001646
1647 if len(copyOfGemPortInstIDsToAdd) == 0 {
1648 // If there are no gemport history MEs to be created, just skip further processing
1649 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1650 // 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 +00001651 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001652 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001653 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001654 continue
1655 }
1656
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001657 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001658 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1659 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001660 if err != nil {
1661 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001662 log.Fields{"device-id": mm.deviceID})
1663 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001664 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001665 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001666 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001667 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1668 inner4:
1669 // retry L2PmCreateAttempts times to create the instance of PM
1670 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1671 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1672 atLeastOneSuccess = true
1673 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1674 break inner4
1675 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001676 if mm.GetdeviceDeletionInProgress() {
1677 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1678 return nil
1679 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001680 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001681 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1682 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1683 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001684 }
1685
Girish Gowdrae0140f02021-02-02 16:55:09 -08001686 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001687 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001688 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001689 // 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
1690 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001691 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001692 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001693 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1694 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001695 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001696 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1697 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001698 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 +00001699 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001700 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001701 // 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 -08001702 // 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 +00001703 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001704 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001705 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001706 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001707
Girish Gowdrae0140f02021-02-02 16:55:09 -08001708 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001709 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001710 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001711 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001712 }
1713 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001714 mm.OnuMetricsManagerLock.RLock()
1715 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1716 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001717 // Does not matter we send success or failure here.
1718 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1719 // we have not exceed max attempts to create the PM ME)
1720 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001721 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1722 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001723 }
1724 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001725 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001726}
1727
Girish Gowdra0e533642021-03-02 22:02:51 -08001728// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001729func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001730 if mm.GetdeviceDeletionInProgress() {
1731 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1732 return nil
1733 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001734 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001735 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001736 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1737 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001738 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001739
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001740 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001741 for _, n := range copyOfL2PmToDelete {
1742 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001743 cnt := 0
1744 atLeastOneDeleteFailure := false
1745
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001746 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1747 mm.OnuMetricsManagerLock.RLock()
1748 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1749 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1750 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001751
1752 if len(copyOfEntityIDs) == 0 {
1753 // 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 +00001754 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001755 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1756 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1757 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 +00001758 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001759 continue
1760 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001761 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001762 switch n {
1763 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001764 // 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 +05301765 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001766 for _, entityID := range copyOfEntityIDs {
1767 inner1:
1768 // retry L2PmDeleteAttempts times to delete the instance of PM
1769 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001770 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1771 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001772 if err != nil {
1773 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001774 log.Fields{"device-id": mm.deviceID})
1775 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001776 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001777 go func(p_pmFsm *cmn.AdapterFsm) {
1778 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001779 }(pPMFsm)
1780 }
1781 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001782 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001783 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001784 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1785 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001786 if mm.GetdeviceDeletionInProgress() {
1787 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1788 return nil
1789 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001790 atLeastOneDeleteFailure = true
1791 } else {
1792 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1793 break inner1
1794 }
1795 }
1796 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1797 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001798 }
1799 }
1800 }
1801 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001802 for _, entityID := range copyOfEntityIDs {
1803 inner2:
1804 // retry L2PmDeleteAttempts times to delete the instance of PM
1805 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001806 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1807 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001808 if err != nil {
1809 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001810 log.Fields{"device-id": mm.deviceID})
1811 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001812 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001813 go func(p_pmFsm *cmn.AdapterFsm) {
1814 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001815 }(pmFsm)
1816 return err
1817 }
1818 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001819 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001820 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001821 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001822 if mm.GetdeviceDeletionInProgress() {
1823 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1824 return nil
1825 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001826 atLeastOneDeleteFailure = true
1827 } else {
1828 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001829 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001830 }
1831 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001832 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1833 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1834 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001835 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001836 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001837 for _, entityID := range copyOfEntityIDs {
1838 inner3:
1839 // retry L2PmDeleteAttempts times to delete the instance of PM
1840 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001841 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1842 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001843 if err != nil {
1844 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001845 log.Fields{"device-id": mm.deviceID})
1846 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001847 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001848 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001849 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001850 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001851 if mm.GetdeviceDeletionInProgress() {
1852 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1853 return nil
1854 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001855 atLeastOneDeleteFailure = true
1856 } else {
1857 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1858 break inner3
1859 }
1860 }
1861 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1862 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001863 }
1864 }
1865 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001866 for _, entityID := range copyOfEntityIDs {
1867 inner4:
1868 // retry L2PmDeleteAttempts times to delete the instance of PM
1869 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001870 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1871 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001872 if err != nil {
1873 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001874 log.Fields{"device-id": mm.deviceID})
1875 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001876 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001877 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001878 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001879 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001880 if mm.GetdeviceDeletionInProgress() {
1881 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1882 return nil
1883 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001884 atLeastOneDeleteFailure = true
1885 } else {
1886 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1887 break inner4
1888 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001889 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001890 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1891 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1892 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001893 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001894 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001895 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001896 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001897 // If we could not completely clean up the PM ME then just give up.
1898 if atLeastOneDeleteFailure {
1899 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001900 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001901 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001902 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001903 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1904 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1905 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001906 mm.GroupMetricMap[n].Enabled = false
1907 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001908 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001909 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001910 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001911 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1912 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001913 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001914 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1915 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001916 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 +00001917 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001918 }
1919 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001920 mm.OnuMetricsManagerLock.RLock()
1921 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1922 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001923 // Does not matter we send success or failure here.
1924 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1925 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001926 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1927 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001928 }
1929 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001930 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001931}
1932
1933// ** L2 PM FSM Handlers end **
1934
1935// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001936func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001937 if mm.GetdeviceDeletionInProgress() {
1938 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1939 return nil
1940 }
1941
1942 if !mm.GetOmciProcessingStatus() {
1943 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})
1944 return fmt.Errorf("omci-resp-processor-not-running")
1945 }
1946
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001947 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1948 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001949 return err
1950 }
1951
1952 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001953 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1954 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1955 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001956 case syncTimeRes := <-mm.syncTimeResponseChan:
1957 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001958 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001959 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001960 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001961 return nil
1962 }
1963}
1964
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001965func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001966 var mEnt *me.ManagedEntity
1967 var omciErr me.OmciErrors
1968 var classID me.ClassID
1969 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001970 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001971 meParam := me.ParamData{EntityID: entityID}
1972 if upstream {
1973 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001974 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001975 return nil
1976 }
1977 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1978 } else {
1979 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001980 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001981 return nil
1982 }
1983 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
1984 }
1985
Girish Gowdrae0140f02021-02-02 16:55:09 -08001986 intervalEndTime := -1
1987 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001988 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
1989 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001990 }
1991
1992 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
1993 ethPMHistData["class_id"] = float32(classID)
1994 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
1995 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
1996 ethPMHistData["parent_entity_id"] = float32(entityID)
1997 if upstream {
1998 ethPMHistData["upstream"] = float32(1)
1999 } else {
2000 ethPMHistData["upstream"] = float32(0)
2001 }
2002
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002003 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002004
Girish Gowdrae0140f02021-02-02 16:55:09 -08002005 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002006 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002007 return &metricInfo
2008}
2009
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002010func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002011 var mEnt *me.ManagedEntity
2012 var omciErr me.OmciErrors
2013 var classID me.ClassID
2014 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002015 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002016 meParam := me.ParamData{EntityID: entityID}
2017 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002018 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002019 return nil
2020 }
2021 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
2022
Girish Gowdrae0140f02021-02-02 16:55:09 -08002023 intervalEndTime := -1
2024 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002025 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
2026 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002027 }
2028
2029 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2030 ethUniHistData["class_id"] = float32(classID)
2031 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
2032
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002033 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002034
Girish Gowdrae0140f02021-02-02 16:55:09 -08002035 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002036 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002037 return &metricInfo
2038}
2039
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002040func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002041 var mEnt *me.ManagedEntity
2042 var omciErr me.OmciErrors
2043 var classID me.ClassID
2044 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002045 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002046 meParam := me.ParamData{EntityID: entityID}
2047 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002048 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002049 return nil
2050 }
2051 classID = me.FecPerformanceMonitoringHistoryDataClassID
2052
2053 intervalEndTime := -1
2054 fecHistData := make(map[string]float32)
2055 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
2056 return nil
2057 }
2058
2059 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2060 fecHistData["class_id"] = float32(classID)
2061 fecHistData["interval_end_time"] = float32(intervalEndTime)
2062
2063 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2064
2065 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002066 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002067 return &metricInfo
2068}
2069
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002070func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002071 var mEnt *me.ManagedEntity
2072 var omciErr me.OmciErrors
2073 var classID me.ClassID
2074 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002075 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002076 meParam := me.ParamData{EntityID: entityID}
2077 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002078 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002079 return nil
2080 }
2081 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2082
2083 intervalEndTime := -1
2084 gemHistData := make(map[string]float32)
2085 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
2086 return nil
2087 }
2088
2089 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2090 gemHistData["class_id"] = float32(classID)
2091 gemHistData["interval_end_time"] = float32(intervalEndTime)
2092
2093 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2094
2095 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002096 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002097 return &metricInfo
2098}
2099
Girish Gowdrae0140f02021-02-02 16:55:09 -08002100// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002101func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002102 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002103 upstream := false
2104 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2105 upstream = true
2106 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002107 // 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 +00002108 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002109 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2110 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002111 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002112 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2113 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002114 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002115 go func(p_pmFsm *cmn.AdapterFsm) {
2116 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002117 }(pmFsm)
2118 return err
2119 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002120 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002121 }
2122 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002123 select {
2124 case meAttributes = <-mm.l2PmChan:
2125 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002126 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2127 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002128 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002129 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002130 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002131 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002132 }
2133 // 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 -08002134 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002135 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002136 }
2137 }
2138 for k := range EthernetBridgeHistory {
2139 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2140 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2141 if _, ok := ethPMHistData[k]; !ok {
2142 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002143 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002144 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002145 ethPMHistData[k] = float32(val.(uint16))
2146 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002147 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002148 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002149 ethPMHistData[k] = float32(val.(uint32))
2150 }
2151 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002152 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002153 ethPMHistData[k] = float32(val.(uint32))
2154 }
2155 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002156 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002157 ethPMHistData[k] = float32(val.(uint32))
2158 }
2159 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002160 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002161 ethPMHistData[k] = float32(val.(uint32))
2162 }
2163 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002164 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002165 ethPMHistData[k] = float32(val.(uint32))
2166 }
2167 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002168 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002169 ethPMHistData[k] = float32(val.(uint32))
2170 }
2171 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002172 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002173 ethPMHistData[k] = float32(val.(uint32))
2174 }
2175 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002176 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002177 ethPMHistData[k] = float32(val.(uint32))
2178 }
2179 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002180 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002181 ethPMHistData[k] = float32(val.(uint32))
2182 }
2183 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002184 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002185 ethPMHistData[k] = float32(val.(uint32))
2186 }
2187 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002188 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002189 ethPMHistData[k] = float32(val.(uint32))
2190 }
2191 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002192 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002193 ethPMHistData[k] = float32(val.(uint32))
2194 }
2195 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002196 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002197 ethPMHistData[k] = float32(val.(uint32))
2198 }
2199 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002200 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002201 ethPMHistData[k] = float32(val.(uint32))
2202 }
2203 default:
2204 // do nothing
2205 }
2206 }
2207 }
2208 return nil
2209}
2210
2211// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002212func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002213 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002214 // 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 +03002215 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2216 requestedAttributes["IntervalEndTime"] = 0
2217 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002218 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2219 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002220 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002221 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2222 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2223 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002224 }
2225 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002226 select {
2227 case meAttributes = <-mm.l2PmChan:
2228 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002229 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2230 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002231 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002232 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002233 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002234 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002235 }
2236 // 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 -08002237 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002238 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002239 }
2240 }
2241 for k := range EthernetUniHistory {
2242 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2243 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2244 if _, ok := ethPMUniHistData[k]; !ok {
2245 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002246 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002247 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002248 ethPMUniHistData[k] = float32(val.(uint16))
2249 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002250 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002251 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002252 ethPMUniHistData[k] = float32(val.(uint32))
2253 }
2254 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002255 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002256 ethPMUniHistData[k] = float32(val.(uint32))
2257 }
2258 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002259 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002260 ethPMUniHistData[k] = float32(val.(uint32))
2261 }
2262 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002263 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002264 ethPMUniHistData[k] = float32(val.(uint32))
2265 }
2266 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002267 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002268 ethPMUniHistData[k] = float32(val.(uint32))
2269 }
2270 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002271 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002272 ethPMUniHistData[k] = float32(val.(uint32))
2273 }
2274 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002275 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002276 ethPMUniHistData[k] = float32(val.(uint32))
2277 }
2278 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002279 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002280 ethPMUniHistData[k] = float32(val.(uint32))
2281 }
2282 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002283 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002284 ethPMUniHistData[k] = float32(val.(uint32))
2285 }
2286 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002287 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002288 ethPMUniHistData[k] = float32(val.(uint32))
2289 }
2290 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002291 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002292 ethPMUniHistData[k] = float32(val.(uint32))
2293 }
2294 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002295 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002296 ethPMUniHistData[k] = float32(val.(uint32))
2297 }
2298 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002299 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002300 ethPMUniHistData[k] = float32(val.(uint32))
2301 }
2302 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002303 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002304 ethPMUniHistData[k] = float32(val.(uint32))
2305 }
2306 default:
2307 // do nothing
2308 }
2309 }
2310 }
2311 return nil
2312}
2313
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002314// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002315func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002316 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002317 // 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 +00002318 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2319 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002320 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002321 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2322 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002323 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002324 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2325 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2326 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002327 }
2328 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002329 select {
2330 case meAttributes = <-mm.l2PmChan:
2331 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002332 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2333 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002334 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002335 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002336 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002337 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002338 }
2339 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2340 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002341 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002342 }
2343 }
2344 for k := range FecHistory {
2345 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2346 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2347 if _, ok := fecHistData[k]; !ok {
2348 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002349 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002350 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002351 fecHistData[k] = float32(val.(uint16))
2352 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002353 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002354 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002355 fecHistData[k] = float32(val.(uint32))
2356 }
2357 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002358 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002359 fecHistData[k] = float32(val.(uint32))
2360 }
2361 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002362 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002363 fecHistData[k] = float32(val.(uint32))
2364 }
2365 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002366 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002367 fecHistData[k] = float32(val.(uint32))
2368 }
2369 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002370 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002371 fecHistData[k] = float32(val.(uint16))
2372 }
2373 default:
2374 // do nothing
2375 }
2376 }
2377 }
2378 return nil
2379}
2380
2381// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002382func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002383 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002384 // 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 +00002385 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2386 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002387 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002388 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2389 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002390 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002391 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2392 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2393 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002394 }
2395 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002396 select {
2397 case meAttributes = <-mm.l2PmChan:
2398 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002399 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2400 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002401 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002402 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002403 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002404 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002405 }
2406 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2407 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002408 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002409 }
2410 }
2411 for k := range GemPortHistory {
2412 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2413 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2414 if _, ok := gemPortHistData[k]; !ok {
2415 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002416 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002417 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002418 gemPortHistData[k] = float32(val.(uint16))
2419 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002420 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002421 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002422 gemPortHistData[k] = float32(val.(uint32))
2423 }
2424 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002425 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002426 gemPortHistData[k] = float32(val.(uint32))
2427 }
2428 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002429 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002430 gemPortHistData[k] = float32(val.(uint64))
2431 }
2432 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002433 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002434 gemPortHistData[k] = float32(val.(uint64))
2435 }
2436 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002437 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002438 gemPortHistData[k] = float32(val.(uint32))
2439 }
2440 default:
2441 // do nothing
2442 }
2443 }
2444 }
2445 return nil
2446}
2447
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002448func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002449 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2450 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002451 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2452 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 -08002453 }
2454 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2455 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002456 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2457 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 -08002458 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002459 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002460 switch msgObj.EntityClass {
2461 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2462 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002463 me.EthernetPerformanceMonitoringHistoryDataClassID,
2464 me.FecPerformanceMonitoringHistoryDataClassID,
2465 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002466 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2467 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2468 mm.l2PmCreateOrDeleteResponseChan <- true
2469 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002470 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002471 mm.l2PmCreateOrDeleteResponseChan <- false
2472 }
2473 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302474 case me.EthernetFrameExtendedPmClassID,
2475 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302476 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302477 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002478 default:
2479 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002480 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002481 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002482 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002483}
2484
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002485func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002486 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2487 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002488 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2489 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 -08002490 }
2491 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2492 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002493 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2494 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 -08002495 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002496 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002497 switch msgObj.EntityClass {
2498 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2499 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002500 me.EthernetPerformanceMonitoringHistoryDataClassID,
2501 me.FecPerformanceMonitoringHistoryDataClassID,
2502 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002503 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2504 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2505 mm.l2PmCreateOrDeleteResponseChan <- true
2506 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002507 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002508 mm.l2PmCreateOrDeleteResponseChan <- false
2509 }
2510 return nil
2511 default:
2512 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002513 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002514 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002515 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002516}
2517
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002518func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002519 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002520 for {
2521 select {
2522 case <-time.After(L2PmCollectionInterval * time.Second):
2523 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002524 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2525 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002526 }
2527 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002528 case <-mm.StopTicks:
2529 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002530 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002531 return
2532 }
2533 }
2534}
2535
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002536func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002537 // Publish metrics if it is valid
2538 if metricInfoSlice != nil {
2539 mm.publishMetrics(ctx, metricInfoSlice)
2540 } else {
2541 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2542 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002543 mm.OnuMetricsManagerLock.Lock()
2544 mm.GroupMetricMap[metricName].collectAttempts++
2545 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002546 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2547 }
2548 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002549 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2550 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002551 }
2552}
2553
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002554func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002555 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2556 var grpFunc groupMetricPopulateFunc
2557 switch classID {
2558 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2559 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2560 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2561 grpFunc = mm.populateEthernetUniHistoryMetrics
2562 case me.FecPerformanceMonitoringHistoryDataClassID:
2563 grpFunc = mm.populateFecHistoryMetrics
2564 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2565 grpFunc = mm.populateGemPortMetrics
2566 default:
2567 return fmt.Errorf("unknown-classid-%v", classID)
2568 }
2569
2570 size := 0
2571 requestedAttributes := make(me.AttributeValueMap)
2572 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002573 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2574 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2575 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2576 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2577 continue
2578 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002579 if v.Size+size <= mm.maxL2PMGetPayLoadSize {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002580 requestedAttributes[v.Name] = v.DefValue
2581 size = v.Size + size
2582 } else { // We exceeded the allow omci get size
2583 // Let's collect the attributes via get now and collect remaining in the next iteration
2584 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2585 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002586 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002587 return err
2588 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002589 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002590 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2591 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002592 }
2593 }
2594 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002595 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2596 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002597 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002598 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002599 }
2600 return nil
2601}
2602
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002603func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002604 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002605 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2606 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2607 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002608
2609 raisedTs := time.Now().Unix()
2610 mmd := voltha.MetricMetaData{
2611 Title: title,
2612 Ts: float64(raisedTs),
2613 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002614 DeviceId: mm.deviceID,
2615 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2616 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002617 }
2618
2619 // create slice of metrics given that there could be more than one VEIP instance
2620 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2621 return metricInfo
2622}
2623
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002624func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002625 valid := false
2626 if *intervalEndTime == -1 { // first time
2627 // Update the interval end time
2628 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2629 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2630 valid = true
2631 }
2632 } else {
2633 var currIntervalEndTime int
2634 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2635 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2636 }
2637 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2638 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002639 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002640 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2641 } else {
2642 valid = true
2643 }
2644 }
2645 return valid
2646}
2647
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002648func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002649 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002650 if !mm.GetOmciProcessingStatus() {
2651 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})
2652 return false
2653 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002654 select {
2655 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002656 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002657 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002658 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002659 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002660 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002661 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002662 }
2663 return false
2664}
2665
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002666func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002667 var pmConfigSlice []*voltha.PmConfig
2668 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002669 pmConfigSlice = append(pmConfigSlice,
2670 &voltha.PmConfig{
2671 Name: k,
2672 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002673 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002674 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002675 }
2676 groupMetric := voltha.PmGroupConfig{
2677 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002678 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002679 GroupFreq: grpFreq,
2680 Metrics: pmConfigSlice,
2681 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002682 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002683
2684}
2685
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002686func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2687 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2688 if mm.PAdaptFsm == nil {
2689 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2690 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002691 return fmt.Errorf("nil-adapter-fsm")
2692 }
2693 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002694 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2695 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002696 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002697 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2698 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2699 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2700 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2701 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2702 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2703 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2704 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2705 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002706 },
2707 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002708 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2709 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2710 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2711 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2712 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2713 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2714 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2715 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002716 },
2717 )
2718 return nil
2719}
2720
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002721func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2722 mm.pDeviceHandler.InitPmConfigs()
2723 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2724 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2725 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2726 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002727
2728 // Populate group metrics.
2729 // Lets populate irrespective of GroupMetricEnabled is true or not.
2730 // The group metrics collection will decided on this flag later
2731
2732 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2733 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2734
2735 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2736 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2737
2738 // classical l2 pm counter start
2739
2740 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2741 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2742
2743 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2744 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2745
2746 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2747 FecHistoryEnabled, FecHistoryFrequency)
2748
2749 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2750 GemPortHistoryEnabled, GemPortHistoryFrequency)
2751
2752 // classical l2 pm counter end
2753
2754 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2755}
2756
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002757func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002758 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002759 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2760 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002761 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002762 Enabled: g.Enabled,
2763 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002764 }
2765 switch g.GroupName {
2766 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002767 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002768 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002769 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002770 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002771 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2772 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002773 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002774 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2775 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002776 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002777 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2778 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002779 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002780 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2781 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002782 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002783 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002784 }
2785 }
2786
2787 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002788 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2789 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002790 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002791 Enabled: m.Enabled,
2792 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002793 }
2794 switch m.Name {
2795 // None exist as of now. Add when available.
2796 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002797 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002798 }
2799 }
2800}
2801
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002802// AddGemPortForPerfMonitoring - TODO: add comment
2803func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2804 mm.OnuMetricsManagerLock.Lock()
2805 defer mm.OnuMetricsManagerLock.Unlock()
2806 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002807 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002808 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002809 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002810 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002811
2812 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2813 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2814 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2815 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2816 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002817
2818 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002819 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2820 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002821 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002822 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002823 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002824 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002825 }
2826 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002827}
2828
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002829// RemoveGemPortForPerfMonitoring - TODO: add comment
2830func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2831 mm.OnuMetricsManagerLock.Lock()
2832 defer mm.OnuMetricsManagerLock.Unlock()
2833 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2834 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002835 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002836 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002837
2838 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2839 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2840 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2841 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2842 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002843
2844 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002845 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2846 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002847 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002848 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002849 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002850 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002851 }
2852 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002853}
2854
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002855func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2856 if mm.pDeviceHandler.GetOnuTP() != nil {
2857 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002858 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002859 for _, v := range gemPortInstIDs {
2860 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002861 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002862 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002863 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002864 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002865 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002866 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002867 }
2868}
2869
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002870func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2871 if mm.pDeviceHandler.GetOnuTP() != nil {
2872 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002873 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002874 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002875 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002876 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002877 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002878 }
2879 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002880 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002881 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002882}
2883
2884// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002885func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2886 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002887 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002888 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2889 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002890 }
2891 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002892 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002893 group.pmMEData = &pmMEData{}
2894 Value, err := mm.pmKvStore.Get(ctx, groupName)
2895 if err == nil {
2896 if Value != nil {
2897 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002898 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002899 tmpBytes, _ := kvstore.ToByte(Value.Value)
2900
2901 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002902 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2903 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 -08002904 continue
2905 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002906 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002907 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002908 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002909 continue
2910 }
2911 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002912 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2913 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 -08002914 continue
2915 }
2916 }
2917 if len(errorsList) > 0 {
2918 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2919 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002920 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002921 return nil
2922}
2923
2924// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2925// the data must be available in cache.
2926// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002927func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2928 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002929 return grp.pmMEData, nil
2930 }
2931 // Data not in cache, try to fetch from kv store.
2932 data := &pmMEData{}
2933 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002934 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2935 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002936 }
2937 Value, err := mm.pmKvStore.Get(ctx, groupName)
2938 if err == nil {
2939 if Value != nil {
2940 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002941 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002942 tmpBytes, _ := kvstore.ToByte(Value.Value)
2943
2944 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002945 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002946 return data, err
2947 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002948 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002949 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002950 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002951 return data, err
2952 }
2953 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002954 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002955 return data, err
2956 }
2957
2958 return data, nil
2959}
2960
2961// 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 +00002962func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2963 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2964 mm.OnuMetricsManagerLock.Lock()
2965 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002966
2967 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002968 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2969 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002970 }
2971
2972 pmMEData, err := mm.getPmData(ctx, groupName)
2973 if err != nil || pmMEData == nil {
2974 // error already logged in called function.
2975 return err
2976 }
2977 switch pmAction {
2978 case cPmAdd:
2979 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
2980 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2981 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2982 case cPmAdded:
2983 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
2984 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2985 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2986 case cPmRemove:
2987 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
2988 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2989 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2990 case cPmRemoved:
2991 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2992 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2993 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2994 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002995 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
2996 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 -08002997 }
2998 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002999 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08003000
3001 Value, err := json.Marshal(*pmMEData)
3002 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003003 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
3004 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003005 return err
3006 }
3007 // Update back to kv store
3008 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003009 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
3010 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003011 return err
3012 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003013 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
3014 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08003015
3016 return nil
3017}
3018
3019// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003020func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
3021 mm.OnuMetricsManagerLock.Lock()
3022 defer mm.OnuMetricsManagerLock.Unlock()
3023 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003024 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003025 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3026 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003027 }
3028
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003029 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003030 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003031 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003032 // do not abort this procedure. continue to delete next group.
3033 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003034 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08003035 }
3036 }
3037
3038 return nil
3039}
3040
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003041// ClearAllPmData clears all PM data associated with the device from KV store
3042func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3043 mm.OnuMetricsManagerLock.Lock()
3044 defer mm.OnuMetricsManagerLock.Unlock()
3045 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003046 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003047 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3048 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003049 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003050 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003051 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003052 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003053 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003054 value = err
3055 // do not abort this procedure - continue to delete next group.
3056 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003057 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003058 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003059 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003060 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003061 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003062 }
3063 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003064}
3065
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003066func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3067 mm.OnuMetricsManagerLock.Lock()
3068 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003069 mm.omciProcessingActive = status
3070}
3071
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003072// updateTickGenerationStatus - TODO: add comment
3073func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3074 mm.OnuMetricsManagerLock.Lock()
3075 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003076 mm.tickGenerationActive = status
3077}
3078
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003079// GetOmciProcessingStatus - TODO: add comment
3080func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3081 mm.OnuMetricsManagerLock.RLock()
3082 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003083 return mm.omciProcessingActive
3084}
3085
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003086// GetTickGenerationStatus - TODO: add comment
3087func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3088 mm.OnuMetricsManagerLock.RLock()
3089 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003090 return mm.tickGenerationActive
3091}
3092
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003093func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003094 for _, ele := range slice {
3095 if ele == n {
3096 return slice
3097 }
3098 }
3099 return append(slice, n)
3100}
3101
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003102func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003103 for i, ele := range slice {
3104 if ele == n {
3105 return append(slice[:i], slice[i+1:]...)
3106 }
3107 }
3108 return slice
3109}
3110
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003111func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003112 for _, ele := range slice {
3113 if ele == n {
3114 return slice
3115 }
3116 }
3117 return append(slice, n)
3118}
3119
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003120func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003121 for i, ele := range slice {
3122 if ele == n {
3123 return append(slice[:i], slice[i+1:]...)
3124 }
3125 }
3126 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003127}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303128
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003129func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303130 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3131 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003132 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003133 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003134 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303135 Value, err := mm.extPmKvStore.Get(ctx, key)
3136 if err == nil {
3137 if Value != nil {
3138 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003139 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303140 tmpBytes, _ := kvstore.ToByte(Value.Value)
3141
3142 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003143 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303144 return false, err
3145 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003146 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303147 // We have found the data from db, no need to get through omci get message.
3148 mm.supportedEthernetFrameExtendedPMClass = data
3149 return true, nil
3150 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003151 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303152 return false, nil
3153 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003154 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303155 return false, err
3156}
3157
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003158func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303159 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 -07003160 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3161 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})
3162 return false, fmt.Errorf("omci-processor-shutdown")
3163 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303164 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303165 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303166 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003167 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303168 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3169 if resp == me.Success || resp == me.InstanceExists {
3170 return true, nil
3171 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3172 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3173 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3174 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003175 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 +05303176 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3177 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003178 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303179 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003180 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303181 }
3182 return false, fmt.Errorf("timeout-while-waiting-for-response")
3183}
3184
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003185func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303186 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303187 // 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 +05303188 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003189 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303190 var entityID uint16
3191 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003192 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303193 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003194 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303195 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303196 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303197 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303198 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303199
3200 inner1:
3201 // retry ExtendedPmCreateAttempts times to create the instance of PM
3202 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003203 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3204 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3205 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303206 if err != nil {
3207 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003208 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303209 return false, err
3210 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303211 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3212 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303213 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303214 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303215 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303216 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303217 }
3218 break inner1
3219 } else if err != nil {
3220 if !supported {
3221 // Need to return immediately
3222 return false, err
3223 }
3224 //In case of failure, go for a retry
3225 }
3226 }
3227 if cnt == ExtendedPmCreateAttempts {
3228 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3229 return true, fmt.Errorf("unable-to-create-me")
3230 }
3231 }
3232 }
3233 return true, nil
3234}
3235
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003236func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3237 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003238 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003239 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303240 // check if we get the supported type me for ethernet frame extended pm class id
3241 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3242 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3243 }
3244 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3245 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003246 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303247 }
3248 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003249 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303250 }
3251}
3252
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003253func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303254 mm.onuEthernetFrameExtendedPmLock.Lock()
3255 mm.isDeviceReadyToCollectExtendedPmStats = true
3256 mm.onuEthernetFrameExtendedPmLock.Unlock()
3257}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003258
Himani Chawlaee10b542021-09-20 16:46:40 +05303259// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003260func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303261 //get the type of extended frame pm me supported by onu first
3262 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3263 if err != nil {
3264 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3265 return
3266 }
3267 if exist {
3268 // we have the me type, go ahead with the me type supported.
3269 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003270 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303271 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3272 return
3273 }
3274 mm.setAllExtPmMeCreatedFlag()
3275 return
3276 }
3277 // First try with 64 bit me
3278 // we have the me type, go ahead with the me type supported.
3279 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3280 if err != nil && !supported64Bit {
3281 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003282 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303283 "supported": supported64Bit})
3284 // Then Try with 32 bit type
3285 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003286 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303287 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3288 } else if supported32Bit {
3289 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3290 mm.putExtPmMeKvStore(ctx)
3291 mm.setAllExtPmMeCreatedFlag()
3292 }
3293 } else if err == nil && supported64Bit {
3294 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3295 mm.putExtPmMeKvStore(ctx)
3296 mm.setAllExtPmMeCreatedFlag()
3297 }
3298}
3299
Himani Chawlaee10b542021-09-20 16:46:40 +05303300func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3301 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3302 uniPortEntityID := entityID
3303 if upstream {
3304 uniPortEntityID = entityID - 0x100
3305 }
3306 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3307 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3308 mm.pDeviceHandler.GetOmciTimeout(), true,
3309 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3310 if err != nil {
3311 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3312 log.Fields{"device-id": mm.deviceID})
3313 return extension.GetValueResponse_INTERNAL_ERROR, err
3314 }
3315
3316 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3317 return extension.GetValueResponse_REASON_UNDEFINED, nil
3318 }
3319 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3320}
3321
3322func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3323 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 -07003324 if !mm.GetOmciProcessingStatus() {
3325 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})
3326 return false
3327 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303328 select {
3329 case resp := <-mm.extendedPMMeResponseChan:
3330 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3331 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3332 if resp == me.Success {
3333 return true
3334 }
3335 return false
3336 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3337 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3338 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3339 }
3340 return false
3341}
3342
3343func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3344 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3345 className := "EthernetFrameExtendedPm64Bit"
3346 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3347 className = "EthernetFrameExtendedPm"
3348 }
3349 // Reset the counters if option is specified
3350 for entityID := range upstreamEntityMap {
3351 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3352 true)
3353 if err != nil {
3354 return errReason, err
3355 }
3356 }
3357
3358 for entityID := range downstreamEntityMap {
3359 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3360 true)
3361 if err != nil {
3362 return errReason, err
3363 }
3364 }
3365 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3366 // device itself.
3367 // Unset the reset bit if option is specified
3368 for entityID := range upstreamEntityMap {
3369 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3370 false)
3371 if err != nil {
3372 return errReason, err
3373 }
3374 }
3375
3376 for entityID := range downstreamEntityMap {
3377 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3378 false)
3379 if err != nil {
3380 return errReason, err
3381 }
3382 }
3383 return extension.GetValueResponse_REASON_UNDEFINED, nil
3384}
3385
3386func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3387 mm.onuEthernetFrameExtendedPmLock.Lock()
3388 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3389 mm.isEthernetFrameExtendedPmOperationOngoing = val
3390}
3391
3392func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3393 mm.onuEthernetFrameExtendedPmLock.Lock()
3394 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3395 return mm.isEthernetFrameExtendedPmOperationOngoing
3396}
3397
3398// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3399func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3400 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3401 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3402 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303403 return &extension.SingleGetValueResponse{
3404 Response: &extension.GetValueResponse{
3405 Status: extension.GetValueResponse_ERROR,
3406 ErrReason: reason,
3407 },
3408 }
3409 }
3410 mm.onuEthernetFrameExtendedPmLock.RLock()
3411 if !mm.isDeviceReadyToCollectExtendedPmStats {
3412 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303413 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303414 }
3415 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303416
3417 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3418 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3419 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3420 }
3421 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3422 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3423
3424 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3425 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3426 if onuInfo.IsUniIndex != nil {
3427 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3428 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3429 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3430 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3431 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3432 break
3433 }
3434 }
3435 if len(downstreamEntityMap) == 0 {
3436 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3437 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3438 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3439 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3440 }
3441 } else {
3442 // make a copy of all downstream and upstream maps in the local ones
3443 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3444 upstreamEntityMap[entityID] = meEnt
3445 }
3446 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3447 downstreamEntityMap[entityID] = meEnt
3448 }
3449 }
3450 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3451 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3452 // Reset the metrics first for all required me's
3453 if onuInfo.Reset_ {
3454 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3455 if err != nil {
3456 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3457 log.Fields{"device-id": mm.deviceID})
3458 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3459 }
3460 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303461 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3462 var pmUpstream extension.OmciEthernetFrameExtendedPm
3463 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303464 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3465 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3466 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3467 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303468 if !onuInfo.Reset_ {
3469 for entityID, meEnt := range upstreamEntityMap {
3470 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3471 var receivedMask uint16
3472 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3473 if receivedMask == 0 {
3474 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303475 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3476 // It might be possible that still some downstream pms are supported and hence we need to continue
3477 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3478 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303479 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303480 // Aggregate the result for upstream
3481 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3482 } else {
3483 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303484 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303485 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303486
Himani Chawlaee10b542021-09-20 16:46:40 +05303487 for entityID, meEnt := range downstreamEntityMap {
3488 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3489 var receivedMask uint16
3490 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303491 if receivedMask == 0 {
3492 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3493 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3494 // Stop collecting downstream counters for other ME's.
3495 break
3496 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303497 // Aggregate the result for downstream
3498 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3499 } else {
3500 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3501 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303502 }
3503 }
3504 singleValResp := extension.SingleGetValueResponse{
3505 Response: &extension.GetValueResponse{
3506 Status: extension.GetValueResponse_OK,
3507 Response: &extension.GetValueResponse_OnuCounters{
3508 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303509 Upstream: &pmUpstream,
3510 Downstream: &pmDownstream,
3511 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303512 },
3513 },
3514 },
3515 }
3516 return &singleValResp
3517}
3518
Himani Chawlaee10b542021-09-20 16:46:40 +05303519func (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 +05303520 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003521 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 +05303522
3523 classID = mm.supportedEthernetFrameExtendedPMClass
3524 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3525 if classID == me.EthernetFrameExtendedPmClassID {
3526 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3527 }
3528 ethPMData := make(map[string]uint64)
3529 var sumReceivedMask uint16
3530 for mask := range attributeMaskList {
3531 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3532 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003533 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303534 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303535 }
3536 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3537 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3538 //populate all counters as failure and return
3539 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3540 break
3541 }
3542 }
3543 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303544 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303545}
3546
3547// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003548func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303549 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3550 var meAttributes me.AttributeValueMap
3551 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003552 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303553 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003554 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303555 return extension.GetValueResponse_INTERNAL_ERROR, err
3556 }
3557 select {
3558 case meAttributes = <-mm.extendedPmMeChan:
3559 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003560 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3561 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303562 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003563 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303564 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3565 }
3566 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3567 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3568 *sumReceivedMask += mask
3569 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3570 } else {
3571 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3572 *sumReceivedMask += mask
3573 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3574 }
3575
3576 return extension.GetValueResponse_REASON_UNDEFINED, nil
3577}
3578
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003579func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303580 sourceMap := maskToEthernetFrameExtendedPM64Bit
3581 errorCounterValue := UnsupportedCounterValue64bit
3582 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3583 sourceMap = maskToEthernetFrameExtendedPM32Bit
3584 errorCounterValue = UnsupportedCounterValue32bit
3585 }
3586 for _, value := range sourceMap {
3587 for _, k := range value {
3588 if _, ok := ethFrameExtPMData[k]; !ok {
3589 ethFrameExtPMData[k] = errorCounterValue
3590 }
3591 }
3592 }
3593}
3594
3595// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003596func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303597 receivedMask := uint16(0)
3598 switch requestedAttributesMask {
3599 case 0x3F00:
3600 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3601 if _, ok := ethFrameExtPMData[k]; !ok {
3602 switch k {
3603 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003604 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303605 ethFrameExtPMData[k] = uint64(val.(uint32))
3606 receivedMask |= 0x2000
3607 } else if !ok {
3608 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3609 }
3610 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003611 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303612 ethFrameExtPMData[k] = uint64(val.(uint32))
3613 receivedMask |= 0x1000
3614 } else if !ok {
3615 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3616 }
3617 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003618 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303619 ethFrameExtPMData[k] = uint64(val.(uint32))
3620 receivedMask |= 0x800
3621 } else if !ok {
3622 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3623 }
3624 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003625 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303626 ethFrameExtPMData[k] = uint64(val.(uint32))
3627 receivedMask |= 0x400
3628 } else if !ok {
3629 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3630 }
3631 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003632 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303633 ethFrameExtPMData[k] = uint64(val.(uint32))
3634 receivedMask |= 0x200
3635 } else if !ok {
3636 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3637 }
3638 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003639 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303640 ethFrameExtPMData[k] = uint64(val.(uint32))
3641 receivedMask |= 0x100
3642 } else if !ok {
3643 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3644 }
3645 default:
3646 //do nothing
3647 }
3648 }
3649 }
3650 case 0x00FC:
3651 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3652 if _, ok := ethFrameExtPMData[k]; !ok {
3653 switch k {
3654 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003655 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303656 ethFrameExtPMData[k] = uint64(val.(uint32))
3657 receivedMask |= 0x80
3658 } else if !ok {
3659 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3660 }
3661 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003662 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303663 ethFrameExtPMData[k] = uint64(val.(uint32))
3664 receivedMask |= 0x40
3665 } else if !ok {
3666 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3667 }
3668 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003669 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303670 ethFrameExtPMData[k] = uint64(val.(uint32))
3671 receivedMask |= 0x20
3672 } else if !ok {
3673 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3674 }
3675 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003676 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303677 ethFrameExtPMData[k] = uint64(val.(uint32))
3678 receivedMask |= 0x10
3679 } else if !ok {
3680 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3681 }
3682 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003683 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303684 ethFrameExtPMData[k] = uint64(val.(uint32))
3685 receivedMask |= 0x8
3686 } else if !ok {
3687 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3688 }
3689 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003690 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303691 ethFrameExtPMData[k] = uint64(val.(uint32))
3692 receivedMask |= 0x4
3693 } else if !ok {
3694 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3695 }
3696 default:
3697 //do nothing
3698 }
3699 }
3700 }
3701 case 0x0003:
3702 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3703 if _, ok := ethFrameExtPMData[k]; !ok {
3704 switch k {
3705 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003706 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303707 ethFrameExtPMData[k] = uint64(val.(uint32))
3708 receivedMask |= 0x2
3709 } else if !ok {
3710 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3711 }
3712 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003713 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303714 ethFrameExtPMData[k] = uint64(val.(uint32))
3715 receivedMask |= 0x1
3716 } else if !ok {
3717 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3718 }
3719 default:
3720 //do nothing
3721 }
3722 }
3723 }
3724 default:
3725 //do nothing
3726 }
3727 return receivedMask
3728}
3729
3730// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003731func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303732 receivedMask := uint16(0)
3733 switch requestedAttributesMask {
3734 case 0x3800:
3735 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3736 if _, ok := ethFrameExtPMData[k]; !ok {
3737 switch k {
3738 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003739 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303740 ethFrameExtPMData[k] = val.(uint64)
3741 receivedMask |= 0x2000
3742 } else if !ok {
3743 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3744 }
3745 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003746 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303747 ethFrameExtPMData[k] = val.(uint64)
3748 receivedMask |= 0x1000
3749 } else if !ok {
3750 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3751 }
3752 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003753 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303754 ethFrameExtPMData[k] = val.(uint64)
3755 receivedMask |= 0x800
3756 } else if !ok {
3757 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3758 }
3759 }
3760 }
3761 }
3762 case 0x0700:
3763 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3764 if _, ok := ethFrameExtPMData[k]; !ok {
3765 switch k {
3766 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003767 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303768 ethFrameExtPMData[k] = val.(uint64)
3769 receivedMask |= 0x400
3770 } else if !ok {
3771 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3772 }
3773 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003774 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303775 ethFrameExtPMData[k] = val.(uint64)
3776 receivedMask |= 0x200
3777 } else if !ok {
3778 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3779 }
3780 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003781 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303782 ethFrameExtPMData[k] = val.(uint64)
3783 receivedMask |= 0x100
3784 } else if !ok {
3785 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3786 }
3787 }
3788 }
3789 }
3790 case 0x00E0:
3791 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3792 if _, ok := ethFrameExtPMData[k]; !ok {
3793 switch k {
3794 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003795 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303796 ethFrameExtPMData[k] = val.(uint64)
3797 receivedMask |= 0x80
3798 } else if !ok {
3799 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3800 }
3801 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003802 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303803 ethFrameExtPMData[k] = val.(uint64)
3804 receivedMask |= 0x40
3805 } else if !ok {
3806 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3807 }
3808 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003809 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303810 ethFrameExtPMData[k] = val.(uint64)
3811 receivedMask |= 0x20
3812 } else if !ok {
3813 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3814 }
3815 }
3816 }
3817 }
3818 case 0x001C:
3819 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3820 if _, ok := ethFrameExtPMData[k]; !ok {
3821 switch k {
3822 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003823 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303824 ethFrameExtPMData[k] = val.(uint64)
3825 receivedMask |= 0x10
3826 } else if !ok {
3827 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3828 }
3829 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003830 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303831 ethFrameExtPMData[k] = val.(uint64)
3832 receivedMask |= 0x8
3833 } else if !ok {
3834 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3835 }
3836 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003837 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303838 ethFrameExtPMData[k] = val.(uint64)
3839 receivedMask |= 0x4
3840 } else if !ok {
3841 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3842 }
3843 default:
3844 //do nothing
3845 }
3846 }
3847 }
3848 case 0x0003:
3849 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3850 if _, ok := ethFrameExtPMData[k]; !ok {
3851 switch k {
3852 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003853 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303854 ethFrameExtPMData[k] = val.(uint64)
3855 receivedMask |= 0x2
3856 } else if !ok {
3857 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3858 }
3859 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003860 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303861 ethFrameExtPMData[k] = val.(uint64)
3862 receivedMask |= 0x1
3863 } else if !ok {
3864 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3865 }
3866 default:
3867 //do nothing
3868 }
3869 }
3870 }
3871 }
3872 return receivedMask
3873}
3874
Himani Chawlaee10b542021-09-20 16:46:40 +05303875func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3876 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303877 errorCounterValue := UnsupportedCounterValue64bit
3878 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3879 errorCounterValue = UnsupportedCounterValue32bit
3880 }
3881 var pmDataOut extension.OmciEthernetFrameExtendedPm
3882 if aggregate {
3883 if pmData.DropEvents != errorCounterValue {
3884 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3885 } else {
3886 pmDataOut.DropEvents = pmData.DropEvents
3887 }
3888 if pmData.Octets != errorCounterValue {
3889 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3890 } else {
3891 pmDataOut.Octets = pmData.Octets
3892 }
3893 if pmData.Frames != errorCounterValue {
3894 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3895 } else {
3896 pmDataOut.Frames = pmData.Frames
3897 }
3898 if pmData.BroadcastFrames != errorCounterValue {
3899 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3900 } else {
3901 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3902 }
3903 if pmData.MulticastFrames != errorCounterValue {
3904 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3905 } else {
3906 pmDataOut.MulticastFrames = pmData.MulticastFrames
3907 }
3908 if pmData.CrcErroredFrames != errorCounterValue {
3909 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3910 } else {
3911 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3912 }
3913 if pmData.UndersizeFrames != errorCounterValue {
3914 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3915 } else {
3916 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3917 }
3918 if pmData.OversizeFrames != errorCounterValue {
3919 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3920 } else {
3921 pmDataOut.OversizeFrames = pmData.OversizeFrames
3922 }
3923 if pmData.Frames_64Octets != errorCounterValue {
3924 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3925 } else {
3926 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3927 }
3928 if pmData.Frames_65To_127Octets != errorCounterValue {
3929 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3930 } else {
3931 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3932 }
3933 if pmData.Frames_128To_255Octets != errorCounterValue {
3934 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3935 } else {
3936 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3937 }
3938 if pmData.Frames_256To_511Octets != errorCounterValue {
3939 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3940 } else {
3941 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3942 }
3943 if pmData.Frames_512To_1023Octets != errorCounterValue {
3944 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3945 } else {
3946 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3947 }
3948 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3949 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3950 } else {
3951 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3952 }
3953 } else {
3954 pmDataOut.DropEvents = pmDataIn["drop_events"]
3955 pmDataOut.Octets = pmDataIn["octets"]
3956 pmDataOut.Frames = pmDataIn["frames"]
3957 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3958 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3959 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3960 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3961 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3962 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3963 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3964 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3965 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3966 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3967 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3968 }
3969 return pmDataOut
3970}
3971
Himani Chawlaee10b542021-09-20 16:46:40 +05303972func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303973 controlBlock := make([]uint16, 8)
3974 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3975 controlBlock[0] = 0
3976 // Next two bytes are for the parent class ID
3977 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3978 // Next two bytes are for the parent me instance id
3979 controlBlock[2] = entityID
3980 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05303981 if reset {
3982 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
3983 } else {
3984 controlBlock[3] = 0
3985 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303986 // Next two bytes are for tca disable
3987 controlBlock[4] = 0x4000 //tca global disable
3988 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
3989 if upstream {
3990 controlBlock[5] = 1 << 0
3991 } else {
3992 controlBlock[5] = (1 << 0) | (1 << 1)
3993 }
3994 // Next two bytes are for tci - does not matter here
3995 controlBlock[6] = 0
3996 // Next two bytes are for reserved bits - does not matter here
3997 controlBlock[7] = 0
3998 return controlBlock
3999}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00004000
Girish Gowdraabcceb12022-04-13 23:35:22 -07004001// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
4002func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
4003 mm.OnuMetricsManagerLock.RLock()
4004 defer mm.OnuMetricsManagerLock.RUnlock()
4005 return mm.deviceDeletionInProgress
4006}
4007
4008// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
4009func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
4010 mm.OnuMetricsManagerLock.Lock()
4011 defer mm.OnuMetricsManagerLock.Unlock()
4012 mm.deviceDeletionInProgress = true
4013}