blob: 242e38c31e54fb6796ad9b50b6630aca3e2f8aa2 [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"
mpagenko836a1fd2021-11-01 16:12:42 +000029 "github.com/opencord/omci-lib-go/v2"
30 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.
Himani Chawla43f95ff2021-06-03 00:24:12 +0530213 MaxL2PMGetPayLoadSize = 24
214 MaxEthernetFrameExtPmPayloadSize = 25
Girish Gowdrae0140f02021-02-02 16:55:09 -0800215)
216
217// EthernetUniHistoryName specific constants
218const (
219 EthernetBridgeHistoryName = "Ethernet_Bridge_Port_History"
220 EthernetBridgeHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
221 EthernetBridgeHistoryFrequency = L2PmCollectionInterval
222)
223
224// EthernetBridgeHistory specific constants
225const (
226 EthernetUniHistoryName = "Ethernet_UNI_History"
227 EthernetUniHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
228 EthernetUniHistoryFrequency = L2PmCollectionInterval
229)
230
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800231// FecHistory specific constants
232const (
233 FecHistoryName = "FEC_History"
234 FecHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
235 FecHistoryFrequency = L2PmCollectionInterval
236)
237
238// GemPortHistory specific constants
239const (
240 GemPortHistoryName = "GEM_Port_History"
241 GemPortHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
242 GemPortHistoryFrequency = L2PmCollectionInterval
243)
244
Holger Hildebrandt60652202021-11-02 11:09:36 +0000245// CPmKvStorePrefixBase - kv store base path of ONU specific PM data
246const CPmKvStorePrefixBase = cmn.CBasePathOnuKVStore + "/pm-data" // <some-base-path>/openonu/pm-data
247
Girish Gowdra0e533642021-03-02 22:02:51 -0800248// KV Store related constants
249const (
Holger Hildebrandt60652202021-11-02 11:09:36 +0000250 cPmKvStorePrefix = CPmKvStorePrefixBase + "/%s" // <some-base-path>/openonu/pm-data/<onu-device-id>
Himani Chawla43f95ff2021-06-03 00:24:12 +0530251 cPmAdd = "add"
252 cPmAdded = "added"
253 cPmRemove = "remove"
254 cPmRemoved = "removed"
255 cExtPmKvStorePrefix = "%s/omci_me" //<some-base-path>/omci_me/<onu_vendor>/<onu_equipment_id>/<onu_sw_version>
Girish Gowdra0e533642021-03-02 22:02:51 -0800256)
257
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800258// Defines the type for generic metric population function
259type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
260
Girish Gowdrae0140f02021-02-02 16:55:09 -0800261// *** Classical L2 PM Counters end ***
262
Girish Gowdra0e533642021-03-02 22:02:51 -0800263type pmMEData struct {
264 InstancesActive []uint16 `json:"instances_active"` // list of active ME instance IDs for the group
265 InstancesToDelete []uint16 `json:"instances_to_delete"` // list of ME instance IDs marked for deletion for the group
266 InstancesToAdd []uint16 `json:"instances_to_add"` // list of ME instance IDs marked for addition for the group
267}
268
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800269type groupMetric struct {
270 groupName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000271 Enabled bool
272 Frequency uint32 // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800273 metricMap map[string]voltha.PmConfig_PmType
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000274 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
275 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdrae0140f02021-02-02 16:55:09 -0800276 collectAttempts uint32 // number of attempts to collect L2 PM data
Girish Gowdra0e533642021-03-02 22:02:51 -0800277 pmMEData *pmMEData
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800278}
279
280type standaloneMetric struct {
281 metricName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000282 Enabled bool
283 Frequency uint32 // valid only if FrequencyOverride is enabled.
284 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800285}
286
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000287// OnuMetricsManager - TODO: add comment
288type OnuMetricsManager struct {
289 deviceID string
290 pDeviceHandler cmn.IdeviceHandler
291 pOnuDeviceEntry cmn.IonuDeviceEntry
292 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800293
Himani Chawlaee10b542021-09-20 16:46:40 +0530294 opticalMetricsChan chan me.AttributeValueMap
295 uniStatusMetricsChan chan me.AttributeValueMap
296 l2PmChan chan me.AttributeValueMap
297 extendedPmMeChan chan me.AttributeValueMap
298 syncTimeResponseChan chan bool // true is success, false is fail
299 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
300 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -0800301
302 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
303 l2PmToDelete []string // list of L2 PMs to delete
304 l2PmToAdd []string // list of L2 PM to add
Girish Gowdrae09a6202021-01-12 18:10:59 -0800305
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000306 GroupMetricMap map[string]*groupMetric
307 StandaloneMetricMap map[string]*standaloneMetric
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800308
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000309 StopProcessingOmciResponses chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700310 omciProcessingActive bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800311
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000312 StopTicks chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700313 tickGenerationActive bool
Girish Gowdrae0140f02021-02-02 16:55:09 -0800314
Girish Gowdraabcceb12022-04-13 23:35:22 -0700315 deviceDeletionInProgress bool
316 GarbageCollectionComplete chan bool
317
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000318 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800319
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000320 OnuMetricsManagerLock sync.RWMutex
Girish Gowdra0e533642021-03-02 22:02:51 -0800321
322 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530323
324 supportedEthernetFrameExtendedPMClass me.ClassID
Himani Chawlac77d5372021-07-12 15:42:26 +0530325 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
326 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530327 extPmKvStore *db.Backend
328 onuEthernetFrameExtendedPmLock sync.RWMutex
329 isDeviceReadyToCollectExtendedPmStats bool
Himani Chawlaee10b542021-09-20 16:46:40 +0530330 isEthernetFrameExtendedPmOperationOngoing bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800331}
332
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000333// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800334// The metrics manager module is responsible for configuration and management of individual and group metrics.
335// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
336// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
337// the collection interval configurable.
338// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
339// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000340func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800341
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000342 var metricsManager OnuMetricsManager
343 metricsManager.deviceID = dh.GetDeviceID()
344 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800345 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000346 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800347
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000348 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800349 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
350 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800351 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530352 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800353
354 metricsManager.syncTimeResponseChan = make(chan bool)
355 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530356 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800357
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000358 metricsManager.StopProcessingOmciResponses = make(chan bool)
359 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800360
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000361 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
362 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800363
Himani Chawlac77d5372021-07-12 15:42:26 +0530364 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
365 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530366
Girish Gowdraabcceb12022-04-13 23:35:22 -0700367 // make this a buffered channel so that the sender is not blocked for any reason if there is no listener
368 metricsManager.GarbageCollectionComplete = make(chan bool, 1)
369
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000370 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 -0800371 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800372 }
373
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800374 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800375
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800376 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800377 return nil
378 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800379
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800380 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000381 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800382
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000383 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
384 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800385 if metricsManager.pmKvStore == nil {
386 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000387 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800388 return nil
389 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700390 // restore data from KV store
391 if err := metricsManager.restorePmData(ctx); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000392 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700393 // we continue given that it does not effect the actual services for the ONU,
394 // but there may be some negative effect on PM collection (there may be some mismatch in
395 // the actual PM config and what is present on the device).
396 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800397
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000398 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
399 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530400 if metricsManager.extPmKvStore == nil {
401 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000402 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530403 return nil
404 }
405
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000406 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800407 return &metricsManager
408}
409
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000410// InitializeMetricCollectionTime - TODO: add comment
411func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
412 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
413 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
414 mm.OnuMetricsManagerLock.Lock()
415 defer mm.OnuMetricsManagerLock.Unlock()
416 for _, v := range mm.GroupMetricMap {
417 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
418 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800419 }
420 }
421
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000422 for _, v := range mm.StandaloneMetricMap {
423 if v.Enabled {
424 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800425 }
426 }
427 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000428 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
429 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800430 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000431 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800432}
433
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000434// UpdateDefaultFrequency - TODO: add comment
435func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800436 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800437 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800438 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
439 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
440 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000441 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
442 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
443 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
444 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 -0800445 return nil
446}
447
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000448// UpdateGroupFreq - TODO: add comment
449func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800450 var newGroupFreq uint32
451 found := false
452 groupSliceIdx := 0
453 var group *voltha.PmGroupConfig
454 for groupSliceIdx, group = range pmConfigs.Groups {
455 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800456 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
457 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
458 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
459 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800460 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800461 newGroupFreq = group.GroupFreq
462 found = true
463 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800464 }
465 }
466 // if not found update group freq and next collection interval for the group
467 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000468 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800469 return fmt.Errorf("group-name-not-found-%v", aGroupName)
470 }
471
472 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000473 mm.OnuMetricsManagerLock.Lock()
474 defer mm.OnuMetricsManagerLock.Unlock()
475 for k, v := range mm.GroupMetricMap {
476 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
477 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800478 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000479 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800480 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000481 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800482 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000483 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800484 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800485 }
486 }
487 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000488 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800489 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
490 }
491 return nil
492}
493
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000494// UpdateMetricFreq - TODO: add comment
495func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800496 var newMetricFreq uint32
497 found := false
498 metricSliceIdx := 0
499 var metric *voltha.PmConfig
500 for metricSliceIdx, metric = range pmConfigs.Metrics {
501 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800502 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
503 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
504 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
505 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800506 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800507 newMetricFreq = metric.SampleFreq
508 found = true
509 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800510 }
511 }
512 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000513 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800514 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
515 }
516
517 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000518 mm.OnuMetricsManagerLock.Lock()
519 defer mm.OnuMetricsManagerLock.Unlock()
520 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800521 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000522 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800523 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000524 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800525 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000526 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800527 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000528 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800529 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800530 }
531 }
532 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000533 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800534 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
535 }
536 return nil
537}
538
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000539// UpdateGroupSupport - TODO: add comment
540func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800541 groupSliceIdx := 0
542 var group *voltha.PmGroupConfig
543
544 for groupSliceIdx, group = range pmConfigs.Groups {
545 if group.GroupName == aGroupName {
546 break
547 }
548 }
549 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000550 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800551 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
552 }
553
554 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000555 mm.OnuMetricsManagerLock.Lock()
556 defer mm.OnuMetricsManagerLock.Unlock()
557 for k, v := range mm.GroupMetricMap {
558 if k == aGroupName && v.Enabled != group.Enabled {
559 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
560 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800561 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000562 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800563 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800564 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800565 // 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 -0800566 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
567
568 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
569 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
570 // take further action
571 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800572 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800573 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000574 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
575 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800576 }
577 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000578 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800579 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800580 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800581 // 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 -0800582 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
583
584 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
585 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
586 // take further action
587 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800588 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800589 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800590 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800591 }
592 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000593 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800594 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000595 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800596 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000597 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 -0800598 }
599 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800600 }
601 }
602
603 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000604 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800605 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
606 }
607 return nil
608}
609
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000610// UpdateMetricSupport - TODO: add comment
611func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800612 metricSliceIdx := 0
613 var metric *voltha.PmConfig
614
615 for metricSliceIdx, metric = range pmConfigs.Metrics {
616 if metric.Name == aMetricName {
617 break
618 }
619 }
620
621 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000622 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800623 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
624 }
625
626 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000627 mm.OnuMetricsManagerLock.Lock()
628 defer mm.OnuMetricsManagerLock.Unlock()
629 for k, v := range mm.StandaloneMetricMap {
630 if k == aMetricName && v.Enabled != metric.Enabled {
631 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
632 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800633 // 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 +0000634 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
635 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800636 }
637 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000638 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 -0800639 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800640 }
641 }
642 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000643 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800644 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
645 }
646 return nil
647}
648
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000649// CollectAllGroupAndStandaloneMetrics - TODO: add comment
650func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
651 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800652 go mm.collectAllGroupMetrics(ctx)
653 } else {
654 go mm.collectAllStandaloneMetrics(ctx)
655 }
656}
657
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000658func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800659 go func() {
660 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300661 metricInfo, err := mm.collectOpticalMetrics(ctx)
662 if err != nil {
663 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000664 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300665 return
666 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800667 if metricInfo != nil {
668 mm.publishMetrics(ctx, metricInfo)
669 }
670 }()
671
672 go func() {
673 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300674 metricInfo, err := mm.collectUniStatusMetrics(ctx)
675 if err != nil {
676 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000677 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300678 return
679 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800680 if metricInfo != nil {
681 mm.publishMetrics(ctx, metricInfo)
682 }
683 }()
684
685 // Add more here
686}
687
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000688func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800689 // None exists as of now, add when available here
690}
691
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000692// CollectGroupMetric - TODO: add comment
693func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800694 switch groupName {
695 case OpticalPowerGroupMetricName:
696 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300697 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800698 mm.publishMetrics(ctx, mi)
699 }
700 }()
701 case UniStatusGroupMetricName:
702 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300703 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800704 mm.publishMetrics(ctx, mi)
705 }
706 }()
707 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000708 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800709 }
710}
711
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000712// CollectStandaloneMetric - TODO: add comment
713func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800714 switch metricName {
715 // None exist as of now, add when available
716 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000717 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800718 }
719}
720
721// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000722func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
723 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800724
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000725 mm.OnuMetricsManagerLock.RLock()
726 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
727 mm.OnuMetricsManagerLock.RUnlock()
728 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300729 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800730 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000731 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800732
Girish Gowdrae09a6202021-01-12 18:10:59 -0800733 var metricInfoSlice []*voltha.MetricInformation
734 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000735 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
736 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
737 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800738
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800739 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800740 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800741 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800742 Ts: float64(raisedTs),
743 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000744 DeviceId: mm.deviceID,
745 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
746 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800747 }
748
Girish Gowdrae09a6202021-01-12 18:10:59 -0800749 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000750 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800751loop:
752 for _, anigInstID := range anigInstKeys {
753 var meAttributes me.AttributeValueMap
754 opticalMetrics := make(map[string]float32)
755 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000756 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000757 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300758 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000759 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
760 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300761 return nil, err
762 }
763
764 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800765 select {
766 case meAttributes = <-mm.opticalMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000767 logger.Debugw(ctx, "received optical metrics", log.Fields{"device-id": mm.deviceID})
768 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
769 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 -0800770 // The metrics will be empty in this case
771 break loop
772 }
773 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800774 for k := range OpticalPowerGroupMetrics {
775 switch k {
776 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000777 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800778 opticalMetrics[k] = float32(val.(uint16))
779 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800780 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000781 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000782 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 -0800783 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800784 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000785 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; 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 Gowdrae09a6202021-01-12 18:10:59 -0800788 default:
789 // do nothing
790 }
791 }
792 }
793 // create slice of metrics given that there could be more than one ANI-G instance and
794 // optical metrics are collected per ANI-G instance
795 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
796 metricInfoSlice = append(metricInfoSlice, &metricInfo)
797 }
798
ozgecanetsiab36ed572021-04-01 10:38:48 +0300799 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800800}
801
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800802// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800803// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000804func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
805 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
806 mm.OnuMetricsManagerLock.RLock()
807 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
808 mm.OnuMetricsManagerLock.RUnlock()
809 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300810 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800811 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000812 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800813
Girish Gowdrae09a6202021-01-12 18:10:59 -0800814 var metricInfoSlice []*voltha.MetricInformation
815 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000816 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
817 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
818 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800819
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800820 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800821 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700822 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800823 Ts: float64(raisedTs),
824 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000825 DeviceId: mm.deviceID,
826 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
827 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800828 }
829
Girish Gowdrae09a6202021-01-12 18:10:59 -0800830 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000831 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800832loop1:
833 for _, unigInstID := range unigInstKeys {
834 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
835 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
836 unigMetrics := make(map[string]float32)
837 var meAttributes me.AttributeValueMap
838 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000839 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000840 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300841 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000842 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
843 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300844 return nil, err
845 }
846 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800847 // Wait for metrics or timeout
848 select {
849 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000850 logger.Debugw(ctx, "received uni-g metrics", log.Fields{"device-id": mm.deviceID})
851 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
852 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 -0800853 // The metrics could be empty in this case
854 break loop1
855 }
856 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800857 for k := range UniStatusGroupMetrics {
858 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800859 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000860 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800861 unigMetrics[k] = float32(val.(byte))
862 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800863 default:
864 // do nothing
865 }
866 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000867 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800868 entityID := val.(uint16)
869 unigMetrics["entity_id"] = float32(entityID)
870 // 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 +0000871 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
872 if uni.EntityID == entityID {
873 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700874 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800875 }
876 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800877 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700878 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800879
Girish Gowdrae09a6202021-01-12 18:10:59 -0800880 // create slice of metrics given that there could be more than one UNI-G instance
881 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
882 metricInfoSlice = append(metricInfoSlice, &metricInfo)
883 }
884 }
885
886 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000887 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800888loop2:
889 for _, pptpInstID := range pptpInstKeys {
890 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
891 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
892 var meAttributes me.AttributeValueMap
893 pptpMetrics := make(map[string]float32)
894
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000895 requestedAttributes := me.AttributeValueMap{
896 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
897 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
898 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
899 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
900 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300901 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000902 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
903 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300904 return nil, err
905 }
906 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800907 // Wait for metrics or timeout
908 select {
909 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000910 logger.Debugw(ctx, "received pptp metrics", log.Fields{"device-id": mm.deviceID})
911 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
912 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 -0800913 // The metrics could be empty in this case
914 break loop2
915 }
916
917 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800918 for k := range UniStatusGroupMetrics {
919 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700920 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000921 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800922 pptpMetrics[k] = float32(val.(byte))
923 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800924 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000925 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800926 pptpMetrics[k] = float32(val.(byte))
927 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800928 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000929 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800930 pptpMetrics[k] = float32(val.(byte))
931 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800932 default:
933 // do nothing
934 }
935 }
936 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000937 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800938 entityID := val.(uint16)
939 pptpMetrics["entity_id"] = float32(entityID)
940 // 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 +0000941 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
942 if uni.EntityID == entityID {
943 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700944 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800945 }
946 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800947 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700948 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800949
Girish Gowdrae09a6202021-01-12 18:10:59 -0800950 // create slice of metrics given that there could be more than one PPTP instance and
951 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
952 metricInfoSlice = append(metricInfoSlice, &metricInfo)
953 }
954
955 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000956 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800957loop3:
958 for _, veipInstID := range veipInstKeys {
959 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
960 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
961 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800962 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800963
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000964 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0, me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000965 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300966 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000967 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
968 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300969 return nil, err
970 }
971 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800972 // Wait for metrics or timeout
973 select {
974 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000975 logger.Debugw(ctx, "received veip metrics", log.Fields{"device-id": mm.deviceID})
976 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
977 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 -0800978 // The metrics could be empty in this case
979 break loop3
980 }
981
982 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800983 for k := range UniStatusGroupMetrics {
984 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800985 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000986 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800987 veipMetrics[k] = float32(val.(byte))
988 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800989 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000990 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800991 veipMetrics[k] = float32(val.(byte))
992 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800993 default:
994 // do nothing
995 }
996 }
997 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800998
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000999 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001000 entityID := val.(uint16)
1001 veipMetrics["entity_id"] = float32(entityID)
1002 // 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 +00001003 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1004 if uni.EntityID == entityID {
1005 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001006 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001007 }
1008 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001009 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001010 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001011
Girish Gowdrae09a6202021-01-12 18:10:59 -08001012 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001013 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001014 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1015 }
1016
ozgecanetsiab36ed572021-04-01 10:38:48 +03001017 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001018}
1019
1020// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001021func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001022 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001023 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001024 ke.SliceData = metricInfo
1025 ke.Type = voltha.KpiEventType_slice
1026 ke.Ts = float64(ts)
1027
Himani Chawlaf9768882021-12-01 00:18:58 +05301028 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 +00001029 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001030 }
1031}
1032
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001033// ProcessOmciMessages - TODO: add comment
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001034func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context, waitForOmciProcessor *sync.WaitGroup) {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001035 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 -08001036 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001037 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001038 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001039 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001040 // is stopped - as a result of ONU going down.
1041 mm.flushMetricCollectionChannels(ctx)
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001042 mm.updateOmciProcessingStatus(true)
Girish Gowdraf7d82d02022-04-26 16:18:35 -07001043 waitForOmciProcessor.Done()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001044 for {
1045 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001046 case <-mm.StopProcessingOmciResponses: // stop this routine
1047 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 -07001048 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001049 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001050 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001051 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001052 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001053 continue
1054 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001055 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001056
1057 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001058 case cmn.OMCI:
1059 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001060 mm.handleOmciMessage(ctx, msg)
1061 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001062 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001063 }
1064 }
1065 }
1066}
1067
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001068func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1069 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001070 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1071 switch msg.OmciMsg.MessageType {
1072 case omci.GetResponseType:
1073 //TODO: error handling
1074 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001075 case omci.SynchronizeTimeResponseType:
1076 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1077 case omci.CreateResponseType:
1078 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1079 case omci.DeleteResponseType:
1080 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301081 case omci.GetCurrentDataResponseType:
1082 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301083 case omci.SetResponseType:
1084 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001085 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001086 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001087
1088 }
1089}
1090
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001091func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001092 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1093 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001094 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1095 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001096 }
1097 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1098 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001099 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1100 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001101 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001102 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 -08001103 if msgObj.Result == me.Success {
1104 meAttributes := msgObj.Attributes
1105 switch msgObj.EntityClass {
1106 case me.AniGClassID:
1107 mm.opticalMetricsChan <- meAttributes
1108 return nil
1109 case me.UniGClassID:
1110 mm.uniStatusMetricsChan <- meAttributes
1111 return nil
1112 case me.PhysicalPathTerminationPointEthernetUniClassID:
1113 mm.uniStatusMetricsChan <- meAttributes
1114 return nil
1115 case me.VirtualEthernetInterfacePointClassID:
1116 mm.uniStatusMetricsChan <- meAttributes
1117 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001118 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1119 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001120 me.EthernetPerformanceMonitoringHistoryDataClassID,
1121 me.FecPerformanceMonitoringHistoryDataClassID,
1122 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001123 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301124 return nil
1125 case me.EthernetFrameExtendedPmClassID,
1126 me.EthernetFrameExtendedPm64BitClassID:
1127 mm.extendedPmMeChan <- meAttributes
1128 return nil
1129 default:
1130 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001131 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301132 }
1133 } else {
1134 meAttributes := msgObj.Attributes
1135 switch msgObj.EntityClass {
1136 case me.EthernetFrameExtendedPmClassID,
1137 me.EthernetFrameExtendedPm64BitClassID:
1138 // not all counters may be supported in which case we have seen some ONUs throwing
1139 // AttributeFailure error code, while correctly populating other counters it supports
1140 mm.extendedPmMeChan <- meAttributes
1141 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001142 default:
1143 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001144 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001145 }
1146 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001147 return fmt.Errorf("unhandled-omci-get-response-message")
1148}
1149
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001150func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301151 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1152 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001153 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1154 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301155 }
1156 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1157 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001158 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1159 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301160 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001161 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 +05301162 if msgObj.Result == me.Success {
1163 meAttributes := msgObj.Attributes
1164 switch msgObj.EntityClass {
1165 case me.EthernetFrameExtendedPmClassID,
1166 me.EthernetFrameExtendedPm64BitClassID:
1167 mm.extendedPmMeChan <- meAttributes
1168 return nil
1169 default:
1170 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001171 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301172 }
1173 } else {
1174 meAttributes := msgObj.Attributes
1175 switch msgObj.EntityClass {
1176 case me.EthernetFrameExtendedPmClassID,
1177 me.EthernetFrameExtendedPm64BitClassID:
1178 // not all counters may be supported in which case we have seen some ONUs throwing
1179 // AttributeFailure error code, while correctly populating other counters it supports
1180 mm.extendedPmMeChan <- meAttributes
1181 return nil
1182 default:
1183 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001184 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301185 }
1186 }
1187 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1188}
1189
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001190func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001191 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1192 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001193 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1194 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 -08001195 }
1196 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1197 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001198 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1199 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 -08001200 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001201 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001202 if msgObj.Result == me.Success {
1203 switch msgObj.EntityClass {
1204 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001205 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001206 mm.syncTimeResponseChan <- true
1207 return nil
1208 default:
1209 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001210 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001211 }
1212 }
1213 mm.syncTimeResponseChan <- false
1214 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1215 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001216}
1217
Himani Chawlaee10b542021-09-20 16:46:40 +05301218func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1219 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1220 if msgLayer == nil {
1221 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1222 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1223 }
1224 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1225 if !msgOk {
1226 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1227 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1228 }
1229 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1230 switch msgObj.EntityClass {
1231 case me.EthernetFrameExtendedPmClassID,
1232 me.EthernetFrameExtendedPm64BitClassID:
1233 mm.extendedPMMeResponseChan <- msgObj.Result
1234 return nil
1235 default:
1236 logger.Errorw(ctx, "unhandled omci set response message",
1237 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1238 }
1239 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1240}
1241
Girish Gowdrae09a6202021-01-12 18:10:59 -08001242// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001243func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001244 // flush commMetricsChan
1245 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001246 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001247 logger.Debug(ctx, "flushed common metrics channel")
1248 default:
1249 }
1250
1251 // flush opticalMetricsChan
1252 select {
1253 case <-mm.opticalMetricsChan:
1254 logger.Debug(ctx, "flushed optical metrics channel")
1255 default:
1256 }
1257
1258 // flush uniStatusMetricsChan
1259 select {
1260 case <-mm.uniStatusMetricsChan:
1261 logger.Debug(ctx, "flushed uni status metrics channel")
1262 default:
1263 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001264
1265 // flush syncTimeResponseChan
1266 select {
1267 case <-mm.syncTimeResponseChan:
1268 logger.Debug(ctx, "flushed sync time response channel")
1269 default:
1270 }
1271
1272 // flush l2PmChan
1273 select {
1274 case <-mm.l2PmChan:
1275 logger.Debug(ctx, "flushed L2 PM collection channel")
1276 default:
1277 }
1278
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001279 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001280 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001281 case <-mm.StopTicks:
1282 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001283 default:
1284 }
1285
1286}
1287
1288// ** L2 PM FSM Handlers start **
1289
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001290func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001291 if mm.GetdeviceDeletionInProgress() {
1292 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1293 return
1294 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001295
Girish Gowdrae0140f02021-02-02 16:55:09 -08001296 // Loop through all the group metrics
1297 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1298 // list of active L2 PM list then mark it for creation
1299 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1300 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001301 mm.OnuMetricsManagerLock.Lock()
1302 for n, g := range mm.GroupMetricMap {
1303 if g.IsL2PMCounter { // it is a l2 pm counter
1304 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001305 found := false
1306 inner1:
1307 for _, v := range mm.activeL2Pms {
1308 if v == n {
1309 found = true // metric already present in active l2 pm list
1310 break inner1
1311 }
1312 }
1313 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001314 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001315 }
1316 } else { // metric not enabled.
1317 found := false
1318 inner2:
1319 for _, v := range mm.activeL2Pms {
1320 if v == n {
1321 found = true // metric is found in active l2 pm list
1322 break inner2
1323 }
1324 }
1325 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001326 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001327 }
1328 }
1329 }
1330 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001331 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001332 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001333 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001334 go func() {
1335 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001336 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1337 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001338 }
1339 }()
1340}
1341
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001342func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001343 if mm.GetdeviceDeletionInProgress() {
1344 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1345 return
1346 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001347 // Sync time with the ONU to establish 15min boundary for PM collection.
1348 if err := mm.syncTime(ctx); err != nil {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001349 // device could be deleted while waiting on sync time response
1350 if mm.GetdeviceDeletionInProgress() {
1351 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1352 return
1353 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001354 go func() {
1355 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1356 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001357 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1358 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001359 }
1360 }()
1361 }
1362 // Initiate a tick generation routine every L2PmCollectionInterval
1363 go mm.generateTicks(ctx)
1364
1365 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001366 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1367 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001368 }
1369 }()
1370}
1371
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001372func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001373 // 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 +00001374 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001375 mm.activeL2Pms = nil
1376 mm.l2PmToAdd = nil
1377 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001378 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001379 // If the FSM was stopped, then clear PM data from KV store
1380 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001381 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001382 _ = mm.clearPmGroupData(ctx) // ignore error
1383 }
1384
Girish Gowdraabcceb12022-04-13 23:35:22 -07001385 if mm.GetdeviceDeletionInProgress() {
1386 mm.pDeviceHandler = nil
1387 mm.pOnuDeviceEntry = nil
1388 mm.GarbageCollectionComplete <- true
1389 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001390}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001391func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1392 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001393 if mm.GetdeviceDeletionInProgress() {
1394 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1395 return
1396 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001397
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001398 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001399 numOfPmToDelete := len(mm.l2PmToDelete)
1400 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001401 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001402
1403 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001404 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 -08001405 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001406 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1407 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001408 }
1409 }()
1410 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001411 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 -08001412 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001413 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1414 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001415 }
1416 }()
1417 }
1418}
1419
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001420func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1421 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07001422 if mm.GetdeviceDeletionInProgress() {
1423 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1424 return
1425 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001426 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001427 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001428 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1429 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001430 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001431
1432 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001433 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001434
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001435 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1436 mm.OnuMetricsManagerLock.RLock()
1437 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1438 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1439 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001440
Girish Gowdrae0140f02021-02-02 16:55:09 -08001441 switch n {
1442 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001443 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001444 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001445 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1446 metricInfoSlice = append(metricInfoSlice, metricInfo)
1447 }
1448 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1449 metricInfoSlice = append(metricInfoSlice, metricInfo)
1450 }
1451 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001452 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001453 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001454 for _, entityID := range copyOfEntityIDs {
1455 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1456 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001457 }
1458 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001459
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001460 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001461 for _, entityID := range copyOfEntityIDs {
1462 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001463 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001464 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001465 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001466 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001467 for _, entityID := range copyOfEntityIDs {
1468 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001469 metricInfoSlice = append(metricInfoSlice, metricInfo)
1470 }
1471 }
1472
Girish Gowdrae0140f02021-02-02 16:55:09 -08001473 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001474 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001475 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001476 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001477 }
1478 // Does not matter we send success or failure here.
1479 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1480 // we have not exceed max attempts to collect the PM data)
1481 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001482 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1483 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001484 }
1485 }()
1486}
1487
Girish Gowdra0e533642021-03-02 22:02:51 -08001488// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001489func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001490 if mm.GetdeviceDeletionInProgress() {
1491 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1492 return nil
1493 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001494 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001495 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001496 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1497 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001498 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001499
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001500 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001501 for _, n := range copyOfL2PmToAdd {
1502 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001503 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1504 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001505 switch n {
1506 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001507 // 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 +05301508 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001509 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001510 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001511 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001512 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1513 inner1:
1514 // retry L2PmCreateAttempts times to create the instance of PM
1515 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001516 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1517 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001518 if err != nil {
1519 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001520 log.Fields{"device-id": mm.deviceID})
1521 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001522 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001523 go func(p_pmFsm *cmn.AdapterFsm) {
1524 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001525 }(pPMFsm)
1526 }
1527 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001528 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001529 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001530 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1531 atLeastOneSuccess = true
1532 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1533 break inner1
1534 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001535 if mm.GetdeviceDeletionInProgress() {
1536 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1537 return nil
1538 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001539 }
1540 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1541 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001542 }
1543 }
1544 }
1545 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001546 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1547 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001548 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001549 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001550 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1551 inner2:
1552 // retry L2PmCreateAttempts times to create the instance of PM
1553 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001554 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1555 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001556 if err != nil {
1557 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001558 log.Fields{"device-id": mm.deviceID})
1559 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001560 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001561 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001562 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001563 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1564 atLeastOneSuccess = true
1565 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1566 break inner2
1567 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001568 if mm.GetdeviceDeletionInProgress() {
1569 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1570 return nil
1571 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001572 }
1573 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1574 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001575 }
1576 }
1577 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001578 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001579 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001580 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001581 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1582 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001583 if err != nil {
1584 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001585 log.Fields{"device-id": mm.deviceID})
1586 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001587 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001588 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001589 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001590 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1591 inner3:
1592 // retry L2PmCreateAttempts times to create the instance of PM
1593 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1594 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1595 atLeastOneSuccess = true
1596 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1597 break inner3
1598 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001599 if mm.GetdeviceDeletionInProgress() {
1600 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1601 return nil
1602 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001603 }
1604 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1605 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001606 }
1607 }
1608 case GemPortHistoryName:
1609
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001610 mm.OnuMetricsManagerLock.RLock()
1611 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1612 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1613 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001614
1615 if len(copyOfGemPortInstIDsToAdd) == 0 {
1616 // If there are no gemport history MEs to be created, just skip further processing
1617 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1618 // 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 +00001619 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001620 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001621 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001622 continue
1623 }
1624
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001625 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001626 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1627 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001628 if err != nil {
1629 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001630 log.Fields{"device-id": mm.deviceID})
1631 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001632 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001633 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001634 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001635 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1636 inner4:
1637 // retry L2PmCreateAttempts times to create the instance of PM
1638 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1639 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1640 atLeastOneSuccess = true
1641 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1642 break inner4
1643 }
Girish Gowdraabcceb12022-04-13 23:35:22 -07001644 if mm.GetdeviceDeletionInProgress() {
1645 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1646 return nil
1647 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001648 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001649 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1650 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1651 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001652 }
1653
Girish Gowdrae0140f02021-02-02 16:55:09 -08001654 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001655 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001656 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001657 // 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
1658 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001659 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001660 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001661 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1662 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001663 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001664 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1665 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001666 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 +00001667 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001668 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001669 // 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 -08001670 // 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 +00001671 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001672 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001673 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001674 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001675
Girish Gowdrae0140f02021-02-02 16:55:09 -08001676 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001677 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001678 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001679 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001680 }
1681 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001682 mm.OnuMetricsManagerLock.RLock()
1683 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1684 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001685 // Does not matter we send success or failure here.
1686 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1687 // we have not exceed max attempts to create the PM ME)
1688 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001689 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1690 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001691 }
1692 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001693 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001694}
1695
Girish Gowdra0e533642021-03-02 22:02:51 -08001696// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001697func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001698 if mm.GetdeviceDeletionInProgress() {
1699 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1700 return nil
1701 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001702 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001703 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001704 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1705 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001706 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001707
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001708 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001709 for _, n := range copyOfL2PmToDelete {
1710 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001711 cnt := 0
1712 atLeastOneDeleteFailure := false
1713
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001714 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1715 mm.OnuMetricsManagerLock.RLock()
1716 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1717 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1718 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001719
1720 if len(copyOfEntityIDs) == 0 {
1721 // 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 +00001722 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001723 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1724 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1725 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 +00001726 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001727 continue
1728 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001729 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001730 switch n {
1731 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001732 // 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 +05301733 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001734 for _, entityID := range copyOfEntityIDs {
1735 inner1:
1736 // retry L2PmDeleteAttempts times to delete the instance of PM
1737 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001738 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1739 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001740 if err != nil {
1741 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001742 log.Fields{"device-id": mm.deviceID})
1743 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001744 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001745 go func(p_pmFsm *cmn.AdapterFsm) {
1746 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001747 }(pPMFsm)
1748 }
1749 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001750 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001751 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001752 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1753 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001754 if mm.GetdeviceDeletionInProgress() {
1755 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1756 return nil
1757 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001758 atLeastOneDeleteFailure = true
1759 } else {
1760 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1761 break inner1
1762 }
1763 }
1764 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1765 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001766 }
1767 }
1768 }
1769 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001770 for _, entityID := range copyOfEntityIDs {
1771 inner2:
1772 // retry L2PmDeleteAttempts times to delete the instance of PM
1773 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001774 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1775 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001776 if err != nil {
1777 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001778 log.Fields{"device-id": mm.deviceID})
1779 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001780 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001781 go func(p_pmFsm *cmn.AdapterFsm) {
1782 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001783 }(pmFsm)
1784 return err
1785 }
1786 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001787 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001788 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001789 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001790 if mm.GetdeviceDeletionInProgress() {
1791 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1792 return nil
1793 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001794 atLeastOneDeleteFailure = true
1795 } else {
1796 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001797 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001798 }
1799 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001800 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1801 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1802 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001803 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001804 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001805 for _, entityID := range copyOfEntityIDs {
1806 inner3:
1807 // retry L2PmDeleteAttempts times to delete the instance of PM
1808 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001809 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1810 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001811 if err != nil {
1812 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001813 log.Fields{"device-id": mm.deviceID})
1814 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001815 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001816 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001817 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001818 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001819 if mm.GetdeviceDeletionInProgress() {
1820 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1821 return nil
1822 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001823 atLeastOneDeleteFailure = true
1824 } else {
1825 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1826 break inner3
1827 }
1828 }
1829 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1830 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001831 }
1832 }
1833 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001834 for _, entityID := range copyOfEntityIDs {
1835 inner4:
1836 // retry L2PmDeleteAttempts times to delete the instance of PM
1837 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001838 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1839 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001840 if err != nil {
1841 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001842 log.Fields{"device-id": mm.deviceID})
1843 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001844 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001845 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001846 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001847 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001848 if mm.GetdeviceDeletionInProgress() {
1849 logger.Debugw(ctx, "device deleted, no more pm processing", log.Fields{"deviceID": mm.deviceID})
1850 return nil
1851 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001852 atLeastOneDeleteFailure = true
1853 } else {
1854 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1855 break inner4
1856 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001857 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001858 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1859 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1860 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001861 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001862 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001863 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001864 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001865 // If we could not completely clean up the PM ME then just give up.
1866 if atLeastOneDeleteFailure {
1867 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001868 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001869 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001870 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001871 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1872 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1873 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001874 mm.GroupMetricMap[n].Enabled = false
1875 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001876 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001877 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001878 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001879 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1880 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001881 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001882 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1883 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001884 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 +00001885 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001886 }
1887 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001888 mm.OnuMetricsManagerLock.RLock()
1889 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1890 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001891 // Does not matter we send success or failure here.
1892 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1893 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001894 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1895 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001896 }
1897 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001898 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001899}
1900
1901// ** L2 PM FSM Handlers end **
1902
1903// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001904func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
Girish Gowdraabcceb12022-04-13 23:35:22 -07001905 if mm.GetdeviceDeletionInProgress() {
1906 logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
1907 return nil
1908 }
1909
1910 if !mm.GetOmciProcessingStatus() {
1911 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})
1912 return fmt.Errorf("omci-resp-processor-not-running")
1913 }
1914
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001915 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1916 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001917 return err
1918 }
1919
1920 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001921 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1922 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1923 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001924 case syncTimeRes := <-mm.syncTimeResponseChan:
1925 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001926 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001927 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001928 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001929 return nil
1930 }
1931}
1932
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001933func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001934 var mEnt *me.ManagedEntity
1935 var omciErr me.OmciErrors
1936 var classID me.ClassID
1937 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001938 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001939 meParam := me.ParamData{EntityID: entityID}
1940 if upstream {
1941 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001942 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001943 return nil
1944 }
1945 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1946 } else {
1947 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001948 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001949 return nil
1950 }
1951 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
1952 }
1953
Girish Gowdrae0140f02021-02-02 16:55:09 -08001954 intervalEndTime := -1
1955 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001956 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
1957 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001958 }
1959
1960 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
1961 ethPMHistData["class_id"] = float32(classID)
1962 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
1963 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
1964 ethPMHistData["parent_entity_id"] = float32(entityID)
1965 if upstream {
1966 ethPMHistData["upstream"] = float32(1)
1967 } else {
1968 ethPMHistData["upstream"] = float32(0)
1969 }
1970
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001971 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001972
Girish Gowdrae0140f02021-02-02 16:55:09 -08001973 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001974 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001975 return &metricInfo
1976}
1977
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001978func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001979 var mEnt *me.ManagedEntity
1980 var omciErr me.OmciErrors
1981 var classID me.ClassID
1982 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001983 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001984 meParam := me.ParamData{EntityID: entityID}
1985 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001986 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001987 return nil
1988 }
1989 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
1990
Girish Gowdrae0140f02021-02-02 16:55:09 -08001991 intervalEndTime := -1
1992 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001993 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
1994 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001995 }
1996
1997 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
1998 ethUniHistData["class_id"] = float32(classID)
1999 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
2000
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002001 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002002
Girish Gowdrae0140f02021-02-02 16:55:09 -08002003 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002004 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002005 return &metricInfo
2006}
2007
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002008func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002009 var mEnt *me.ManagedEntity
2010 var omciErr me.OmciErrors
2011 var classID me.ClassID
2012 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002013 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002014 meParam := me.ParamData{EntityID: entityID}
2015 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002016 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002017 return nil
2018 }
2019 classID = me.FecPerformanceMonitoringHistoryDataClassID
2020
2021 intervalEndTime := -1
2022 fecHistData := make(map[string]float32)
2023 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
2024 return nil
2025 }
2026
2027 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
2028 fecHistData["class_id"] = float32(classID)
2029 fecHistData["interval_end_time"] = float32(intervalEndTime)
2030
2031 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
2032
2033 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002034 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002035 return &metricInfo
2036}
2037
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002038func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002039 var mEnt *me.ManagedEntity
2040 var omciErr me.OmciErrors
2041 var classID me.ClassID
2042 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002043 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002044 meParam := me.ParamData{EntityID: entityID}
2045 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002046 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002047 return nil
2048 }
2049 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
2050
2051 intervalEndTime := -1
2052 gemHistData := make(map[string]float32)
2053 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
2054 return nil
2055 }
2056
2057 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
2058 gemHistData["class_id"] = float32(classID)
2059 gemHistData["interval_end_time"] = float32(intervalEndTime)
2060
2061 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
2062
2063 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002064 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002065 return &metricInfo
2066}
2067
Girish Gowdrae0140f02021-02-02 16:55:09 -08002068// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002069func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002070 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002071 upstream := false
2072 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
2073 upstream = true
2074 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002075 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002076 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002077 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002078 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002079 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2080 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002081 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002082 go func(p_pmFsm *cmn.AdapterFsm) {
2083 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002084 }(pmFsm)
2085 return err
2086 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002087 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002088 }
2089 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002090 select {
2091 case meAttributes = <-mm.l2PmChan:
2092 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002093 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2094 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002095 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002096 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002097 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002098 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002099 }
2100 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002101 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002102 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002103 }
2104 }
2105 for k := range EthernetBridgeHistory {
2106 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2107 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2108 if _, ok := ethPMHistData[k]; !ok {
2109 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002110 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002111 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002112 ethPMHistData[k] = float32(val.(uint16))
2113 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002114 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002115 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002116 ethPMHistData[k] = float32(val.(uint32))
2117 }
2118 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002119 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002120 ethPMHistData[k] = float32(val.(uint32))
2121 }
2122 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002123 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002124 ethPMHistData[k] = float32(val.(uint32))
2125 }
2126 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002127 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002128 ethPMHistData[k] = float32(val.(uint32))
2129 }
2130 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002131 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002132 ethPMHistData[k] = float32(val.(uint32))
2133 }
2134 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002135 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002136 ethPMHistData[k] = float32(val.(uint32))
2137 }
2138 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002139 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002140 ethPMHistData[k] = float32(val.(uint32))
2141 }
2142 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002143 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002144 ethPMHistData[k] = float32(val.(uint32))
2145 }
2146 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002147 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002148 ethPMHistData[k] = float32(val.(uint32))
2149 }
2150 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002151 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002152 ethPMHistData[k] = float32(val.(uint32))
2153 }
2154 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002155 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002156 ethPMHistData[k] = float32(val.(uint32))
2157 }
2158 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002159 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002160 ethPMHistData[k] = float32(val.(uint32))
2161 }
2162 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002163 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002164 ethPMHistData[k] = float32(val.(uint32))
2165 }
2166 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002167 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002168 ethPMHistData[k] = float32(val.(uint32))
2169 }
2170 default:
2171 // do nothing
2172 }
2173 }
2174 }
2175 return nil
2176}
2177
2178// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002179func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002180 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002181 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
ozgecanetsiab36ed572021-04-01 10:38:48 +03002182 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2183 requestedAttributes["IntervalEndTime"] = 0
2184 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002185 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002186 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002187 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2188 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2189 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002190 }
2191 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002192 select {
2193 case meAttributes = <-mm.l2PmChan:
2194 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002195 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2196 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002197 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002198 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002199 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002200 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002201 }
2202 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002203 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002204 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002205 }
2206 }
2207 for k := range EthernetUniHistory {
2208 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2209 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2210 if _, ok := ethPMUniHistData[k]; !ok {
2211 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002212 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002213 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002214 ethPMUniHistData[k] = float32(val.(uint16))
2215 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002216 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002217 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002218 ethPMUniHistData[k] = float32(val.(uint32))
2219 }
2220 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002221 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002222 ethPMUniHistData[k] = float32(val.(uint32))
2223 }
2224 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002225 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002226 ethPMUniHistData[k] = float32(val.(uint32))
2227 }
2228 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002229 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002230 ethPMUniHistData[k] = float32(val.(uint32))
2231 }
2232 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002233 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002234 ethPMUniHistData[k] = float32(val.(uint32))
2235 }
2236 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002237 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002238 ethPMUniHistData[k] = float32(val.(uint32))
2239 }
2240 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002241 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002242 ethPMUniHistData[k] = float32(val.(uint32))
2243 }
2244 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002245 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002246 ethPMUniHistData[k] = float32(val.(uint32))
2247 }
2248 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002249 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002250 ethPMUniHistData[k] = float32(val.(uint32))
2251 }
2252 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002253 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002254 ethPMUniHistData[k] = float32(val.(uint32))
2255 }
2256 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002257 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002258 ethPMUniHistData[k] = float32(val.(uint32))
2259 }
2260 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002261 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002262 ethPMUniHistData[k] = float32(val.(uint32))
2263 }
2264 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002265 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002266 ethPMUniHistData[k] = float32(val.(uint32))
2267 }
2268 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002269 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002270 ethPMUniHistData[k] = float32(val.(uint32))
2271 }
2272 default:
2273 // do nothing
2274 }
2275 }
2276 }
2277 return nil
2278}
2279
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002280// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002281func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002282 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002283 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002284 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2285 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002286 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002287 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002288 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002289 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2290 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2291 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002292 }
2293 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002294 select {
2295 case meAttributes = <-mm.l2PmChan:
2296 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002297 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2298 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002299 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002300 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002301 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002302 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002303 }
2304 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2305 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002306 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002307 }
2308 }
2309 for k := range FecHistory {
2310 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2311 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2312 if _, ok := fecHistData[k]; !ok {
2313 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002314 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002315 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002316 fecHistData[k] = float32(val.(uint16))
2317 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002318 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002319 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002320 fecHistData[k] = float32(val.(uint32))
2321 }
2322 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002323 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002324 fecHistData[k] = float32(val.(uint32))
2325 }
2326 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002327 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002328 fecHistData[k] = float32(val.(uint32))
2329 }
2330 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002331 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002332 fecHistData[k] = float32(val.(uint32))
2333 }
2334 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002335 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002336 fecHistData[k] = float32(val.(uint16))
2337 }
2338 default:
2339 // do nothing
2340 }
2341 }
2342 }
2343 return nil
2344}
2345
2346// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002347func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002348 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002349 // Insert "IntervalEndTime" is part of the requested attributes as we need this to compare the get responses when get request is multipart
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002350 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2351 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002352 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002353 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002354 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002355 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2356 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2357 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002358 }
2359 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002360 select {
2361 case meAttributes = <-mm.l2PmChan:
2362 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002363 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2364 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002365 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002366 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002367 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002368 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002369 }
2370 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2371 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002372 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002373 }
2374 }
2375 for k := range GemPortHistory {
2376 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2377 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2378 if _, ok := gemPortHistData[k]; !ok {
2379 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002380 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002381 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002382 gemPortHistData[k] = float32(val.(uint16))
2383 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002384 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002385 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002386 gemPortHistData[k] = float32(val.(uint32))
2387 }
2388 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002389 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002390 gemPortHistData[k] = float32(val.(uint32))
2391 }
2392 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002393 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002394 gemPortHistData[k] = float32(val.(uint64))
2395 }
2396 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002397 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002398 gemPortHistData[k] = float32(val.(uint64))
2399 }
2400 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002401 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002402 gemPortHistData[k] = float32(val.(uint32))
2403 }
2404 default:
2405 // do nothing
2406 }
2407 }
2408 }
2409 return nil
2410}
2411
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002412func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002413 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2414 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002415 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2416 return fmt.Errorf("omci Msg layer could not be detected for create response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002417 }
2418 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2419 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002420 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2421 return fmt.Errorf("omci Msg layer could not be assigned for delete response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002422 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002423 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002424 switch msgObj.EntityClass {
2425 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2426 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002427 me.EthernetPerformanceMonitoringHistoryDataClassID,
2428 me.FecPerformanceMonitoringHistoryDataClassID,
2429 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002430 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2431 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2432 mm.l2PmCreateOrDeleteResponseChan <- true
2433 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002434 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002435 mm.l2PmCreateOrDeleteResponseChan <- false
2436 }
2437 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302438 case me.EthernetFrameExtendedPmClassID,
2439 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302440 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302441 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002442 default:
2443 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002444 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002445 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002446 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002447}
2448
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002449func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002450 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2451 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002452 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2453 return fmt.Errorf("omci Msg layer could not be detected for create response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002454 }
2455 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2456 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002457 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2458 return fmt.Errorf("omci Msg layer could not be assigned for delete response - handling stopped: %s", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002459 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002460 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002461 switch msgObj.EntityClass {
2462 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2463 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002464 me.EthernetPerformanceMonitoringHistoryDataClassID,
2465 me.FecPerformanceMonitoringHistoryDataClassID,
2466 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002467 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2468 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2469 mm.l2PmCreateOrDeleteResponseChan <- true
2470 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002471 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002472 mm.l2PmCreateOrDeleteResponseChan <- false
2473 }
2474 return nil
2475 default:
2476 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002477 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002478 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002479 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002480}
2481
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002482func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002483 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002484 for {
2485 select {
2486 case <-time.After(L2PmCollectionInterval * time.Second):
2487 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002488 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2489 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002490 }
2491 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002492 case <-mm.StopTicks:
2493 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002494 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002495 return
2496 }
2497 }
2498}
2499
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002500func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002501 // Publish metrics if it is valid
2502 if metricInfoSlice != nil {
2503 mm.publishMetrics(ctx, metricInfoSlice)
2504 } else {
2505 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2506 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002507 mm.OnuMetricsManagerLock.Lock()
2508 mm.GroupMetricMap[metricName].collectAttempts++
2509 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002510 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2511 }
2512 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002513 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2514 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002515 }
2516}
2517
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002518func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002519 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2520 var grpFunc groupMetricPopulateFunc
2521 switch classID {
2522 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2523 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2524 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2525 grpFunc = mm.populateEthernetUniHistoryMetrics
2526 case me.FecPerformanceMonitoringHistoryDataClassID:
2527 grpFunc = mm.populateFecHistoryMetrics
2528 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2529 grpFunc = mm.populateGemPortMetrics
2530 default:
2531 return fmt.Errorf("unknown-classid-%v", classID)
2532 }
2533
2534 size := 0
2535 requestedAttributes := make(me.AttributeValueMap)
2536 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002537 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2538 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2539 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2540 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2541 continue
2542 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002543 if (v.Size + size) <= MaxL2PMGetPayLoadSize {
2544 requestedAttributes[v.Name] = v.DefValue
2545 size = v.Size + size
2546 } else { // We exceeded the allow omci get size
2547 // Let's collect the attributes via get now and collect remaining in the next iteration
2548 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2549 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002550 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002551 return err
2552 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002553 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002554 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2555 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002556 }
2557 }
2558 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002559 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2560 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002561 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002562 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002563 }
2564 return nil
2565}
2566
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002567func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002568 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002569 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2570 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2571 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002572
2573 raisedTs := time.Now().Unix()
2574 mmd := voltha.MetricMetaData{
2575 Title: title,
2576 Ts: float64(raisedTs),
2577 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002578 DeviceId: mm.deviceID,
2579 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2580 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002581 }
2582
2583 // create slice of metrics given that there could be more than one VEIP instance
2584 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2585 return metricInfo
2586}
2587
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002588func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002589 valid := false
2590 if *intervalEndTime == -1 { // first time
2591 // Update the interval end time
2592 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2593 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2594 valid = true
2595 }
2596 } else {
2597 var currIntervalEndTime int
2598 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2599 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2600 }
2601 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2602 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002603 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002604 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2605 } else {
2606 valid = true
2607 }
2608 }
2609 return valid
2610}
2611
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002612func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002613 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07002614 if !mm.GetOmciProcessingStatus() {
2615 logger.Errorw(ctx, "not waiting for omci resp, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
2616 return false
2617 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002618 select {
2619 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002620 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002621 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002622 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002623 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002624 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002625 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002626 }
2627 return false
2628}
2629
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002630func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002631 var pmConfigSlice []*voltha.PmConfig
2632 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002633 pmConfigSlice = append(pmConfigSlice,
2634 &voltha.PmConfig{
2635 Name: k,
2636 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002637 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002638 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002639 }
2640 groupMetric := voltha.PmGroupConfig{
2641 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002642 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002643 GroupFreq: grpFreq,
2644 Metrics: pmConfigSlice,
2645 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002646 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002647
2648}
2649
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002650func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2651 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2652 if mm.PAdaptFsm == nil {
2653 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2654 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002655 return fmt.Errorf("nil-adapter-fsm")
2656 }
2657 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002658 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2659 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002660 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002661 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2662 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2663 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2664 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2665 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2666 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2667 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2668 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2669 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002670 },
2671 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002672 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2673 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2674 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2675 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2676 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2677 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2678 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2679 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002680 },
2681 )
2682 return nil
2683}
2684
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002685func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2686 mm.pDeviceHandler.InitPmConfigs()
2687 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2688 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2689 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2690 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002691
2692 // Populate group metrics.
2693 // Lets populate irrespective of GroupMetricEnabled is true or not.
2694 // The group metrics collection will decided on this flag later
2695
2696 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2697 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2698
2699 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2700 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2701
2702 // classical l2 pm counter start
2703
2704 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2705 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2706
2707 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2708 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2709
2710 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2711 FecHistoryEnabled, FecHistoryFrequency)
2712
2713 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2714 GemPortHistoryEnabled, GemPortHistoryFrequency)
2715
2716 // classical l2 pm counter end
2717
2718 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2719}
2720
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002721func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002722 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002723 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2724 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002725 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002726 Enabled: g.Enabled,
2727 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002728 }
2729 switch g.GroupName {
2730 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002731 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002732 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002733 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002734 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002735 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2736 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002737 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002738 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2739 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002740 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002741 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2742 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002743 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002744 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2745 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002746 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002747 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002748 }
2749 }
2750
2751 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002752 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2753 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002754 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002755 Enabled: m.Enabled,
2756 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002757 }
2758 switch m.Name {
2759 // None exist as of now. Add when available.
2760 default:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002761 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002762 }
2763 }
2764}
2765
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002766// AddGemPortForPerfMonitoring - TODO: add comment
2767func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2768 mm.OnuMetricsManagerLock.Lock()
2769 defer mm.OnuMetricsManagerLock.Unlock()
2770 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002771 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002772 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002773 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002774 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002775
2776 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2777 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2778 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2779 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2780 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002781
2782 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002783 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2784 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002785 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002786 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002787 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002788 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002789 }
2790 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002791}
2792
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002793// RemoveGemPortForPerfMonitoring - TODO: add comment
2794func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2795 mm.OnuMetricsManagerLock.Lock()
2796 defer mm.OnuMetricsManagerLock.Unlock()
2797 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2798 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002799 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002800 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002801
2802 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2803 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2804 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2805 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2806 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002807
2808 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002809 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2810 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002811 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002812 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002813 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002814 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002815 }
2816 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002817}
2818
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002819func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2820 if mm.pDeviceHandler.GetOnuTP() != nil {
2821 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002822 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002823 for _, v := range gemPortInstIDs {
2824 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002825 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002826 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002827 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002828 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002829 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002830 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002831 }
2832}
2833
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002834func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2835 if mm.pDeviceHandler.GetOnuTP() != nil {
2836 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002837 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002838 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002839 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002840 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002841 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002842 }
2843 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002844 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002845 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002846}
2847
2848// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002849func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2850 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002851 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002852 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2853 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002854 }
2855 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002856 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002857 group.pmMEData = &pmMEData{}
2858 Value, err := mm.pmKvStore.Get(ctx, groupName)
2859 if err == nil {
2860 if Value != nil {
2861 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002862 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002863 tmpBytes, _ := kvstore.ToByte(Value.Value)
2864
2865 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002866 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2867 errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("unable-to-unmarshal-PM-data-%s-for-group-%s", mm.deviceID, groupName)))
Girish Gowdra0e533642021-03-02 22:02:51 -08002868 continue
2869 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002870 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002871 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002872 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002873 continue
2874 }
2875 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002876 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2877 errorsList = append(errorsList, fmt.Errorf(fmt.Sprintf("unable-to-read-from-KVstore-%s-for-group-%s", mm.deviceID, groupName)))
Girish Gowdra0e533642021-03-02 22:02:51 -08002878 continue
2879 }
2880 }
2881 if len(errorsList) > 0 {
2882 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2883 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002884 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002885 return nil
2886}
2887
2888// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2889// the data must be available in cache.
2890// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002891func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2892 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002893 return grp.pmMEData, nil
2894 }
2895 // Data not in cache, try to fetch from kv store.
2896 data := &pmMEData{}
2897 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002898 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2899 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002900 }
2901 Value, err := mm.pmKvStore.Get(ctx, groupName)
2902 if err == nil {
2903 if Value != nil {
2904 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002905 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002906 tmpBytes, _ := kvstore.ToByte(Value.Value)
2907
2908 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002909 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002910 return data, err
2911 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002912 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002913 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002914 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002915 return data, err
2916 }
2917 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002918 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002919 return data, err
2920 }
2921
2922 return data, nil
2923}
2924
2925// updatePmData update pmMEData to store. It is write through cache, i.e., write to cache first and then update store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002926func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2927 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2928 mm.OnuMetricsManagerLock.Lock()
2929 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002930
2931 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002932 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2933 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002934 }
2935
2936 pmMEData, err := mm.getPmData(ctx, groupName)
2937 if err != nil || pmMEData == nil {
2938 // error already logged in called function.
2939 return err
2940 }
2941 switch pmAction {
2942 case cPmAdd:
2943 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
2944 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2945 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2946 case cPmAdded:
2947 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
2948 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2949 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2950 case cPmRemove:
2951 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
2952 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2953 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2954 case cPmRemoved:
2955 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2956 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2957 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2958 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002959 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
2960 return fmt.Errorf(fmt.Sprintf("unknown-pm-action-deviceid-%s-groupName-%s-pmaction-%s", mm.deviceID, groupName, pmAction))
Girish Gowdra0e533642021-03-02 22:02:51 -08002961 }
2962 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002963 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08002964
2965 Value, err := json.Marshal(*pmMEData)
2966 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002967 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
2968 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002969 return err
2970 }
2971 // Update back to kv store
2972 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002973 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
2974 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002975 return err
2976 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002977 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
2978 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08002979
2980 return nil
2981}
2982
2983// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002984func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
2985 mm.OnuMetricsManagerLock.Lock()
2986 defer mm.OnuMetricsManagerLock.Unlock()
2987 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002988 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002989 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2990 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002991 }
2992
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002993 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002994 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002995 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002996 // do not abort this procedure. continue to delete next group.
2997 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002998 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08002999 }
3000 }
3001
3002 return nil
3003}
3004
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003005// ClearAllPmData clears all PM data associated with the device from KV store
3006func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
3007 mm.OnuMetricsManagerLock.Lock()
3008 defer mm.OnuMetricsManagerLock.Unlock()
3009 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08003010 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003011 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
3012 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08003013 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003014 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003015 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003016 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003017 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003018 value = err
3019 // do not abort this procedure - continue to delete next group.
3020 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003021 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003022 }
Girish Gowdra0e533642021-03-02 22:02:51 -08003023 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003024 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003025 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00003026 }
3027 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003028}
3029
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003030func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
3031 mm.OnuMetricsManagerLock.Lock()
3032 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003033 mm.omciProcessingActive = status
3034}
3035
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003036// updateTickGenerationStatus - TODO: add comment
3037func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
3038 mm.OnuMetricsManagerLock.Lock()
3039 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003040 mm.tickGenerationActive = status
3041}
3042
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003043// GetOmciProcessingStatus - TODO: add comment
3044func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
3045 mm.OnuMetricsManagerLock.RLock()
3046 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003047 return mm.omciProcessingActive
3048}
3049
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003050// GetTickGenerationStatus - TODO: add comment
3051func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
3052 mm.OnuMetricsManagerLock.RLock()
3053 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07003054 return mm.tickGenerationActive
3055}
3056
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003057func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003058 for _, ele := range slice {
3059 if ele == n {
3060 return slice
3061 }
3062 }
3063 return append(slice, n)
3064}
3065
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003066func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003067 for i, ele := range slice {
3068 if ele == n {
3069 return append(slice[:i], slice[i+1:]...)
3070 }
3071 }
3072 return slice
3073}
3074
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003075func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08003076 for _, ele := range slice {
3077 if ele == n {
3078 return slice
3079 }
3080 }
3081 return append(slice, n)
3082}
3083
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003084func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003085 for i, ele := range slice {
3086 if ele == n {
3087 return append(slice[:i], slice[i+1:]...)
3088 }
3089 }
3090 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003091}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303092
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003093func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303094 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3095 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003096 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003097 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003098 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303099 Value, err := mm.extPmKvStore.Get(ctx, key)
3100 if err == nil {
3101 if Value != nil {
3102 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003103 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303104 tmpBytes, _ := kvstore.ToByte(Value.Value)
3105
3106 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003107 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303108 return false, err
3109 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003110 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303111 // We have found the data from db, no need to get through omci get message.
3112 mm.supportedEthernetFrameExtendedPMClass = data
3113 return true, nil
3114 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003115 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303116 return false, nil
3117 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003118 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303119 return false, err
3120}
3121
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003122func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303123 logger.Debugw(ctx, "wait-for-ethernet-frame-create-or-delete-response-or-timeout", log.Fields{"create": create, "instID": instID, "meClassID": meClassID})
Girish Gowdraabcceb12022-04-13 23:35:22 -07003124 if !mm.GetOmciProcessingStatus() || mm.GetdeviceDeletionInProgress() {
3125 logger.Errorw(ctx, "not waiting for omci resp, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
3126 return false, fmt.Errorf("omci-processor-shutdown")
3127 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303128 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303129 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303130 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003131 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303132 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3133 if resp == me.Success || resp == me.InstanceExists {
3134 return true, nil
3135 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3136 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3137 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3138 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003139 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "resp": resp, "class-id": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303140 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3141 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003142 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303143 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003144 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303145 }
3146 return false, fmt.Errorf("timeout-while-waiting-for-response")
3147}
3148
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003149func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303150 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303151 // 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 +05303152 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003153 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303154 var entityID uint16
3155 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003156 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303157 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003158 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303159 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303160 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303161 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303162 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303163
3164 inner1:
3165 // retry ExtendedPmCreateAttempts times to create the instance of PM
3166 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003167 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3168 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3169 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303170 if err != nil {
3171 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003172 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303173 return false, err
3174 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303175 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3176 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303177 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303178 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303179 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303180 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303181 }
3182 break inner1
3183 } else if err != nil {
3184 if !supported {
3185 // Need to return immediately
3186 return false, err
3187 }
3188 //In case of failure, go for a retry
3189 }
3190 }
3191 if cnt == ExtendedPmCreateAttempts {
3192 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3193 return true, fmt.Errorf("unable-to-create-me")
3194 }
3195 }
3196 }
3197 return true, nil
3198}
3199
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003200func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3201 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
Holger Hildebrandt6a001d02022-06-15 08:32:48 +00003202 mm.pOnuDeviceEntry.GetPersVersion(),
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003203 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303204 // check if we get the supported type me for ethernet frame extended pm class id
3205 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3206 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3207 }
3208 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3209 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003210 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303211 }
3212 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003213 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303214 }
3215}
3216
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003217func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303218 mm.onuEthernetFrameExtendedPmLock.Lock()
3219 mm.isDeviceReadyToCollectExtendedPmStats = true
3220 mm.onuEthernetFrameExtendedPmLock.Unlock()
3221}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003222
Himani Chawlaee10b542021-09-20 16:46:40 +05303223// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003224func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303225 //get the type of extended frame pm me supported by onu first
3226 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3227 if err != nil {
3228 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3229 return
3230 }
3231 if exist {
3232 // we have the me type, go ahead with the me type supported.
3233 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003234 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303235 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3236 return
3237 }
3238 mm.setAllExtPmMeCreatedFlag()
3239 return
3240 }
3241 // First try with 64 bit me
3242 // we have the me type, go ahead with the me type supported.
3243 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3244 if err != nil && !supported64Bit {
3245 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003246 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303247 "supported": supported64Bit})
3248 // Then Try with 32 bit type
3249 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003250 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303251 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3252 } else if supported32Bit {
3253 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3254 mm.putExtPmMeKvStore(ctx)
3255 mm.setAllExtPmMeCreatedFlag()
3256 }
3257 } else if err == nil && supported64Bit {
3258 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3259 mm.putExtPmMeKvStore(ctx)
3260 mm.setAllExtPmMeCreatedFlag()
3261 }
3262}
3263
Himani Chawlaee10b542021-09-20 16:46:40 +05303264func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3265 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3266 uniPortEntityID := entityID
3267 if upstream {
3268 uniPortEntityID = entityID - 0x100
3269 }
3270 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3271 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3272 mm.pDeviceHandler.GetOmciTimeout(), true,
3273 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3274 if err != nil {
3275 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3276 log.Fields{"device-id": mm.deviceID})
3277 return extension.GetValueResponse_INTERNAL_ERROR, err
3278 }
3279
3280 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3281 return extension.GetValueResponse_REASON_UNDEFINED, nil
3282 }
3283 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3284}
3285
3286func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3287 logger.Debugw(ctx, "wait-for-ethernet-frame-reset-counters-response-or-timeout", log.Fields{"instID": instID, "meClassName": meClassName})
Girish Gowdraabcceb12022-04-13 23:35:22 -07003288 if !mm.GetOmciProcessingStatus() {
3289 logger.Errorw(ctx, "not waiting for omci resp, because the omci resp processor is shutdown due to device down/delete", log.Fields{"device-id": mm.deviceID})
3290 return false
3291 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303292 select {
3293 case resp := <-mm.extendedPMMeResponseChan:
3294 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3295 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3296 if resp == me.Success {
3297 return true
3298 }
3299 return false
3300 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3301 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3302 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3303 }
3304 return false
3305}
3306
3307func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3308 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3309 className := "EthernetFrameExtendedPm64Bit"
3310 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3311 className = "EthernetFrameExtendedPm"
3312 }
3313 // Reset the counters if option is specified
3314 for entityID := range upstreamEntityMap {
3315 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3316 true)
3317 if err != nil {
3318 return errReason, err
3319 }
3320 }
3321
3322 for entityID := range downstreamEntityMap {
3323 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3324 true)
3325 if err != nil {
3326 return errReason, err
3327 }
3328 }
3329 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3330 // device itself.
3331 // Unset the reset bit if option is specified
3332 for entityID := range upstreamEntityMap {
3333 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3334 false)
3335 if err != nil {
3336 return errReason, err
3337 }
3338 }
3339
3340 for entityID := range downstreamEntityMap {
3341 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3342 false)
3343 if err != nil {
3344 return errReason, err
3345 }
3346 }
3347 return extension.GetValueResponse_REASON_UNDEFINED, nil
3348}
3349
3350func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3351 mm.onuEthernetFrameExtendedPmLock.Lock()
3352 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3353 mm.isEthernetFrameExtendedPmOperationOngoing = val
3354}
3355
3356func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3357 mm.onuEthernetFrameExtendedPmLock.Lock()
3358 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3359 return mm.isEthernetFrameExtendedPmOperationOngoing
3360}
3361
3362// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3363func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3364 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3365 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3366 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303367 return &extension.SingleGetValueResponse{
3368 Response: &extension.GetValueResponse{
3369 Status: extension.GetValueResponse_ERROR,
3370 ErrReason: reason,
3371 },
3372 }
3373 }
3374 mm.onuEthernetFrameExtendedPmLock.RLock()
3375 if !mm.isDeviceReadyToCollectExtendedPmStats {
3376 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303377 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303378 }
3379 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303380
3381 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3382 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3383 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3384 }
3385 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3386 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3387
3388 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3389 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3390 if onuInfo.IsUniIndex != nil {
3391 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3392 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3393 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3394 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3395 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3396 break
3397 }
3398 }
3399 if len(downstreamEntityMap) == 0 {
3400 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3401 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3402 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3403 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3404 }
3405 } else {
3406 // make a copy of all downstream and upstream maps in the local ones
3407 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3408 upstreamEntityMap[entityID] = meEnt
3409 }
3410 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3411 downstreamEntityMap[entityID] = meEnt
3412 }
3413 }
3414 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3415 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3416 // Reset the metrics first for all required me's
3417 if onuInfo.Reset_ {
3418 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3419 if err != nil {
3420 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3421 log.Fields{"device-id": mm.deviceID})
3422 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3423 }
3424 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303425 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3426 var pmUpstream extension.OmciEthernetFrameExtendedPm
3427 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303428 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3429 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3430 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3431 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303432 if !onuInfo.Reset_ {
3433 for entityID, meEnt := range upstreamEntityMap {
3434 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3435 var receivedMask uint16
3436 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3437 if receivedMask == 0 {
3438 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303439 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3440 // It might be possible that still some downstream pms are supported and hence we need to continue
3441 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3442 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303443 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303444 // Aggregate the result for upstream
3445 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3446 } else {
3447 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303448 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303449 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303450
Himani Chawlaee10b542021-09-20 16:46:40 +05303451 for entityID, meEnt := range downstreamEntityMap {
3452 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3453 var receivedMask uint16
3454 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303455 if receivedMask == 0 {
3456 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3457 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3458 // Stop collecting downstream counters for other ME's.
3459 break
3460 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303461 // Aggregate the result for downstream
3462 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3463 } else {
3464 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3465 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303466 }
3467 }
3468 singleValResp := extension.SingleGetValueResponse{
3469 Response: &extension.GetValueResponse{
3470 Status: extension.GetValueResponse_OK,
3471 Response: &extension.GetValueResponse_OnuCounters{
3472 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303473 Upstream: &pmUpstream,
3474 Downstream: &pmDownstream,
3475 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303476 },
3477 },
3478 },
3479 }
3480 return &singleValResp
3481}
3482
Himani Chawlaee10b542021-09-20 16:46:40 +05303483func (mm *OnuMetricsManager) collectEthernetFrameExtendedPMData(ctx context.Context, meEnt *me.ManagedEntity, entityID uint16, upstream bool, receivedMask *uint16) (map[string]uint64, extension.GetValueResponse_ErrorReason, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303484 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003485 logger.Debugw(ctx, "collecting-data-for-ethernet-frame-extended-pm", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303486
3487 classID = mm.supportedEthernetFrameExtendedPMClass
3488 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3489 if classID == me.EthernetFrameExtendedPmClassID {
3490 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3491 }
3492 ethPMData := make(map[string]uint64)
3493 var sumReceivedMask uint16
3494 for mask := range attributeMaskList {
3495 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3496 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003497 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303498 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303499 }
3500 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3501 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3502 //populate all counters as failure and return
3503 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3504 break
3505 }
3506 }
3507 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303508 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303509}
3510
3511// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003512func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303513 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3514 var meAttributes me.AttributeValueMap
3515 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003516 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303517 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003518 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303519 return extension.GetValueResponse_INTERNAL_ERROR, err
3520 }
3521 select {
3522 case meAttributes = <-mm.extendedPmMeChan:
3523 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003524 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3525 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303526 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003527 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303528 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3529 }
3530 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3531 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3532 *sumReceivedMask += mask
3533 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3534 } else {
3535 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3536 *sumReceivedMask += mask
3537 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3538 }
3539
3540 return extension.GetValueResponse_REASON_UNDEFINED, nil
3541}
3542
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003543func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303544 sourceMap := maskToEthernetFrameExtendedPM64Bit
3545 errorCounterValue := UnsupportedCounterValue64bit
3546 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3547 sourceMap = maskToEthernetFrameExtendedPM32Bit
3548 errorCounterValue = UnsupportedCounterValue32bit
3549 }
3550 for _, value := range sourceMap {
3551 for _, k := range value {
3552 if _, ok := ethFrameExtPMData[k]; !ok {
3553 ethFrameExtPMData[k] = errorCounterValue
3554 }
3555 }
3556 }
3557}
3558
3559// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003560func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303561 receivedMask := uint16(0)
3562 switch requestedAttributesMask {
3563 case 0x3F00:
3564 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3565 if _, ok := ethFrameExtPMData[k]; !ok {
3566 switch k {
3567 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003568 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303569 ethFrameExtPMData[k] = uint64(val.(uint32))
3570 receivedMask |= 0x2000
3571 } else if !ok {
3572 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3573 }
3574 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003575 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303576 ethFrameExtPMData[k] = uint64(val.(uint32))
3577 receivedMask |= 0x1000
3578 } else if !ok {
3579 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3580 }
3581 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003582 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303583 ethFrameExtPMData[k] = uint64(val.(uint32))
3584 receivedMask |= 0x800
3585 } else if !ok {
3586 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3587 }
3588 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003589 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303590 ethFrameExtPMData[k] = uint64(val.(uint32))
3591 receivedMask |= 0x400
3592 } else if !ok {
3593 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3594 }
3595 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003596 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303597 ethFrameExtPMData[k] = uint64(val.(uint32))
3598 receivedMask |= 0x200
3599 } else if !ok {
3600 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3601 }
3602 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003603 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303604 ethFrameExtPMData[k] = uint64(val.(uint32))
3605 receivedMask |= 0x100
3606 } else if !ok {
3607 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3608 }
3609 default:
3610 //do nothing
3611 }
3612 }
3613 }
3614 case 0x00FC:
3615 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3616 if _, ok := ethFrameExtPMData[k]; !ok {
3617 switch k {
3618 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003619 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303620 ethFrameExtPMData[k] = uint64(val.(uint32))
3621 receivedMask |= 0x80
3622 } else if !ok {
3623 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3624 }
3625 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003626 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303627 ethFrameExtPMData[k] = uint64(val.(uint32))
3628 receivedMask |= 0x40
3629 } else if !ok {
3630 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3631 }
3632 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003633 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303634 ethFrameExtPMData[k] = uint64(val.(uint32))
3635 receivedMask |= 0x20
3636 } else if !ok {
3637 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3638 }
3639 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003640 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303641 ethFrameExtPMData[k] = uint64(val.(uint32))
3642 receivedMask |= 0x10
3643 } else if !ok {
3644 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3645 }
3646 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003647 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303648 ethFrameExtPMData[k] = uint64(val.(uint32))
3649 receivedMask |= 0x8
3650 } else if !ok {
3651 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3652 }
3653 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003654 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303655 ethFrameExtPMData[k] = uint64(val.(uint32))
3656 receivedMask |= 0x4
3657 } else if !ok {
3658 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3659 }
3660 default:
3661 //do nothing
3662 }
3663 }
3664 }
3665 case 0x0003:
3666 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3667 if _, ok := ethFrameExtPMData[k]; !ok {
3668 switch k {
3669 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003670 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303671 ethFrameExtPMData[k] = uint64(val.(uint32))
3672 receivedMask |= 0x2
3673 } else if !ok {
3674 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3675 }
3676 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003677 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303678 ethFrameExtPMData[k] = uint64(val.(uint32))
3679 receivedMask |= 0x1
3680 } else if !ok {
3681 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3682 }
3683 default:
3684 //do nothing
3685 }
3686 }
3687 }
3688 default:
3689 //do nothing
3690 }
3691 return receivedMask
3692}
3693
3694// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003695func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303696 receivedMask := uint16(0)
3697 switch requestedAttributesMask {
3698 case 0x3800:
3699 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3700 if _, ok := ethFrameExtPMData[k]; !ok {
3701 switch k {
3702 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003703 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303704 ethFrameExtPMData[k] = val.(uint64)
3705 receivedMask |= 0x2000
3706 } else if !ok {
3707 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3708 }
3709 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003710 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303711 ethFrameExtPMData[k] = val.(uint64)
3712 receivedMask |= 0x1000
3713 } else if !ok {
3714 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3715 }
3716 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003717 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303718 ethFrameExtPMData[k] = val.(uint64)
3719 receivedMask |= 0x800
3720 } else if !ok {
3721 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3722 }
3723 }
3724 }
3725 }
3726 case 0x0700:
3727 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3728 if _, ok := ethFrameExtPMData[k]; !ok {
3729 switch k {
3730 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003731 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303732 ethFrameExtPMData[k] = val.(uint64)
3733 receivedMask |= 0x400
3734 } else if !ok {
3735 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3736 }
3737 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003738 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303739 ethFrameExtPMData[k] = val.(uint64)
3740 receivedMask |= 0x200
3741 } else if !ok {
3742 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3743 }
3744 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003745 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303746 ethFrameExtPMData[k] = val.(uint64)
3747 receivedMask |= 0x100
3748 } else if !ok {
3749 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3750 }
3751 }
3752 }
3753 }
3754 case 0x00E0:
3755 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3756 if _, ok := ethFrameExtPMData[k]; !ok {
3757 switch k {
3758 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003759 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303760 ethFrameExtPMData[k] = val.(uint64)
3761 receivedMask |= 0x80
3762 } else if !ok {
3763 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3764 }
3765 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003766 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303767 ethFrameExtPMData[k] = val.(uint64)
3768 receivedMask |= 0x40
3769 } else if !ok {
3770 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3771 }
3772 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003773 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303774 ethFrameExtPMData[k] = val.(uint64)
3775 receivedMask |= 0x20
3776 } else if !ok {
3777 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3778 }
3779 }
3780 }
3781 }
3782 case 0x001C:
3783 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3784 if _, ok := ethFrameExtPMData[k]; !ok {
3785 switch k {
3786 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003787 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303788 ethFrameExtPMData[k] = val.(uint64)
3789 receivedMask |= 0x10
3790 } else if !ok {
3791 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3792 }
3793 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003794 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303795 ethFrameExtPMData[k] = val.(uint64)
3796 receivedMask |= 0x8
3797 } else if !ok {
3798 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3799 }
3800 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003801 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303802 ethFrameExtPMData[k] = val.(uint64)
3803 receivedMask |= 0x4
3804 } else if !ok {
3805 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3806 }
3807 default:
3808 //do nothing
3809 }
3810 }
3811 }
3812 case 0x0003:
3813 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3814 if _, ok := ethFrameExtPMData[k]; !ok {
3815 switch k {
3816 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003817 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303818 ethFrameExtPMData[k] = val.(uint64)
3819 receivedMask |= 0x2
3820 } else if !ok {
3821 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3822 }
3823 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003824 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303825 ethFrameExtPMData[k] = val.(uint64)
3826 receivedMask |= 0x1
3827 } else if !ok {
3828 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3829 }
3830 default:
3831 //do nothing
3832 }
3833 }
3834 }
3835 }
3836 return receivedMask
3837}
3838
Himani Chawlaee10b542021-09-20 16:46:40 +05303839func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3840 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303841 errorCounterValue := UnsupportedCounterValue64bit
3842 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3843 errorCounterValue = UnsupportedCounterValue32bit
3844 }
3845 var pmDataOut extension.OmciEthernetFrameExtendedPm
3846 if aggregate {
3847 if pmData.DropEvents != errorCounterValue {
3848 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3849 } else {
3850 pmDataOut.DropEvents = pmData.DropEvents
3851 }
3852 if pmData.Octets != errorCounterValue {
3853 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3854 } else {
3855 pmDataOut.Octets = pmData.Octets
3856 }
3857 if pmData.Frames != errorCounterValue {
3858 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3859 } else {
3860 pmDataOut.Frames = pmData.Frames
3861 }
3862 if pmData.BroadcastFrames != errorCounterValue {
3863 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3864 } else {
3865 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3866 }
3867 if pmData.MulticastFrames != errorCounterValue {
3868 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3869 } else {
3870 pmDataOut.MulticastFrames = pmData.MulticastFrames
3871 }
3872 if pmData.CrcErroredFrames != errorCounterValue {
3873 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3874 } else {
3875 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3876 }
3877 if pmData.UndersizeFrames != errorCounterValue {
3878 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3879 } else {
3880 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3881 }
3882 if pmData.OversizeFrames != errorCounterValue {
3883 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3884 } else {
3885 pmDataOut.OversizeFrames = pmData.OversizeFrames
3886 }
3887 if pmData.Frames_64Octets != errorCounterValue {
3888 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3889 } else {
3890 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3891 }
3892 if pmData.Frames_65To_127Octets != errorCounterValue {
3893 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3894 } else {
3895 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3896 }
3897 if pmData.Frames_128To_255Octets != errorCounterValue {
3898 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3899 } else {
3900 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3901 }
3902 if pmData.Frames_256To_511Octets != errorCounterValue {
3903 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3904 } else {
3905 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3906 }
3907 if pmData.Frames_512To_1023Octets != errorCounterValue {
3908 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3909 } else {
3910 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3911 }
3912 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3913 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3914 } else {
3915 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3916 }
3917 } else {
3918 pmDataOut.DropEvents = pmDataIn["drop_events"]
3919 pmDataOut.Octets = pmDataIn["octets"]
3920 pmDataOut.Frames = pmDataIn["frames"]
3921 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3922 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3923 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3924 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3925 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3926 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3927 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3928 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3929 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3930 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3931 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3932 }
3933 return pmDataOut
3934}
3935
Himani Chawlaee10b542021-09-20 16:46:40 +05303936func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303937 controlBlock := make([]uint16, 8)
3938 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3939 controlBlock[0] = 0
3940 // Next two bytes are for the parent class ID
3941 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3942 // Next two bytes are for the parent me instance id
3943 controlBlock[2] = entityID
3944 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05303945 if reset {
3946 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
3947 } else {
3948 controlBlock[3] = 0
3949 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303950 // Next two bytes are for tca disable
3951 controlBlock[4] = 0x4000 //tca global disable
3952 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
3953 if upstream {
3954 controlBlock[5] = 1 << 0
3955 } else {
3956 controlBlock[5] = (1 << 0) | (1 << 1)
3957 }
3958 // Next two bytes are for tci - does not matter here
3959 controlBlock[6] = 0
3960 // Next two bytes are for reserved bits - does not matter here
3961 controlBlock[7] = 0
3962 return controlBlock
3963}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003964
Girish Gowdraabcceb12022-04-13 23:35:22 -07003965// GetdeviceDeletionInProgress gets the deviceDeletionInProgress flag
3966func (mm *OnuMetricsManager) GetdeviceDeletionInProgress() bool {
3967 mm.OnuMetricsManagerLock.RLock()
3968 defer mm.OnuMetricsManagerLock.RUnlock()
3969 return mm.deviceDeletionInProgress
3970}
3971
3972// SetdeviceDeletionInProgress sets the deviceDeletionInProgress flag
3973func (mm *OnuMetricsManager) SetdeviceDeletionInProgress(deleted bool) {
3974 mm.OnuMetricsManagerLock.Lock()
3975 defer mm.OnuMetricsManagerLock.Unlock()
3976 mm.deviceDeletionInProgress = true
3977}
3978
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003979// PrepareForGarbageCollection - remove references to prepare for garbage collection
3980func (mm *OnuMetricsManager) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
Girish Gowdra8feabf82022-05-11 16:39:16 -07003981 currState := L2PmStNull
3982 if mm.PAdaptFsm != nil && mm.PAdaptFsm.PFsm != nil {
3983 currState = mm.PAdaptFsm.PFsm.Current()
3984 }
3985 if currState == L2PmStNull {
3986 logger.Infow(ctx, "pm fsm already stopped, safe to garbage collect", log.Fields{"device-id": mm.deviceID})
3987 mm.pDeviceHandler = nil
3988 mm.pOnuDeviceEntry = nil
3989 mm.GarbageCollectionComplete <- true
3990 return
3991 }
3992 logger.Debugw(ctx, "prepare for garbage collection - no action, garbage collection done when PM FSM is stopped",
3993 log.Fields{"device-id": aDeviceID, "curr-fsm-state": currState})
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003994}