blob: a686d77e6aa672d5831ca7390e5d60afee85d367 [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
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +000017//Package pmmgr provides the utilities to manage onu metrics
18package 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
Girish Gowdrae09a6202021-01-12 18:10:59 -0800334}
335
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000336// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800337// The metrics manager module is responsible for configuration and management of individual and group metrics.
338// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
339// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
340// the collection interval configurable.
341// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
342// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000343func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800344
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000345 var metricsManager OnuMetricsManager
346 metricsManager.deviceID = dh.GetDeviceID()
347 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800348 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000349 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800350
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000351 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800352 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
353 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800354 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530355 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800356
357 metricsManager.syncTimeResponseChan = make(chan bool)
358 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530359 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800360
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000361 metricsManager.StopProcessingOmciResponses = make(chan bool)
362 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800363
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000364 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
365 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800366
Himani Chawlac77d5372021-07-12 15:42:26 +0530367 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
368 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530369
Girish Gowdraabcceb12022-04-13 23:35:22 -0700370 // make this a buffered channel so that the sender is not blocked for any reason if there is no listener
371 metricsManager.GarbageCollectionComplete = make(chan bool, 1)
372
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000373 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 -0800374 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800375 }
376
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800377 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800378
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800379 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800380 return nil
381 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800382
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800383 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000384 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800385
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000386 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
387 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800388 if metricsManager.pmKvStore == nil {
389 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000390 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800391 return nil
392 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700393 // restore data from KV store
394 if err := metricsManager.restorePmData(ctx); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000395 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700396 // we continue given that it does not effect the actual services for the ONU,
397 // but there may be some negative effect on PM collection (there may be some mismatch in
398 // the actual PM config and what is present on the device).
399 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800400
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000401 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
402 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530403 if metricsManager.extPmKvStore == nil {
404 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000405 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530406 return nil
407 }
408
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000409 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800410 return &metricsManager
411}
412
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000413// InitializeMetricCollectionTime - TODO: add comment
414func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
415 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
416 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
417 mm.OnuMetricsManagerLock.Lock()
418 defer mm.OnuMetricsManagerLock.Unlock()
419 for _, v := range mm.GroupMetricMap {
420 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
421 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800422 }
423 }
424
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000425 for _, v := range mm.StandaloneMetricMap {
426 if v.Enabled {
427 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800428 }
429 }
430 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000431 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
432 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800433 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000434 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800435}
436
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000437// UpdateDefaultFrequency - TODO: add comment
438func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800439 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800440 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800441 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
442 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
443 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000444 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
445 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
446 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
447 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 -0800448 return nil
449}
450
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000451// UpdateGroupFreq - TODO: add comment
452func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800453 var newGroupFreq uint32
454 found := false
455 groupSliceIdx := 0
456 var group *voltha.PmGroupConfig
457 for groupSliceIdx, group = range pmConfigs.Groups {
458 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800459 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
460 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
461 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
462 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800463 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800464 newGroupFreq = group.GroupFreq
465 found = true
466 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800467 }
468 }
469 // if not found update group freq and next collection interval for the group
470 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000471 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800472 return fmt.Errorf("group-name-not-found-%v", aGroupName)
473 }
474
475 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000476 mm.OnuMetricsManagerLock.Lock()
477 defer mm.OnuMetricsManagerLock.Unlock()
478 for k, v := range mm.GroupMetricMap {
479 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
480 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800481 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000482 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800483 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000484 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800485 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000486 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800487 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800488 }
489 }
490 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000491 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800492 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
493 }
494 return nil
495}
496
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000497// UpdateMetricFreq - TODO: add comment
498func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800499 var newMetricFreq uint32
500 found := false
501 metricSliceIdx := 0
502 var metric *voltha.PmConfig
503 for metricSliceIdx, metric = range pmConfigs.Metrics {
504 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800505 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
506 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
507 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
508 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800509 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800510 newMetricFreq = metric.SampleFreq
511 found = true
512 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800513 }
514 }
515 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000516 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800517 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
518 }
519
520 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000521 mm.OnuMetricsManagerLock.Lock()
522 defer mm.OnuMetricsManagerLock.Unlock()
523 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800524 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000525 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800526 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000527 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800528 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000529 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800530 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000531 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800532 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800533 }
534 }
535 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000536 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800537 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
538 }
539 return nil
540}
541
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000542// UpdateGroupSupport - TODO: add comment
543func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800544 groupSliceIdx := 0
545 var group *voltha.PmGroupConfig
546
547 for groupSliceIdx, group = range pmConfigs.Groups {
548 if group.GroupName == aGroupName {
549 break
550 }
551 }
552 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000553 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800554 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
555 }
556
557 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000558 mm.OnuMetricsManagerLock.Lock()
559 defer mm.OnuMetricsManagerLock.Unlock()
560 for k, v := range mm.GroupMetricMap {
561 if k == aGroupName && v.Enabled != group.Enabled {
562 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
563 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800564 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000565 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800566 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800567 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800568 // 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 -0800569 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
570
571 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
572 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
573 // take further action
574 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800575 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800576 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000577 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
578 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800579 }
580 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000581 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800582 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800583 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800584 // 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 -0800585 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
586
587 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
588 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
589 // take further action
590 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800591 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800592 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800593 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800594 }
595 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000596 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800597 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000598 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800599 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000600 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 -0800601 }
602 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800603 }
604 }
605
606 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000607 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800608 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
609 }
610 return nil
611}
612
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000613// UpdateMetricSupport - TODO: add comment
614func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800615 metricSliceIdx := 0
616 var metric *voltha.PmConfig
617
618 for metricSliceIdx, metric = range pmConfigs.Metrics {
619 if metric.Name == aMetricName {
620 break
621 }
622 }
623
624 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000625 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800626 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
627 }
628
629 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000630 mm.OnuMetricsManagerLock.Lock()
631 defer mm.OnuMetricsManagerLock.Unlock()
632 for k, v := range mm.StandaloneMetricMap {
633 if k == aMetricName && v.Enabled != metric.Enabled {
634 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
635 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800636 // 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 +0000637 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
638 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800639 }
640 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000641 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 -0800642 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800643 }
644 }
645 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000646 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800647 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
648 }
649 return nil
650}
651
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000652// CollectAllGroupAndStandaloneMetrics - TODO: add comment
653func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
654 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800655 go mm.collectAllGroupMetrics(ctx)
656 } else {
657 go mm.collectAllStandaloneMetrics(ctx)
658 }
659}
660
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000661func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800662 go func() {
663 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300664 metricInfo, err := mm.collectOpticalMetrics(ctx)
665 if err != nil {
666 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000667 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300668 return
669 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800670 if metricInfo != nil {
671 mm.publishMetrics(ctx, metricInfo)
672 }
673 }()
674
675 go func() {
676 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300677 metricInfo, err := mm.collectUniStatusMetrics(ctx)
678 if err != nil {
679 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000680 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300681 return
682 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800683 if metricInfo != nil {
684 mm.publishMetrics(ctx, metricInfo)
685 }
686 }()
687
688 // Add more here
689}
690
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000691func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800692 // None exists as of now, add when available here
693}
694
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000695// CollectGroupMetric - TODO: add comment
696func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800697 switch groupName {
698 case OpticalPowerGroupMetricName:
699 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300700 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800701 mm.publishMetrics(ctx, mi)
702 }
703 }()
704 case UniStatusGroupMetricName:
705 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300706 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800707 mm.publishMetrics(ctx, mi)
708 }
709 }()
710 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000711 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800712 }
713}
714
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000715// CollectStandaloneMetric - TODO: add comment
716func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800717 switch metricName {
718 // None exist as of now, add when available
719 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000720 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800721 }
722}
723
724// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000725func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
726 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800727
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000728 mm.OnuMetricsManagerLock.RLock()
729 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
730 mm.OnuMetricsManagerLock.RUnlock()
731 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300732 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800733 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000734 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800735
Girish Gowdrae09a6202021-01-12 18:10:59 -0800736 var metricInfoSlice []*voltha.MetricInformation
737 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000738 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
739 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
740 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800741
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800742 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800743 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800744 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800745 Ts: float64(raisedTs),
746 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000747 DeviceId: mm.deviceID,
748 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
749 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800750 }
751
Girish Gowdrae09a6202021-01-12 18:10:59 -0800752 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000753 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800754loop:
755 for _, anigInstID := range anigInstKeys {
756 var meAttributes me.AttributeValueMap
757 opticalMetrics := make(map[string]float32)
758 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000759 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000760 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes,
761 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300762 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000763 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
764 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300765 return nil, err
766 }
767
768 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800769 select {
770 case meAttributes = <-mm.opticalMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000771 logger.Debugw(ctx, "received optical metrics", log.Fields{"device-id": mm.deviceID})
772 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
773 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 -0800774 // The metrics will be empty in this case
775 break loop
776 }
777 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800778 for k := range OpticalPowerGroupMetrics {
779 switch k {
780 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000781 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800782 opticalMetrics[k] = float32(val.(uint16))
783 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800784 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000785 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000786 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 -0800787 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800788 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000789 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000790 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 -0800791 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800792 default:
793 // do nothing
794 }
795 }
796 }
797 // create slice of metrics given that there could be more than one ANI-G instance and
798 // optical metrics are collected per ANI-G instance
799 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
800 metricInfoSlice = append(metricInfoSlice, &metricInfo)
801 }
802
ozgecanetsiab36ed572021-04-01 10:38:48 +0300803 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800804}
805
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800806// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800807// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000808func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
809 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
810 mm.OnuMetricsManagerLock.RLock()
811 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
812 mm.OnuMetricsManagerLock.RUnlock()
813 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300814 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800815 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000816 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800817
Girish Gowdrae09a6202021-01-12 18:10:59 -0800818 var metricInfoSlice []*voltha.MetricInformation
819 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000820 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
821 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
822 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800823
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800824 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800825 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700826 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800827 Ts: float64(raisedTs),
828 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000829 DeviceId: mm.deviceID,
830 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
831 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800832 }
833
Girish Gowdrae09a6202021-01-12 18:10:59 -0800834 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000835 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800836loop1:
837 for _, unigInstID := range unigInstKeys {
838 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
839 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
840 unigMetrics := make(map[string]float32)
841 var meAttributes me.AttributeValueMap
842 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000843 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000844 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes,
845 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300846 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000847 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
848 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300849 return nil, err
850 }
851 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800852 // Wait for metrics or timeout
853 select {
854 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000855 logger.Debugw(ctx, "received uni-g metrics", log.Fields{"device-id": mm.deviceID})
856 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
857 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 -0800858 // The metrics could be empty in this case
859 break loop1
860 }
861 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800862 for k := range UniStatusGroupMetrics {
863 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800864 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000865 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800866 unigMetrics[k] = float32(val.(byte))
867 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800868 default:
869 // do nothing
870 }
871 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000872 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800873 entityID := val.(uint16)
874 unigMetrics["entity_id"] = float32(entityID)
875 // 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 +0000876 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
877 if uni.EntityID == entityID {
878 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700879 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800880 }
881 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800882 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700883 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800884
Girish Gowdrae09a6202021-01-12 18:10:59 -0800885 // create slice of metrics given that there could be more than one UNI-G instance
886 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
887 metricInfoSlice = append(metricInfoSlice, &metricInfo)
888 }
889 }
890
891 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000892 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800893loop2:
894 for _, pptpInstID := range pptpInstKeys {
895 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
896 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
897 var meAttributes me.AttributeValueMap
898 pptpMetrics := make(map[string]float32)
899
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000900 requestedAttributes := me.AttributeValueMap{
901 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
902 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
903 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
904 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000905 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300906 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000907 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
908 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300909 return nil, err
910 }
911 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800912 // Wait for metrics or timeout
913 select {
914 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000915 logger.Debugw(ctx, "received pptp metrics", log.Fields{"device-id": mm.deviceID})
916 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
917 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 -0800918 // The metrics could be empty in this case
919 break loop2
920 }
921
922 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800923 for k := range UniStatusGroupMetrics {
924 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700925 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000926 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800927 pptpMetrics[k] = float32(val.(byte))
928 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800929 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000930 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800931 pptpMetrics[k] = float32(val.(byte))
932 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800933 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000934 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800935 pptpMetrics[k] = float32(val.(byte))
936 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800937 default:
938 // do nothing
939 }
940 }
941 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000942 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800943 entityID := val.(uint16)
944 pptpMetrics["entity_id"] = float32(entityID)
945 // 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 +0000946 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
947 if uni.EntityID == entityID {
948 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700949 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800950 }
951 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800952 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700953 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800954
Girish Gowdrae09a6202021-01-12 18:10:59 -0800955 // create slice of metrics given that there could be more than one PPTP instance and
956 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
957 metricInfoSlice = append(metricInfoSlice, &metricInfo)
958 }
959
960 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000961 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800962loop3:
963 for _, veipInstID := range veipInstKeys {
964 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
965 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
966 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800967 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800968
Holger Hildebrandtd930cb22022-06-17 09:24:50 +0000969 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0,
970 me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
971 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes,
972 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300973 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000974 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
975 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300976 return nil, err
977 }
978 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800979 // Wait for metrics or timeout
980 select {
981 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000982 logger.Debugw(ctx, "received veip metrics", log.Fields{"device-id": mm.deviceID})
983 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
984 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 -0800985 // The metrics could be empty in this case
986 break loop3
987 }
988
989 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800990 for k := range UniStatusGroupMetrics {
991 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800992 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000993 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800994 veipMetrics[k] = float32(val.(byte))
995 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800996 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000997 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800998 veipMetrics[k] = float32(val.(byte))
999 }
Girish Gowdrae09a6202021-01-12 18:10:59 -08001000 default:
1001 // do nothing
1002 }
1003 }
1004 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001005
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00001006 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001007 entityID := val.(uint16)
1008 veipMetrics["entity_id"] = float32(entityID)
1009 // 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 +00001010 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1011 if uni.EntityID == entityID {
1012 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001013 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001014 }
1015 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001016 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001017 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001018
Girish Gowdrae09a6202021-01-12 18:10:59 -08001019 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001020 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001021 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1022 }
1023
ozgecanetsiab36ed572021-04-01 10:38:48 +03001024 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001025}
1026
1027// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001028func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001029 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001030 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001031 ke.SliceData = metricInfo
1032 ke.Type = voltha.KpiEventType_slice
1033 ke.Ts = float64(ts)
1034
Himani Chawlaf9768882021-12-01 00:18:58 +05301035 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 +00001036 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001037 }
1038}
1039
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001040// ProcessOmciMessages - TODO: add comment
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001041func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context, waitForOmciProcessor *sync.WaitGroup) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001042 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 -08001043 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001044 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001045 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001046 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001047 // is stopped - as a result of ONU going down.
1048 mm.flushMetricCollectionChannels(ctx)
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00001049 // when instantiating mm it was too early, but now we can check for ONU's extended OMCI support
1050 mm.isExtendedOmci = mm.pOnuDeviceEntry.GetPersIsExtOmciSupported()
1051 if mm.isExtendedOmci {
1052 mm.maxL2PMGetPayLoadSize = MaxExtendedL2PMGetPayLoadSize
1053 } else {
1054 mm.maxL2PMGetPayLoadSize = MaxBaselineL2PMGetPayLoadSize
1055 }
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001056 mm.updateOmciProcessingStatus(true)
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001057 waitForOmciProcessor.Done()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001058 for {
1059 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001060 case <-mm.StopProcessingOmciResponses: // stop this routine
1061 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 -07001062 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001063 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001064 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001065 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001066 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001067 continue
1068 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001069 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001070
1071 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001072 case cmn.OMCI:
1073 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001074 mm.handleOmciMessage(ctx, msg)
1075 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001076 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001077 }
1078 }
1079 }
1080}
1081
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001082func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1083 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001084 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1085 switch msg.OmciMsg.MessageType {
1086 case omci.GetResponseType:
1087 //TODO: error handling
1088 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001089 case omci.SynchronizeTimeResponseType:
1090 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1091 case omci.CreateResponseType:
1092 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1093 case omci.DeleteResponseType:
1094 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301095 case omci.GetCurrentDataResponseType:
1096 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301097 case omci.SetResponseType:
1098 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001099 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001100 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001101
1102 }
1103}
1104
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001105func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001106 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1107 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001108 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1109 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001110 }
1111 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1112 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001113 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1114 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001115 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001116 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 -08001117 if msgObj.Result == me.Success {
1118 meAttributes := msgObj.Attributes
1119 switch msgObj.EntityClass {
1120 case me.AniGClassID:
1121 mm.opticalMetricsChan <- meAttributes
1122 return nil
1123 case me.UniGClassID:
1124 mm.uniStatusMetricsChan <- meAttributes
1125 return nil
1126 case me.PhysicalPathTerminationPointEthernetUniClassID:
1127 mm.uniStatusMetricsChan <- meAttributes
1128 return nil
1129 case me.VirtualEthernetInterfacePointClassID:
1130 mm.uniStatusMetricsChan <- meAttributes
1131 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001132 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1133 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001134 me.EthernetPerformanceMonitoringHistoryDataClassID,
1135 me.FecPerformanceMonitoringHistoryDataClassID,
1136 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001137 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301138 return nil
1139 case me.EthernetFrameExtendedPmClassID,
1140 me.EthernetFrameExtendedPm64BitClassID:
1141 mm.extendedPmMeChan <- meAttributes
1142 return nil
1143 default:
1144 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001145 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301146 }
1147 } else {
1148 meAttributes := msgObj.Attributes
1149 switch msgObj.EntityClass {
1150 case me.EthernetFrameExtendedPmClassID,
1151 me.EthernetFrameExtendedPm64BitClassID:
1152 // not all counters may be supported in which case we have seen some ONUs throwing
1153 // AttributeFailure error code, while correctly populating other counters it supports
1154 mm.extendedPmMeChan <- meAttributes
1155 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001156 default:
1157 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001158 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001159 }
1160 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001161 return fmt.Errorf("unhandled-omci-get-response-message")
1162}
1163
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001164func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301165 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1166 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001167 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1168 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301169 }
1170 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1171 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001172 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1173 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301174 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001175 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 +05301176 if msgObj.Result == me.Success {
1177 meAttributes := msgObj.Attributes
1178 switch msgObj.EntityClass {
1179 case me.EthernetFrameExtendedPmClassID,
1180 me.EthernetFrameExtendedPm64BitClassID:
1181 mm.extendedPmMeChan <- meAttributes
1182 return nil
1183 default:
1184 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001185 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301186 }
1187 } else {
1188 meAttributes := msgObj.Attributes
1189 switch msgObj.EntityClass {
1190 case me.EthernetFrameExtendedPmClassID,
1191 me.EthernetFrameExtendedPm64BitClassID:
1192 // not all counters may be supported in which case we have seen some ONUs throwing
1193 // AttributeFailure error code, while correctly populating other counters it supports
1194 mm.extendedPmMeChan <- meAttributes
1195 return nil
1196 default:
1197 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001198 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301199 }
1200 }
1201 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1202}
1203
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001204func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001205 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1206 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001207 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1208 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 -08001209 }
1210 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1211 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001212 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1213 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 -08001214 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001215 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001216 if msgObj.Result == me.Success {
1217 switch msgObj.EntityClass {
1218 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001219 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001220 mm.syncTimeResponseChan <- true
1221 return nil
1222 default:
1223 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001224 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001225 }
1226 }
1227 mm.syncTimeResponseChan <- false
1228 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1229 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001230}
1231
Himani Chawlaee10b542021-09-20 16:46:40 +05301232func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1233 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1234 if msgLayer == nil {
1235 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1236 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1237 }
1238 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1239 if !msgOk {
1240 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1241 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1242 }
1243 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1244 switch msgObj.EntityClass {
1245 case me.EthernetFrameExtendedPmClassID,
1246 me.EthernetFrameExtendedPm64BitClassID:
1247 mm.extendedPMMeResponseChan <- msgObj.Result
1248 return nil
1249 default:
1250 logger.Errorw(ctx, "unhandled omci set response message",
1251 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1252 }
1253 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1254}
1255
Girish Gowdrae09a6202021-01-12 18:10:59 -08001256// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001257func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001258 // flush commMetricsChan
1259 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001260 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001261 logger.Debug(ctx, "flushed common metrics channel")
1262 default:
1263 }
1264
1265 // flush opticalMetricsChan
1266 select {
1267 case <-mm.opticalMetricsChan:
1268 logger.Debug(ctx, "flushed optical metrics channel")
1269 default:
1270 }
1271
1272 // flush uniStatusMetricsChan
1273 select {
1274 case <-mm.uniStatusMetricsChan:
1275 logger.Debug(ctx, "flushed uni status metrics channel")
1276 default:
1277 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001278
1279 // flush syncTimeResponseChan
1280 select {
1281 case <-mm.syncTimeResponseChan:
1282 logger.Debug(ctx, "flushed sync time response channel")
1283 default:
1284 }
1285
1286 // flush l2PmChan
1287 select {
1288 case <-mm.l2PmChan:
1289 logger.Debug(ctx, "flushed L2 PM collection channel")
1290 default:
1291 }
1292
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001293 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001294 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001295 case <-mm.StopTicks:
1296 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001297 default:
1298 }
1299
1300}
1301
1302// ** L2 PM FSM Handlers start **
1303
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001304func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001305 if mm.GetdeviceDeletionInProgress() {
1306 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1307 return
1308 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001309
Girish Gowdrae0140f02021-02-02 16:55:09 -08001310 // Loop through all the group metrics
1311 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1312 // list of active L2 PM list then mark it for creation
1313 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1314 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001315 mm.OnuMetricsManagerLock.Lock()
1316 for n, g := range mm.GroupMetricMap {
1317 if g.IsL2PMCounter { // it is a l2 pm counter
1318 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001319 found := false
1320 inner1:
1321 for _, v := range mm.activeL2Pms {
1322 if v == n {
1323 found = true // metric already present in active l2 pm list
1324 break inner1
1325 }
1326 }
1327 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001328 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001329 }
1330 } else { // metric not enabled.
1331 found := false
1332 inner2:
1333 for _, v := range mm.activeL2Pms {
1334 if v == n {
1335 found = true // metric is found in active l2 pm list
1336 break inner2
1337 }
1338 }
1339 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001340 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001341 }
1342 }
1343 }
1344 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001345 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001346 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001347 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001348 go func() {
1349 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001350 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1351 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001352 }
1353 }()
1354}
1355
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001356func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001357 if mm.GetdeviceDeletionInProgress() {
1358 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1359 return
1360 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001361 // Sync time with the ONU to establish 15min boundary for PM collection.
1362 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001363 // device could be deleted while waiting on sync time response
1364 if mm.GetdeviceDeletionInProgress() {
1365 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1366 return
1367 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001368 go func() {
1369 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1370 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001371 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1372 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001373 }
1374 }()
1375 }
1376 // Initiate a tick generation routine every L2PmCollectionInterval
1377 go mm.generateTicks(ctx)
1378
1379 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001380 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1381 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001382 }
1383 }()
1384}
1385
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001386func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001387 // 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 +00001388 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001389 mm.activeL2Pms = nil
1390 mm.l2PmToAdd = nil
1391 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001392 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001393 // If the FSM was stopped, then clear PM data from KV store
1394 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001395 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001396 _ = mm.clearPmGroupData(ctx) // ignore error
1397 }
1398
Girish Gowdraabcceb12022-04-13 23:35:22 -07001399 if mm.GetdeviceDeletionInProgress() {
1400 mm.pDeviceHandler = nil
1401 mm.pOnuDeviceEntry = nil
1402 mm.GarbageCollectionComplete <- true
1403 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001404}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001405func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1406 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001407 if mm.GetdeviceDeletionInProgress() {
1408 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1409 return
1410 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001411
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001412 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001413 numOfPmToDelete := len(mm.l2PmToDelete)
1414 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001415 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001416
1417 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001418 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 -08001419 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001420 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1421 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001422 }
1423 }()
1424 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001425 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 -08001426 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001427 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1428 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001429 }
1430 }()
1431 }
1432}
1433
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001434func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1435 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001436 if mm.GetdeviceDeletionInProgress() {
1437 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1438 return
1439 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001440 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001441 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001442 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1443 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001444 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001445
1446 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001447 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001448
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001449 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1450 mm.OnuMetricsManagerLock.RLock()
1451 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1452 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1453 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001454
Girish Gowdrae0140f02021-02-02 16:55:09 -08001455 switch n {
1456 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001457 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001458 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001459 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1460 metricInfoSlice = append(metricInfoSlice, metricInfo)
1461 }
1462 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1463 metricInfoSlice = append(metricInfoSlice, metricInfo)
1464 }
1465 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001466 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001467 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001468 for _, entityID := range copyOfEntityIDs {
1469 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1470 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001471 }
1472 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001473
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001474 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001475 for _, entityID := range copyOfEntityIDs {
1476 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001477 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001478 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001479 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001480 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001481 for _, entityID := range copyOfEntityIDs {
1482 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001483 metricInfoSlice = append(metricInfoSlice, metricInfo)
1484 }
1485 }
1486
Girish Gowdrae0140f02021-02-02 16:55:09 -08001487 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001488 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001489 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001490 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001491 }
1492 // Does not matter we send success or failure here.
1493 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1494 // we have not exceed max attempts to collect the PM data)
1495 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001496 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1497 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001498 }
1499 }()
1500}
1501
Girish Gowdra0e533642021-03-02 22:02:51 -08001502// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001503func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001504 if mm.GetdeviceDeletionInProgress() {
1505 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1506 return nil
1507 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001508 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001509 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001510 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1511 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001512 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001513
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001514 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001515 for _, n := range copyOfL2PmToAdd {
1516 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001517 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1518 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001519 switch n {
1520 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001521 // 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 +05301522 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001523 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001524 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001525 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001526 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1527 inner1:
1528 // retry L2PmCreateAttempts times to create the instance of PM
1529 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001530 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1531 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001532 if err != nil {
1533 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001534 log.Fields{"device-id": mm.deviceID})
1535 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001536 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001537 go func(p_pmFsm *cmn.AdapterFsm) {
1538 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001539 }(pPMFsm)
1540 }
1541 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001542 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001543 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001544 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1545 atLeastOneSuccess = true
1546 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1547 break inner1
1548 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001549 if mm.GetdeviceDeletionInProgress() {
1550 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1551 return nil
1552 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001553 }
1554 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1555 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001556 }
1557 }
1558 }
1559 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001560 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1561 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001562 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001563 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001564 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1565 inner2:
1566 // retry L2PmCreateAttempts times to create the instance of PM
1567 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001568 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1569 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001570 if err != nil {
1571 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001572 log.Fields{"device-id": mm.deviceID})
1573 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001574 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001575 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001576 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001577 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1578 atLeastOneSuccess = true
1579 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1580 break inner2
1581 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001582 if mm.GetdeviceDeletionInProgress() {
1583 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1584 return nil
1585 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001586 }
1587 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1588 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001589 }
1590 }
1591 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001592 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001593 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001594 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001595 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1596 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001597 if err != nil {
1598 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001599 log.Fields{"device-id": mm.deviceID})
1600 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001601 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001602 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001603 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001604 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1605 inner3:
1606 // retry L2PmCreateAttempts times to create the instance of PM
1607 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1608 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1609 atLeastOneSuccess = true
1610 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1611 break inner3
1612 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001613 if mm.GetdeviceDeletionInProgress() {
1614 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1615 return nil
1616 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001617 }
1618 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1619 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001620 }
1621 }
1622 case GemPortHistoryName:
1623
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001624 mm.OnuMetricsManagerLock.RLock()
1625 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1626 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1627 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001628
1629 if len(copyOfGemPortInstIDsToAdd) == 0 {
1630 // If there are no gemport history MEs to be created, just skip further processing
1631 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1632 // 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 +00001633 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001634 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001635 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001636 continue
1637 }
1638
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001639 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001640 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1641 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001642 if err != nil {
1643 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001644 log.Fields{"device-id": mm.deviceID})
1645 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001646 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001647 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001648 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001649 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1650 inner4:
1651 // retry L2PmCreateAttempts times to create the instance of PM
1652 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1653 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1654 atLeastOneSuccess = true
1655 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1656 break inner4
1657 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001658 if mm.GetdeviceDeletionInProgress() {
1659 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1660 return nil
1661 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001662 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001663 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1664 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1665 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001666 }
1667
Girish Gowdrae0140f02021-02-02 16:55:09 -08001668 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001669 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001670 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001671 // 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
1672 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001673 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001674 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001675 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1676 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001677 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001678 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1679 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001680 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 +00001681 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001682 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001683 // 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 -08001684 // 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 +00001685 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001686 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001687 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001688 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001689
Girish Gowdrae0140f02021-02-02 16:55:09 -08001690 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001691 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001692 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001693 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001694 }
1695 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001696 mm.OnuMetricsManagerLock.RLock()
1697 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1698 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001699 // Does not matter we send success or failure here.
1700 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1701 // we have not exceed max attempts to create the PM ME)
1702 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001703 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1704 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001705 }
1706 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001707 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001708}
1709
Girish Gowdra0e533642021-03-02 22:02:51 -08001710// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001711func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001712 if mm.GetdeviceDeletionInProgress() {
1713 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1714 return nil
1715 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001716 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001717 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001718 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1719 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001720 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001721
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001722 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001723 for _, n := range copyOfL2PmToDelete {
1724 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001725 cnt := 0
1726 atLeastOneDeleteFailure := false
1727
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001728 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1729 mm.OnuMetricsManagerLock.RLock()
1730 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1731 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1732 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001733
1734 if len(copyOfEntityIDs) == 0 {
1735 // 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 +00001736 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001737 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1738 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1739 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 +00001740 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001741 continue
1742 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001743 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001744 switch n {
1745 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001746 // 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 +05301747 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001748 for _, entityID := range copyOfEntityIDs {
1749 inner1:
1750 // retry L2PmDeleteAttempts times to delete the instance of PM
1751 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001752 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1753 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001754 if err != nil {
1755 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001756 log.Fields{"device-id": mm.deviceID})
1757 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001758 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001759 go func(p_pmFsm *cmn.AdapterFsm) {
1760 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001761 }(pPMFsm)
1762 }
1763 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001764 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001765 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001766 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1767 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001768 if mm.GetdeviceDeletionInProgress() {
1769 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1770 return nil
1771 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001772 atLeastOneDeleteFailure = true
1773 } else {
1774 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1775 break inner1
1776 }
1777 }
1778 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1779 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001780 }
1781 }
1782 }
1783 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001784 for _, entityID := range copyOfEntityIDs {
1785 inner2:
1786 // retry L2PmDeleteAttempts times to delete the instance of PM
1787 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001788 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1789 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001790 if err != nil {
1791 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001792 log.Fields{"device-id": mm.deviceID})
1793 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001794 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001795 go func(p_pmFsm *cmn.AdapterFsm) {
1796 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001797 }(pmFsm)
1798 return err
1799 }
1800 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001801 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001802 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001803 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001804 if mm.GetdeviceDeletionInProgress() {
1805 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1806 return nil
1807 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001808 atLeastOneDeleteFailure = true
1809 } else {
1810 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001811 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001812 }
1813 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001814 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1815 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1816 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001817 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001818 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001819 for _, entityID := range copyOfEntityIDs {
1820 inner3:
1821 // retry L2PmDeleteAttempts times to delete the instance of PM
1822 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001823 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1824 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001825 if err != nil {
1826 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001827 log.Fields{"device-id": mm.deviceID})
1828 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001829 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001830 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001831 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001832 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001833 if mm.GetdeviceDeletionInProgress() {
1834 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1835 return nil
1836 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001837 atLeastOneDeleteFailure = true
1838 } else {
1839 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1840 break inner3
1841 }
1842 }
1843 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1844 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001845 }
1846 }
1847 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001848 for _, entityID := range copyOfEntityIDs {
1849 inner4:
1850 // retry L2PmDeleteAttempts times to delete the instance of PM
1851 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001852 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1853 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001854 if err != nil {
1855 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001856 log.Fields{"device-id": mm.deviceID})
1857 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001858 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001859 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001860 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001861 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001862 if mm.GetdeviceDeletionInProgress() {
1863 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1864 return nil
1865 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001866 atLeastOneDeleteFailure = true
1867 } else {
1868 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1869 break inner4
1870 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001871 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001872 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1873 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1874 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001875 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001876 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001877 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001878 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001879 // If we could not completely clean up the PM ME then just give up.
1880 if atLeastOneDeleteFailure {
1881 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001882 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001883 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001884 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001885 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1886 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1887 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001888 mm.GroupMetricMap[n].Enabled = false
1889 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001890 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001891 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001892 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001893 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1894 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001895 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001896 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1897 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001898 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 +00001899 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001900 }
1901 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001902 mm.OnuMetricsManagerLock.RLock()
1903 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1904 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001905 // Does not matter we send success or failure here.
1906 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1907 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001908 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1909 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001910 }
1911 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001912 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001913}
1914
1915// ** L2 PM FSM Handlers end **
1916
1917// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001918func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001919 if mm.GetdeviceDeletionInProgress() {
1920 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1921 return nil
1922 }
1923
1924 if !mm.GetOmciProcessingStatus() {
1925 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})
1926 return fmt.Errorf("omci-resp-processor-not-running")
1927 }
1928
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001929 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1930 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001931 return err
1932 }
1933
1934 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001935 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1936 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1937 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001938 case syncTimeRes := <-mm.syncTimeResponseChan:
1939 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001940 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001941 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001942 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001943 return nil
1944 }
1945}
1946
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001947func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001948 var mEnt *me.ManagedEntity
1949 var omciErr me.OmciErrors
1950 var classID me.ClassID
1951 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001952 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001953 meParam := me.ParamData{EntityID: entityID}
1954 if upstream {
1955 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001956 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001957 return nil
1958 }
1959 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1960 } else {
1961 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001962 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001963 return nil
1964 }
1965 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
1966 }
1967
Girish Gowdrae0140f02021-02-02 16:55:09 -08001968 intervalEndTime := -1
1969 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001970 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
1971 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001972 }
1973
1974 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
1975 ethPMHistData["class_id"] = float32(classID)
1976 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
1977 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
1978 ethPMHistData["parent_entity_id"] = float32(entityID)
1979 if upstream {
1980 ethPMHistData["upstream"] = float32(1)
1981 } else {
1982 ethPMHistData["upstream"] = float32(0)
1983 }
1984
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001985 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001986
Girish Gowdrae0140f02021-02-02 16:55:09 -08001987 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001988 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001989 return &metricInfo
1990}
1991
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001992func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001993 var mEnt *me.ManagedEntity
1994 var omciErr me.OmciErrors
1995 var classID me.ClassID
1996 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001997 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001998 meParam := me.ParamData{EntityID: entityID}
1999 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002000 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002001 return nil
2002 }
2003 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
2004
Girish Gowdrae0140f02021-02-02 16:55:09 -08002005 intervalEndTime := -1
2006 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002007 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
2008 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002009 }
2010
2011 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2012 ethUniHistData["class_id"] = float32(classID)
2013 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
2014
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002015 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002016
Girish Gowdrae0140f02021-02-02 16:55:09 -08002017 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002018 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002019 return &metricInfo
2020}
2021
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002022func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002023 var mEnt *me.ManagedEntity
2024 var omciErr me.OmciErrors
2025 var classID me.ClassID
2026 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002027 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002028 meParam := me.ParamData{EntityID: entityID}
2029 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002030 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002031 return nil
2032 }
2033 classID = me.FecPerformanceMonitoringHistoryDataClassID
2034
2035 intervalEndTime := -1
2036 fecHistData := make(map[string]float32)
2037 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
2038 return nil
2039 }
2040
2041 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2042 fecHistData["class_id"] = float32(classID)
2043 fecHistData["interval_end_time"] = float32(intervalEndTime)
2044
2045 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2046
2047 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002048 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002049 return &metricInfo
2050}
2051
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002052func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002053 var mEnt *me.ManagedEntity
2054 var omciErr me.OmciErrors
2055 var classID me.ClassID
2056 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002057 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002058 meParam := me.ParamData{EntityID: entityID}
2059 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002060 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002061 return nil
2062 }
2063 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2064
2065 intervalEndTime := -1
2066 gemHistData := make(map[string]float32)
2067 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
2068 return nil
2069 }
2070
2071 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2072 gemHistData["class_id"] = float32(classID)
2073 gemHistData["interval_end_time"] = float32(intervalEndTime)
2074
2075 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2076
2077 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002078 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002079 return &metricInfo
2080}
2081
Girish Gowdrae0140f02021-02-02 16:55:09 -08002082// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002083func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002084 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002085 upstream := false
2086 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2087 upstream = true
2088 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002089 // 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 +00002090 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002091 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2092 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002093 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002094 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2095 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002096 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002097 go func(p_pmFsm *cmn.AdapterFsm) {
2098 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002099 }(pmFsm)
2100 return err
2101 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002102 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002103 }
2104 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002105 select {
2106 case meAttributes = <-mm.l2PmChan:
2107 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002108 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2109 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002110 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002111 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002112 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002113 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002114 }
2115 // 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 -08002116 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002117 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002118 }
2119 }
2120 for k := range EthernetBridgeHistory {
2121 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2122 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2123 if _, ok := ethPMHistData[k]; !ok {
2124 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002125 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002126 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002127 ethPMHistData[k] = float32(val.(uint16))
2128 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002129 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002130 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002131 ethPMHistData[k] = float32(val.(uint32))
2132 }
2133 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002134 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002135 ethPMHistData[k] = float32(val.(uint32))
2136 }
2137 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002138 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002139 ethPMHistData[k] = float32(val.(uint32))
2140 }
2141 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002142 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002143 ethPMHistData[k] = float32(val.(uint32))
2144 }
2145 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002146 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002147 ethPMHistData[k] = float32(val.(uint32))
2148 }
2149 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002150 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002151 ethPMHistData[k] = float32(val.(uint32))
2152 }
2153 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002154 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002155 ethPMHistData[k] = float32(val.(uint32))
2156 }
2157 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002158 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002159 ethPMHistData[k] = float32(val.(uint32))
2160 }
2161 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002162 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002163 ethPMHistData[k] = float32(val.(uint32))
2164 }
2165 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002166 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002167 ethPMHistData[k] = float32(val.(uint32))
2168 }
2169 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002170 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002171 ethPMHistData[k] = float32(val.(uint32))
2172 }
2173 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002174 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002175 ethPMHistData[k] = float32(val.(uint32))
2176 }
2177 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002178 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002179 ethPMHistData[k] = float32(val.(uint32))
2180 }
2181 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002182 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002183 ethPMHistData[k] = float32(val.(uint32))
2184 }
2185 default:
2186 // do nothing
2187 }
2188 }
2189 }
2190 return nil
2191}
2192
2193// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002194func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002195 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002196 // 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 +03002197 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2198 requestedAttributes["IntervalEndTime"] = 0
2199 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002200 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2201 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002202 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002203 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2204 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2205 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002206 }
2207 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002208 select {
2209 case meAttributes = <-mm.l2PmChan:
2210 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002211 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2212 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002213 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002214 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002215 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002216 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002217 }
2218 // 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 -08002219 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002220 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002221 }
2222 }
2223 for k := range EthernetUniHistory {
2224 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2225 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2226 if _, ok := ethPMUniHistData[k]; !ok {
2227 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002228 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002229 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002230 ethPMUniHistData[k] = float32(val.(uint16))
2231 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002232 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002233 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002234 ethPMUniHistData[k] = float32(val.(uint32))
2235 }
2236 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002237 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002238 ethPMUniHistData[k] = float32(val.(uint32))
2239 }
2240 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002241 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002242 ethPMUniHistData[k] = float32(val.(uint32))
2243 }
2244 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002245 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002246 ethPMUniHistData[k] = float32(val.(uint32))
2247 }
2248 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002249 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002250 ethPMUniHistData[k] = float32(val.(uint32))
2251 }
2252 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002253 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002254 ethPMUniHistData[k] = float32(val.(uint32))
2255 }
2256 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002257 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002258 ethPMUniHistData[k] = float32(val.(uint32))
2259 }
2260 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002261 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002262 ethPMUniHistData[k] = float32(val.(uint32))
2263 }
2264 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002265 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002266 ethPMUniHistData[k] = float32(val.(uint32))
2267 }
2268 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002269 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002270 ethPMUniHistData[k] = float32(val.(uint32))
2271 }
2272 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002273 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002274 ethPMUniHistData[k] = float32(val.(uint32))
2275 }
2276 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002277 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002278 ethPMUniHistData[k] = float32(val.(uint32))
2279 }
2280 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002281 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002282 ethPMUniHistData[k] = float32(val.(uint32))
2283 }
2284 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002285 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002286 ethPMUniHistData[k] = float32(val.(uint32))
2287 }
2288 default:
2289 // do nothing
2290 }
2291 }
2292 }
2293 return nil
2294}
2295
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002296// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002297func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002298 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002299 // 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 +00002300 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2301 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002302 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002303 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2304 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002305 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002306 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2307 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2308 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002309 }
2310 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002311 select {
2312 case meAttributes = <-mm.l2PmChan:
2313 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002314 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2315 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002316 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002317 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002318 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002319 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002320 }
2321 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2322 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002323 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002324 }
2325 }
2326 for k := range FecHistory {
2327 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2328 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2329 if _, ok := fecHistData[k]; !ok {
2330 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002331 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002332 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002333 fecHistData[k] = float32(val.(uint16))
2334 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002335 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002336 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002337 fecHistData[k] = float32(val.(uint32))
2338 }
2339 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002340 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002341 fecHistData[k] = float32(val.(uint32))
2342 }
2343 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002344 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002345 fecHistData[k] = float32(val.(uint32))
2346 }
2347 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002348 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002349 fecHistData[k] = float32(val.(uint32))
2350 }
2351 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002352 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002353 fecHistData[k] = float32(val.(uint16))
2354 }
2355 default:
2356 // do nothing
2357 }
2358 }
2359 }
2360 return nil
2361}
2362
2363// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002364func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002365 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002366 // 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 +00002367 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2368 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002369 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002370 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes,
2371 mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002372 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002373 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2374 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2375 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002376 }
2377 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002378 select {
2379 case meAttributes = <-mm.l2PmChan:
2380 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002381 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2382 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002383 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002384 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002385 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002386 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002387 }
2388 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2389 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002390 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002391 }
2392 }
2393 for k := range GemPortHistory {
2394 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2395 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2396 if _, ok := gemPortHistData[k]; !ok {
2397 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002398 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002399 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002400 gemPortHistData[k] = float32(val.(uint16))
2401 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002402 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002403 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002404 gemPortHistData[k] = float32(val.(uint32))
2405 }
2406 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002407 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002408 gemPortHistData[k] = float32(val.(uint32))
2409 }
2410 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002411 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002412 gemPortHistData[k] = float32(val.(uint64))
2413 }
2414 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002415 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002416 gemPortHistData[k] = float32(val.(uint64))
2417 }
2418 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002419 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002420 gemPortHistData[k] = float32(val.(uint32))
2421 }
2422 default:
2423 // do nothing
2424 }
2425 }
2426 }
2427 return nil
2428}
2429
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002430func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002431 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2432 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002433 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2434 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 -08002435 }
2436 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2437 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002438 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2439 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 -08002440 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002441 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002442 switch msgObj.EntityClass {
2443 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2444 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002445 me.EthernetPerformanceMonitoringHistoryDataClassID,
2446 me.FecPerformanceMonitoringHistoryDataClassID,
2447 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002448 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2449 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2450 mm.l2PmCreateOrDeleteResponseChan <- true
2451 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002452 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002453 mm.l2PmCreateOrDeleteResponseChan <- false
2454 }
2455 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302456 case me.EthernetFrameExtendedPmClassID,
2457 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302458 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302459 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002460 default:
2461 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002462 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002463 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002464 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002465}
2466
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002467func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002468 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2469 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002470 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2471 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 -08002472 }
2473 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2474 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002475 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2476 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 -08002477 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002478 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002479 switch msgObj.EntityClass {
2480 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2481 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002482 me.EthernetPerformanceMonitoringHistoryDataClassID,
2483 me.FecPerformanceMonitoringHistoryDataClassID,
2484 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002485 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2486 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2487 mm.l2PmCreateOrDeleteResponseChan <- true
2488 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002489 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002490 mm.l2PmCreateOrDeleteResponseChan <- false
2491 }
2492 return nil
2493 default:
2494 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002495 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002496 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002497 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002498}
2499
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002500func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002501 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002502 for {
2503 select {
2504 case <-time.After(L2PmCollectionInterval * time.Second):
2505 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002506 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2507 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002508 }
2509 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002510 case <-mm.StopTicks:
2511 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002512 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002513 return
2514 }
2515 }
2516}
2517
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002518func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002519 // Publish metrics if it is valid
2520 if metricInfoSlice != nil {
2521 mm.publishMetrics(ctx, metricInfoSlice)
2522 } else {
2523 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2524 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002525 mm.OnuMetricsManagerLock.Lock()
2526 mm.GroupMetricMap[metricName].collectAttempts++
2527 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002528 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2529 }
2530 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002531 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2532 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002533 }
2534}
2535
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002536func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002537 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2538 var grpFunc groupMetricPopulateFunc
2539 switch classID {
2540 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2541 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2542 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2543 grpFunc = mm.populateEthernetUniHistoryMetrics
2544 case me.FecPerformanceMonitoringHistoryDataClassID:
2545 grpFunc = mm.populateFecHistoryMetrics
2546 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2547 grpFunc = mm.populateGemPortMetrics
2548 default:
2549 return fmt.Errorf("unknown-classid-%v", classID)
2550 }
2551
2552 size := 0
2553 requestedAttributes := make(me.AttributeValueMap)
2554 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002555 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2556 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2557 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2558 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2559 continue
2560 }
Holger Hildebrandtd930cb22022-06-17 09:24:50 +00002561 if v.Size+size <= mm.maxL2PMGetPayLoadSize {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002562 requestedAttributes[v.Name] = v.DefValue
2563 size = v.Size + size
2564 } else { // We exceeded the allow omci get size
2565 // Let's collect the attributes via get now and collect remaining in the next iteration
2566 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2567 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002568 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002569 return err
2570 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002571 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002572 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2573 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002574 }
2575 }
2576 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002577 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2578 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002579 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002580 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002581 }
2582 return nil
2583}
2584
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002585func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002586 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002587 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2588 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2589 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002590
2591 raisedTs := time.Now().Unix()
2592 mmd := voltha.MetricMetaData{
2593 Title: title,
2594 Ts: float64(raisedTs),
2595 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002596 DeviceId: mm.deviceID,
2597 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2598 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002599 }
2600
2601 // create slice of metrics given that there could be more than one VEIP instance
2602 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2603 return metricInfo
2604}
2605
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002606func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002607 valid := false
2608 if *intervalEndTime == -1 { // first time
2609 // Update the interval end time
2610 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2611 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2612 valid = true
2613 }
2614 } else {
2615 var currIntervalEndTime int
2616 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2617 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2618 }
2619 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2620 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002621 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002622 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2623 } else {
2624 valid = true
2625 }
2626 }
2627 return valid
2628}
2629
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002630func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002631 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002632 if !mm.GetOmciProcessingStatus() {
2633 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})
2634 return false
2635 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002636 select {
2637 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002638 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002639 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002640 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002641 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002642 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002643 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002644 }
2645 return false
2646}
2647
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002648func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002649 var pmConfigSlice []*voltha.PmConfig
2650 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002651 pmConfigSlice = append(pmConfigSlice,
2652 &voltha.PmConfig{
2653 Name: k,
2654 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002655 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002656 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002657 }
2658 groupMetric := voltha.PmGroupConfig{
2659 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002660 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002661 GroupFreq: grpFreq,
2662 Metrics: pmConfigSlice,
2663 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002664 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002665
2666}
2667
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002668func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2669 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2670 if mm.PAdaptFsm == nil {
2671 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2672 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002673 return fmt.Errorf("nil-adapter-fsm")
2674 }
2675 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002676 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2677 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002678 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002679 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2680 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2681 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2682 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2683 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2684 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2685 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2686 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2687 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002688 },
2689 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002690 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2691 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2692 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2693 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2694 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2695 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2696 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2697 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002698 },
2699 )
2700 return nil
2701}
2702
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002703func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2704 mm.pDeviceHandler.InitPmConfigs()
2705 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2706 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2707 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2708 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002709
2710 // Populate group metrics.
2711 // Lets populate irrespective of GroupMetricEnabled is true or not.
2712 // The group metrics collection will decided on this flag later
2713
2714 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2715 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2716
2717 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2718 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2719
2720 // classical l2 pm counter start
2721
2722 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2723 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2724
2725 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2726 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2727
2728 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2729 FecHistoryEnabled, FecHistoryFrequency)
2730
2731 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2732 GemPortHistoryEnabled, GemPortHistoryFrequency)
2733
2734 // classical l2 pm counter end
2735
2736 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2737}
2738
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002739func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002740 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002741 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2742 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002743 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002744 Enabled: g.Enabled,
2745 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002746 }
2747 switch g.GroupName {
2748 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002749 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002750 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002751 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002752 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002753 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2754 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002755 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002756 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2757 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002758 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002759 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2760 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002761 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002762 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2763 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002764 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002765 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002766 }
2767 }
2768
2769 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002770 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2771 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002772 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002773 Enabled: m.Enabled,
2774 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002775 }
2776 switch m.Name {
2777 // None exist as of now. Add when available.
2778 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002779 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002780 }
2781 }
2782}
2783
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002784// AddGemPortForPerfMonitoring - TODO: add comment
2785func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2786 mm.OnuMetricsManagerLock.Lock()
2787 defer mm.OnuMetricsManagerLock.Unlock()
2788 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002789 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002790 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002791 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002792 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002793
2794 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2795 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2796 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2797 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2798 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002799
2800 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002801 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2802 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002803 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002804 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002805 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002806 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002807 }
2808 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002809}
2810
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002811// RemoveGemPortForPerfMonitoring - TODO: add comment
2812func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2813 mm.OnuMetricsManagerLock.Lock()
2814 defer mm.OnuMetricsManagerLock.Unlock()
2815 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2816 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002817 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002818 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002819
2820 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2821 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2822 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2823 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2824 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002825
2826 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002827 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2828 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002829 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002830 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002831 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002832 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002833 }
2834 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002835}
2836
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002837func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2838 if mm.pDeviceHandler.GetOnuTP() != nil {
2839 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002840 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002841 for _, v := range gemPortInstIDs {
2842 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002843 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002844 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002845 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002846 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002847 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002848 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002849 }
2850}
2851
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002852func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2853 if mm.pDeviceHandler.GetOnuTP() != nil {
2854 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002855 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002856 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002857 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002858 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002859 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002860 }
2861 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002862 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002863 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002864}
2865
2866// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002867func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2868 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002869 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002870 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2871 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002872 }
2873 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002874 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002875 group.pmMEData = &pmMEData{}
2876 Value, err := mm.pmKvStore.Get(ctx, groupName)
2877 if err == nil {
2878 if Value != nil {
2879 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002880 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002881 tmpBytes, _ := kvstore.ToByte(Value.Value)
2882
2883 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002884 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2885 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 -08002886 continue
2887 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002888 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002889 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002890 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002891 continue
2892 }
2893 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002894 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2895 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 -08002896 continue
2897 }
2898 }
2899 if len(errorsList) > 0 {
2900 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2901 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002902 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002903 return nil
2904}
2905
2906// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2907// the data must be available in cache.
2908// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002909func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2910 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002911 return grp.pmMEData, nil
2912 }
2913 // Data not in cache, try to fetch from kv store.
2914 data := &pmMEData{}
2915 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002916 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2917 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002918 }
2919 Value, err := mm.pmKvStore.Get(ctx, groupName)
2920 if err == nil {
2921 if Value != nil {
2922 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002923 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002924 tmpBytes, _ := kvstore.ToByte(Value.Value)
2925
2926 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002927 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002928 return data, err
2929 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002930 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002931 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002932 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002933 return data, err
2934 }
2935 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002936 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002937 return data, err
2938 }
2939
2940 return data, nil
2941}
2942
2943// 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 +00002944func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2945 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2946 mm.OnuMetricsManagerLock.Lock()
2947 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002948
2949 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002950 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2951 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002952 }
2953
2954 pmMEData, err := mm.getPmData(ctx, groupName)
2955 if err != nil || pmMEData == nil {
2956 // error already logged in called function.
2957 return err
2958 }
2959 switch pmAction {
2960 case cPmAdd:
2961 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
2962 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2963 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2964 case cPmAdded:
2965 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
2966 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2967 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2968 case cPmRemove:
2969 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
2970 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2971 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2972 case cPmRemoved:
2973 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2974 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2975 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2976 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002977 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
2978 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 -08002979 }
2980 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002981 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08002982
2983 Value, err := json.Marshal(*pmMEData)
2984 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002985 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
2986 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002987 return err
2988 }
2989 // Update back to kv store
2990 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002991 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
2992 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002993 return err
2994 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002995 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
2996 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08002997
2998 return nil
2999}
3000
3001// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003002func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
3003 mm.OnuMetricsManagerLock.Lock()
3004 defer mm.OnuMetricsManagerLock.Unlock()
3005 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003006 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003007 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3008 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003009 }
3010
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003011 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08003012 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003013 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08003014 // do not abort this procedure. continue to delete next group.
3015 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003016 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08003017 }
3018 }
3019
3020 return nil
3021}
3022
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003023// ClearAllPmData clears all PM data associated with the device from KV store
3024func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3025 mm.OnuMetricsManagerLock.Lock()
3026 defer mm.OnuMetricsManagerLock.Unlock()
3027 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003028 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003029 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3030 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003031 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003032 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003033 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003034 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003035 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003036 value = err
3037 // do not abort this procedure - continue to delete next group.
3038 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003039 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003040 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003041 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003042 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003043 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003044 }
3045 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003046}
3047
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003048func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3049 mm.OnuMetricsManagerLock.Lock()
3050 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003051 mm.omciProcessingActive = status
3052}
3053
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003054// updateTickGenerationStatus - TODO: add comment
3055func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3056 mm.OnuMetricsManagerLock.Lock()
3057 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003058 mm.tickGenerationActive = status
3059}
3060
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003061// GetOmciProcessingStatus - TODO: add comment
3062func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3063 mm.OnuMetricsManagerLock.RLock()
3064 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003065 return mm.omciProcessingActive
3066}
3067
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003068// GetTickGenerationStatus - TODO: add comment
3069func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3070 mm.OnuMetricsManagerLock.RLock()
3071 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003072 return mm.tickGenerationActive
3073}
3074
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003075func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003076 for _, ele := range slice {
3077 if ele == n {
3078 return slice
3079 }
3080 }
3081 return append(slice, n)
3082}
3083
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003084func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003085 for i, ele := range slice {
3086 if ele == n {
3087 return append(slice[:i], slice[i+1:]...)
3088 }
3089 }
3090 return slice
3091}
3092
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003093func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003094 for _, ele := range slice {
3095 if ele == n {
3096 return slice
3097 }
3098 }
3099 return append(slice, n)
3100}
3101
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003102func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003103 for i, ele := range slice {
3104 if ele == n {
3105 return append(slice[:i], slice[i+1:]...)
3106 }
3107 }
3108 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003109}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303110
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003111func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303112 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3113 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003114 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003115 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003116 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303117 Value, err := mm.extPmKvStore.Get(ctx, key)
3118 if err == nil {
3119 if Value != nil {
3120 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003121 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303122 tmpBytes, _ := kvstore.ToByte(Value.Value)
3123
3124 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003125 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303126 return false, err
3127 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003128 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303129 // We have found the data from db, no need to get through omci get message.
3130 mm.supportedEthernetFrameExtendedPMClass = data
3131 return true, nil
3132 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003133 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303134 return false, nil
3135 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003136 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303137 return false, err
3138}
3139
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003140func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303141 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 -07003142 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3143 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})
3144 return false, fmt.Errorf("omci-processor-shutdown")
3145 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303146 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303147 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303148 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003149 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303150 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3151 if resp == me.Success || resp == me.InstanceExists {
3152 return true, nil
3153 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3154 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3155 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3156 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003157 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 +05303158 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3159 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003160 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303161 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003162 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303163 }
3164 return false, fmt.Errorf("timeout-while-waiting-for-response")
3165}
3166
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003167func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303168 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303169 // 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 +05303170 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003171 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303172 var entityID uint16
3173 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003174 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303175 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003176 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303177 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303178 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303179 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303180 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303181
3182 inner1:
3183 // retry ExtendedPmCreateAttempts times to create the instance of PM
3184 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003185 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3186 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3187 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303188 if err != nil {
3189 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003190 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303191 return false, err
3192 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303193 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3194 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303195 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303196 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303197 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303198 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303199 }
3200 break inner1
3201 } else if err != nil {
3202 if !supported {
3203 // Need to return immediately
3204 return false, err
3205 }
3206 //In case of failure, go for a retry
3207 }
3208 }
3209 if cnt == ExtendedPmCreateAttempts {
3210 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3211 return true, fmt.Errorf("unable-to-create-me")
3212 }
3213 }
3214 }
3215 return true, nil
3216}
3217
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003218func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3219 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003220 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003221 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303222 // check if we get the supported type me for ethernet frame extended pm class id
3223 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3224 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3225 }
3226 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3227 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003228 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303229 }
3230 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003231 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303232 }
3233}
3234
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003235func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303236 mm.onuEthernetFrameExtendedPmLock.Lock()
3237 mm.isDeviceReadyToCollectExtendedPmStats = true
3238 mm.onuEthernetFrameExtendedPmLock.Unlock()
3239}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003240
Himani Chawlaee10b542021-09-20 16:46:40 +05303241// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003242func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303243 //get the type of extended frame pm me supported by onu first
3244 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3245 if err != nil {
3246 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3247 return
3248 }
3249 if exist {
3250 // we have the me type, go ahead with the me type supported.
3251 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003252 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303253 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3254 return
3255 }
3256 mm.setAllExtPmMeCreatedFlag()
3257 return
3258 }
3259 // First try with 64 bit me
3260 // we have the me type, go ahead with the me type supported.
3261 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3262 if err != nil && !supported64Bit {
3263 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003264 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303265 "supported": supported64Bit})
3266 // Then Try with 32 bit type
3267 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003268 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303269 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3270 } else if supported32Bit {
3271 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3272 mm.putExtPmMeKvStore(ctx)
3273 mm.setAllExtPmMeCreatedFlag()
3274 }
3275 } else if err == nil && supported64Bit {
3276 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3277 mm.putExtPmMeKvStore(ctx)
3278 mm.setAllExtPmMeCreatedFlag()
3279 }
3280}
3281
Himani Chawlaee10b542021-09-20 16:46:40 +05303282func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3283 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3284 uniPortEntityID := entityID
3285 if upstream {
3286 uniPortEntityID = entityID - 0x100
3287 }
3288 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3289 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3290 mm.pDeviceHandler.GetOmciTimeout(), true,
3291 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3292 if err != nil {
3293 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3294 log.Fields{"device-id": mm.deviceID})
3295 return extension.GetValueResponse_INTERNAL_ERROR, err
3296 }
3297
3298 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3299 return extension.GetValueResponse_REASON_UNDEFINED, nil
3300 }
3301 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3302}
3303
3304func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3305 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 -07003306 if !mm.GetOmciProcessingStatus() {
3307 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})
3308 return false
3309 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303310 select {
3311 case resp := <-mm.extendedPMMeResponseChan:
3312 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3313 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3314 if resp == me.Success {
3315 return true
3316 }
3317 return false
3318 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3319 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3320 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3321 }
3322 return false
3323}
3324
3325func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3326 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3327 className := "EthernetFrameExtendedPm64Bit"
3328 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3329 className = "EthernetFrameExtendedPm"
3330 }
3331 // Reset the counters if option is specified
3332 for entityID := range upstreamEntityMap {
3333 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3334 true)
3335 if err != nil {
3336 return errReason, err
3337 }
3338 }
3339
3340 for entityID := range downstreamEntityMap {
3341 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3342 true)
3343 if err != nil {
3344 return errReason, err
3345 }
3346 }
3347 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3348 // device itself.
3349 // Unset the reset bit if option is specified
3350 for entityID := range upstreamEntityMap {
3351 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3352 false)
3353 if err != nil {
3354 return errReason, err
3355 }
3356 }
3357
3358 for entityID := range downstreamEntityMap {
3359 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3360 false)
3361 if err != nil {
3362 return errReason, err
3363 }
3364 }
3365 return extension.GetValueResponse_REASON_UNDEFINED, nil
3366}
3367
3368func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3369 mm.onuEthernetFrameExtendedPmLock.Lock()
3370 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3371 mm.isEthernetFrameExtendedPmOperationOngoing = val
3372}
3373
3374func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3375 mm.onuEthernetFrameExtendedPmLock.Lock()
3376 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3377 return mm.isEthernetFrameExtendedPmOperationOngoing
3378}
3379
3380// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3381func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3382 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3383 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3384 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303385 return &extension.SingleGetValueResponse{
3386 Response: &extension.GetValueResponse{
3387 Status: extension.GetValueResponse_ERROR,
3388 ErrReason: reason,
3389 },
3390 }
3391 }
3392 mm.onuEthernetFrameExtendedPmLock.RLock()
3393 if !mm.isDeviceReadyToCollectExtendedPmStats {
3394 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303395 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303396 }
3397 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303398
3399 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3400 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3401 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3402 }
3403 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3404 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3405
3406 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3407 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3408 if onuInfo.IsUniIndex != nil {
3409 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3410 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3411 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3412 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3413 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3414 break
3415 }
3416 }
3417 if len(downstreamEntityMap) == 0 {
3418 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3419 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3420 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3421 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3422 }
3423 } else {
3424 // make a copy of all downstream and upstream maps in the local ones
3425 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3426 upstreamEntityMap[entityID] = meEnt
3427 }
3428 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3429 downstreamEntityMap[entityID] = meEnt
3430 }
3431 }
3432 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3433 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3434 // Reset the metrics first for all required me's
3435 if onuInfo.Reset_ {
3436 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3437 if err != nil {
3438 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3439 log.Fields{"device-id": mm.deviceID})
3440 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3441 }
3442 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303443 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3444 var pmUpstream extension.OmciEthernetFrameExtendedPm
3445 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303446 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3447 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3448 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3449 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303450 if !onuInfo.Reset_ {
3451 for entityID, meEnt := range upstreamEntityMap {
3452 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3453 var receivedMask uint16
3454 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3455 if receivedMask == 0 {
3456 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303457 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3458 // It might be possible that still some downstream pms are supported and hence we need to continue
3459 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3460 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303461 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303462 // Aggregate the result for upstream
3463 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3464 } else {
3465 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303466 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303467 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303468
Himani Chawlaee10b542021-09-20 16:46:40 +05303469 for entityID, meEnt := range downstreamEntityMap {
3470 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3471 var receivedMask uint16
3472 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303473 if receivedMask == 0 {
3474 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3475 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3476 // Stop collecting downstream counters for other ME's.
3477 break
3478 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303479 // Aggregate the result for downstream
3480 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3481 } else {
3482 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3483 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303484 }
3485 }
3486 singleValResp := extension.SingleGetValueResponse{
3487 Response: &extension.GetValueResponse{
3488 Status: extension.GetValueResponse_OK,
3489 Response: &extension.GetValueResponse_OnuCounters{
3490 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303491 Upstream: &pmUpstream,
3492 Downstream: &pmDownstream,
3493 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303494 },
3495 },
3496 },
3497 }
3498 return &singleValResp
3499}
3500
Himani Chawlaee10b542021-09-20 16:46:40 +05303501func (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 +05303502 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003503 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 +05303504
3505 classID = mm.supportedEthernetFrameExtendedPMClass
3506 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3507 if classID == me.EthernetFrameExtendedPmClassID {
3508 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3509 }
3510 ethPMData := make(map[string]uint64)
3511 var sumReceivedMask uint16
3512 for mask := range attributeMaskList {
3513 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3514 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003515 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303516 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303517 }
3518 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3519 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3520 //populate all counters as failure and return
3521 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3522 break
3523 }
3524 }
3525 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303526 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303527}
3528
3529// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003530func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303531 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3532 var meAttributes me.AttributeValueMap
3533 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003534 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303535 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003536 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303537 return extension.GetValueResponse_INTERNAL_ERROR, err
3538 }
3539 select {
3540 case meAttributes = <-mm.extendedPmMeChan:
3541 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003542 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3543 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303544 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003545 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303546 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3547 }
3548 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3549 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3550 *sumReceivedMask += mask
3551 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3552 } else {
3553 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3554 *sumReceivedMask += mask
3555 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3556 }
3557
3558 return extension.GetValueResponse_REASON_UNDEFINED, nil
3559}
3560
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003561func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303562 sourceMap := maskToEthernetFrameExtendedPM64Bit
3563 errorCounterValue := UnsupportedCounterValue64bit
3564 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3565 sourceMap = maskToEthernetFrameExtendedPM32Bit
3566 errorCounterValue = UnsupportedCounterValue32bit
3567 }
3568 for _, value := range sourceMap {
3569 for _, k := range value {
3570 if _, ok := ethFrameExtPMData[k]; !ok {
3571 ethFrameExtPMData[k] = errorCounterValue
3572 }
3573 }
3574 }
3575}
3576
3577// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003578func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303579 receivedMask := uint16(0)
3580 switch requestedAttributesMask {
3581 case 0x3F00:
3582 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3583 if _, ok := ethFrameExtPMData[k]; !ok {
3584 switch k {
3585 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003586 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303587 ethFrameExtPMData[k] = uint64(val.(uint32))
3588 receivedMask |= 0x2000
3589 } else if !ok {
3590 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3591 }
3592 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003593 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303594 ethFrameExtPMData[k] = uint64(val.(uint32))
3595 receivedMask |= 0x1000
3596 } else if !ok {
3597 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3598 }
3599 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003600 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303601 ethFrameExtPMData[k] = uint64(val.(uint32))
3602 receivedMask |= 0x800
3603 } else if !ok {
3604 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3605 }
3606 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003607 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303608 ethFrameExtPMData[k] = uint64(val.(uint32))
3609 receivedMask |= 0x400
3610 } else if !ok {
3611 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3612 }
3613 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003614 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303615 ethFrameExtPMData[k] = uint64(val.(uint32))
3616 receivedMask |= 0x200
3617 } else if !ok {
3618 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3619 }
3620 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003621 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303622 ethFrameExtPMData[k] = uint64(val.(uint32))
3623 receivedMask |= 0x100
3624 } else if !ok {
3625 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3626 }
3627 default:
3628 //do nothing
3629 }
3630 }
3631 }
3632 case 0x00FC:
3633 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3634 if _, ok := ethFrameExtPMData[k]; !ok {
3635 switch k {
3636 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003637 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303638 ethFrameExtPMData[k] = uint64(val.(uint32))
3639 receivedMask |= 0x80
3640 } else if !ok {
3641 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3642 }
3643 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003644 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303645 ethFrameExtPMData[k] = uint64(val.(uint32))
3646 receivedMask |= 0x40
3647 } else if !ok {
3648 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3649 }
3650 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003651 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303652 ethFrameExtPMData[k] = uint64(val.(uint32))
3653 receivedMask |= 0x20
3654 } else if !ok {
3655 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3656 }
3657 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003658 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303659 ethFrameExtPMData[k] = uint64(val.(uint32))
3660 receivedMask |= 0x10
3661 } else if !ok {
3662 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3663 }
3664 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003665 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303666 ethFrameExtPMData[k] = uint64(val.(uint32))
3667 receivedMask |= 0x8
3668 } else if !ok {
3669 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3670 }
3671 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003672 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303673 ethFrameExtPMData[k] = uint64(val.(uint32))
3674 receivedMask |= 0x4
3675 } else if !ok {
3676 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3677 }
3678 default:
3679 //do nothing
3680 }
3681 }
3682 }
3683 case 0x0003:
3684 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3685 if _, ok := ethFrameExtPMData[k]; !ok {
3686 switch k {
3687 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003688 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303689 ethFrameExtPMData[k] = uint64(val.(uint32))
3690 receivedMask |= 0x2
3691 } else if !ok {
3692 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3693 }
3694 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003695 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303696 ethFrameExtPMData[k] = uint64(val.(uint32))
3697 receivedMask |= 0x1
3698 } else if !ok {
3699 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3700 }
3701 default:
3702 //do nothing
3703 }
3704 }
3705 }
3706 default:
3707 //do nothing
3708 }
3709 return receivedMask
3710}
3711
3712// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003713func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303714 receivedMask := uint16(0)
3715 switch requestedAttributesMask {
3716 case 0x3800:
3717 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3718 if _, ok := ethFrameExtPMData[k]; !ok {
3719 switch k {
3720 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003721 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303722 ethFrameExtPMData[k] = val.(uint64)
3723 receivedMask |= 0x2000
3724 } else if !ok {
3725 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3726 }
3727 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003728 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303729 ethFrameExtPMData[k] = val.(uint64)
3730 receivedMask |= 0x1000
3731 } else if !ok {
3732 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3733 }
3734 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003735 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303736 ethFrameExtPMData[k] = val.(uint64)
3737 receivedMask |= 0x800
3738 } else if !ok {
3739 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3740 }
3741 }
3742 }
3743 }
3744 case 0x0700:
3745 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3746 if _, ok := ethFrameExtPMData[k]; !ok {
3747 switch k {
3748 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003749 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303750 ethFrameExtPMData[k] = val.(uint64)
3751 receivedMask |= 0x400
3752 } else if !ok {
3753 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3754 }
3755 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003756 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303757 ethFrameExtPMData[k] = val.(uint64)
3758 receivedMask |= 0x200
3759 } else if !ok {
3760 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3761 }
3762 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003763 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303764 ethFrameExtPMData[k] = val.(uint64)
3765 receivedMask |= 0x100
3766 } else if !ok {
3767 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3768 }
3769 }
3770 }
3771 }
3772 case 0x00E0:
3773 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3774 if _, ok := ethFrameExtPMData[k]; !ok {
3775 switch k {
3776 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003777 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303778 ethFrameExtPMData[k] = val.(uint64)
3779 receivedMask |= 0x80
3780 } else if !ok {
3781 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3782 }
3783 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003784 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303785 ethFrameExtPMData[k] = val.(uint64)
3786 receivedMask |= 0x40
3787 } else if !ok {
3788 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3789 }
3790 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003791 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303792 ethFrameExtPMData[k] = val.(uint64)
3793 receivedMask |= 0x20
3794 } else if !ok {
3795 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3796 }
3797 }
3798 }
3799 }
3800 case 0x001C:
3801 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3802 if _, ok := ethFrameExtPMData[k]; !ok {
3803 switch k {
3804 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003805 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303806 ethFrameExtPMData[k] = val.(uint64)
3807 receivedMask |= 0x10
3808 } else if !ok {
3809 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3810 }
3811 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003812 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303813 ethFrameExtPMData[k] = val.(uint64)
3814 receivedMask |= 0x8
3815 } else if !ok {
3816 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3817 }
3818 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003819 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303820 ethFrameExtPMData[k] = val.(uint64)
3821 receivedMask |= 0x4
3822 } else if !ok {
3823 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3824 }
3825 default:
3826 //do nothing
3827 }
3828 }
3829 }
3830 case 0x0003:
3831 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3832 if _, ok := ethFrameExtPMData[k]; !ok {
3833 switch k {
3834 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003835 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303836 ethFrameExtPMData[k] = val.(uint64)
3837 receivedMask |= 0x2
3838 } else if !ok {
3839 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3840 }
3841 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003842 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303843 ethFrameExtPMData[k] = val.(uint64)
3844 receivedMask |= 0x1
3845 } else if !ok {
3846 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3847 }
3848 default:
3849 //do nothing
3850 }
3851 }
3852 }
3853 }
3854 return receivedMask
3855}
3856
Himani Chawlaee10b542021-09-20 16:46:40 +05303857func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3858 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303859 errorCounterValue := UnsupportedCounterValue64bit
3860 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3861 errorCounterValue = UnsupportedCounterValue32bit
3862 }
3863 var pmDataOut extension.OmciEthernetFrameExtendedPm
3864 if aggregate {
3865 if pmData.DropEvents != errorCounterValue {
3866 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3867 } else {
3868 pmDataOut.DropEvents = pmData.DropEvents
3869 }
3870 if pmData.Octets != errorCounterValue {
3871 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3872 } else {
3873 pmDataOut.Octets = pmData.Octets
3874 }
3875 if pmData.Frames != errorCounterValue {
3876 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3877 } else {
3878 pmDataOut.Frames = pmData.Frames
3879 }
3880 if pmData.BroadcastFrames != errorCounterValue {
3881 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3882 } else {
3883 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3884 }
3885 if pmData.MulticastFrames != errorCounterValue {
3886 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3887 } else {
3888 pmDataOut.MulticastFrames = pmData.MulticastFrames
3889 }
3890 if pmData.CrcErroredFrames != errorCounterValue {
3891 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3892 } else {
3893 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3894 }
3895 if pmData.UndersizeFrames != errorCounterValue {
3896 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3897 } else {
3898 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3899 }
3900 if pmData.OversizeFrames != errorCounterValue {
3901 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3902 } else {
3903 pmDataOut.OversizeFrames = pmData.OversizeFrames
3904 }
3905 if pmData.Frames_64Octets != errorCounterValue {
3906 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3907 } else {
3908 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3909 }
3910 if pmData.Frames_65To_127Octets != errorCounterValue {
3911 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3912 } else {
3913 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3914 }
3915 if pmData.Frames_128To_255Octets != errorCounterValue {
3916 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3917 } else {
3918 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3919 }
3920 if pmData.Frames_256To_511Octets != errorCounterValue {
3921 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3922 } else {
3923 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3924 }
3925 if pmData.Frames_512To_1023Octets != errorCounterValue {
3926 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3927 } else {
3928 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3929 }
3930 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3931 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3932 } else {
3933 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3934 }
3935 } else {
3936 pmDataOut.DropEvents = pmDataIn["drop_events"]
3937 pmDataOut.Octets = pmDataIn["octets"]
3938 pmDataOut.Frames = pmDataIn["frames"]
3939 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3940 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3941 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3942 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3943 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3944 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3945 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3946 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3947 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3948 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3949 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3950 }
3951 return pmDataOut
3952}
3953
Himani Chawlaee10b542021-09-20 16:46:40 +05303954func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303955 controlBlock := make([]uint16, 8)
3956 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3957 controlBlock[0] = 0
3958 // Next two bytes are for the parent class ID
3959 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3960 // Next two bytes are for the parent me instance id
3961 controlBlock[2] = entityID
3962 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05303963 if reset {
3964 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
3965 } else {
3966 controlBlock[3] = 0
3967 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303968 // Next two bytes are for tca disable
3969 controlBlock[4] = 0x4000 //tca global disable
3970 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
3971 if upstream {
3972 controlBlock[5] = 1 << 0
3973 } else {
3974 controlBlock[5] = (1 << 0) | (1 << 1)
3975 }
3976 // Next two bytes are for tci - does not matter here
3977 controlBlock[6] = 0
3978 // Next two bytes are for reserved bits - does not matter here
3979 controlBlock[7] = 0
3980 return controlBlock
3981}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003982
Girish Gowdraabcceb12022-04-13 23:35:22 -07003983// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
3984func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
3985 mm.OnuMetricsManagerLock.RLock()
3986 defer mm.OnuMetricsManagerLock.RUnlock()
3987 return mm.deviceDeletionInProgress
3988}
3989
3990// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
3991func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
3992 mm.OnuMetricsManagerLock.Lock()
3993 defer mm.OnuMetricsManagerLock.Unlock()
3994 mm.deviceDeletionInProgress = true
3995}
3996
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003997// PrepareForGarbageCollection - remove references to prepare for garbage collection
3998func (mm *OnuMetricsManager) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
Girish Gowdra8feabf82022-05-11 16:39:16 -07003999 currState := L2PmStNull
4000 if mm.PAdaptFsm != nil && mm.PAdaptFsm.PFsm != nil {
4001 currState = mm.PAdaptFsm.PFsm.Current()
4002 }
4003 if currState == L2PmStNull {
4004 logger.Infow(ctx, "pm fsm already stopped, safe to garbage collect", log.Fields{"device-id": mm.deviceID})
4005 mm.pDeviceHandler = nil
4006 mm.pOnuDeviceEntry = nil
4007 mm.GarbageCollectionComplete <- true
4008 return
4009 }
4010 logger.Debugw(ctx, "prepare for garbage collection - no action, garbage collection done when PM FSM is stopped",
4011 log.Fields{"device-id": aDeviceID, "curr-fsm-state": currState})
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00004012}