blob: 4f439ea68c767e1048d7115c14e2e1907530df9c [file] [log] [blame]
Girish Gowdrae09a6202021-01-12 18:10:59 -08001/*
2 * Copyright 2021-present Open Networking Foundation
3
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</