blob: 03f7af7292bdfa8c3cd7924b3ec330b24d04a830 [file] [log] [blame]
Girish Gowdrae09a6202021-01-12 18:10:59 -08001/*
Joey Armstronge8c091f2023-01-17 16:56:26 -05002 * Copyright 2021-2023 Open Networking Foundation (ONF) and the ONF Contributors
Girish Gowdrae09a6202021-01-12 18:10:59 -08003
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
praneeth nalmas808f43a2023-05-14 12:54:34 +053017// Package pmmgr provides the utilities to manage onu metrics
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000018package pmmgr
Girish Gowdrae09a6202021-01-12 18:10:59 -080019
20import (
21 "context"
Girish Gowdra0e533642021-03-02 22:02:51 -080022 "encoding/json"
Girish Gowdrae09a6202021-01-12 18:10:59 -080023 "fmt"
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +000024 "math"
25 "sync"
26 "time"
27
Girish Gowdrae0140f02021-02-02 16:55:09 -080028 "github.com/looplab/fsm"
Holger Hildebrandtd930cb22022-06-17 09:24:50 +000029 omci "github.com/opencord/omci-lib-go/v2"
mpagenko836a1fd2021-11-01 16:12:42 +000030 me "github.com/opencord/omci-lib-go/v2/generated"
khenaidoo7d3c5582021-08-11 18:09:44 -040031 "github.com/opencord/voltha-lib-go/v7/pkg/db"
32 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000034 cmn "github.com/opencord/voltha-openonu-adapter-go/internal/pkg/common"
khenaidoo7d3c5582021-08-11 18:09:44 -040035 "github.com/opencord/voltha-protos/v5/go/extension"
36 "github.com/opencord/voltha-protos/v5/go/voltha"
Girish Gowdrae09a6202021-01-12 18:10:59 -080037)
38
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000039// events of L2 PM FSM
Girish Gowdrae0140f02021-02-02 16:55:09 -080040const (
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000041 L2PmEventInit = "L2PmEventInit"
42 L2PmEventTick = "L2PmEventTick"
43 L2PmEventSuccess = "L2PmEventSuccess"
44 L2PmEventFailure = "L2PmEventFailure"
45 L2PmEventAddMe = "L2PmEventAddMe"
46 L2PmEventDeleteMe = "L2PmEventDeleteMe"
47 L2PmEventStop = "L2PmEventStop"
Girish Gowdrae0140f02021-02-02 16:55:09 -080048)
49
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000050// states of L2 PM FSM
51const (
52 L2PmStNull = "L2PmStNull"
53 L2PmStStarting = "L2PmStStarting"
54 L2PmStSyncTime = "L2PmStSyncTime"
55 L2PmStIdle = "L2PmStIdle"
56 L2PmStCreatePmMe = "L2PmStCreatePm"
57 L2PmStDeletePmMe = "L2PmStDeletePmMe"
58 L2PmStCollectData = "L2PmStCollectData"
59)
60
61// CL2PmFsmIdleState - TODO: add comment
62const CL2PmFsmIdleState = L2PmStIdle
Girish Gowdrae0140f02021-02-02 16:55:09 -080063
Girish Gowdra5a7c4922021-01-22 18:33:41 -080064// general constants used for overall Metric Collection management
65const (
66 DefaultMetricCollectionFrequency = 15 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
67 GroupMetricEnabled = true // This is READONLY and cannot be changed from VOLTHA NBI
68 DefaultFrequencyOverrideEnabled = true // This is READONLY and cannot be changed from VOLTHA NBI
69 FrequencyGranularity = 5 // The frequency (in seconds) has to be multiple of 5. This setting cannot changed later.
Girish Gowdraabcceb12022-04-13 23:35:22 -070070 MaxTimeForPmFsmShutDown = 120 // in seconds
Girish Gowdra5a7c4922021-01-22 18:33:41 -080071)
72
Himani Chawla43f95ff2021-06-03 00:24:12 +053073// constants for ethernet frame extended pm collection
74const (
75 ExtendedPmCreateAttempts = 3
76 UnsupportedCounterValue32bit uint64 = 4294967294
77 UnsupportedCounterValue64bit uint64 = 18446744073709551614
Himani Chawla43f95ff2021-06-03 00:24:12 +053078)
79
Girish Gowdra5a7c4922021-01-22 18:33:41 -080080// OpticalPowerGroupMetrics are supported optical pm names
81var OpticalPowerGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrae20a4f62021-03-09 16:06:23 -080082 "ani_g_instance_id": voltha.PmConfig_CONTEXT,
83 "transmit_power_dBm": voltha.PmConfig_GAUGE,
84 "receive_power_dBm": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -080085}
86
87// OpticalPowerGroupMetrics specific constants
88const (
Girish Gowdrae0140f02021-02-02 16:55:09 -080089 OpticalPowerGroupMetricName = "PON_Optical"
Girish Gowdra5a7c4922021-01-22 18:33:41 -080090 OpticalPowerGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
91 OpticalPowerMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
92)
93
94// UniStatusGroupMetrics are supported UNI status names
95var UniStatusGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrad3436802021-06-28 13:15:40 -070096 "uni_port_no": voltha.PmConfig_CONTEXT,
97 "me_class_id": voltha.PmConfig_CONTEXT,
98 "entity_id": voltha.PmConfig_CONTEXT,
99 "configuration_ind": voltha.PmConfig_GAUGE,
100 "oper_status": voltha.PmConfig_GAUGE,
101 "uni_admin_state": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800102}
103
104// UniStatusGroupMetrics specific constants
105const (
Girish Gowdrae0140f02021-02-02 16:55:09 -0800106 UniStatusGroupMetricName = "UNI_Status"
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800107 UniStatusGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
108 UniStatusMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
109)
110
Girish Gowdrae0140f02021-02-02 16:55:09 -0800111// *** Classical L2 PM Counters begin ***
112
113// EthernetBridgeHistory are supported ethernet bridge history counters fetched from
114// Ethernet Frame Performance Monitoring History Data Downstream and Ethernet Frame Performance Monitoring History Data Upstream MEs.
115var EthernetBridgeHistory = map[string]voltha.PmConfig_PmType{
116 "class_id": voltha.PmConfig_CONTEXT,
117 "entity_id": voltha.PmConfig_CONTEXT,
118 "interval_end_time": voltha.PmConfig_CONTEXT,
119 "parent_class_id": voltha.PmConfig_CONTEXT,
120 "parent_entity_id": voltha.PmConfig_CONTEXT,
121 "upstream": voltha.PmConfig_CONTEXT,
122
123 "drop_events": voltha.PmConfig_COUNTER,
124 "octets": voltha.PmConfig_COUNTER,
125 "packets": voltha.PmConfig_COUNTER,
126 "broadcast_packets": voltha.PmConfig_COUNTER,
127 "multicast_packets": voltha.PmConfig_COUNTER,
128 "crc_errored_packets": voltha.PmConfig_COUNTER,
129 "undersize_packets": voltha.PmConfig_COUNTER,
130 "oversize_packets": voltha.PmConfig_COUNTER,
131 "64_octets": voltha.PmConfig_COUNTER,
132 "65_to_127_octets": voltha.PmConfig_COUNTER,
133 "128_to_255_octets": voltha.PmConfig_COUNTER,
134 "256_to_511_octets": voltha.PmConfig_COUNTER,
135 "512_to_1023_octets": voltha.PmConfig_COUNTER,
136 "1024_to_1518_octets": voltha.PmConfig_COUNTER,
137}
138
139// EthernetUniHistory are supported ethernet uni history counters fetched from
140// Ethernet Performance Monitoring History Data ME.
141var EthernetUniHistory = map[string]voltha.PmConfig_PmType{
142 "class_id": voltha.PmConfig_CONTEXT,
143 "entity_id": voltha.PmConfig_CONTEXT,
144 "interval_end_time": voltha.PmConfig_CONTEXT,
145
146 "fcs_errors": voltha.PmConfig_COUNTER,
147 "excessive_collision_counter": voltha.PmConfig_COUNTER,
148 "late_collision_counter": voltha.PmConfig_COUNTER,
149 "frames_too_long": voltha.PmConfig_COUNTER,
150 "buffer_overflows_on_rx": voltha.PmConfig_COUNTER,
151 "buffer_overflows_on_tx": voltha.PmConfig_COUNTER,
152 "single_collision_frame_counter": voltha.PmConfig_COUNTER,
153 "multiple_collisions_frame_counter": voltha.PmConfig_COUNTER,
154 "sqe_counter": voltha.PmConfig_COUNTER,
155 "deferred_tx_counter": voltha.PmConfig_COUNTER,
156 "internal_mac_tx_error_counter": voltha.PmConfig_COUNTER,
157 "carrier_sense_error_counter": voltha.PmConfig_COUNTER,
158 "alignment_error_counter": voltha.PmConfig_COUNTER,
159 "internal_mac_rx_error_counter": voltha.PmConfig_COUNTER,
160}
161
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800162// FecHistory is supported FEC Performance Monitoring History Data related metrics
163var FecHistory = map[string]voltha.PmConfig_PmType{
164 "class_id": voltha.PmConfig_CONTEXT,
165 "entity_id": voltha.PmConfig_CONTEXT,
166 "interval_end_time": voltha.PmConfig_CONTEXT,
167
168 "corrected_bytes": voltha.PmConfig_COUNTER,
169 "corrected_code_words": voltha.PmConfig_COUNTER,
170 "uncorrectable_code_words": voltha.PmConfig_COUNTER,
171 "total_code_words": voltha.PmConfig_COUNTER,
172 "fec_seconds": voltha.PmConfig_COUNTER,
173}
174
175// GemPortHistory is supported GEM Port Network Ctp Performance Monitoring History Data
176// related metrics
177var GemPortHistory = map[string]voltha.PmConfig_PmType{
178 "class_id": voltha.PmConfig_CONTEXT,
179 "entity_id": voltha.PmConfig_CONTEXT,
180 "interval_end_time": voltha.PmConfig_CONTEXT,
181
182 "transmitted_gem_frames": voltha.PmConfig_COUNTER,
183 "received_gem_frames": voltha.PmConfig_COUNTER,
184 "received_payload_bytes": voltha.PmConfig_COUNTER,
185 "transmitted_payload_bytes": voltha.PmConfig_COUNTER,
186 "encryption_key_errors": voltha.PmConfig_COUNTER,
187}
188
Himani Chawla43f95ff2021-06-03 00:24:12 +0530189var maskToEthernetFrameExtendedPM32Bit = map[uint16][]string{
190 0x3F00: {"drop_events", "octets", "frames", "broadcast_frames", "multicast_frames", "crc_errored_frames"},
191 0x00FC: {"undersize_frames", "oversize_frames", "64_octets", "65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
192 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
193}
194
195var maskToEthernetFrameExtendedPM64Bit = map[uint16][]string{
196 0x3800: {"drop_events", "octets", "frames"},
197 0x0700: {"broadcast_frames", "multicast_frames", "crc_errored_frames"},
198 0x00E0: {"undersize_frames", "oversize_frames", "64_octets"},
199 0x001C: {"65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
200 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
201}
202
Girish Gowdrae0140f02021-02-02 16:55:09 -0800203// Constants specific for L2 PM collection
204const (
205 L2PmCollectionInterval = 15 * 60 // Unit in seconds. Do not change this as this fixed by OMCI specification for L2 PM counters
206 SyncTimeRetryInterval = 15 // Unit seconds
207 L2PmCreateAttempts = 3
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800208 L2PmDeleteAttempts = 3
Girish Gowdrae0140f02021-02-02 16:55:09 -0800209 L2PmCollectAttempts = 3
Girish Gowdra453750f2021-02-16 16:36:46 -0800210 // Per Table 11.2.9-1 – OMCI baseline message limitations in G.988 spec, the max GET Response
211 // payload size is 25. We define 24 (one less) to allow for dynamic insertion of IntervalEndTime
212 // attribute (1 byte) in L2 PM GET Requests.
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000213 MaxBaselineL2PMGetPayLoadSize = 24
214 // unused: MaxEthernetFrameExtPmPayloadSize = 25
215 MaxExtendedL2PMGetPayLoadSize = omci.MaxExtendedLength - 17 - 1 - 4 // minus header, attribute IntervalEndTime and MIC
Girish Gowdrae0140f02021-02-02 16:55:09 -0800216)
217
218// EthernetUniHistoryName specific constants
219const (
220 EthernetBridgeHistoryName = "Ethernet_Bridge_Port_History"
221 EthernetBridgeHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
222 EthernetBridgeHistoryFrequency = L2PmCollectionInterval
223)
224
225// EthernetBridgeHistory specific constants
226const (
227 EthernetUniHistoryName = "Ethernet_UNI_History"
228 EthernetUniHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
229 EthernetUniHistoryFrequency = L2PmCollectionInterval
230)
231
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800232// FecHistory specific constants
233const (
234 FecHistoryName = "FEC_History"
235 FecHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
236 FecHistoryFrequency = L2PmCollectionInterval
237)
238
239// GemPortHistory specific constants
240const (
241 GemPortHistoryName = "GEM_Port_History"
242 GemPortHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
243 GemPortHistoryFrequency = L2PmCollectionInterval
244)
245
Holger Hildebrandt60652202021-11-02 11:09:36 +0000246// CPmKvStorePrefixBase - kv store base path of ONU specific PM data
247const CPmKvStorePrefixBase = cmn.CBasePathOnuKVStore + "/pm-data" // <some-base-path>/openonu/pm-data
248
Girish Gowdra0e533642021-03-02 22:02:51 -0800249// KV Store related constants
250const (
Holger Hildebrandt60652202021-11-02 11:09:36 +0000251 cPmKvStorePrefix = CPmKvStorePrefixBase + "/%s" // <some-base-path>/openonu/pm-data/<onu-device-id>
Himani Chawla43f95ff2021-06-03 00:24:12 +0530252 cPmAdd = "add"
253 cPmAdded = "added"
254 cPmRemove = "remove"
255 cPmRemoved = "removed"
256 cExtPmKvStorePrefix = "%s/omci_me" //<some-base-path>/omci_me/<onu_vendor>/<onu_equipment_id>/<onu_sw_version>
Girish Gowdra0e533642021-03-02 22:02:51 -0800257)
258
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800259// Defines the type for generic metric population function
260type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
261
Girish Gowdrae0140f02021-02-02 16:55:09 -0800262// *** Classical L2 PM Counters end ***
263
Girish Gowdra0e533642021-03-02 22:02:51 -0800264type pmMEData struct {
265 InstancesActive []uint16 `json:"instances_active"` // list of active ME instance IDs for the group
266 InstancesToDelete []uint16 `json:"instances_to_delete"` // list of ME instance IDs marked for deletion for the group
267 InstancesToAdd []uint16 `json:"instances_to_add"` // list of ME instance IDs marked for addition for the group
268}
269
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800270type groupMetric struct {
271 groupName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000272 Enabled bool
273 Frequency uint32 // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800274 metricMap map[string]voltha.PmConfig_PmType
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000275 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
276 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdrae0140f02021-02-02 16:55:09 -0800277 collectAttempts uint32 // number of attempts to collect L2 PM data
Girish Gowdra0e533642021-03-02 22:02:51 -0800278 pmMEData *pmMEData
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800279}
280
281type standaloneMetric struct {
282 metricName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000283 Enabled bool
284 Frequency uint32 // valid only if FrequencyOverride is enabled.
285 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800286}
287
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000288// OnuMetricsManager - TODO: add comment
289type OnuMetricsManager struct {
290 deviceID string
291 pDeviceHandler cmn.IdeviceHandler
292 pOnuDeviceEntry cmn.IonuDeviceEntry
293 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800294
Himani Chawlaee10b542021-09-20 16:46:40 +0530295 opticalMetricsChan chan me.AttributeValueMap
296 uniStatusMetricsChan chan me.AttributeValueMap
297 l2PmChan chan me.AttributeValueMap
298 extendedPmMeChan chan me.AttributeValueMap
299 syncTimeResponseChan chan bool // true is success, false is fail
300 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
301 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -0800302
303 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
304 l2PmToDelete []string // list of L2 PMs to delete
305 l2PmToAdd []string // list of L2 PM to add
Girish Gowdrae09a6202021-01-12 18:10:59 -0800306
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000307 GroupMetricMap map[string]*groupMetric
308 StandaloneMetricMap map[string]*standaloneMetric
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800309
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000310 StopProcessingOmciResponses chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700311 omciProcessingActive bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800312
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000313 StopTicks chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700314 tickGenerationActive bool
Girish Gowdrae0140f02021-02-02 16:55:09 -0800315
Girish Gowdraabcceb12022-04-13 23:35:22 -0700316 deviceDeletionInProgress bool
317 GarbageCollectionComplete chan bool
318
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000319 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800320
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000321 OnuMetricsManagerLock sync.RWMutex
Girish Gowdra0e533642021-03-02 22:02:51 -0800322
323 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530324
325 supportedEthernetFrameExtendedPMClass me.ClassID
Himani Chawlac77d5372021-07-12 15:42:26 +0530326 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
327 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530328 extPmKvStore *db.Backend
329 onuEthernetFrameExtendedPmLock sync.RWMutex
330 isDeviceReadyToCollectExtendedPmStats bool
Himani Chawlaee10b542021-09-20 16:46:40 +0530331 isEthernetFrameExtendedPmOperationOngoing bool
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000332 isExtendedOmci bool
333 maxL2PMGetPayLoadSize int
praneeth nalmas808f43a2023-05-14 12:54:34 +0530334 onuOpticalMetricstimer *time.Timer
335 onuUniStatusMetricstimer *time.Timer
praneeth nalmasf405e962023-08-07 15:02:03 +0530336 opticalMetricsDelCommChan chan bool
337 uniMetricsDelCommChan chan bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800338}
339
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000340// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800341// The metrics manager module is responsible for configuration and management of individual and group metrics.
342// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
343// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
344// the collection interval configurable.
345// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
346// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000347func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800348
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000349 var metricsManager OnuMetricsManager
350 metricsManager.deviceID = dh.GetDeviceID()
351 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800352 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000353 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800354
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000355 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800356 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
357 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800358 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530359 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800360
361 metricsManager.syncTimeResponseChan = make(chan bool)
362 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530363 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800364
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000365 metricsManager.StopProcessingOmciResponses = make(chan bool)
366 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800367
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000368 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
369 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800370
Himani Chawlac77d5372021-07-12 15:42:26 +0530371 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
372 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530373
Girish Gowdraabcceb12022-04-13 23:35:22 -0700374 // make this a buffered channel so that the sender is not blocked for any reason if there is no listener
375 metricsManager.GarbageCollectionComplete = make(chan bool, 1)
376
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000377 if dh.GetPmConfigs() == nil { // dh.GetPmConfigs() is NOT nil if adapter comes back from a restart. We should NOT go back to defaults in this case
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800378 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800379 }
380
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800381 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800382
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800383 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800384 return nil
385 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800386
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800387 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000388 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800389
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000390 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
391 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800392 if metricsManager.pmKvStore == nil {
393 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000394 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800395 return nil
396 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700397 // restore data from KV store
398 if err := metricsManager.restorePmData(ctx); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000399 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700400 // we continue given that it does not effect the actual services for the ONU,
401 // but there may be some negative effect on PM collection (there may be some mismatch in
402 // the actual PM config and what is present on the device).
403 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800404
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000405 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
406 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530407 if metricsManager.extPmKvStore == nil {
408 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000409 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530410 return nil
411 }
412
praneeth nalmas808f43a2023-05-14 12:54:34 +0530413 //Metrics collection timers are initialized with a default timer value, will be stopped immediately and further
414 //timers are reset during the actual stats collection begins.
415 metricsManager.onuOpticalMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
416 metricsManager.onuOpticalMetricstimer.Stop()
417
418 metricsManager.onuUniStatusMetricstimer = time.NewTimer(DefaultMetricCollectionFrequency)
419 metricsManager.onuUniStatusMetricstimer.Stop()
420
praneeth nalmasf405e962023-08-07 15:02:03 +0530421 metricsManager.opticalMetricsDelCommChan = make(chan bool, 2)
422 metricsManager.uniMetricsDelCommChan = make(chan bool, 2)
423
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000424 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800425 return &metricsManager
426}
427
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000428// InitializeMetricCollectionTime - TODO: add comment
429func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
430 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
431 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
432 mm.OnuMetricsManagerLock.Lock()
433 defer mm.OnuMetricsManagerLock.Unlock()
434 for _, v := range mm.GroupMetricMap {
435 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
436 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800437 }
438 }
439
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000440 for _, v := range mm.StandaloneMetricMap {
441 if v.Enabled {
442 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800443 }
444 }
445 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000446 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
447 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800448 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000449 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800450}
451
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000452// UpdateDefaultFrequency - TODO: add comment
453func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800454 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800455 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800456 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
457 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
458 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000459 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
460 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
461 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
462 logger.Debugw(ctx, "frequency-updated--new-frequency", log.Fields{"device-id": mm.deviceID, "frequency": mm.pDeviceHandler.GetPmConfigs().DefaultFreq})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800463 return nil
464}
465
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000466// UpdateGroupFreq - TODO: add comment
467func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800468 var newGroupFreq uint32
469 found := false
470 groupSliceIdx := 0
471 var group *voltha.PmGroupConfig
472 for groupSliceIdx, group = range pmConfigs.Groups {
473 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800474 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
475 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
476 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
477 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800478 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800479 newGroupFreq = group.GroupFreq
480 found = true
481 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800482 }
483 }
484 // if not found update group freq and next collection interval for the group
485 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000486 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800487 return fmt.Errorf("group-name-not-found-%v", aGroupName)
488 }
489
490 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000491 mm.OnuMetricsManagerLock.Lock()
492 defer mm.OnuMetricsManagerLock.Unlock()
493 for k, v := range mm.GroupMetricMap {
494 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
495 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800496 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000497 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800498 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000499 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800500 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000501 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800502 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800503 }
504 }
505 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000506 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800507 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
508 }
509 return nil
510}
511
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000512// UpdateMetricFreq - TODO: add comment
513func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800514 var newMetricFreq uint32
515 found := false
516 metricSliceIdx := 0
517 var metric *voltha.PmConfig
518 for metricSliceIdx, metric = range pmConfigs.Metrics {
519 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800520 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
521 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
522 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
523 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800524 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800525 newMetricFreq = metric.SampleFreq
526 found = true
527 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800528 }
529 }
530 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000531 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800532 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
533 }
534
535 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000536 mm.OnuMetricsManagerLock.Lock()
537 defer mm.OnuMetricsManagerLock.Unlock()
538 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800539 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000540 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800541 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000542 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800543 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000544 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800545 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000546 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800547 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800548 }
549 }
550 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000551 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800552 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
553 }
554 return nil
555}
556
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000557// UpdateGroupSupport - TODO: add comment
558func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800559 groupSliceIdx := 0
560 var group *voltha.PmGroupConfig
561
562 for groupSliceIdx, group = range pmConfigs.Groups {
563 if group.GroupName == aGroupName {
564 break
565 }
566 }
567 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000568 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800569 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
570 }
571
572 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000573 mm.OnuMetricsManagerLock.Lock()
574 defer mm.OnuMetricsManagerLock.Unlock()
575 for k, v := range mm.GroupMetricMap {
576 if k == aGroupName && v.Enabled != group.Enabled {
577 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
578 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800579 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000580 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800581 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800582 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800583 // If the group support flag toggles too soon, we need to delete the group name from l2PmToDelete slice
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800584 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
585
586 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
587 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
588 // take further action
589 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800590 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800591 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000592 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
593 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800594 }
595 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000596 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800597 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800598 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800599 // If the group support flag toggles too soon, we need to delete the group name from l2PmToAdd slice
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800600 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
601
602 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
603 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
604 // take further action
605 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800606 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800607 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800608 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800609 }
610 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000611 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800612 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000613 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800614 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000615 logger.Infow(ctx, "group metric support updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800616 }
617 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800618 }
619 }
620
621 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000622 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800623 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
624 }
625 return nil
626}
627
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000628// UpdateMetricSupport - TODO: add comment
629func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800630 metricSliceIdx := 0
631 var metric *voltha.PmConfig
632
633 for metricSliceIdx, metric = range pmConfigs.Metrics {
634 if metric.Name == aMetricName {
635 break
636 }
637 }
638
639 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000640 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800641 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
642 }
643
644 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000645 mm.OnuMetricsManagerLock.Lock()
646 defer mm.OnuMetricsManagerLock.Unlock()
647 for k, v := range mm.StandaloneMetricMap {
648 if k == aMetricName && v.Enabled != metric.Enabled {
649 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
650 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800651 // If the standalone metric is now enabled and frequency override is enabled, set the next metric collection time
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000652 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
653 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800654 }
655 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000656 logger.Infow(ctx, "standalone metric support updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName, "enabled": metric.Enabled})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800657 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800658 }
659 }
660 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000661 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800662 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
663 }
664 return nil
665}
666
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000667// CollectAllGroupAndStandaloneMetrics - TODO: add comment
668func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
669 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800670 go mm.collectAllGroupMetrics(ctx)
671 } else {
672 go mm.collectAllStandaloneMetrics(ctx)
673 }
674}
675
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000676func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800677 go func() {
678 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300679 metricInfo, err := mm.collectOpticalMetrics(ctx)
680 if err != nil {
681 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000682 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300683 return
684 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800685 if metricInfo != nil {
686 mm.publishMetrics(ctx, metricInfo)
687 }
688 }()
689
690 go func() {
691 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300692 metricInfo, err := mm.collectUniStatusMetrics(ctx)
693 if err != nil {
694 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000695 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300696 return
697 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800698 if metricInfo != nil {
699 mm.publishMetrics(ctx, metricInfo)
700 }
701 }()
702
703 // Add more here
704}
705
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000706func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800707 // None exists as of now, add when available here
708}
709
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000710// CollectGroupMetric - TODO: add comment
711func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800712 switch groupName {
713 case OpticalPowerGroupMetricName:
714 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300715 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800716 mm.publishMetrics(ctx, mi)
717 }
718 }()
719 case UniStatusGroupMetricName:
720 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300721 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800722 mm.publishMetrics(ctx, mi)
723 }
724 }()
725 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000726 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800727 }
728}
729
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000730// CollectStandaloneMetric - TODO: add comment
731func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800732 switch metricName {
733 // None exist as of now, add when available
734 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000735 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800736 }
737}
738
739// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000740func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
741 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800742
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000743 mm.OnuMetricsManagerLock.RLock()
744 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
745 mm.OnuMetricsManagerLock.RUnlock()
746 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300747 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800748 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000749 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800750
Girish Gowdrae09a6202021-01-12 18:10:59 -0800751 var metricInfoSlice []*voltha.MetricInformation
752 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000753 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
754 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
755 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800756
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800757 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800758 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800759 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800760 Ts: float64(raisedTs),
761 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000762 DeviceId: mm.deviceID,
763 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
764 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800765 }
766
Girish Gowdrae09a6202021-01-12 18:10:59 -0800767 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000768 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800769loop:
770 for _, anigInstID := range anigInstKeys {
771 var meAttributes me.AttributeValueMap
772 opticalMetrics := make(map[string]float32)
773 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000774 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000775 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes,
776 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300777 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000778 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
779 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300780 return nil, err
781 }
782
783 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530784 mm.onuOpticalMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800785 select {
786 case meAttributes = <-mm.opticalMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530787 mm.onuOpticalMetricstimer.Stop()
788 logger.Debugw(ctx, "received optical metrics, stopping the optical metrics collection timer", log.Fields{"device-id": mm.deviceID})
789 case <-mm.onuOpticalMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000790 logger.Errorw(ctx, "timeout waiting for omci-get response for optical metrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800791 // The metrics will be empty in this case
792 break loop
praneeth nalmasf405e962023-08-07 15:02:03 +0530793 case <-mm.opticalMetricsDelCommChan:
794 logger.Warnw(ctx, "Deleting the device, stopping optical metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
795 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800796 }
797 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800798 for k := range OpticalPowerGroupMetrics {
799 switch k {
800 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000801 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800802 opticalMetrics[k] = float32(val.(uint16))
803 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800804 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000805 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000806 opticalMetrics[k] = float32(math.Round((float64(cmn.TwosComplementToSignedInt16(val.(uint16)))/500.0)*10) / 10) // convert to dBm rounded of to single decimal place
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800807 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800808 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000809 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000810 opticalMetrics[k] = float32(math.Round((float64(cmn.TwosComplementToSignedInt16(val.(uint16)))/500.0)*10) / 10) // convert to dBm rounded of to single decimal place
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800811 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800812 default:
813 // do nothing
814 }
815 }
816 }
817 // create slice of metrics given that there could be more than one ANI-G instance and
818 // optical metrics are collected per ANI-G instance
819 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
820 metricInfoSlice = append(metricInfoSlice, &metricInfo)
821 }
822
ozgecanetsiab36ed572021-04-01 10:38:48 +0300823 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800824}
825
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800826// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800827// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000828func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
829 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
830 mm.OnuMetricsManagerLock.RLock()
831 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
832 mm.OnuMetricsManagerLock.RUnlock()
833 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300834 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800835 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000836 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800837
Girish Gowdrae09a6202021-01-12 18:10:59 -0800838 var metricInfoSlice []*voltha.MetricInformation
839 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000840 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
841 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
842 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800843
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800844 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800845 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700846 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800847 Ts: float64(raisedTs),
848 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000849 DeviceId: mm.deviceID,
850 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
851 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800852 }
853
Girish Gowdrae09a6202021-01-12 18:10:59 -0800854 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000855 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800856loop1:
857 for _, unigInstID := range unigInstKeys {
858 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
859 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
860 unigMetrics := make(map[string]float32)
861 var meAttributes me.AttributeValueMap
862 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000863 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000864 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes,
865 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300866 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000867 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
868 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300869 return nil, err
870 }
871 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530872 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800873 // Wait for metrics or timeout
874 select {
875 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530876 mm.onuUniStatusMetricstimer.Stop()
877 logger.Debugw(ctx, "received uni-g metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
878 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000879 logger.Errorw(ctx, "timeout waiting for omci-get response for uni status", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800880 // The metrics could be empty in this case
881 break loop1
praneeth nalmasf405e962023-08-07 15:02:03 +0530882 case <-mm.uniMetricsDelCommChan:
883 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
884 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800885 }
886 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800887 for k := range UniStatusGroupMetrics {
888 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800889 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000890 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800891 unigMetrics[k] = float32(val.(byte))
892 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800893 default:
894 // do nothing
895 }
896 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000897 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800898 entityID := val.(uint16)
899 unigMetrics["entity_id"] = float32(entityID)
900 // TODO: Rlock needed for reading uniEntityMap? May not be needed given uniEntityMap is populated setup at initial ONU bring up
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000901 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
902 if uni.EntityID == entityID {
903 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700904 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800905 }
906 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800907 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700908 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800909
Girish Gowdrae09a6202021-01-12 18:10:59 -0800910 // create slice of metrics given that there could be more than one UNI-G instance
911 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
912 metricInfoSlice = append(metricInfoSlice, &metricInfo)
913 }
914 }
915
916 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000917 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800918loop2:
919 for _, pptpInstID := range pptpInstKeys {
920 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
921 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
922 var meAttributes me.AttributeValueMap
923 pptpMetrics := make(map[string]float32)
924
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000925 requestedAttributes := me.AttributeValueMap{
926 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
927 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
928 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
929 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000930 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300931 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000932 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
933 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300934 return nil, err
935 }
936 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +0530937 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800938 // Wait for metrics or timeout
939 select {
940 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +0530941 mm.onuUniStatusMetricstimer.Stop()
942 logger.Debugw(ctx, "received pptp metrics, stopping Onu Uni Status metrics timer ", log.Fields{"device-id": mm.deviceID})
943 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000944 logger.Errorw(ctx, "timeout waiting for omci-get response for uni status", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800945 // The metrics could be empty in this case
946 break loop2
praneeth nalmasf405e962023-08-07 15:02:03 +0530947 case <-mm.uniMetricsDelCommChan:
948 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
949 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -0800950 }
951
952 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800953 for k := range UniStatusGroupMetrics {
954 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700955 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000956 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800957 pptpMetrics[k] = float32(val.(byte))
958 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800959 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000960 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800961 pptpMetrics[k] = float32(val.(byte))
962 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800963 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000964 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800965 pptpMetrics[k] = float32(val.(byte))
966 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800967 default:
968 // do nothing
969 }
970 }
971 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000972 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800973 entityID := val.(uint16)
974 pptpMetrics["entity_id"] = float32(entityID)
975 // TODO: Rlock needed for reading uniEntityMap? May not be needed given uniEntityMap is populated setup at initial ONU bring up
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000976 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
977 if uni.EntityID == entityID {
978 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700979 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800980 }
981 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800982 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700983 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800984
Girish Gowdrae09a6202021-01-12 18:10:59 -0800985 // create slice of metrics given that there could be more than one PPTP instance and
986 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
987 metricInfoSlice = append(metricInfoSlice, &metricInfo)
988 }
989
990 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000991 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800992loop3:
993 for _, veipInstID := range veipInstKeys {
994 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
995 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
996 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800997 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800998
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000999 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0,
1000 me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
1001 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes,
1002 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001003 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001004 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
1005 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001006 return nil, err
1007 }
1008 if meInstance != nil {
praneeth nalmas808f43a2023-05-14 12:54:34 +05301009 mm.onuUniStatusMetricstimer.Reset(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001010 // Wait for metrics or timeout
1011 select {
1012 case meAttributes = <-mm.uniStatusMetricsChan:
praneeth nalmas808f43a2023-05-14 12:54:34 +05301013 mm.onuUniStatusMetricstimer.Stop()
1014 logger.Debugw(ctx, "received veip metrics, stopping Onu Uni status metrics timer ", log.Fields{"device-id": mm.deviceID})
1015 case <-mm.onuUniStatusMetricstimer.C:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001016 logger.Errorw(ctx, "timeout waiting for omci-get response for uni status", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001017 // The metrics could be empty in this case
1018 break loop3
praneeth nalmasf405e962023-08-07 15:02:03 +05301019 case <-mm.uniMetricsDelCommChan:
1020 logger.Warnw(ctx, "Deleting the device, stopping UniMetrics collection for the device ", log.Fields{"device-id": mm.deviceID})
1021 return nil, err
Girish Gowdrae09a6202021-01-12 18:10:59 -08001022 }
1023
1024 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001025 for k := range UniStatusGroupMetrics {
1026 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001027 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001028 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001029 veipMetrics[k] = float32(val.(byte))
1030 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001031 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001032 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001033 veipMetrics[k] = float32(val.(byte))
1034 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001035 default:
1036 // do nothing
1037 }
1038 }
1039 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001040
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001041 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001042 entityID := val.(uint16)
1043 veipMetrics["entity_id"] = float32(entityID)
1044 // TODO: Rlock needed for reading uniEntityMap? May not be needed given uniEntityMap is populated setup at initial ONU bring up
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001045 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1046 if uni.EntityID == entityID {
1047 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001048 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001049 }
1050 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001051 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001052 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001053
Girish Gowdrae09a6202021-01-12 18:10:59 -08001054 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001055 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001056 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1057 }
1058
ozgecanetsiab36ed572021-04-01 10:38:48 +03001059 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001060}
1061
1062// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001063func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001064 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001065 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001066 ke.SliceData = metricInfo
1067 ke.Type = voltha.KpiEventType_slice
1068 ke.Ts = float64(ts)
1069
Himani Chawlaf9768882021-12-01 00:18:58 +05301070 if err := mm.pDeviceHandler.GetEventProxy().SendKpiEvent(ctx, "STATS_PUBLISH_EVENT", &ke, voltha.EventCategory_EQUIPMENT, voltha.EventSubCategory_ONU, ts); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001071 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001072 }
1073}
1074
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001075// ProcessOmciMessages - TODO: add comment
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001076func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context, waitForOmciProcessor *sync.WaitGroup) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001077 logger.Infow(ctx, "Start routine to process OMCI-GET messages for device-id", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001078 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001079 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001080 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001081 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001082 // is stopped - as a result of ONU going down.
1083 mm.flushMetricCollectionChannels(ctx)
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001084 // when instantiating mm it was too early, but now we can check for ONU's extended OMCI support
1085 mm.isExtendedOmci = mm.pOnuDeviceEntry.GetPersIsExtOmciSupported()
1086 if mm.isExtendedOmci {
1087 mm.maxL2PMGetPayLoadSize = MaxExtendedL2PMGetPayLoadSize
1088 } else {
1089 mm.maxL2PMGetPayLoadSize = MaxBaselineL2PMGetPayLoadSize
1090 }
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001091 mm.updateOmciProcessingStatus(true)
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001092 waitForOmciProcessor.Done()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001093 for {
1094 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001095 case <-mm.StopProcessingOmciResponses: // stop this routine
1096 logger.Infow(ctx, "Stop routine to process OMCI-GET messages for device-id", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001097 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001098 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001099 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001100 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001101 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001102 continue
1103 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001104 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001105
1106 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001107 case cmn.OMCI:
1108 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001109 mm.handleOmciMessage(ctx, msg)
1110 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001111 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001112 }
1113 }
1114 }
1115}
1116
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001117func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1118 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001119 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1120 switch msg.OmciMsg.MessageType {
1121 case omci.GetResponseType:
1122 //TODO: error handling
1123 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001124 case omci.SynchronizeTimeResponseType:
1125 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1126 case omci.CreateResponseType:
1127 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1128 case omci.DeleteResponseType:
1129 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301130 case omci.GetCurrentDataResponseType:
1131 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301132 case omci.SetResponseType:
1133 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001134 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001135 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001136
1137 }
1138}
1139
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001140func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001141 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1142 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001143 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1144 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001145 }
1146 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1147 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001148 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1149 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001150 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001151 logger.Debugw(ctx, "OMCI GetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001152 if msgObj.Result == me.Success {
1153 meAttributes := msgObj.Attributes
1154 switch msgObj.EntityClass {
1155 case me.AniGClassID:
1156 mm.opticalMetricsChan <- meAttributes
1157 return nil
1158 case me.UniGClassID:
1159 mm.uniStatusMetricsChan <- meAttributes
1160 return nil
1161 case me.PhysicalPathTerminationPointEthernetUniClassID:
1162 mm.uniStatusMetricsChan <- meAttributes
1163 return nil
1164 case me.VirtualEthernetInterfacePointClassID:
1165 mm.uniStatusMetricsChan <- meAttributes
1166 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001167 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1168 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001169 me.EthernetPerformanceMonitoringHistoryDataClassID,
1170 me.FecPerformanceMonitoringHistoryDataClassID,
1171 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001172 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301173 return nil
1174 case me.EthernetFrameExtendedPmClassID,
1175 me.EthernetFrameExtendedPm64BitClassID:
1176 mm.extendedPmMeChan <- meAttributes
1177 return nil
1178 default:
1179 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001180 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301181 }
1182 } else {
1183 meAttributes := msgObj.Attributes
1184 switch msgObj.EntityClass {
1185 case me.EthernetFrameExtendedPmClassID,
1186 me.EthernetFrameExtendedPm64BitClassID:
1187 // not all counters may be supported in which case we have seen some ONUs throwing
1188 // AttributeFailure error code, while correctly populating other counters it supports
1189 mm.extendedPmMeChan <- meAttributes
1190 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001191 default:
1192 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001193 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001194 }
1195 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001196 return fmt.Errorf("unhandled-omci-get-response-message")
1197}
1198
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001199func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301200 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1201 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001202 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1203 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301204 }
1205 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1206 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001207 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1208 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301209 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001210 logger.Debugw(ctx, "OMCI GetCurrentDataResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301211 if msgObj.Result == me.Success {
1212 meAttributes := msgObj.Attributes
1213 switch msgObj.EntityClass {
1214 case me.EthernetFrameExtendedPmClassID,
1215 me.EthernetFrameExtendedPm64BitClassID:
1216 mm.extendedPmMeChan <- meAttributes
1217 return nil
1218 default:
1219 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001220 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301221 }
1222 } else {
1223 meAttributes := msgObj.Attributes
1224 switch msgObj.EntityClass {
1225 case me.EthernetFrameExtendedPmClassID,
1226 me.EthernetFrameExtendedPm64BitClassID:
1227 // not all counters may be supported in which case we have seen some ONUs throwing
1228 // AttributeFailure error code, while correctly populating other counters it supports
1229 mm.extendedPmMeChan <- meAttributes
1230 return nil
1231 default:
1232 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001233 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301234 }
1235 }
1236 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1237}
1238
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001239func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001240 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1241 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001242 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1243 return fmt.Errorf("omci Msg layer could not be detected for synchronize time response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001244 }
1245 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1246 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001247 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1248 return fmt.Errorf("omci Msg layer could not be assigned for synchronize time response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001249 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001250 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001251 if msgObj.Result == me.Success {
1252 switch msgObj.EntityClass {
1253 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001254 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001255 mm.syncTimeResponseChan <- true
1256 return nil
1257 default:
1258 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001259 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001260 }
1261 }
1262 mm.syncTimeResponseChan <- false
1263 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1264 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001265}
1266
Himani Chawlaee10b542021-09-20 16:46:40 +05301267func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1268 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1269 if msgLayer == nil {
1270 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1271 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1272 }
1273 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1274 if !msgOk {
1275 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1276 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1277 }
1278 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1279 switch msgObj.EntityClass {
1280 case me.EthernetFrameExtendedPmClassID,
1281 me.EthernetFrameExtendedPm64BitClassID:
1282 mm.extendedPMMeResponseChan <- msgObj.Result
1283 return nil
1284 default:
1285 logger.Errorw(ctx, "unhandled omci set response message",
1286 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1287 }
1288 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1289}
1290
Girish Gowdrae09a6202021-01-12 18:10:59 -08001291// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001292func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001293 // flush commMetricsChan
1294 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001295 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001296 logger.Debug(ctx, "flushed common metrics channel")
1297 default:
1298 }
1299
1300 // flush opticalMetricsChan
1301 select {
1302 case <-mm.opticalMetricsChan:
1303 logger.Debug(ctx, "flushed optical metrics channel")
1304 default:
1305 }
1306
1307 // flush uniStatusMetricsChan
1308 select {
1309 case <-mm.uniStatusMetricsChan:
1310 logger.Debug(ctx, "flushed uni status metrics channel")
1311 default:
1312 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001313
1314 // flush syncTimeResponseChan
1315 select {
1316 case <-mm.syncTimeResponseChan:
1317 logger.Debug(ctx, "flushed sync time response channel")
1318 default:
1319 }
1320
1321 // flush l2PmChan
1322 select {
1323 case <-mm.l2PmChan:
1324 logger.Debug(ctx, "flushed L2 PM collection channel")
1325 default:
1326 }
1327
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001328 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001329 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001330 case <-mm.StopTicks:
1331 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001332 default:
1333 }
1334
1335}
1336
1337// ** L2 PM FSM Handlers start **
1338
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001339func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001340 if mm.GetdeviceDeletionInProgress() {
1341 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1342 return
1343 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001344
Girish Gowdrae0140f02021-02-02 16:55:09 -08001345 // Loop through all the group metrics
1346 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1347 // list of active L2 PM list then mark it for creation
1348 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1349 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001350 mm.OnuMetricsManagerLock.Lock()
1351 for n, g := range mm.GroupMetricMap {
1352 if g.IsL2PMCounter { // it is a l2 pm counter
1353 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001354 found := false
1355 inner1:
1356 for _, v := range mm.activeL2Pms {
1357 if v == n {
1358 found = true // metric already present in active l2 pm list
1359 break inner1
1360 }
1361 }
1362 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001363 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001364 }
1365 } else { // metric not enabled.
1366 found := false
1367 inner2:
1368 for _, v := range mm.activeL2Pms {
1369 if v == n {
1370 found = true // metric is found in active l2 pm list
1371 break inner2
1372 }
1373 }
1374 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001375 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001376 }
1377 }
1378 }
1379 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001380 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001381 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001382 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001383 go func() {
1384 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001385 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1386 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001387 }
1388 }()
1389}
1390
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001391func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001392 if mm.GetdeviceDeletionInProgress() {
1393 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1394 return
1395 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001396 // Sync time with the ONU to establish 15min boundary for PM collection.
1397 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001398 // device could be deleted while waiting on sync time response
1399 if mm.GetdeviceDeletionInProgress() {
1400 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1401 return
1402 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001403 go func() {
1404 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1405 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001406 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1407 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001408 }
1409 }()
1410 }
1411 // Initiate a tick generation routine every L2PmCollectionInterval
1412 go mm.generateTicks(ctx)
1413
1414 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001415 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1416 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001417 }
1418 }()
1419}
1420
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001421func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001422 // We need to reset the local data so that the L2 PM MEs are re-provisioned once the ONU is back up based on the latest PM CONFIG
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001423 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001424 mm.activeL2Pms = nil
1425 mm.l2PmToAdd = nil
1426 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001427 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001428 // If the FSM was stopped, then clear PM data from KV store
1429 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001430 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001431 _ = mm.clearPmGroupData(ctx) // ignore error
1432 }
1433
Girish Gowdraabcceb12022-04-13 23:35:22 -07001434 if mm.GetdeviceDeletionInProgress() {
praneeth nalmasf405e962023-08-07 15:02:03 +05301435 mm.onuOpticalMetricstimer.Stop()
1436 mm.onuUniStatusMetricstimer.Stop()
1437 mm.opticalMetricsDelCommChan <- true
1438 mm.uniMetricsDelCommChan <- true
Girish Gowdraabcceb12022-04-13 23:35:22 -07001439 mm.pDeviceHandler = nil
1440 mm.pOnuDeviceEntry = nil
1441 mm.GarbageCollectionComplete <- true
1442 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001443}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001444func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1445 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001446 if mm.GetdeviceDeletionInProgress() {
1447 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1448 return
1449 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001450
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001451 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001452 numOfPmToDelete := len(mm.l2PmToDelete)
1453 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001454 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001455
1456 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001457 logger.Debugw(ctx, "state idle - pms to delete", log.Fields{"device-id": mm.deviceID, "pms-to-delete": numOfPmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001458 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001459 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1460 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001461 }
1462 }()
1463 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001464 logger.Debugw(ctx, "state idle - pms to add", log.Fields{"device-id": mm.deviceID, "pms-to-add": numOfPmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001465 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001466 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1467 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001468 }
1469 }()
1470 }
1471}
1472
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001473func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1474 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001475 if mm.GetdeviceDeletionInProgress() {
1476 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1477 return
1478 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001479 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001480 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001481 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1482 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001483 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001484
1485 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001486 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001487
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001488 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1489 mm.OnuMetricsManagerLock.RLock()
1490 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1491 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1492 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001493
Girish Gowdrae0140f02021-02-02 16:55:09 -08001494 switch n {
1495 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001496 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001497 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001498 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1499 metricInfoSlice = append(metricInfoSlice, metricInfo)
1500 }
1501 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1502 metricInfoSlice = append(metricInfoSlice, metricInfo)
1503 }
1504 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001505 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001506 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001507 for _, entityID := range copyOfEntityIDs {
1508 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1509 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001510 }
1511 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001512
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001513 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001514 for _, entityID := range copyOfEntityIDs {
1515 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001516 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001517 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001518 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001519 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001520 for _, entityID := range copyOfEntityIDs {
1521 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001522 metricInfoSlice = append(metricInfoSlice, metricInfo)
1523 }
1524 }
1525
Girish Gowdrae0140f02021-02-02 16:55:09 -08001526 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001527 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001528 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001529 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001530 }
1531 // Does not matter we send success or failure here.
1532 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1533 // we have not exceed max attempts to collect the PM data)
1534 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001535 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1536 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001537 }
1538 }()
1539}
1540
Girish Gowdra0e533642021-03-02 22:02:51 -08001541// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001542func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001543 if mm.GetdeviceDeletionInProgress() {
1544 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1545 return nil
1546 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001547 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001548 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001549 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1550 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001551 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001552
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001553 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001554 for _, n := range copyOfL2PmToAdd {
1555 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001556 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1557 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001558 switch n {
1559 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001560 // Create ME twice, one for each direction. Boolean true is used to indicate upstream and false for downstream.
Himani Chawlac77d5372021-07-12 15:42:26 +05301561 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001562 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001563 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001564 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001565 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1566 inner1:
1567 // retry L2PmCreateAttempts times to create the instance of PM
1568 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001569 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1570 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001571 if err != nil {
1572 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001573 log.Fields{"device-id": mm.deviceID})
1574 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001575 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001576 go func(p_pmFsm *cmn.AdapterFsm) {
1577 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001578 }(pPMFsm)
1579 }
1580 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001581 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001582 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001583 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1584 atLeastOneSuccess = true
1585 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1586 break inner1
1587 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001588 if mm.GetdeviceDeletionInProgress() {
1589 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1590 return nil
1591 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001592 }
1593 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1594 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001595 }
1596 }
1597 }
1598 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001599 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1600 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001601 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001602 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001603 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1604 inner2:
1605 // retry L2PmCreateAttempts times to create the instance of PM
1606 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001607 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1608 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001609 if err != nil {
1610 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001611 log.Fields{"device-id": mm.deviceID})
1612 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001613 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001614 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001615 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001616 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1617 atLeastOneSuccess = true
1618 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1619 break inner2
1620 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001621 if mm.GetdeviceDeletionInProgress() {
1622 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1623 return nil
1624 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001625 }
1626 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1627 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001628 }
1629 }
1630 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001631 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001632 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001633 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001634 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1635 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001636 if err != nil {
1637 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001638 log.Fields{"device-id": mm.deviceID})
1639 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001640 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001641 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001642 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001643 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1644 inner3:
1645 // retry L2PmCreateAttempts times to create the instance of PM
1646 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1647 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1648 atLeastOneSuccess = true
1649 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1650 break inner3
1651 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001652 if mm.GetdeviceDeletionInProgress() {
1653 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1654 return nil
1655 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001656 }
1657 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1658 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001659 }
1660 }
1661 case GemPortHistoryName:
1662
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001663 mm.OnuMetricsManagerLock.RLock()
1664 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1665 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1666 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001667
1668 if len(copyOfGemPortInstIDsToAdd) == 0 {
1669 // If there are no gemport history MEs to be created, just skip further processing
1670 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1671 // Normally there are no GemPortHistory MEs to create at start up. They come in only after provisioning service on the ONU.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001672 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001673 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001674 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001675 continue
1676 }
1677
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001678 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001679 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1680 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001681 if err != nil {
1682 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001683 log.Fields{"device-id": mm.deviceID})
1684 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001685 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001686 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001687 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001688 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1689 inner4:
1690 // retry L2PmCreateAttempts times to create the instance of PM
1691 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1692 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1693 atLeastOneSuccess = true
1694 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1695 break inner4
1696 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001697 if mm.GetdeviceDeletionInProgress() {
1698 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1699 return nil
1700 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001701 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001702 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1703 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1704 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001705 }
1706
Girish Gowdrae0140f02021-02-02 16:55:09 -08001707 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001708 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001709 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001710 // On success of at least one instance of the PM for a given ME, update the local list maintained for active PMs and PMs to add
1711 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001712 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001713 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001714 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1715 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001716 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001717 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1718 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001719 logger.Debugw(ctx, "success-resp", log.Fields{"pm-name": n, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001720 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001721 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001722 // If we are here then no instance of the PM of the given ME were created successfully, so locally disable the PM
Girish Gowdrae0140f02021-02-02 16:55:09 -08001723 // and also remove it from l2PmToAdd slice so that we do not try to create the PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001724 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001725 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001726 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001727 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001728
Girish Gowdrae0140f02021-02-02 16:55:09 -08001729 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001730 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001731 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001732 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001733 }
1734 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001735 mm.OnuMetricsManagerLock.RLock()
1736 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1737 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001738 // Does not matter we send success or failure here.
1739 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1740 // we have not exceed max attempts to create the PM ME)
1741 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001742 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1743 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001744 }
1745 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001746 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001747}
1748
Girish Gowdra0e533642021-03-02 22:02:51 -08001749// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001750func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001751 if mm.GetdeviceDeletionInProgress() {
1752 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1753 return nil
1754 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001755 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001756 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001757 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1758 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001759 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001760
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001761 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001762 for _, n := range copyOfL2PmToDelete {
1763 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001764 cnt := 0
1765 atLeastOneDeleteFailure := false
1766
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001767 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1768 mm.OnuMetricsManagerLock.RLock()
1769 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1770 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1771 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001772
1773 if len(copyOfEntityIDs) == 0 {
1774 // if there are no enityIDs to remove for the PM ME just clear the PM name entry from cache and continue
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001775 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001776 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1777 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1778 logger.Debugw(ctx, "success-resp", log.Fields{"pm-name": n, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001779 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001780 continue
1781 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001782 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001783 switch n {
1784 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001785 // Create ME twice, one for each direction. Boolean true is used to indicate upstream and false for downstream.
Himani Chawlac77d5372021-07-12 15:42:26 +05301786 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001787 for _, entityID := range copyOfEntityIDs {
1788 inner1:
1789 // retry L2PmDeleteAttempts times to delete the instance of PM
1790 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001791 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1792 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001793 if err != nil {
1794 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001795 log.Fields{"device-id": mm.deviceID})
1796 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001797 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001798 go func(p_pmFsm *cmn.AdapterFsm) {
1799 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001800 }(pPMFsm)
1801 }
1802 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001803 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001804 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001805 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1806 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001807 if mm.GetdeviceDeletionInProgress() {
1808 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1809 return nil
1810 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001811 atLeastOneDeleteFailure = true
1812 } else {
1813 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1814 break inner1
1815 }
1816 }
1817 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1818 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001819 }
1820 }
1821 }
1822 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001823 for _, entityID := range copyOfEntityIDs {
1824 inner2:
1825 // retry L2PmDeleteAttempts times to delete the instance of PM
1826 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001827 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1828 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001829 if err != nil {
1830 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001831 log.Fields{"device-id": mm.deviceID})
1832 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001833 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001834 go func(p_pmFsm *cmn.AdapterFsm) {
1835 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001836 }(pmFsm)
1837 return err
1838 }
1839 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001840 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001841 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001842 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001843 if mm.GetdeviceDeletionInProgress() {
1844 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1845 return nil
1846 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001847 atLeastOneDeleteFailure = true
1848 } else {
1849 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001850 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001851 }
1852 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001853 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1854 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1855 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001856 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001857 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001858 for _, entityID := range copyOfEntityIDs {
1859 inner3:
1860 // retry L2PmDeleteAttempts times to delete the instance of PM
1861 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001862 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1863 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001864 if err != nil {
1865 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001866 log.Fields{"device-id": mm.deviceID})
1867 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001868 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001869 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001870 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001871 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001872 if mm.GetdeviceDeletionInProgress() {
1873 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1874 return nil
1875 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001876 atLeastOneDeleteFailure = true
1877 } else {
1878 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1879 break inner3
1880 }
1881 }
1882 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1883 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001884 }
1885 }
1886 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001887 for _, entityID := range copyOfEntityIDs {
1888 inner4:
1889 // retry L2PmDeleteAttempts times to delete the instance of PM
1890 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001891 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1892 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001893 if err != nil {
1894 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001895 log.Fields{"device-id": mm.deviceID})
1896 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001897 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001898 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001899 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001900 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001901 if mm.GetdeviceDeletionInProgress() {
1902 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1903 return nil
1904 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001905 atLeastOneDeleteFailure = true
1906 } else {
1907 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1908 break inner4
1909 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001910 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001911 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1912 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1913 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001914 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001915 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001916 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001917 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001918 // If we could not completely clean up the PM ME then just give up.
1919 if atLeastOneDeleteFailure {
1920 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001921 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001922 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001923 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001924 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1925 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1926 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001927 mm.GroupMetricMap[n].Enabled = false
1928 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001929 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001930 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001931 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001932 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1933 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001934 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001935 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1936 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001937 logger.Debugw(ctx, "success-resp", log.Fields{"pm-name": n, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001938 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001939 }
1940 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001941 mm.OnuMetricsManagerLock.RLock()
1942 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1943 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001944 // Does not matter we send success or failure here.
1945 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1946 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001947 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1948 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001949 }
1950 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001951 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001952}
1953
1954// ** L2 PM FSM Handlers end **
1955
1956// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001957func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001958 if mm.GetdeviceDeletionInProgress() {
1959 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1960 return nil
1961 }
1962
1963 if !mm.GetOmciProcessingStatus() {
1964 logger.Errorw(ctx, "not sending sync time, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
1965 return fmt.Errorf("omci-resp-processor-not-running")
1966 }
1967
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001968 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1969 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001970 return err
1971 }
1972
1973 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001974 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1975 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1976 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001977 case syncTimeRes := <-mm.syncTimeResponseChan:
1978 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001979 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001980 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001981 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001982 return nil
1983 }
1984}
1985
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001986func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001987 var mEnt *me.ManagedEntity
1988 var omciErr me.OmciErrors
1989 var classID me.ClassID
1990 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001991 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001992 meParam := me.ParamData{EntityID: entityID}
1993 if upstream {
1994 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001995 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001996 return nil
1997 }
1998 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1999 } else {
2000 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002001 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002002 return nil
2003 }
2004 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
2005 }
2006
Girish Gowdrae0140f02021-02-02 16:55:09 -08002007 intervalEndTime := -1
2008 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002009 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
2010 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002011 }
2012
2013 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
2014 ethPMHistData["class_id"] = float32(classID)
2015 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
2016 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
2017 ethPMHistData["parent_entity_id"] = float32(entityID)
2018 if upstream {
2019 ethPMHistData["upstream"] = float32(1)
2020 } else {
2021 ethPMHistData["upstream"] = float32(0)
2022 }
2023
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002024 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002025
Girish Gowdrae0140f02021-02-02 16:55:09 -08002026 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002027 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002028 return &metricInfo
2029}
2030
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002031func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002032 var mEnt *me.ManagedEntity
2033 var omciErr me.OmciErrors
2034 var classID me.ClassID
2035 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002036 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002037 meParam := me.ParamData{EntityID: entityID}
2038 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002039 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002040 return nil
2041 }
2042 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
2043
Girish Gowdrae0140f02021-02-02 16:55:09 -08002044 intervalEndTime := -1
2045 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002046 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
2047 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002048 }
2049
2050 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2051 ethUniHistData["class_id"] = float32(classID)
2052 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
2053
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002054 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002055
Girish Gowdrae0140f02021-02-02 16:55:09 -08002056 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002057 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002058 return &metricInfo
2059}
2060
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002061func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002062 var mEnt *me.ManagedEntity
2063 var omciErr me.OmciErrors
2064 var classID me.ClassID
2065 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002066 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002067 meParam := me.ParamData{EntityID: entityID}
2068 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002069 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002070 return nil
2071 }
2072 classID = me.FecPerformanceMonitoringHistoryDataClassID
2073
2074 intervalEndTime := -1
2075 fecHistData := make(map[string]float32)
2076 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
2077 return nil
2078 }
2079
2080 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2081 fecHistData["class_id"] = float32(classID)
2082 fecHistData["interval_end_time"] = float32(intervalEndTime)
2083
2084 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2085
2086 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002087 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002088 return &metricInfo
2089}
2090
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002091func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002092 var mEnt *me.ManagedEntity
2093 var omciErr me.OmciErrors
2094 var classID me.ClassID
2095 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002096 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002097 meParam := me.ParamData{EntityID: entityID}
2098 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002099 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002100 return nil
2101 }
2102 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2103
2104 intervalEndTime := -1
2105 gemHistData := make(map[string]float32)
2106 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
2107 return nil
2108 }
2109
2110 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2111 gemHistData["class_id"] = float32(classID)
2112 gemHistData["interval_end_time"] = float32(intervalEndTime)
2113
2114 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2115
2116 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002117 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002118 return &metricInfo
2119}
2120
Girish Gowdrae0140f02021-02-02 16:55:09 -08002121// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002122func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002123 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002124 upstream := false
2125 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2126 upstream = true
2127 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002128 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002129 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002130 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2131 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002132 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002133 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2134 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002135 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002136 go func(p_pmFsm *cmn.AdapterFsm) {
2137 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002138 }(pmFsm)
2139 return err
2140 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002141 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002142 }
2143 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002144 select {
2145 case meAttributes = <-mm.l2PmChan:
2146 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002147 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2148 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002149 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002150 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002151 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002152 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002153 }
2154 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002155 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002156 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002157 }
2158 }
2159 for k := range EthernetBridgeHistory {
2160 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2161 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2162 if _, ok := ethPMHistData[k]; !ok {
2163 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002164 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002165 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002166 ethPMHistData[k] = float32(val.(uint16))
2167 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002168 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002169 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002170 ethPMHistData[k] = float32(val.(uint32))
2171 }
2172 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002173 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002174 ethPMHistData[k] = float32(val.(uint32))
2175 }
2176 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002177 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002178 ethPMHistData[k] = float32(val.(uint32))
2179 }
2180 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002181 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002182 ethPMHistData[k] = float32(val.(uint32))
2183 }
2184 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002185 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002186 ethPMHistData[k] = float32(val.(uint32))
2187 }
2188 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002189 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002190 ethPMHistData[k] = float32(val.(uint32))
2191 }
2192 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002193 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002194 ethPMHistData[k] = float32(val.(uint32))
2195 }
2196 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002197 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002198 ethPMHistData[k] = float32(val.(uint32))
2199 }
2200 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002201 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002202 ethPMHistData[k] = float32(val.(uint32))
2203 }
2204 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002205 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002206 ethPMHistData[k] = float32(val.(uint32))
2207 }
2208 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002209 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002210 ethPMHistData[k] = float32(val.(uint32))
2211 }
2212 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002213 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002214 ethPMHistData[k] = float32(val.(uint32))
2215 }
2216 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002217 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002218 ethPMHistData[k] = float32(val.(uint32))
2219 }
2220 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002221 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002222 ethPMHistData[k] = float32(val.(uint32))
2223 }
2224 default:
2225 // do nothing
2226 }
2227 }
2228 }
2229 return nil
2230}
2231
2232// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002233func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002234 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002235 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
ozgecanetsiab36ed572021-04-01 10:38:48 +03002236 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2237 requestedAttributes["IntervalEndTime"] = 0
2238 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002239 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2240 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002241 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002242 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2243 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2244 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002245 }
2246 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002247 select {
2248 case meAttributes = <-mm.l2PmChan:
2249 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002250 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2251 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002252 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002253 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002254 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002255 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002256 }
2257 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002258 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002259 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002260 }
2261 }
2262 for k := range EthernetUniHistory {
2263 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2264 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2265 if _, ok := ethPMUniHistData[k]; !ok {
2266 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002267 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002268 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002269 ethPMUniHistData[k] = float32(val.(uint16))
2270 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002271 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002272 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002273 ethPMUniHistData[k] = float32(val.(uint32))
2274 }
2275 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002276 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002277 ethPMUniHistData[k] = float32(val.(uint32))
2278 }
2279 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002280 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002281 ethPMUniHistData[k] = float32(val.(uint32))
2282 }
2283 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002284 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002285 ethPMUniHistData[k] = float32(val.(uint32))
2286 }
2287 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002288 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002289 ethPMUniHistData[k] = float32(val.(uint32))
2290 }
2291 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002292 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002293 ethPMUniHistData[k] = float32(val.(uint32))
2294 }
2295 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002296 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002297 ethPMUniHistData[k] = float32(val.(uint32))
2298 }
2299 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002300 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002301 ethPMUniHistData[k] = float32(val.(uint32))
2302 }
2303 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002304 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002305 ethPMUniHistData[k] = float32(val.(uint32))
2306 }
2307 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002308 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002309 ethPMUniHistData[k] = float32(val.(uint32))
2310 }
2311 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002312 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002313 ethPMUniHistData[k] = float32(val.(uint32))
2314 }
2315 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002316 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002317 ethPMUniHistData[k] = float32(val.(uint32))
2318 }
2319 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002320 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002321 ethPMUniHistData[k] = float32(val.(uint32))
2322 }
2323 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002324 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002325 ethPMUniHistData[k] = float32(val.(uint32))
2326 }
2327 default:
2328 // do nothing
2329 }
2330 }
2331 }
2332 return nil
2333}
2334
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002335// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002336func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002337 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002338 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002339 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2340 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002341 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002342 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2343 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002344 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002345 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2346 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2347 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002348 }
2349 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002350 select {
2351 case meAttributes = <-mm.l2PmChan:
2352 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002353 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2354 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002355 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002356 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002357 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002358 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002359 }
2360 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2361 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002362 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002363 }
2364 }
2365 for k := range FecHistory {
2366 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2367 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2368 if _, ok := fecHistData[k]; !ok {
2369 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002370 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002371 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002372 fecHistData[k] = float32(val.(uint16))
2373 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002374 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002375 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002376 fecHistData[k] = float32(val.(uint32))
2377 }
2378 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002379 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002380 fecHistData[k] = float32(val.(uint32))
2381 }
2382 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002383 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002384 fecHistData[k] = float32(val.(uint32))
2385 }
2386 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002387 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002388 fecHistData[k] = float32(val.(uint32))
2389 }
2390 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002391 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002392 fecHistData[k] = float32(val.(uint16))
2393 }
2394 default:
2395 // do nothing
2396 }
2397 }
2398 }
2399 return nil
2400}
2401
2402// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002403func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002404 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002405 // Insert "IntervalEndTime" is part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002406 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2407 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002408 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002409 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2410 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002411 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002412 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2413 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2414 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002415 }
2416 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002417 select {
2418 case meAttributes = <-mm.l2PmChan:
2419 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002420 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2421 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002422 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002423 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002424 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002425 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002426 }
2427 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2428 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002429 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002430 }
2431 }
2432 for k := range GemPortHistory {
2433 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2434 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2435 if _, ok := gemPortHistData[k]; !ok {
2436 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002437 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002438 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002439 gemPortHistData[k] = float32(val.(uint16))
2440 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002441 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002442 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002443 gemPortHistData[k] = float32(val.(uint32))
2444 }
2445 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002446 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002447 gemPortHistData[k] = float32(val.(uint32))
2448 }
2449 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002450 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002451 gemPortHistData[k] = float32(val.(uint64))
2452 }
2453 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002454 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002455 gemPortHistData[k] = float32(val.(uint64))
2456 }
2457 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002458 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002459 gemPortHistData[k] = float32(val.(uint32))
2460 }
2461 default:
2462 // do nothing
2463 }
2464 }
2465 }
2466 return nil
2467}
2468
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002469func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002470 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2471 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002472 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2473 return fmt.Errorf("omci Msg layer could not be detected for create response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002474 }
2475 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2476 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002477 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2478 return fmt.Errorf("omci Msg layer could not be assigned for delete response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002479 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002480 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002481 switch msgObj.EntityClass {
2482 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2483 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002484 me.EthernetPerformanceMonitoringHistoryDataClassID,
2485 me.FecPerformanceMonitoringHistoryDataClassID,
2486 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002487 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2488 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2489 mm.l2PmCreateOrDeleteResponseChan <- true
2490 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002491 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002492 mm.l2PmCreateOrDeleteResponseChan <- false
2493 }
2494 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302495 case me.EthernetFrameExtendedPmClassID,
2496 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302497 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302498 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002499 default:
2500 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002501 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002502 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002503 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002504}
2505
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002506func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002507 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2508 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002509 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2510 return fmt.Errorf("omci Msg layer could not be detected for create response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002511 }
2512 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2513 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002514 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2515 return fmt.Errorf("omci Msg layer could not be assigned for delete response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002516 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002517 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002518 switch msgObj.EntityClass {
2519 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2520 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002521 me.EthernetPerformanceMonitoringHistoryDataClassID,
2522 me.FecPerformanceMonitoringHistoryDataClassID,
2523 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002524 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2525 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2526 mm.l2PmCreateOrDeleteResponseChan <- true
2527 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002528 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002529 mm.l2PmCreateOrDeleteResponseChan <- false
2530 }
2531 return nil
2532 default:
2533 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002534 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002535 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002536 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002537}
2538
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002539func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002540 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002541 for {
2542 select {
2543 case <-time.After(L2PmCollectionInterval * time.Second):
2544 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002545 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2546 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002547 }
2548 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002549 case <-mm.StopTicks:
2550 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002551 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002552 return
2553 }
2554 }
2555}
2556
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002557func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002558 // Publish metrics if it is valid
2559 if metricInfoSlice != nil {
2560 mm.publishMetrics(ctx, metricInfoSlice)
2561 } else {
2562 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2563 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002564 mm.OnuMetricsManagerLock.Lock()
2565 mm.GroupMetricMap[metricName].collectAttempts++
2566 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002567 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2568 }
2569 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002570 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2571 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002572 }
2573}
2574
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002575func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002576 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2577 var grpFunc groupMetricPopulateFunc
2578 switch classID {
2579 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2580 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2581 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2582 grpFunc = mm.populateEthernetUniHistoryMetrics
2583 case me.FecPerformanceMonitoringHistoryDataClassID:
2584 grpFunc = mm.populateFecHistoryMetrics
2585 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2586 grpFunc = mm.populateGemPortMetrics
2587 default:
2588 return fmt.Errorf("unknown-classid-%v", classID)
2589 }
2590
2591 size := 0
2592 requestedAttributes := make(me.AttributeValueMap)
2593 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002594 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2595 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2596 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2597 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2598 continue
2599 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002600 if v.Size+size <= mm.maxL2PMGetPayLoadSize {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002601 requestedAttributes[v.Name] = v.DefValue
2602 size = v.Size + size
2603 } else { // We exceeded the allow omci get size
2604 // Let's collect the attributes via get now and collect remaining in the next iteration
2605 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2606 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002607 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002608 return err
2609 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002610 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002611 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2612 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002613 }
2614 }
2615 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002616 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2617 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002618 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002619 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002620 }
2621 return nil
2622}
2623
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002624func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002625 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002626 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2627 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2628 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002629
2630 raisedTs := time.Now().Unix()
2631 mmd := voltha.MetricMetaData{
2632 Title: title,
2633 Ts: float64(raisedTs),
2634 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002635 DeviceId: mm.deviceID,
2636 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2637 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002638 }
2639
2640 // create slice of metrics given that there could be more than one VEIP instance
2641 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2642 return metricInfo
2643}
2644
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002645func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002646 valid := false
2647 if *intervalEndTime == -1 { // first time
2648 // Update the interval end time
2649 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2650 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2651 valid = true
2652 }
2653 } else {
2654 var currIntervalEndTime int
2655 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2656 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2657 }
2658 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2659 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002660 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002661 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2662 } else {
2663 valid = true
2664 }
2665 }
2666 return valid
2667}
2668
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002669func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002670 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002671 if !mm.GetOmciProcessingStatus() {
2672 logger.Errorw(ctx, "not waiting for omci resp, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
2673 return false
2674 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002675 select {
2676 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002677 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002678 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002679 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002680 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002681 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002682 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002683 }
2684 return false
2685}
2686
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002687func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002688 var pmConfigSlice []*voltha.PmConfig
2689 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002690 pmConfigSlice = append(pmConfigSlice,
2691 &voltha.PmConfig{
2692 Name: k,
2693 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002694 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002695 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002696 }
2697 groupMetric := voltha.PmGroupConfig{
2698 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002699 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002700 GroupFreq: grpFreq,
2701 Metrics: pmConfigSlice,
2702 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002703 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002704
2705}
2706
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002707func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2708 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2709 if mm.PAdaptFsm == nil {
2710 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2711 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002712 return fmt.Errorf("nil-adapter-fsm")
2713 }
2714 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002715 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2716 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002717 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002718 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2719 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2720 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2721 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2722 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2723 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2724 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2725 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2726 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002727 },
2728 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002729 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2730 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2731 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2732 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2733 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2734 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2735 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2736 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002737 },
2738 )
2739 return nil
2740}
2741
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002742func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2743 mm.pDeviceHandler.InitPmConfigs()
2744 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2745 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2746 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2747 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002748
2749 // Populate group metrics.
2750 // Lets populate irrespective of GroupMetricEnabled is true or not.
2751 // The group metrics collection will decided on this flag later
2752
2753 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2754 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2755
2756 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2757 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2758
2759 // classical l2 pm counter start
2760
2761 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2762 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2763
2764 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2765 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2766
2767 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2768 FecHistoryEnabled, FecHistoryFrequency)
2769
2770 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2771 GemPortHistoryEnabled, GemPortHistoryFrequency)
2772
2773 // classical l2 pm counter end
2774
2775 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2776}
2777
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002778func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002779 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002780 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2781 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002782 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002783 Enabled: g.Enabled,
2784 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002785 }
2786 switch g.GroupName {
2787 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002788 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002789 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002790 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002791 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002792 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2793 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002794 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002795 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2796 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002797 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002798 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2799 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002800 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002801 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2802 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002803 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002804 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002805 }
2806 }
2807
2808 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002809 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2810 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002811 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002812 Enabled: m.Enabled,
2813 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002814 }
2815 switch m.Name {
2816 // None exist as of now. Add when available.
2817 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002818 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002819 }
2820 }
2821}
2822
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002823// AddGemPortForPerfMonitoring - TODO: add comment
2824func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2825 mm.OnuMetricsManagerLock.Lock()
2826 defer mm.OnuMetricsManagerLock.Unlock()
2827 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002828 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002829 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002830 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002831 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002832
2833 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2834 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2835 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2836 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2837 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002838
2839 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002840 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2841 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002842 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002843 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002844 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002845 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002846 }
2847 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002848}
2849
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002850// RemoveGemPortForPerfMonitoring - TODO: add comment
2851func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2852 mm.OnuMetricsManagerLock.Lock()
2853 defer mm.OnuMetricsManagerLock.Unlock()
2854 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2855 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002856 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002857 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002858
2859 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2860 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2861 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2862 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2863 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002864
2865 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002866 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2867 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002868 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002869 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002870 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002871 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002872 }
2873 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002874}
2875
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002876func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2877 if mm.pDeviceHandler.GetOnuTP() != nil {
2878 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002879 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002880 for _, v := range gemPortInstIDs {
2881 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002882 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002883 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002884 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002885 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002886 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002887 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002888 }
2889}
2890
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002891func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2892 if mm.pDeviceHandler.GetOnuTP() != nil {
2893 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002894 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002895 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002896 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002897 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002898 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002899 }
2900 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002901 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002902 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002903}
2904
2905// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002906func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2907 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002908 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002909 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2910 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002911 }
2912 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002913 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002914 group.pmMEData = &pmMEData{}
2915 Value, err := mm.pmKvStore.Get(ctx, groupName)
2916 if err == nil {
2917 if Value != nil {
2918 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002919 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002920 tmpBytes, _ := kvstore.ToByte(Value.Value)
2921
2922 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002923 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2924 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 -08002925 continue
2926 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002927 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002928 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002929 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002930 continue
2931 }
2932 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002933 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2934 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 -08002935 continue
2936 }
2937 }
2938 if len(errorsList) > 0 {
2939 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2940 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002941 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002942 return nil
2943}
2944
2945// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2946// the data must be available in cache.
2947// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002948func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2949 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002950 return grp.pmMEData, nil
2951 }
2952 // Data not in cache, try to fetch from kv store.
2953 data := &pmMEData{}
2954 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002955 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2956 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002957 }
2958 Value, err := mm.pmKvStore.Get(ctx, groupName)
2959 if err == nil {
2960 if Value != nil {
2961 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002962 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002963 tmpBytes, _ := kvstore.ToByte(Value.Value)
2964
2965 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002966 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002967 return data, err
2968 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002969 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002970 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002971 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002972 return data, err
2973 }
2974 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002975 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002976 return data, err
2977 }
2978
2979 return data, nil
2980}
2981
2982// 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 +00002983func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2984 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2985 mm.OnuMetricsManagerLock.Lock()
2986 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002987
2988 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002989 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2990 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002991 }
2992
2993 pmMEData, err := mm.getPmData(ctx, groupName)
2994 if err != nil || pmMEData == nil {
2995 // error already logged in called function.
2996 return err
2997 }
2998 switch pmAction {
2999 case cPmAdd:
3000 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
3001 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3002 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3003 case cPmAdded:
3004 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
3005 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3006 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3007 case cPmRemove:
3008 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
3009 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3010 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3011 case cPmRemoved:
3012 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
3013 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
3014 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
3015 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003016 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
3017 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 -08003018 }
3019 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003020 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08003021
3022 Value, err := json.Marshal(*pmMEData)
3023 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003024 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
3025 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003026 return err
3027 }
3028 // Update back to kv store
3029 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003030 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
3031 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003032 return err
3033 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003034 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
3035 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08003036
3037 return nil
3038}
3039
3040// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003041func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
3042 mm.OnuMetricsManagerLock.Lock()
3043 defer mm.OnuMetricsManagerLock.Unlock()
3044 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003045 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003046 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3047 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003048 }
3049
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003050 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003051 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003052 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003053 // do not abort this procedure. continue to delete next group.
3054 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003055 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08003056 }
3057 }
3058
3059 return nil
3060}
3061
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003062// ClearAllPmData clears all PM data associated with the device from KV store
3063func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3064 mm.OnuMetricsManagerLock.Lock()
3065 defer mm.OnuMetricsManagerLock.Unlock()
3066 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003067 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003068 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3069 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003070 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003071 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003072 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003073 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003074 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003075 value = err
3076 // do not abort this procedure - continue to delete next group.
3077 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003078 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003079 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003080 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003081 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003082 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003083 }
3084 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003085}
3086
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003087func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3088 mm.OnuMetricsManagerLock.Lock()
3089 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003090 mm.omciProcessingActive = status
3091}
3092
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003093// updateTickGenerationStatus - TODO: add comment
3094func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3095 mm.OnuMetricsManagerLock.Lock()
3096 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003097 mm.tickGenerationActive = status
3098}
3099
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003100// GetOmciProcessingStatus - TODO: add comment
3101func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3102 mm.OnuMetricsManagerLock.RLock()
3103 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003104 return mm.omciProcessingActive
3105}
3106
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003107// GetTickGenerationStatus - TODO: add comment
3108func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3109 mm.OnuMetricsManagerLock.RLock()
3110 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003111 return mm.tickGenerationActive
3112}
3113
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003114func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003115 for _, ele := range slice {
3116 if ele == n {
3117 return slice
3118 }
3119 }
3120 return append(slice, n)
3121}
3122
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003123func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003124 for i, ele := range slice {
3125 if ele == n {
3126 return append(slice[:i], slice[i+1:]...)
3127 }
3128 }
3129 return slice
3130}
3131
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003132func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003133 for _, ele := range slice {
3134 if ele == n {
3135 return slice
3136 }
3137 }
3138 return append(slice, n)
3139}
3140
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003141func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003142 for i, ele := range slice {
3143 if ele == n {
3144 return append(slice[:i], slice[i+1:]...)
3145 }
3146 }
3147 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003148}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303149
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003150func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303151 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3152 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003153 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003154 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003155 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303156 Value, err := mm.extPmKvStore.Get(ctx, key)
3157 if err == nil {
3158 if Value != nil {
3159 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003160 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303161 tmpBytes, _ := kvstore.ToByte(Value.Value)
3162
3163 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003164 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303165 return false, err
3166 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003167 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303168 // We have found the data from db, no need to get through omci get message.
3169 mm.supportedEthernetFrameExtendedPMClass = data
3170 return true, nil
3171 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003172 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303173 return false, nil
3174 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003175 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303176 return false, err
3177}
3178
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003179func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303180 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 -07003181 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3182 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})
3183 return false, fmt.Errorf("omci-processor-shutdown")
3184 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303185 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303186 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303187 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003188 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303189 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3190 if resp == me.Success || resp == me.InstanceExists {
3191 return true, nil
3192 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3193 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3194 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3195 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003196 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 +05303197 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3198 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003199 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303200 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003201 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303202 }
3203 return false, fmt.Errorf("timeout-while-waiting-for-response")
3204}
3205
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003206func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303207 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303208 // 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 +05303209 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003210 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303211 var entityID uint16
3212 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003213 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303214 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003215 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303216 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303217 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303218 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303219 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303220
3221 inner1:
3222 // retry ExtendedPmCreateAttempts times to create the instance of PM
3223 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003224 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3225 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3226 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303227 if err != nil {
3228 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003229 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303230 return false, err
3231 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303232 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3233 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303234 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303235 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303236 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303237 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303238 }
3239 break inner1
3240 } else if err != nil {
3241 if !supported {
3242 // Need to return immediately
3243 return false, err
3244 }
3245 //In case of failure, go for a retry
3246 }
3247 }
3248 if cnt == ExtendedPmCreateAttempts {
3249 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3250 return true, fmt.Errorf("unable-to-create-me")
3251 }
3252 }
3253 }
3254 return true, nil
3255}
3256
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003257func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3258 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003259 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003260 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303261 // check if we get the supported type me for ethernet frame extended pm class id
3262 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3263 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3264 }
3265 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3266 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003267 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303268 }
3269 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003270 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303271 }
3272}
3273
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003274func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303275 mm.onuEthernetFrameExtendedPmLock.Lock()
3276 mm.isDeviceReadyToCollectExtendedPmStats = true
3277 mm.onuEthernetFrameExtendedPmLock.Unlock()
3278}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003279
Himani Chawlaee10b542021-09-20 16:46:40 +05303280// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003281func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303282 //get the type of extended frame pm me supported by onu first
3283 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3284 if err != nil {
3285 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3286 return
3287 }
3288 if exist {
3289 // we have the me type, go ahead with the me type supported.
3290 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003291 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303292 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3293 return
3294 }
3295 mm.setAllExtPmMeCreatedFlag()
3296 return
3297 }
3298 // First try with 64 bit me
3299 // we have the me type, go ahead with the me type supported.
3300 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3301 if err != nil && !supported64Bit {
3302 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003303 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303304 "supported": supported64Bit})
3305 // Then Try with 32 bit type
3306 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003307 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303308 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3309 } else if supported32Bit {
3310 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3311 mm.putExtPmMeKvStore(ctx)
3312 mm.setAllExtPmMeCreatedFlag()
3313 }
3314 } else if err == nil && supported64Bit {
3315 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3316 mm.putExtPmMeKvStore(ctx)
3317 mm.setAllExtPmMeCreatedFlag()
3318 }
3319}
3320
Himani Chawlaee10b542021-09-20 16:46:40 +05303321func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3322 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3323 uniPortEntityID := entityID
3324 if upstream {
3325 uniPortEntityID = entityID - 0x100
3326 }
3327 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3328 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3329 mm.pDeviceHandler.GetOmciTimeout(), true,
3330 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3331 if err != nil {
3332 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3333 log.Fields{"device-id": mm.deviceID})
3334 return extension.GetValueResponse_INTERNAL_ERROR, err
3335 }
3336
3337 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3338 return extension.GetValueResponse_REASON_UNDEFINED, nil
3339 }
3340 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3341}
3342
3343func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3344 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 -07003345 if !mm.GetOmciProcessingStatus() {
3346 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})
3347 return false
3348 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303349 select {
3350 case resp := <-mm.extendedPMMeResponseChan:
3351 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3352 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3353 if resp == me.Success {
3354 return true
3355 }
3356 return false
3357 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3358 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3359 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3360 }
3361 return false
3362}
3363
3364func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3365 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3366 className := "EthernetFrameExtendedPm64Bit"
3367 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3368 className = "EthernetFrameExtendedPm"
3369 }
3370 // Reset the counters if option is specified
3371 for entityID := range upstreamEntityMap {
3372 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3373 true)
3374 if err != nil {
3375 return errReason, err
3376 }
3377 }
3378
3379 for entityID := range downstreamEntityMap {
3380 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3381 true)
3382 if err != nil {
3383 return errReason, err
3384 }
3385 }
3386 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3387 // device itself.
3388 // Unset the reset bit if option is specified
3389 for entityID := range upstreamEntityMap {
3390 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3391 false)
3392 if err != nil {
3393 return errReason, err
3394 }
3395 }
3396
3397 for entityID := range downstreamEntityMap {
3398 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3399 false)
3400 if err != nil {
3401 return errReason, err
3402 }
3403 }
3404 return extension.GetValueResponse_REASON_UNDEFINED, nil
3405}
3406
3407func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3408 mm.onuEthernetFrameExtendedPmLock.Lock()
3409 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3410 mm.isEthernetFrameExtendedPmOperationOngoing = val
3411}
3412
3413func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3414 mm.onuEthernetFrameExtendedPmLock.Lock()
3415 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3416 return mm.isEthernetFrameExtendedPmOperationOngoing
3417}
3418
3419// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3420func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3421 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3422 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3423 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303424 return &extension.SingleGetValueResponse{
3425 Response: &extension.GetValueResponse{
3426 Status: extension.GetValueResponse_ERROR,
3427 ErrReason: reason,
3428 },
3429 }
3430 }
3431 mm.onuEthernetFrameExtendedPmLock.RLock()
3432 if !mm.isDeviceReadyToCollectExtendedPmStats {
3433 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303434 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303435 }
3436 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303437
3438 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3439 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3440 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3441 }
3442 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3443 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3444
3445 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3446 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3447 if onuInfo.IsUniIndex != nil {
3448 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3449 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3450 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3451 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3452 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3453 break
3454 }
3455 }
3456 if len(downstreamEntityMap) == 0 {
3457 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3458 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3459 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3460 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3461 }
3462 } else {
3463 // make a copy of all downstream and upstream maps in the local ones
3464 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3465 upstreamEntityMap[entityID] = meEnt
3466 }
3467 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3468 downstreamEntityMap[entityID] = meEnt
3469 }
3470 }
3471 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3472 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3473 // Reset the metrics first for all required me's
3474 if onuInfo.Reset_ {
3475 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3476 if err != nil {
3477 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3478 log.Fields{"device-id": mm.deviceID})
3479 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3480 }
3481 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303482 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3483 var pmUpstream extension.OmciEthernetFrameExtendedPm
3484 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303485 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3486 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3487 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3488 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303489 if !onuInfo.Reset_ {
3490 for entityID, meEnt := range upstreamEntityMap {
3491 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3492 var receivedMask uint16
3493 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3494 if receivedMask == 0 {
3495 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303496 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3497 // It might be possible that still some downstream pms are supported and hence we need to continue
3498 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3499 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303500 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303501 // Aggregate the result for upstream
3502 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3503 } else {
3504 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303505 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303506 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303507
Himani Chawlaee10b542021-09-20 16:46:40 +05303508 for entityID, meEnt := range downstreamEntityMap {
3509 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3510 var receivedMask uint16
3511 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303512 if receivedMask == 0 {
3513 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3514 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3515 // Stop collecting downstream counters for other ME's.
3516 break
3517 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303518 // Aggregate the result for downstream
3519 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3520 } else {
3521 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3522 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303523 }
3524 }
3525 singleValResp := extension.SingleGetValueResponse{
3526 Response: &extension.GetValueResponse{
3527 Status: extension.GetValueResponse_OK,
3528 Response: &extension.GetValueResponse_OnuCounters{
3529 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303530 Upstream: &pmUpstream,
3531 Downstream: &pmDownstream,
3532 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303533 },
3534 },
3535 },
3536 }
3537 return &singleValResp
3538}
3539
Himani Chawlaee10b542021-09-20 16:46:40 +05303540func (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 +05303541 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003542 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 +05303543
3544 classID = mm.supportedEthernetFrameExtendedPMClass
3545 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3546 if classID == me.EthernetFrameExtendedPmClassID {
3547 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3548 }
3549 ethPMData := make(map[string]uint64)
3550 var sumReceivedMask uint16
3551 for mask := range attributeMaskList {
3552 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3553 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003554 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303555 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303556 }
3557 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3558 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3559 //populate all counters as failure and return
3560 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3561 break
3562 }
3563 }
3564 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303565 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303566}
3567
3568// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003569func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303570 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3571 var meAttributes me.AttributeValueMap
3572 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003573 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303574 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003575 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303576 return extension.GetValueResponse_INTERNAL_ERROR, err
3577 }
3578 select {
3579 case meAttributes = <-mm.extendedPmMeChan:
3580 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003581 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3582 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303583 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003584 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303585 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3586 }
3587 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3588 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3589 *sumReceivedMask += mask
3590 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3591 } else {
3592 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3593 *sumReceivedMask += mask
3594 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3595 }
3596
3597 return extension.GetValueResponse_REASON_UNDEFINED, nil
3598}
3599
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003600func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303601 sourceMap := maskToEthernetFrameExtendedPM64Bit
3602 errorCounterValue := UnsupportedCounterValue64bit
3603 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3604 sourceMap = maskToEthernetFrameExtendedPM32Bit
3605 errorCounterValue = UnsupportedCounterValue32bit
3606 }
3607 for _, value := range sourceMap {
3608 for _, k := range value {
3609 if _, ok := ethFrameExtPMData[k]; !ok {
3610 ethFrameExtPMData[k] = errorCounterValue
3611 }
3612 }
3613 }
3614}
3615
3616// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003617func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303618 receivedMask := uint16(0)
3619 switch requestedAttributesMask {
3620 case 0x3F00:
3621 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3622 if _, ok := ethFrameExtPMData[k]; !ok {
3623 switch k {
3624 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003625 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303626 ethFrameExtPMData[k] = uint64(val.(uint32))
3627 receivedMask |= 0x2000
3628 } else if !ok {
3629 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3630 }
3631 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003632 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303633 ethFrameExtPMData[k] = uint64(val.(uint32))
3634 receivedMask |= 0x1000
3635 } else if !ok {
3636 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3637 }
3638 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003639 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303640 ethFrameExtPMData[k] = uint64(val.(uint32))
3641 receivedMask |= 0x800
3642 } else if !ok {
3643 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3644 }
3645 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003646 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303647 ethFrameExtPMData[k] = uint64(val.(uint32))
3648 receivedMask |= 0x400
3649 } else if !ok {
3650 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3651 }
3652 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003653 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303654 ethFrameExtPMData[k] = uint64(val.(uint32))
3655 receivedMask |= 0x200
3656 } else if !ok {
3657 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3658 }
3659 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003660 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303661 ethFrameExtPMData[k] = uint64(val.(uint32))
3662 receivedMask |= 0x100
3663 } else if !ok {
3664 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3665 }
3666 default:
3667 //do nothing
3668 }
3669 }
3670 }
3671 case 0x00FC:
3672 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3673 if _, ok := ethFrameExtPMData[k]; !ok {
3674 switch k {
3675 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003676 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303677 ethFrameExtPMData[k] = uint64(val.(uint32))
3678 receivedMask |= 0x80
3679 } else if !ok {
3680 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3681 }
3682 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003683 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303684 ethFrameExtPMData[k] = uint64(val.(uint32))
3685 receivedMask |= 0x40
3686 } else if !ok {
3687 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3688 }
3689 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003690 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303691 ethFrameExtPMData[k] = uint64(val.(uint32))
3692 receivedMask |= 0x20
3693 } else if !ok {
3694 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3695 }
3696 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003697 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303698 ethFrameExtPMData[k] = uint64(val.(uint32))
3699 receivedMask |= 0x10
3700 } else if !ok {
3701 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3702 }
3703 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003704 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303705 ethFrameExtPMData[k] = uint64(val.(uint32))
3706 receivedMask |= 0x8
3707 } else if !ok {
3708 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3709 }
3710 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003711 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303712 ethFrameExtPMData[k] = uint64(val.(uint32))
3713 receivedMask |= 0x4
3714 } else if !ok {
3715 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3716 }
3717 default:
3718 //do nothing
3719 }
3720 }
3721 }
3722 case 0x0003:
3723 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3724 if _, ok := ethFrameExtPMData[k]; !ok {
3725 switch k {
3726 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003727 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303728 ethFrameExtPMData[k] = uint64(val.(uint32))
3729 receivedMask |= 0x2
3730 } else if !ok {
3731 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3732 }
3733 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003734 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303735 ethFrameExtPMData[k] = uint64(val.(uint32))
3736 receivedMask |= 0x1
3737 } else if !ok {
3738 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3739 }
3740 default:
3741 //do nothing
3742 }
3743 }
3744 }
3745 default:
3746 //do nothing
3747 }
3748 return receivedMask
3749}
3750
3751// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003752func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303753 receivedMask := uint16(0)
3754 switch requestedAttributesMask {
3755 case 0x3800:
3756 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3757 if _, ok := ethFrameExtPMData[k]; !ok {
3758 switch k {
3759 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003760 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303761 ethFrameExtPMData[k] = val.(uint64)
3762 receivedMask |= 0x2000
3763 } else if !ok {
3764 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3765 }
3766 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003767 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303768 ethFrameExtPMData[k] = val.(uint64)
3769 receivedMask |= 0x1000
3770 } else if !ok {
3771 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3772 }
3773 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003774 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303775 ethFrameExtPMData[k] = val.(uint64)
3776 receivedMask |= 0x800
3777 } else if !ok {
3778 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3779 }
3780 }
3781 }
3782 }
3783 case 0x0700:
3784 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3785 if _, ok := ethFrameExtPMData[k]; !ok {
3786 switch k {
3787 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003788 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303789 ethFrameExtPMData[k] = val.(uint64)
3790 receivedMask |= 0x400
3791 } else if !ok {
3792 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3793 }
3794 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003795 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303796 ethFrameExtPMData[k] = val.(uint64)
3797 receivedMask |= 0x200
3798 } else if !ok {
3799 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3800 }
3801 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003802 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303803 ethFrameExtPMData[k] = val.(uint64)
3804 receivedMask |= 0x100
3805 } else if !ok {
3806 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3807 }
3808 }
3809 }
3810 }
3811 case 0x00E0:
3812 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3813 if _, ok := ethFrameExtPMData[k]; !ok {
3814 switch k {
3815 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003816 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303817 ethFrameExtPMData[k] = val.(uint64)
3818 receivedMask |= 0x80
3819 } else if !ok {
3820 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3821 }
3822 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003823 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303824 ethFrameExtPMData[k] = val.(uint64)
3825 receivedMask |= 0x40
3826 } else if !ok {
3827 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3828 }
3829 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003830 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303831 ethFrameExtPMData[k] = val.(uint64)
3832 receivedMask |= 0x20
3833 } else if !ok {
3834 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3835 }
3836 }
3837 }
3838 }
3839 case 0x001C:
3840 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3841 if _, ok := ethFrameExtPMData[k]; !ok {
3842 switch k {
3843 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003844 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303845 ethFrameExtPMData[k] = val.(uint64)
3846 receivedMask |= 0x10
3847 } else if !ok {
3848 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3849 }
3850 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003851 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303852 ethFrameExtPMData[k] = val.(uint64)
3853 receivedMask |= 0x8
3854 } else if !ok {
3855 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3856 }
3857 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003858 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303859 ethFrameExtPMData[k] = val.(uint64)
3860 receivedMask |= 0x4
3861 } else if !ok {
3862 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3863 }
3864 default:
3865 //do nothing
3866 }
3867 }
3868 }
3869 case 0x0003:
3870 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3871 if _, ok := ethFrameExtPMData[k]; !ok {
3872 switch k {
3873 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003874 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303875 ethFrameExtPMData[k] = val.(uint64)
3876 receivedMask |= 0x2
3877 } else if !ok {
3878 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3879 }
3880 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003881 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303882 ethFrameExtPMData[k] = val.(uint64)
3883 receivedMask |= 0x1
3884 } else if !ok {
3885 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3886 }
3887 default:
3888 //do nothing
3889 }
3890 }
3891 }
3892 }
3893 return receivedMask
3894}
3895
Himani Chawlaee10b542021-09-20 16:46:40 +05303896func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3897 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303898 errorCounterValue := UnsupportedCounterValue64bit
3899 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3900 errorCounterValue = UnsupportedCounterValue32bit
3901 }
3902 var pmDataOut extension.OmciEthernetFrameExtendedPm
3903 if aggregate {
3904 if pmData.DropEvents != errorCounterValue {
3905 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3906 } else {
3907 pmDataOut.DropEvents = pmData.DropEvents
3908 }
3909 if pmData.Octets != errorCounterValue {
3910 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3911 } else {
3912 pmDataOut.Octets = pmData.Octets
3913 }
3914 if pmData.Frames != errorCounterValue {
3915 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3916 } else {
3917 pmDataOut.Frames = pmData.Frames
3918 }
3919 if pmData.BroadcastFrames != errorCounterValue {
3920 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3921 } else {
3922 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3923 }
3924 if pmData.MulticastFrames != errorCounterValue {
3925 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3926 } else {
3927 pmDataOut.MulticastFrames = pmData.MulticastFrames
3928 }
3929 if pmData.CrcErroredFrames != errorCounterValue {
3930 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3931 } else {
3932 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3933 }
3934 if pmData.UndersizeFrames != errorCounterValue {
3935 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3936 } else {
3937 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3938 }
3939 if pmData.OversizeFrames != errorCounterValue {
3940 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3941 } else {
3942 pmDataOut.OversizeFrames = pmData.OversizeFrames
3943 }
3944 if pmData.Frames_64Octets != errorCounterValue {
3945 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3946 } else {
3947 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3948 }
3949 if pmData.Frames_65To_127Octets != errorCounterValue {
3950 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3951 } else {
3952 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3953 }
3954 if pmData.Frames_128To_255Octets != errorCounterValue {
3955 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3956 } else {
3957 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3958 }
3959 if pmData.Frames_256To_511Octets != errorCounterValue {
3960 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3961 } else {
3962 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3963 }
3964 if pmData.Frames_512To_1023Octets != errorCounterValue {
3965 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3966 } else {
3967 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3968 }
3969 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3970 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3971 } else {
3972 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3973 }
3974 } else {
3975 pmDataOut.DropEvents = pmDataIn["drop_events"]
3976 pmDataOut.Octets = pmDataIn["octets"]
3977 pmDataOut.Frames = pmDataIn["frames"]
3978 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3979 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3980 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3981 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3982 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3983 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3984 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3985 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3986 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3987 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3988 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3989 }
3990 return pmDataOut
3991}
3992
Himani Chawlaee10b542021-09-20 16:46:40 +05303993func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303994 controlBlock := make([]uint16, 8)
3995 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3996 controlBlock[0] = 0
3997 // Next two bytes are for the parent class ID
3998 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3999 // Next two bytes are for the parent me instance id
4000 controlBlock[2] = entityID
4001 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05304002 if reset {
4003 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
4004 } else {
4005 controlBlock[3] = 0
4006 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05304007 // Next two bytes are for tca disable
4008 controlBlock[4] = 0x4000 //tca global disable
4009 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
4010 if upstream {
4011 controlBlock[5] = 1 << 0
4012 } else {
4013 controlBlock[5] = (1 << 0) | (1 << 1)
4014 }
4015 // Next two bytes are for tci - does not matter here
4016 controlBlock[6] = 0
4017 // Next two bytes are for reserved bits - does not matter here
4018 controlBlock[7] = 0
4019 return controlBlock
4020}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00004021
Girish Gowdraabcceb12022-04-13 23:35:22 -07004022// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
4023func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
4024 mm.OnuMetricsManagerLock.RLock()
4025 defer mm.OnuMetricsManagerLock.RUnlock()
4026 return mm.deviceDeletionInProgress
4027}
4028
4029// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
4030func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
4031 mm.OnuMetricsManagerLock.Lock()
4032 defer mm.OnuMetricsManagerLock.Unlock()
4033 mm.deviceDeletionInProgress = true
4034}